Como você usa a digitação de pato em javascript sem sempre verificar propriedades e métodos?


11

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.


2
Eu acho que você pode estar se atrapalhando com a natureza de uma linguagem de tipo dinâmico. Você precisa se acostumar com a mentalidade de que muitos erros ocorrerão no tempo de execução, em vez do tempo de compilação. Se você sentir a necessidade de verificar se todo argumento é um número em todas as funções que inserem números, isso pode se tornar um fardo (embora talvez valha a pena se você estiver enviando uma lib com a segurança sendo o objetivo principal). Para qualquer escala, acho essencial que apenas permita que as funções falhem se os tipos errados forem passados. Em vez disso, um foco mais produtivo pode estar na construção de testes.

Onde isso pode ajudar a fazer essas verificações para garantir que os tipos estejam em conformidade com os requisitos de interface necessários (verificar se eles têm os métodos necessários, por exemplo) está em suas funções mais centrais e amplamente usadas (aquelas com instabilidade = 0 com o (métrica de acoplamento eferente / aferente que Martin fornece). Esse deve ser um alvo bem pequeno. Normalmente, existem muitas funções locais pontuais que são isoladas no escopo - essas provavelmente não precisam de um conjunto abrangente de verificações de tempo de execução. Eles não acumulam muita complexidade.

Alterne para o Script de tipo. Ele ainda é digitado em forma de pato, mas suporta digitação estática para detectar muitos erros em tempo de compilação.
CodesInChaos

2
Você encontrou o maior problema da digitação de patos: seu poder deriva de sua fraqueza. Se você deseja fazer JavaScript orientado a objetos, basta viver com os erros de tempo de execução e torcer para que seus testes de unidade os encontrem logo após criá-los :-(
Ross Patterson

@RossPatterson O problema dos OPs é com a digitação dinâmica, não com a digitação com duck. O TypeScript e o Go são do tipo duck, mas evitam o problema do OP. O problema com a digitação de patos é diferente: você pode ter membros que passam no teste de patos, mas não cumprem o contrato que esperam.
CodesInChaos

Respostas:


11

Como você usa a digitação de pato em javascript sem sempre verificar propriedades e métodos?

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.

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 #.

Você está confundindo vários eixos ortogonais de digitação aqui. Existem quatro eixos ortogonais de digitação:

  • When : digitação dinâmica (tipos não são conhecidos e verificados até o tempo de execução) vs. digitação estática (tipos são conhecidos e verificados antes do tempo de execução)
  • O que : digitação de pato (os tipos são baseados no comportamento ), tipagem estrutural (os tipos são baseados na estrutura ) e digitação nominal (os tipos são baseados no nome )
  • Você pode vê-los? digitação explícita (os tipos precisam ser anotados explicitamente) vs. digitação implícita (tipos são inferidos)
  • digitação forte vs. digitação fraca - você deve ter notado que eu não dei a esse título cativante nem explicação entre parênteses, porque, diferentemente dos sete termos acima, cada um com uma definição precisa universalmente aceita, esses dois termos têm cerca de uma dúzia de definições vagas semi-amplamente usadas que se contradizem; idealmente, você deve evitar esses termos completamente e, se precisar usá-los, defina-os com precisão primeiro

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.

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.

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:

Bata neles alto, bata neles baixo :

Teste de regressão e o aperto do Saff

Kent Beck, Instituto dos Três Rios

Resumo: Para isolar efetivamente um defeito, comece com um teste no nível do sistema e progressivamente inline e poda até que você tenha o menor teste possível que demonstre o defeito.


Esse link de alto impacto e baixo recebe um http 500 para mim, com "Página não está mais disponível" como mensagem orientada para humanos.
joshp

O domínio threeriversinstitute.org parece ter sido abandonado.
Bart van Ingen Schenau

Ah, droga. E nem sequer é arquivado na WayBack Machine .
Jörg W Mittag

Como o chamador deve honrar o lado do contrato? Parece que não há como comunicar (no código) quais devem ser os parâmetros. Toda função tem o formato de função fname (objParam, objParam, ...). Isso significa que idiomas como javascript dependem totalmente da documentação externa para comunicar o uso?
Legion

@ Legion: documentação, boa nomeação, senso comum, testes como especificações comportamentais, leitura do código fonte, etc. Observe que, na verdade, isso não é muito diferente dos sistemas de tipos mais fracos, como C # ou Java: Por exemplo, o significado do valor de retorno IComparer<T>.Compare(T, T)é apenas claro na documentação, não no tipo. E onde no tipo de java.util.Collections.binarySearch(java.util.List<T>)diz que…
Jörg W Mittag

1

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.

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.


0

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 usar if( myobj.prop !== undefined ). Assim, o BTW funcionará apenas no modo não estrito, no modo estrito que você precisaria usar if( 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 )), onde is_validcomeça if( !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 )o Dataconstrutor 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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.