Há muito que eu queria escrever um texto semelhante, mas minhas mãos não chegaram. Mas, após a reunião de verão do Comitê de Padronização em C ++ que terminou e os uivos de que a complexidade da linguagem aumentou ainda mais, tive que encontrar tempo e consertar meus próprios pensamentos sobre esse assunto.
Haverá muito texto, portanto, aqueles que não se arrependerem de seu tempo, convido você a procurar sob o gato.
Linguagem de programação é um produto tecnológico, mas não tão simples
Há algum tempo, tive a oportunidade de ler um livro interessante, o dilema do inovador . Lá, com exemplos de produtos de alta tecnologia, é mostrado como surgem novos produtos que primeiro perdem para as decisões que atualmente dominam o mercado e depois mudam radicalmente o estado do mercado.
Um dos exemplos mais impressionantes: a fotografia digital, que estava completamente ausente na década de 1990, mas apenas 20 anos depois levou ao colapso de um monstro do século 20 como a Kodak (que, aliás, foi a primeira a criar um protótipo de câmera digital).

Outro exemplo próximo dos desenvolvedores é a evolução dos discos rígidos. Desde os monstruosos tempos do mainframe e dos minicomputadores, aos pequenos modelos de 3,5 "e 2,5" de polegada e, em seguida, aos SSDs de formato M.2 e conectados diretamente à placa eMMC.

A mesma coisa com os disquetes, que chegaram a 3,5 "e depois desapareceram como uma classe sob a pressão das unidades flash USB.

Outro exemplo do nosso campo profissional é o desenvolvimento de computadores pessoais. Que inicialmente não eram capazes de competir com os computadores "reais" de meados do final da década de 1970. E então eles simplesmente destruíram os mini computadores como uma classe. Em seguida, eles levaram ao surgimento de servidores modernos, um pouco reminiscentes dos então mini-computadores. E agora os próprios PCs estão desaparecendo do consumo em massa sob a influência de laptops, tablets e smartphones.

Os autores do livro declaram que os eventos em todos esses casos se desenvolvem de acordo com o mesmo cenário:
- Primeiro, é necessário um produto que resolva um problema específico. Digamos que um disco magnético flexível;
- uma vez que, na fase inicial, todas as soluções concorrentes (das quais, em princípio, são poucas) são baseadas nas mesmas tecnologias, o mercado é dividido entre produtos mais ou menos semelhantes;
- os fabricantes de produtos de sucesso começam a competir entre si e, nessa competição, levam seus produtos quase à relação preço-qualidade mais favorável. E, o mais importante, enquanto os produtos existentes são tão consistentes quanto possível com as visões de como as tarefas para as quais esses produtos devem ser abordados. Grosso modo, todo mundo sabe que os disquetes de 8 "são excelentes para transferir informações de um mini computador para outro usando disquetes. E ninguém mais pode imaginar outra maneira no mainstream;
- em algum lugar à margem, com base em algumas novas descobertas / materiais / tecnologias, um novo produto parece ser significativamente inferior aos produtos existentes em quase todos os aspectos. Geralmente mais caro. Como regra, não é comparável em capacidades / capacidades. Mas tem uma qualidade muito importante: pode ser usada onde é impossível ou difícil aplicar soluções convencionais. Por exemplo, você não pode conectar uma unidade de 8 "a um computador pessoal. Mas os proprietários de PCs não estão interessados em transportar disquetes de 8". Simplesmente não é prático. Considerando que o disquete de 5.25 "é bastante próprio. E não se preocupe com o custo de um 5.25 kilobyte" de disquete era originalmente mais caro que 8. "Ainda não havia escolha;
- Um novo mercado foi formado em torno do novo produto, que inicialmente não era de todo interessante para os principais fabricantes de produtos. Mas, como se tratava de um novo mercado, novos participantes se juntaram a ele, o que criou uma competição séria entre si. E essa competição transformou rapidamente a tecnologia marginal e ineficaz em extremamente eficaz. O que logo deixou de ser marginal, porque, assim que excedeu os produtos tradicionais antigos em termos de sua totalidade, rapidamente os substituiu em seu próprio nicho. Grosso modo, se existem centenas de milhares de unidades de 5,25 "e milhões de disquetes de 5,25", então qual é o sentido de manter os dispositivos de 8 "muito mais marginais no momento?
Linguagens de programação como produtos tecnológicos
À primeira vista, analogias semelhantes podem ser vistas na maneira como as linguagens de programação chegaram ao mainstream. E talvez os exemplos mais impressionantes aqui sejam as linguagens Java e Go.
A linguagem Java surgiu como resultado de uma tentativa de criar "C ++ adequado". Mas a linguagem resultante dificilmente seria necessária para qualquer pessoa, porque ele estava muito infeliz e, mais importante, lento e guloso. Na área de trabalho da época, mesmo considerando o rápido crescimento da energia do PC na época, Java não tinha chance.
No entanto, o Java entrou no "mercado" de uma perspectiva completamente diferente, através de um nicho no qual ninguém poderia realmente funcionar: via Internet e applets de navegador (tudo era um pouco mais complicado e ainda havia um mercado para os applets JavaCard e STK, mas não vamos sair na natureza). A Internet era um tópico muito quente, e simplesmente não havia nada para fazer sites / páginas dinâmicos (o JavaScript apareceu após o anúncio do Java). E, como não havia nada para usar além do Java, o Java começou a ser usado. Bem, e então, ao desenvolver e superar as doenças da infância, o Java entrou em outras áreas, expulsando outras tecnologias a partir daí. Embora na mesma mesa ela não pudesse morder um pedaço significativo da torta.
A linguagem Go dificilmente poderia interessar a ninguém em nichos tradicionais onde C, C ++, Java, C #, Python, Ruby etc. já existiam. Mas o desenvolvimento de produtos para a Internet gerou outro nicho - os serviços RESTful. Para o desenvolvimento do qual Java era um exagero, o C ++ é muito complicado e perigoso, Python / Ruby e outras dinâmicas são muito lentas. E agora um dos mais infelizes nos termos expressivos das línguas desenvolvidas no século XXI torna-se quase uma bala de prata para esse nicho aplicado. De onde, talvez, ele se espalhe para outros lugares ao longo do tempo (o que eu pessoalmente não ficarei surpreso com o nível de qualificação geral da jovem geração de desenvolvedores).
Portanto, sentimos que a programação deve ser a mesma com as linguagens e com outros produtos tecnológicos: o surgimento de novas linguagens leva a um desaparecimento quase completo ou a expulsar as linguagens anteriores em nichos marginais separados. Ao mesmo tempo, os idiomas antigos, no processo de desenvolvimento dentro da estrutura do ambiente competitivo, estão se tornando mais poderosos e expressivos para soluções mais baratas para suas tarefas típicas. Como resultado, os idiomas antigos estão se tornando cada vez mais volumosos e complexos. E menos atraente para uso fora dos nichos que eles já ocuparam.
Portanto, parece que o ciclo de vida de um produto tecnológico descrito no dilema do inovador também deve se estender às linguagens de programação.
Mas nem tudo é tão simples com linguagens de programação
No esquema de penetração de novos produtos tecnológicos no mercado descrito no dilema do inovador, uma das razões mais importantes para os usuários mudarem de produtos tradicionais antigos para novos é simplesmente uma redução significativa no custo de propriedade ou a aquisição de oportunidades disponíveis anteriormente + uma diminuição no custo de propriedade.
Digamos, o desenvolvimento de PCs e o aumento de sua potência tornam mais barato possuir uma frota de PCs do que possuir um ou mais mini-computadores. Como resultado, os disquetes de três polegadas são mais baratos por unidade de capacidade do que 5,25 "(levando em conta maior confiabilidade e outros fatores). A fotografia digital acaba sendo mais barata por quadro do que o filme. E assim por diante.
Mas dois indicadores mais importantes estão associados à transição de um produto para outro - esse é o custo / complexidade da própria transição, bem como a velocidade com a qual você pode mudar para um novo produto. Esses indicadores podem ser estimados em dinheiro. E se o benefício da transição para um novo produto estiver presente, a transição será realizada. Talvez não seja rápido, mas realizado.
E aqui acontece que o custo de alternar de uma linguagem de programação para outra é muito maior do que no caso de alternar de um mini computador para um PC, de 8 "disquetes para 5,25" ou de HDD para SSD. Como alterar uma linguagem de programação geralmente é uma reescrita completa de um produto de software. Muitas vezes do zero.
E o que significa reescrever? Salário de uma nova equipe de programadores, que precisará repetir a funcionalidade já disponível no produto. E mesmo que o novo PL permita reduzir pela metade o tamanho da equipe, isso ainda significará custos significativos. Se US $ 10 milhões foram gastos no desenvolvimento da versão antiga do produto, a reescrita exigirá pelo menos US $ 5 milhões.
Mais importante, porém, é que o produto reescrito não aparecerá imediatamente, de uma só vez. Isso leva tempo. Muito tempo. Novamente, se assumirmos que a nova linguagem permite escrever código de trabalho duas vezes mais rápido, reescrever o produto, cujo desenvolvimento da versão antiga demorou 5 anos, exigirá apenas 2,5 anos.
Acontece que agora você precisa começar a investir muito dinheiro para obter uma cópia de algo que está funcionando há muito tempo e que gera dinheiro agora.
E mais um lado dessa moeda deve ser mencionado: se um produto de software for operado em condições variáveis, o produto será inevitavelmente finalizado ou processado para atender às necessidades modernas. Ao mesmo tempo, o negócio não tem a oportunidade de esperar um ano e meio, até que uma nova versão do produto apareça em um novo PL, uma nova funcionalidade, como regra, seja necessária em um futuro próximo. Muitas vezes ontem.
Portanto, ao reescrever, as despesas aumentam: você precisa escrever uma nova versão ao mesmo tempo e desenvolver a antiga.
Na minha opinião, é exatamente isso que explica por que as novas linguagens são "acionadas", principalmente no desenvolvimento de novas aplicações para um novo nicho de aplicação. Mas excluir idiomas antigos de áreas anteriormente ocupadas já é muito mais lento. Fortran e Cobol provavelmente podem ser considerados os exemplos mais impressionantes. Além de o software gravado neles ainda estar em operação, eles continuam a escrever um novo código nesses idiomas. E essas próprias línguas estão evoluindo.
E parece-me que um dos piores sonhos dos proprietários de produtos de software em Cobol é reescrever o produto em Java ou C #;)
E outro fator importante: o desenvolvimento da própria TI
Outro ponto que eu gostaria de chamar a atenção é o fato de que a TI existe há não muito tempo e a história da evolução das linguagens de alto nível é ainda mais curta. É improvável que a primeira parte desta história forneça um suporte sólido para a discussão de como algumas línguas substituem outras. As décadas de 1950 e 1960 foram anos de experimentação. Além disso, os anos em que o próprio mercado de computadores foi segmentado e uma parte significativa do software foi escrita para computadores e sistemas operacionais específicos, sem requisitos especiais de portabilidade. O número de desenvolvedores de software existentes, bem como a variedade de áreas em que os computadores são amplamente utilizados, não podem ser comparados com o estado atual das coisas.
IMHO, as coisas mudaram fundamentalmente nos anos 1970 e, desde os anos 80, vimos o surgimento de armas nucleares que já se baseiam tanto na experiência prática dos últimos anos quanto nos resultados de estudos teóricos. Quanto a mim, são precisamente os anos 80 (e talvez o final dos anos 70) que são o início da era das linguagens de programação voltadas para a fabricação de software em escala industrial. Pois é aqui que vemos Modula-2, SmallTalk, Ada, C ++, Eiffel, extensões de objeto de Pascal, Objective-C, Perl.
Portanto, irei além do que exatamente apareceu nesta era de armas nucleares industriais.
By the way
Listando as línguas que surgiram na década de 1980, lembrei-me do PL desenvolvido por Niklaus Wirth: primeiro Pascal, depois Modula / Modula-2, depois Oberon.
Pelo exemplo dessas linguagens, pode-se ver como a experiência de seu autor leva ao aparecimento de ferramentas que levam em consideração as deficiências de tentativas anteriores, além de atender aos novos requisitos de seu tempo.
Mas esses mesmos idiomas também mostram o quanto é importante para os usuários do YaP permanecerem dentro da estrutura do idioma escolhido anteriormente. A transição de Pascal para Modula-2 foi. Mas de maneira alguma maciço. E, apesar de o Modula-2 ter sido usado mais ou menos ativamente, ele não se tornou tão popular quanto os herdeiros de Pascal, especialmente Delphi. E não houve transição observável para Oberon, até onde me lembro.
A linguagem de programação popular não pode ser substituída apenas. E daí?
Portanto, a principal mensagem do meu raciocínio anterior é que, se uma linguagem encontrou uso mais ou menos difundido e com a ajuda de vários produtos de software que são usados no dia a dia foram criados, essa linguagem não pode ser simplesmente completamente substituída por outras linguagens de programação. Especialmente em pouco tempo.
Linguagens de programação bem-sucedidas estão fadadas a continuar sendo usadas por anos. E provavelmente evoluirá.
E a evolução de uma linguagem de programação implica a expansão da linguagem com novos recursos. O que é inevitável, porque o progresso não pára. As pessoas apresentam maneiras mais convenientes de resolver problemas conhecidos. Diante de novas tarefas, que exigem recursos expressivos adicionais de linguagens de programação. E, como a linguagem de programação é apenas uma ferramenta, as pessoas estão avançando no sentido de melhorar sua ferramenta.
O que significa que as linguagens de programação amplamente usadas estão simplesmente fadadas a se tornarem cada vez mais volumosas e mais complexas, ao longo de seu desenvolvimento, adquirindo oportunidades que nem foram discutidas a princípio.
Em princípio, Bjarn Straustrup falou sobre isso há muito tempo. E mesmo o que eu mesmo venho observando há quase trinta anos confirma as palavras de Straustrup. Digamos, o Java moderno já é muito diferente do Java 1.0 de 1995. A linguagem C # demonstra uma evolução ainda mais impressionante, de um clone bem-sucedido do primeiro Java para talvez a linguagem mainstream mais expressiva, adequada para o uso de programadores hindus (independentemente de sua nacionalidade).
Mas o exemplo mais impressionante para mim ainda é a linguagem Go. O que, já no século 21, eles começaram a fazer deliberadamente jogando fora um monte de coisas que se provaram bem ao longo das décadas de uso difundido em diferentes materiais nucleares. E que graças, inclusive isso, se tornou popular. Mas, no entanto, a vida cobra seu preço e o Go é forçado a acrescentar algo que os autores inicialmente recusaram intencionalmente - ferramentas para programação generalizada (também conhecidas como templates / genéricos) .
Então, linguagens de programação populares evoluem para expandir seus recursos. E isso significa complicações. Como novos recursos precisam ser adicionados para não violar seriamente o código já escrito. Pois a história épica com Python da segunda e terceira versões se tornou um bom exemplo, que poucos ousam repetir.
Isso é tão ruim?
O lado negativo da complexidade cada vez maior das linguagens de programação (especialmente uma linguagem como C ++) parece ser óbvio: o limite de entrada é muito alto. É necessário gastar muito tempo aprendendo um idioma para começar a emitir um código de qualidade aceitável em um prazo aceitável. O que torna o desenvolvimento em uma linguagem de programação complexa caro e arriscado. O que acontece se um ou mais desenvolvedores qualificados deixarem o projeto? Quão rápido e fácil será encontrar um substituto? Perguntas difíceis.
Por outro lado, como uma linguagem de programação é a mesma ferramenta para registrar as intenções de uma pessoa em particular, como, por exemplo, expressões matemáticas, é apropriado fazer uma analogia com a matemática.
Na escola, começamos a estudar matemática começando pelas operações aritméticas mais simples. Então passamos a coisas mais complexas: frações, graus e raízes. Então vamos mais longe, em direção aos logaritmos. Depois, fazemos um pequeno cálculo integral. Da mesma forma com a geometria.
Como resultado, um graduado de uma escola normal possui um certo aparato matemático, que pode ser redundante para uma única pessoa. Não me enganarei se assumir que muitos depois da escola nunca precisaram calcular nada usando logaritmos ou fazer integrais.
No entanto, o aparato matemático, que é dominado no ensino médio, não pode ser comparado ao fato de que os estudantes universitários receberão cursos de matemática superior. Especialmente se for aluno de uma faculdade de matemática ou física (e não apenas baixar seriamente a matemática superior em muitas especialidades).
Afinal, não ocorre a ninguém culpar a matemática pelo fato de que, quanto mais você mergulha nela, mais difícil é. Como se uma pessoa se depara com uma área de atividade em que precisa do TFKP, nada pode ser feito, o TFKP terá que estudar. Por mais difícil que seja. Bem, sim, é normal que nem todos tenham sucesso.
Na verdade, a mesma coisa com linguagens de programação.
Se você precisar resolver problemas relativamente simples, poderá escolher: ou usa uma linguagem de programação mais simples ou usa um subconjunto limitado de uma linguagem mais complexa. Mas se você se deparar com uma tarefa difícil (ou condições específicas para sua solução), poderá não ter essa opção: a complexidade de resolver esse problema em uma linguagem "simples" pode ser muito grande.
Falando de tarefas
, (.. , , , .., ..), , .
. , .. , . , , . , , , . , , , .
, , Go, Python, Ruby PHP, , , , . , , , , . .
, , , , . , 25 GUI , . , 25 .
, , , . , / , , .
, , , , , C++, Scala Haskell. , , . , , Go C.
. . , , : , , . , - C++, . .., -, C++ . , -, C++ , , .
Total
, ? :
- -, . , , , « », 1960-1970- , . , . , . ( ). - X, , X . , C. , . . , — . ;
- -, , 40 , . , , . , .. , , ;
- -, . - Ruby/Python, - Go, - Java. - Rust-, C++, Scala Haskell-. , . - , « », . .
, , - : , - . - . , ( , , ). , - , , : , , -. ;)