Ouvi muitas vezes a afirmação de que as linguagens dinamicamente tipadas são mais produtivas que as linguagens estaticamente. Quais são as razões para esta reivindicação? Não é apenas trabalhar com conceitos modernos, como convenção sobre configuração, uso de programação funcional, modelos avançados de programação e uso de abstrações consistentes? É certo que há menos confusão porque as declarações de tipo (por exemplo, em Java) geralmente redundantes não são necessárias, mas você também pode omitir a maioria das declarações de tipo em linguagens estaticamente tipadas que usam inferência de tipo, sem perder as outras vantagens da digitação estática. E tudo isso está disponível para linguagens modernas de tipo estatístico, como o Scala.
Então: o que há para dizer com relação à produtividade com a digitação dinâmica, que realmente é uma vantagem do próprio modelo de texto?
Esclarecimento: Estou mais interessado em projetos de grande / médio porte do que em hacks rápidos. :-)
fonte
Respostas:
Na verdade, acho que é por pouco. Tanto a digitação dinâmica quanto a estática têm suas vantagens.
Razões para a digitação dinâmica ser mais produtiva:
Razões para a digitação estática ser mais produtiva:
Em média, minha conclusão (após muitos anos de experiência em ambos os lados da barreira) é que a digitação dinâmica pode ser mais produtiva a curto prazo, mas acaba se tornando difícil de manter, a menos que você tenha muito bons conjuntos de testes e disciplina de teste.
Por outro lado, na verdade, prefiro abordagens de tipo estatístico em geral, porque acho que os benefícios da correção e o suporte à ferramenta oferecem melhor produtividade a longo prazo.
fonte
Com idiomas dinâmicos, você pode escrever códigos de baixa qualidade mais rapidamente do que quando usa um idioma digitado.
Depois de criar rapidamente sua enorme pilha de coisas dinâmicas, você pode passar com segurança para outro projeto sem ter que se preocupar com manutenção a longo prazo.
Isso é ganho de produtividade :)
Estou brincando, mas depois de me envolver em um projeto usando 'linguagem dinâmica', fiquei assustado com a quantidade de testes, documentações e convenções desnecessárias com as quais você precisa lidar se quiser ter um produto em funcionamento.
E com a alegria de muitos erros de execução que poderiam ter sido detectados na compilação.
Ah, eu também esqueci de falar sobre todos esses hacks e voodoos que a metaprogramação permite que você introduza no seu código!
Portanto, o ganho de produtividade pode ser um mito para projetos médios / grandes ao longo de sua vida útil.
fonte
Também existe uma visão teórica para esse problema: um sistema de tipo estático é essencialmente um provador de teoremas especializado que só aceita o programa quando pode provar a correção de tipo dele. Todos os sistemas de tipo estático rejeitam alguns programas válidos porque nenhum sistema de tipo estático decidível é poderoso o suficiente para provar todos os programas possíveis de correção de tipo.
Pode-se argumentar que os programas que não são prováveis por um typechecker estático são hacks e / ou estilo ruim, mas se você já possui um programa válido e o typechecker não o aceita, certamente está prejudicando sua produtividade no curto prazo.
Alguns casos em que você pode notar que o verificador de tipo está atrapalhando são contêineres genéricos e co / contravariância em argumentos e tipos de retorno.
fonte
Uma vantagem que encontrei nas linguagens mais dinâmicas é que elas facilitam a escrita de códigos mais genéricos. É muito mais fácil escrever em um nível mais alto de abstração quando você não precisa combater o sistema de tipos para fazer isso.
Você não precisa pensar muito sobre isso - escrever código que faz algo não trivial com qualquer objeto em Java é difícil e provavelmente requer reflexão, tipicamente dinamicamente digitada; com algo como JavaScript, escrever uma função que faz algo interessante para todos os objetos é uma segunda natureza. Um exemplo perfeito seria uma função que escrevi recentemente que pega um objeto e substitui todos os seus métodos por outros que fazem a mesma coisa, mas também acionam um evento. Não tenho idéia de como abordar algo assim em Java. No entanto, não sei quanto disso se deve aos sistemas de tipos e quanto a outras diferenças de idioma.
No entanto, recentemente comecei a usar o Haskell. Haskell me permite escrever um código genérico abstrato, tão facilmente quanto qualquer linguagem dinamicamente usada. Meu exemplo de Java / JavaScript acima não faz sentido no Haskell porque não possui objetos, métodos, eventos ou mesmo muita mutação, mas outros tipos de código genérico são realmente fáceis de escrever.
De fato, Haskell pode escrever um código genérico que as linguagens dinamicamente digitadas não podem; um exemplo perfeito é a
read
função que é basicamente o oposto detoString
. Você pode obter umInt
ou umDouble
ou qualquer tipo que desejar (desde que esteja em uma determinada classe de tipo). Você pode até ter polimórficos constantes , por issomaxBound
pode ser o máximoInt
,Double
,Char
... etc., Tudo dependendo de que tipo é suposto ser.Minha teoria agora é que o ganho de produtividade ao usar uma linguagem dinâmica é sempre comparado a linguagens como Java, com sistemas do tipo menos capazes, mais detalhados e menos flexíveis.
No entanto, mesmo o sistema de tipos de Haskell tem alguns problemas irritantes que você não teria em um idioma digitado dinamicamente. O maior que me incomoda é a maneira como os números são tratados; por exemplo, você precisa mexer no sistema de tipos para usar
length
(de uma lista) como um duplo, algo com o qual você não teria problemas sem um sistema de tipos. Outra coisa irritante em que me deparei é trabalhar comWord8
(um tipo int não assinado) e funções que esperamosInt
.Portanto, não ter um sistema de tipos facilita escrever código genérico sem pensar muito e também evita armadilhas irritantes dos sistemas de tipos. Você nunca precisa combater o sistema de tipos em uma linguagem dinâmica, mas também não pode confiar nele.
fonte
Int
retornado por uma lista é trivial; exemplo1.0 + fromIntegral (length myList)
:, ou seja, basta usarfromIntegral
.P: Ouvi muitas vezes a afirmação de que as linguagens dinamicamente digitadas são mais produtivas que as linguagens estaticamente. Quais são as razões para esta reivindicação? "
Isso tem razões históricas. Se você voltar algumas décadas, as linguagens dinâmicas eram indiscutivelmente mais produtivas que as linguagens estáticas (embora também significativamente mais lentas). Perl é claramente muito mais produtivo que C, se você conhece os dois e a tarefa em questão permite isso. Porém, com o tempo, os idiomas se emprestaram muito e os idiomas mais novos estão diminuindo a diferença (tanto em produtividade quanto em desempenho).
Aqui estão alguns pontos a considerar:
Coleta de lixo : A coleta de lixo é um enorme aumento de produtividade. Eu acredito que Java foi a primeira linguagem estática mainstream com GC. Antes disso, estática significava basicamente gerenciamento manual de memória. (Nota: Aqui e a seguir, considero apenas as principais linguagens. Existem muitas linguagens experimentais e de nicho que fornecerão contra-exemplos a qualquer ponto que eu faça.)
Segurança da memória : é uma melhoria de produtividade que você não precisa se preocupar em dar um tiro no próprio pé. Antes de linguagens estáticas "gerenciadas" como Java, estática normalmente significava acesso direto à memória. A depuração também faz parte da produtividade, e o acesso inseguro à memória pode levar a erros realmente obscuros.
Sistemas de tipo pesado. Antes da introdução de tipos parametrizados (como modelos ou genéricos) em linguagens estáticas, as limitações dos sistemas de tipos estáticos costumavam ser um fardo. Por exemplo, em Java, era necessário fazer o downcast explicitamente toda vez que você selecionava um item de uma coleção. Então você tem a sobrecarga sintática de um elenco e nenhum tipo de segurança. Considerando o quão onipresente as coleções são na programação, essa foi uma grande desvantagem.
Ter que declarar o tipo de tudo é muita digitação redundante, mas com a inferência de tipo moderna, isso pode ser reduzido significativamente.
Grande biblioteca padrão. O Python foi anunciado como "baterias incluídas" por causa da grande biblioteca padrão. Isso em comparação com C, que tem uma biblioteca padrão muito minimalista. Mas com plataformas como Java e .net, uma vasta biblioteca padrão está se tornando padrão, e linguagens mais recentes como Scala e F # estão herdando isso "de graça".
Estruturas de dados de primeira classe. Linguagens dinâmicas como Perl e Python possuem estruturas de dados de primeira classe, como listas e mapas, com atalhos sintáticos convenientes para operações comuns. Comparado a isso, C não tem coleções internas, exceto matrizes de tamanho fixo.
Encerramentos e sintaxe lambda - linguagens dinâmicas normalmente têm isso desde o início, mas linguagens estáticas adotam isso, mais recentemente Java.
A capacidade do REPL de testar rapidamente trechos de código de maneira interativa é um grande benefício. Porém, embora as ferramentas IDE, como a janela "imediata" no Visual Studio, as linguagens estáticas possam emular isso até certo ponto.
Ferramentas avançadas - além dos pontos acima em que as linguagens estáticas estão se aproximando da conveniência das linguagens dinâmicas, os editores modernos estão aproveitando a análise estática de uma maneira que as linguagens dinâmicas enfrentam dificuldades. Por exemplo, os editores podem fornecer refatorações automáticas seguras, algo estritamente impossível em um idioma dinâmico.
Conclusão: Historicamente era verdade, mas hoje a resposta é menos clara.
P: Então: o que há para dizer com relação à produtividade com a digitação dinâmica, que realmente é uma vantagem do próprio modelo de texto?
É um pouco difícil separar o modelo de digitação dinâmica das linguagens dinâmicas, mas, como exemplo, o C # adotou mais recursos mais dinâmicos ao longo do tempo, mesmo que seu núcleo seja uma linguagem estática. Esta é realmente uma prova de benefício do modelo de tipo dinâmico. Exemplos:
Reflexão A reflexão é fundamentalmente um recurso de digitação dinâmica. Você inspeciona os tipos de objetos no runtime rater do que no tempo de compilação. Quando foi introduzido, era meio que desaprovado, mas em C # o uso da reflexão se torna cada vez mais onipresente, por exemplo, o ASP.Net MVC usa a reflexão fortemente.
Atributos Atributos são um exemplo de digitação dinâmica. Você pode adicionar atributos arbitrários a uma classe em tempo de compilação e depois inspecionar em tempo de execução (por meio de reflexão) e manipular objetos com base nela. Algo como o MEP é basicamente uma estrutura de extensão baseada em um modelo de tipo dinâmico.
Linq para SQL, EF mv. Os vários transformadores do Linq inspecionam consultas como objetos de tempo de execução e geram sql em tempo real. Não fica mais dinâmico do que inspecionar o código em tempo de execução. CodeDom é o outro lado da moeda, onde o código pode ser gerado em tempo de execução
Roslyn Roslyn basicamente implementa
eval
, que já foi considerado o recurso definidor de uma linguagem verdadeiramente dinâmica.Dinâmico O
dynamic
tipo-é o recurso mais explicitamente dinâmico em C # e é anunciado para tornar a interação com objetos e linguagens externas mais simples e produtivas. Mas também é usado no MVC do Asp.net por conveniência.O benefício de todos os recursos acima mostra que o modelo dinâmico possui vantagens definidas, mesmo em uma linguagem estática, com tipos parametrizados, tipos estruturais e inferência de tipos.
fonte
O conjunto de todos os recursos da linguagem moderna é tão grande que apenas a digitação estática versus a dinâmica não tem muito peso.
A regra é: quanto melhor o seu idioma, menor o seu código. Isso é bem simples. Java mostra como a digitação estática pode dar muito errado, o que dá aos seus oponentes muito para se alimentar. Recursos de linguagem mal projetados geralmente têm um custo, e a digitação estática em Java é primeiramente um recurso obrigatório (caso contrário, a maioria das pessoas provavelmente nem o usaria) e, em segundo lugar, mal executada.
É por isso que, em comparação, a maioria das linguagens dinâmicas brilha, mesmo que eu argumentasse que o PHP realmente não melhora sua vida no total geral (pelo menos até recentemente), por causa de muitas outras peculiaridades não relacionadas aos sistemas de tipos.
Por outro lado, você tem muitos idiomas com sistemas de tipos expressivos que não atrapalham e que nem são obrigatórios. E alguns deles até permitem a incorporação de código não digitado, sempre que você precisar escapar do sistema de tipos.
Pessoalmente, uso o haXe, que é uma linguagem com inferência de tipos, subtipo nominal e estrutural, código opcional não tipado, tipos de funções de primeira classe, tipos de dados algébricos e macros lexicais (não muito maduras, mas extremamente poderosas), evitando a sintaxe arcana. Depois de usar o haXe há cerca de 3 anos, cheguei a uma conclusão simples:
A programação se torna muito mais fácil, quando sua linguagem não o prende em escolhas religiosas sobre paradigmas, mas tenta ser apenas uma boa ferramenta. Existem várias linguagens estáticas e dinâmicas e linguagens mistas que obtêm sucesso. Alguns deles são fáceis de aprender, mais difíceis de dominar.
Seu poder vem da maneira como seus recursos individuais podem ser compostos para criar facilmente soluções simples para problemas complexos. Isso exclui uma certa ortogonalidade que só pode ser alcançada através de um delicado equilíbrio de inclusão ou omissão de todos os recursos de linguagem explorados até agora. Se você tentasse adicionar uma digitação estática ao Ruby, você o prejudicaria; se tentasse afastá-lo de Haskell, o esmagaria. Em contraste com isso: se você o tirasse do C, as pessoas dificilmente perceberiam e se você o tirasse do Java, alguns podem agradecer.
Pela minha experiência pessoal, posso lhe dizer: eu gosto de Ruby. Ampliou meus horizontes e a maneira como projeto sistemas. IMHO deve ser usado para ensinar as pessoas a programar em primeiro lugar. É discreto, poderoso, conciso, divertido. Entendo por que alguém vindo de uma língua ortodoxa vai gostar.
No entanto, a longo prazo, a digitação estática permite adiar o trabalho para o analisador estático e, com inferência de tipo, isso ocorre basicamente sem nenhum custo. O resultado é um código que é mais fácil de manter e geralmente é executado mais rapidamente.
Mas, novamente, a digitação estática sozinha não pode fazer nada. É uma questão de combinação. Eu acho que em algum lugar entre F #, Scala, Nemerle, OCaml ou haXe, você pode encontrar o seu próprio ótimo. Mas isso depende de você, porque o idioma deve permitir que você incorpore seus pensamentos sem esforço, em vez de forçá-lo a dobrá-los. E, afinal, nada produz mais ganho de produtividade do que se a programação fosse divertida.
fonte
Pessoalmente, a única razão pela qual a digitação dinâmica ajudaria é se você é um datilógrafo muito lento ou cria funções / métodos / métodos gigantes, difíceis de navegar. Você também precisa entrar em toda a questão dos testes de unidade. Os tipos dinâmicos exigem (a menos que você goste de escrever código quebrado) testes de unidade vigorosos (para garantir que seus tipos dinâmicos não explodam inesperadamente (ou seja, a variável é principalmente duck, mas dcuk acidentalmente às vezes)). A estática tentará muito mais evitar isso (e sim, você pode argumentar a favor de testes de unidade vigorosos)
fonte
Acho que, antes de tudo, você precisa definir "produtividade". O que significa "produtividade" significa e inclui?
Se por "mais produtivo" você quer dizer escrever menos linhas de código para implementar o mesmo recurso, então sim, as linguagens de programação de digitação dinâmica são mais "produtivas" do que as linguagens de estática.
No entanto, se você também considerar o tempo gasto na depuração e correção de bugs, as linguagens de digitação dinâmica podem não ser tão produtivas, porque as linguagens de digitação dinâmica tendem a levar a verificação de erros para o tempo de execução, enquanto, por outro lado, as linguagens de digitação estática pode executar alguma verificação de erro no tempo de compilação. Como é geralmente aceito que, geralmente, quanto mais tarde um bug é encontrado, mais caro é corrigi-lo. Portanto, o código de digitação dinâmica pode resultar em geralmente igual ou talvez até menor que a produtividade do que o código de digitação estática.
fonte
A grande vantagem da digitação dinâmica é a produtividade.
Python, Ruby etc. têm muitos outros impulsionadores da produtividade, além da digitação dinâmica (parâmetros padrão, dicionários incorporados nos tipos etc.etc.) O efeito cumulativo na produtividade do programador é impressionante.
As penalidades em termos de velocidade (ou falta de!) E consumo de recursos não são tão ruins quanto você esperaria e, na maioria dos casos, são mais do que compensadas pela velocidade e flexibilidade do desenvolvimento.
Há um (! Muito antiga) de papel sobre o assunto aqui. É um dos poucos estudos realizados adequadamente sobre a produtividade do programador e muitas das conclusões ainda são válidas.
O que (provavelmente) seria diferente seria o estudo a ser realizado hoje:
Portanto, a mensagem é que, a menos que o desempenho seja um problema realmente sério, as linguagens dinâmicas aumentarão sua produtividade.
fonte