Como evitar erros típicos de linguagem dinâmica?

42

Recentemente, dediquei algumas horas ao JavaScript porque queria me beneficiar da enorme base de usuários. Fazendo isso, notei um padrão que a maioria das pessoas atribui a linguagens dinâmicas. Você faz as coisas funcionarem rapidamente, mas quando seu código atinge um determinado tamanho, você perde muito tempo com erros de digitação, ortografia e refatoração em geral. Erros que um compilador normalmente me pouparia. E não me fazer procurar erros na lógica quando acabei de digitar outro módulo.

Considerando o incrível JavaScript a seguir e outras linguagens de tipo dinâmico, sou levado a acreditar que há algo errado com minha abordagem. Ou este é apenas o preço que você tem que pagar?

Para colocar de forma mais concisa:

  • Como você aborda um projeto JavaScript (ou qualquer outra linguagem dinâmica) com ~ 2000 LOC?
  • Existem ferramentas para me impedir de cometer esses erros? Eu tentei o fluxo pelo Facebook e JSHint, que de alguma forma ajudam, mas não capturam erros de digitação.
TomTom
fonte
2
Embora existam maneiras de mitigar os custos, não são custos .
Dcastro
29
Eu tentaria escrever seu programa em uma linguagem de tipo estaticamente compilada em javascript, como Typescript, Scala.js ou Elm.
Dcastro
6
relatórios de testes, testes, mais testes e cobertura.
Njzk2
7
~ 2000 LOC é um projeto pequeno. Ele deve se encaixar facilmente no que uma linguagem dinâmica faz com facilidade e bem. Se você está lutando com esse tipo de projeto de tamanho, tem um problema mais fundamental com suas habilidades de programação do que qualquer coisa que seja relevante especificamente para linguagens dinâmicas.
Jack Aidley
5
@JackAidley discordou. O OP é usado para se concentrar em problemas de alto nível e não se um identificador está escrito corretamente. Isso é habilidade de programação. Garantir a ortografia correta pode ser feita por uma motoniveladora e / ou pelo suporte da ferramenta.
Mucaho

Respostas:

37

Especificamente falando de JavaScript, você pode usar o TypeScript . Ele oferece algumas das coisas às quais você está se referindo. Citando o site:

Os tipos permitem que os desenvolvedores de JavaScript usem ferramentas e práticas de desenvolvimento altamente produtivas, como verificação estática e refatoração de código ao desenvolver aplicativos JavaScript.

E é apenas um superconjunto de JS, o que significa que parte do seu código existente funcionará perfeitamente com o TS:

O TypeScript começa com a mesma sintaxe e semântica que milhões de desenvolvedores de JavaScript conhecem hoje. Use o código JavaScript existente, incorpore bibliotecas JavaScript populares e chame o código TypeScript do JavaScript.

VinArrow
fonte
11
... e typescript é essencialmente EcmaScript 6.
Robert Harvey
11
Essa citação dói. Isso apenas mostra que a Microsoft sempre foi uma empresa de idiomas estáticos que simplesmente não entende idiomas dinâmicos. "Tipos ativam ... refatoração de código"? Sério? O departamento de relações públicas da Microsoft percebe que a refatoração de código como prática foi inventada no Smalltalk (uma linguagem dinâmica) e existia mesmo antes da Forth (uma linguagem sem tipo)? Que a primeira ferramenta de refatoração automatizada fazia parte de um IDE Smalltalk, antes que as linguagens estáticas tivessem IDEs? Que os modernos IDEs do Smalltalk têm ferramentas de refatoração pelo menos tão poderosas quanto mais que Java, C # e C ++? Vamos lá.
Jörg W Mittag 9/16
5
O TypeScript é uma ótima linguagem por si só, por que você precisa tentar empurrá-la com esse absurdo?
Jörg W Mittag 9/16
29
@ Jörg Eu não sei o suficiente sobre Smalltalk, mas cada IDE único para JavaScript ou Python que tenho visto é milhas por trás do que uma boa IDE para Java ou C # pode fazer. Além disso, há algumas coisas que são simplesmente impossíveis de se fazer em uma linguagem dinâmica (algumas das refatorações mais populares): digamos que você tenha uma função pública foo(x) { return x.bar;}ou algo assim. Como não há informações de tipo e a função é pública (portanto, você não pode conhecer todos os chamadores), é impossível descobrir se a barra deve ser renomeada para baz se você renomear alguma classe.
Voo
10
Essa resposta diz que a solução para "erros de linguagem dinâmica" não é usar uma linguagem dinâmica.
bgusach
19

Existem algumas abordagens que podem ajudar:

Teste de unidade

Escreva testes de unidade sempre que possível. Confiar unicamente em testes manuais ou encontrar bugs na natureza é um sucesso.

Usar estruturas

Em vez de criar o seu próprio e arriscar a introdução de bugs, use estruturas estabelecidas sempre que possível.

Prefira CSS / idiomas de alto nível

Onde você pode ceder a funcionalidade para CSS ou qualquer linguagem de alto nível em que está escrevendo.

Refatorar

Refatorar para reduzir a quantidade de código. Menos código = menos lugares para as coisas darem errado.

Reuso

Reutilize o código existente onde você puder. Mesmo que o código não seja uma correspondência exata, pode ser melhor copiar, colar e modificar, em vez de escrever algo novamente.

IDEs

Os IDEs modernos geralmente têm pelo menos algum suporte a Javascript. Alguns editores de texto também têm conhecimento de Javascript.

Robbie Dee
fonte
5
Embora verdadeiro, seu conselho se aplica basicamente a todas as linguagens de programação e visa principalmente corrigir erros lógicos, e não aqueles que surgem de linguagens dinâmicas.
Edmz
1
"o seu conselho se aplica basicamente a toda linguagem de programação" . É bem verdade - de maneira semelhante a passar por mudanças, desde projetos de hobby a soluções corporativas completas, que exigem uma quantidade cada vez maior de restrições - da mesma forma - quanto mais Javascript for escrito, mais disciplina será necessária se as rodas não estiverem funcionando. sair rapidamente. Eric Lippert descreve isso muito bem.
Robbie Dee #
4
"Prefiro CSS / linguagens de alto nível" - eu realmente não entendo o que esse bit significa em relação ao JavaScript: você está dizendo para mover elementos (como animação, talvez?) Para folhas de estilo em vez de código JS? Como o CSS se relaciona com linguagens de alto nível?
anotherdave
@anotherdave Muito do que costumava ser firmemente o domínio do Javascript agora pode ser alcançado no CSS3. Algumas funcionalidades também podem ser movidas para um idioma de nível superior que estaria sujeito a controles mais rigorosos.
Robbie Dee
4
@anotherdave Muito do que as pessoas tentam fazer com o JavaScript é estranho e inadequado. Bibliotecas que fornecem ferramentas de linguagem padrão, estruturas que fornecem pouco mais a elementos HTML padrão, código que replica funcionalidades básicas como âncoras, emulação MVC, estilo, reimplementação de DOM, abstração de AJAX, renderização de objetos triviais (reimplementação de SVG), recursos de polyfilling que não beneficie o usuário ... Você deve minimizar a quantidade de JS que escreve. Se você pode fazê-lo sem JS, faça sem JS.
Bjb568
2

Uma ferramenta que ainda não foi mencionada é a pesquisa de texto simples, local de arquivo ou em todo o projeto .

Parece simples, mas quando você inclui algumas expressões regulares, pode fazer uma filtragem básica ou avançada, por exemplo, procurar palavras localizadas na documentação ou no código-fonte.

Foi uma ferramenta eficaz para mim (além dos analisadores estáticos) e, dado o tamanho do seu projeto de 2k LOC, o que não é particularmente grande na minha opinião, espero que funcione maravilhosamente.

mucaho
fonte
2
greppercorre um longo caminho. A menos que você não faça coisas dinâmicas muito estranhas, ele funciona. No entanto, parece muito manual se você estiver acostumado a IDEs para idiomas de tipo estático.
bgusach
1

Atualmente, estou refatorando vários milhares de linhas de código em um grande projeto AngularJS. Um dos maiores problemas é descobrir o contrato exato de uma determinada função. Às vezes, acabei lendo a documentação da API porque os elementos da resposta bruta da API foram atribuídos a variáveis ​​que passaram por 6 camadas de código antes de serem modificadas e retornadas por mais 6 camadas de código.

Meu primeiro conselho é projetar por contrato . Obtenha entradas específicas, produza saídas específicas, evite efeitos colaterais e documente essas expectativas usando o TypeScript ou pelo menos o JSDoc.

Meu segundo conselho é implementar o maior número possível de verificações. Seguimos o padrão AirBnB e usamos eslint em toda a nossa base de códigos. Os ganchos de confirmação confirmam que sempre seguimos o padrão. Naturalmente, temos uma bateria de testes de unidade e aceitação e todos os commits devem ser revisados ​​por um colega.

Mudar de um editor de texto (Sublime Text) para um IDE adequado (WebStorm) também facilitou muito o trabalho com o código em geral. O WebStorm usará o JSDoc para fornecer dicas sobre os tipos de parâmetros esperados e gerar erros se você fornecer o tipo errado ou usar o valor de retorno da maneira errada.

Em JavaScript, novos recursos, como símbolos e getter / setters, podem ajudar a impor um certo nível de qualidade, adicionando asserções à atribuição de variáveis ​​(por exemplo, verifique se o número inteiro está dentro do intervalo ou se o objeto de dados tem certos atributos).

Infelizmente, não acho que exista uma solução verdadeira para evitar erros dinâmicos de linguagem, apenas uma série de medidas que podem ajudar a reduzir sua frequência.

Nicolas Bouliane
fonte
0

Minha resposta para a pergunta "Como você aborda um projeto JavaScript (ou qualquer outra linguagem dinâmica) com ~ 2000 LOC?"

Desenvolvo aplicativos de formulário PDF. Abordo o meu projeto de desenvolvimento de software JavaScript (independentemente do tamanho do código-fonte) usando os elementos de rede e anotações de Petri. O método não está vinculado a nenhuma tecnologia específica da linguagem de programação. Assim, pode ser usado para outras "linguagens de programação".

Eu crio um diagrama da lógica do aplicativo. Para manter o diagrama organizado, eu adiciono a maioria das minhas anotações a um formulário que eu uso com o diagrama. As entradas no formulário incluem referências a propriedades ou funções. Em seguida, escrevo o código-fonte com base nas informações no diagrama e nas entradas no formulário. O método é sistemático, pois todo código-fonte escrito é mapeado diretamente no diagrama e nas entradas do formulário. O código-fonte pode ser facilmente verificado porque também sigo as convenções de nomeação e codificação quando escrevo o código.

Por exemplo, escolhi uma convenção de que todas as funções são protótipos. Se o desempenho se tornar um problema, ele poderá ser aprimorado declarando as funções no construtor. Para algumas propriedades, uso matrizes. Novamente, se o desempenho se tornar um problema, ele poderá ser aprimorado usando referências diretas.

Eu também uso eval. Isso pode reduzir bastante o tamanho do código fonte. Devido a problemas de desempenho, eu uso eval no início ou na parte de inicialização do meu aplicativo; Eu nunca o uso na “lógica de tempo de execução” - essa é outra convenção de codificação que sigo.

John Frederick Chionglo
fonte