Eu sei que o javascript usa digitação de pato e, a princípio, achei que isso facilitaria o polimorfismo em comparação com linguagens fortemente tipadas como C #. Mas agora minhas funções que recebem argumentos estão repletas de coisas como:
if(myObj.hasSomeProperty())
ou
if(myObj.hasSomeMethod())
ou
if(isNumber(myParam))
etc.
Isso é realmente feio para mim. Eu venho de um background em C # e considero as interfaces definidas muito melhores.
Gostaria de saber se estou incorretamente tentando aplicar estratégias eficazes em linguagens estaticamente tipadas e há alguma maneira melhor de fazer isso em javascript?
Eu sei que não pude verificar, mas rastrear erros de tempo de execução de javascript pode ser um pesadelo, pois nem sempre acontecem onde o erro está realmente ocorrendo no código.
javascript
polymorphism
duck-typing
Legião
fonte
fonte
Respostas:
Simples: nem sempre verifique propriedades e métodos.
No Ruby, o que você está chamando é chamado de "digitação de frango". Em um idioma dinamicamente digitado, você simplesmente confia que o chamador passa um objeto adequado para você. O trabalho do chamador é honrar o lado do contrato.
Você está confundindo vários eixos ortogonais de digitação aqui. Existem quatro eixos ortogonais de digitação:
Como você mencionou o C #: ele é tipicamente estaticamente, mas suporta tipagem dinâmica por meio do tipo
dynamic
, ele é tipicamente nominal, mas tipos anônimos usam tipografia estrutural e padrões sintáticos (como a sintaxe de compreensão de consulta LINQ) podem ser considerados patos -typed ou estruturalmente, é tipicamente explicitamente digitado, mas suporta digitação implícita para argumentos de tipo genérico e variáveis locais (embora o caso da variável local seja bastante estranho comparado à maioria dos outros idiomas, porque você não pode simplesmente deixar o tipo de fora, é necessário dê a ele um pseudo-tipo explícitovar
, em outras palavras, se você deseja um tipo implícito, deve explicitamente dizê-lo). Se o C # é forte ou fracamente digitado, é uma questão de qual definição dos dois termos que você usa, no entanto, observe que pode haver muitos erros de tipo de tempo de execução no C #, especialmente devido à covariância insegura da matriz.Depurar não é uma habilidade fácil de aprender. No entanto, existem técnicas para facilitar a depuração, por exemplo, o Saff Squeeze é uma técnica descrita por Kent Beck que usa testes e refatoração para depuração:
fonte
IComparer<T>.Compare(T, T)
é apenas claro na documentação, não no tipo. E onde no tipo dejava.util.Collections.binarySearch(java.util.List<T>)
diz que…De fato, a prática típica é não verificar. E, sim, isso significa que você receberá erros de javascript que são relatados em outro lugar do problema real. Mas, na prática, não acho que seja um grande problema.
Ao trabalhar em javascript, estou constantemente testando o que estou escrevendo. Na maioria dos códigos, tenho testes de unidade que são executados automaticamente toda vez que eu salvo meu editor. Quando algo inesperadamente dá errado, eu sei quase imediatamente. Eu tenho uma área de código muito pequena na qual eu poderia ter cometido o erro, já que é quase sempre a última coisa que toquei que tem o erro.
Quando recebo um erro de tempo de execução, tenho pelo menos o rastreamento de pilha e, no caso de um erro no navegador, tenho a capacidade de ir para qualquer nível do rastreamento de pilha e inspecionar as variáveis. Geralmente, é fácil rastrear de onde veio o valor ruim e, assim, rastrear o problema original.
Se você é como eu quando escrevi principalmente em linguagens de tipo estaticamente, escrevi blocos de código maiores antes do teste e não tinha prática em rastrear um valor de onde ele veio. A programação em uma linguagem como o javascript é diferente, você precisa usar habilidades diferentes. Eu suspeito que programar assim parece muito mais difícil, porque essas não são as habilidades que você desenvolveu trabalhando em outras linguagens como C #.
Dito isto, acho que há muito a ser dito para tipos explícitos. Eles são ótimos para documentação e detecção precoce de erros. Acho que, no futuro, veremos uma crescente adoção de coisas como Flow e Typescript, que adicionam a verificação de tipo estático ao javascript.
fonte
Eu acho que você está fazendo a coisa certa, você só precisa encontrar o estilo que será mais agradável aos seus olhos. Aqui estão algumas idéias:
Em vez de
if(myObj.hasSomeProperty())
você poderia usarif( myobj.prop !== undefined )
. Assim, o BTW funcionará apenas no modo não estrito, no modo estrito que você precisaria usarif( typeof myobj.prop !== 'undefined' )
.Você pode descarregar parte da verificação de tipo para separar validadores. Isso tem o benefício de poder pular a validação quando as interfaces estiverem maduras, por exemplo
if( is_valid( myobject ))
, ondeis_valid
começaif( !DEBUG ) return true;
.Às vezes, faz sentido clonar a entrada em uma forma canônica; nesse caso, você pode coletar os vários destinos de validação na função / objeto de clonagem. Por exemplo,
my_data = Data( myobj, otherstuff )
oData
construtor poderia executar convenientemente todas as várias validações em um local central.Você pode usar alguma biblioteca que (em um nível de desempenho) simplifique sua validação de tipo para algo mais elegante. Mesmo se você não seguir essa rota a longo prazo, poderá achar confortável entrar no seu próprio estilo sem problemas. Alguns exemplos incluem xtype.js , verificação de tipo , validator.js , etc.
fonte