Sobre linter, qualidade de código, qualidade em geral e gerenciamento de qualidade

Tenha medo dos seus desejos, pois eles podem se tornar realidade.
Sabedoria popular.

Um casal desejava se casar e encontrar a felicidade eterna. Eu explodi o carro deles na igreja imediatamente após o casamento.
One Wish Grant, filme Rota 60.

imagem

Outra nota filosófica sobre administração e, neste caso, qualidade, consiste em três partes: muito abstrata, moderadamente abstrata, concreta e uma conclusão separada. Critica a prática atual de usar o linter.

Uma parte muito abstrata sobre qualidade


Primeiro, quero falar sobre qualidade, ou melhor, sobre gerenciamento de qualidade de qualquer coisa, sobre um produto no sentido mais amplo, um produto como resultado da atividade humana, seja criando um novo (escrevendo um código ou imagem, projetando uma nave espacial), cortando o excesso (escultura moagem, seleção de boas frutas) ou transformação (transporte, congelamento, embalagem, produção de gasolina e plástico a partir de gás).

Um bom produto tem alguns sinais de que é de alta qualidade. Produtos diferentes têm sinais diferentes. Por exemplo, boas frutas cheiram deliciosas, ficam bem, têm bom gosto.

Agora vou dar um exemplo hiperbólico e depois irei diretamente ao código.

Imagine que temos uma loja de frutas e há um problema, nossas frutas começaram a vender pior e o concorrente tem linhas diretas. Realizamos um estudo e descobrimos que o cheiro perto de nossos balcões não é agradável para os visitantes. E o cheiro nas lojas de um concorrente é como. Oh, encontramos um problema, um índice de satisfação do visitante pelo cheiro! Vamos resolver, há marketing de aromaterapia, vamos colocar instalações automáticas perto das prateleiras e sentir um cheiro maravilhoso do pomar de maçãs. Eles fizeram isso. E o índice de satisfação do cliente pelo cheiro naturalmente subiu. Só que agora há ainda menos compradores.

Se você olhar seriamente, o problema original pode ser completamente diferente:

  1. Nossos concorrentes vendem frutas igualmente de alta qualidade, mas fizeram marketing aromático diante de nós e atraíram visitantes com o cheiro.
  2. Nossas frutas são boas, mas as frutas dos concorrentes são realmente melhores que as nossas (variedades, armazenamento, o que for)
  3. Nossos frutos estão podres. Eles apodreceram e cheiram mal.
  4. As frutas do ano passado, que estão por trás da vitrine, estão podres, e esperamos que ainda possamos vendê-las. E eles fede a partir daí.
  5. O concorrente tem mais variedade
  6. O competidor apresentou de maneira mais bonita seus frutos, em geral, os mesmos que os nossos.
  7. É estupidamente mais barato lá
  8. Lá, o vendedor é lindo e, em nosso lugar, Baba Manya substituiu ...

Obviamente, somente no primeiro caso o marketing aromático nos ajudará. Em alguns casos, pode ajudar, mas pode mascarar o problema real, mas no terceiro não tomará nenhuma ação ou causará ainda mais nojo. E quantas vezes o problema é que a fruta está podre.

De fato, quando esse problema surge, é necessário analisar de forma abrangente as causas e, em cada caso, tomar uma decisão específica do caso.

Ainda mais hiperbólico


Você tem tomates verdes e sabe que apenas os vermelhos são vendidos. Não há necessidade de pintar tomates. É bom que você possa acelerar o amadurecimento com etileno . E estará amadurecendo completamente, não pintando. Se fosse impossível acelerar, seria necessário jogar fora esses tomates e obter novos, já bons.

Em outras palavras, se você não estiver satisfeito com a qualidade do produto resultante, haverá problemas em sua cadeia de produção e precisará analisar e alterar o processo, e não pintá-lo na saída.

Bem, você entendeu. Se algo cheira mal, o perfume não ajuda.

Parte moderadamente abstrata sobre a qualidade do código


Entre as propriedades do bom código, encontraremos (sem classificar por importância):

  • consistência de estilo
  • legibilidade
  • performance
  • extensibilidade
  • transparência da arquitetura e padrões.

Isso é alcançado principalmente por meio da autodisciplina e do nível de habilidade dos desenvolvedores, bem como quando existem muitos desenvolvedores, por meio de contratos de estilo de código e contratos de arquitetura (MVC, MVVM, ECS, milhares deles). O código de alta qualidade apareceu muito antes do linter, de quaisquer convenções e padrões de arquitetura.
A maioria das regras do linter é puramente cosmética e resolve o problema de aumentar a legibilidade do código devido à aplicação uniforme de práticas pequenas e locais. O comprimento das linhas lá, os nomes das variáveis, const onde quer que não haja modificação, às vezes até restrições são introduzidas na complexidade ciclomática das funções. Não se trata de regras específicas, mas do fato de que essas regras geralmente são cosméticas, elas ajudam o código a ficar melhor. A palavra-chave aqui é olhar .

Quando qualquer indicador começa a ser usado como objetivo, perde seu valor como ferramenta.
Interpretação livre da lei de Goodhart .

Agora vamos desenhar uma analogia com tomates. Nosso não está maduro o suficiente. Um ponteiro automático nos dirá: "Olhe aqui e não há a cor certa". O que o programador fará? Pintado muito frequentemente. E esta é a principal idéia das minhas críticas ao linter. Agora vou dar um exemplo concreto e depois tirar uma conclusão.

Específicos


PixiJS 2 de fevereiro de 2018 (um ano atrás).

O pool de solicitações chega . A conclusão é que anteriormente um número constante de pontos era usado para desenhar a curva, o que obviamente não é o ideal. Propõe-se o uso de um algoritmo astuto para estimar o comprimento da curva. O algoritmo não é ciência de foguetes, mas definitivamente não é óbvio, publicado em 2013 e citado com um artigo de seu autor (há problemas com https). A felicidade que ele geralmente preservava em sua página pessoal.

Existe um código C (16 linhas):

float blen(v* p0, v* p1, v* p2) { va,b; ax = p0->x - 2*p1->x + p2->x; ay = p0->y - 2*p1->y + p2->y; bx = 2*p1->x - 2*p0->x; by = 2*p1->y - 2*p0->y; float A = 4*(ax*ax + ay*ay); float B = 4*(ax*bx + ay*by); float C = bx*bx + by*by; float Sabc = 2*sqrt(A+B+C); float A_2 = sqrt(A); float A_32 = 2*A*A_2; float C_2 = 2*sqrt(C); float BA = B/A_2; return ( A_32*Sabc + A_2*B*(Sabc-C_2) + (4*C*AB*B)*log( (2*A_2+BA+Sabc)/(BA+C_2) ) )/(4*A_32); }; 

E o seguinte código (JS) foi enviado ao pool de solicitações:

 /** * Calculate length of quadratic curve * @see {@link http://www.malczak.linuxpl.com/blog/quadratic-bezier-curve-length/} * for the detailed explanation of math behind this. * * @private * @param {number} fromX - x-coordinate of curve start point * @param {number} fromY - y-coordinate of curve start point * @param {number} cpX - x-coordinate of curve control point * @param {number} cpY - y-coordinate of curve control point * @param {number} toX - x-coordinate of curve end point * @param {number} toY - y-coordinate of curve end point * @return {number} Length of quadratic curve */ _quadraticCurveLength(fromX, fromY, cpX, cpY, toX, toY) { const ax = fromX - ((2.0 * cpX) + toX); const ay = fromY - ((2.0 * cpY) + toY); const bx = 2.0 * ((cpX - 2.0) * fromX); const by = 2.0 * ((cpY - 2.0) * fromY); const a = 4.0 * ((ax * ax) + (ay * ay)); const b = 4.0 * ((ax * bx) + (ay * by)); const c = (bx * bx) + (by * by); const s = 2.0 * Math.sqrt(a + b + c); const a2 = Math.sqrt(a); const a32 = 2.0 * a * a2; const c2 = 2.0 * Math.sqrt(c); const ba = b / a2; return ( (a32 * s) + (a2 * b * (s - c2)) + ( ((4.0 * c * a) - (b * b)) * Math.log(((2.0 * a2) + ba + s) / (ba + c2)) ) ) / (4.0 * a32); } 

O código foi projetado de acordo com as configurações do linter. As descrições de todos os parâmetros são indicadas, um link para o algoritmo original, um monte de constantes, de acordo com o requisito do operador não misto: 1 parênteses. Mesmo para o desempenho, a API é feita não objetivamente, mas com parâmetros separados; portanto, geralmente é melhor em JS.
Há um problema. Este código produz lixo completo. (Uma tentativa de marcar a expressão fodida em russo, o que é bastante usado nas publicações ocidentais para expressar o grau do problema e parece ser apropriado).

Foi o que o linter disse ao olhar para este código sem parênteses
c:\rep\pixi\pixi.js\src\core\graphics\Graphics.js
258:26 warning Unexpected mix of '-' and '*' no-mixed-operators
258:32 warning Unexpected mix of '-' and '*' no-mixed-operators
259:26 warning Unexpected mix of '-' and '*' no-mixed-operators
259:32 warning Unexpected mix of '-' and '*' no-mixed-operators
260:24 warning Unexpected mix of '*' and '-' no-mixed-operators
260:30 warning Unexpected mix of '*' and '-' no-mixed-operators
260:30 warning Unexpected mix of '-' and '*' no-mixed-operators
260:36 warning Unexpected mix of '-' and '*' no-mixed-operators
261:24 warning Unexpected mix of '*' and '-' no-mixed-operators
261:30 warning Unexpected mix of '*' and '-' no-mixed-operators
261:30 warning Unexpected mix of '-' and '*' no-mixed-operators
261:36 warning Unexpected mix of '-' and '*' no-mixed-operators


Um comprimento enorme volta e muitos pontos se destacam, é bom que houvesse uma restrição de cima, funcionou. Anteriormente, esse modo era desativado por padrão, mas ativado para todos (devido a outro bug a propósito). Correção já pisada pelo caminho . Não entrei em contato com o autor do commit e não perguntei por que ele decidiu colocar os colchetes, mas acho que ele lançou o linter, cujo arquivo de configuração já está no PixiJS. Este linter disse a ele, seu código está incorreto, porque não possui colchetes, adicione colchetes. A opção "sem operadores mistos" diz que você não tem o direito de escrever

 2*2+2*2 

porque pode levar a baixa legibilidade. Alguém criou essa opção e alguém a incluiu no projeto, o que significa que muitas pessoas acham útil.

Conclusão


Não quero dizer que o linter é mau, mas considero esse uso deles mau. Nós (no sentido da humanidade) fomos capazes de automatizar a detecção de apenas uma pequena parte dos sinais de um bom código, principalmente cosméticos, como colchetes. Os linters são bons como ferramentas para analisar a qualidade do código, mas assim que aumentamos a conformidade com os requisitos do linter para a estrutura do requisito obrigatório, obtemos essa mesma conformidade. Não ganhamos nada além de conformidade. É assim que se coloca a câmera em uma esteira com tomates e envia para pintar tudo o que não é vermelho o suficiente. Até que demos ao desenvolvedor uma ferramenta para avaliar a qualidade da aparência do código, ele poderia enviar um código incorreto e poderíamos vê-lo. Agora, o código incorreto ficará melhor disfarçado. Imitará uma boa, porque há todos os sinais externos de um bom código. E perderemos o linter como uma ferramenta de avaliação, porque todo o código é consistente. Tínhamos uma ferramenta de avaliação, mas agora não está lá, mas o código entre colchetes, embora às vezes não esteja lá, mas esses são os detalhes. No total, considero o linter uma ferramenta interessante, mas apenas se a conformidade com os requisitos não se tornar um objetivo .

E sim, aqui podemos dizer que não há testes, que você não precisa copiar e colar o código, que isso é desenvolvimento stackOverflow, que você não insere código no projeto que não entende. Isso é tudo sim. E isso é um sinal de código incorreto. Mas o linter ajudou a torná-lo visualmente semelhante a tudo o mais no projeto. Mas o linter nunca verificará se você entendeu bem o que escreveu.

Em outras palavras, acredito que o uso correto do linter é lançá-lo regularmente no projeto como líder e avaliar como e o que está acontecendo. Bem, regras como mais parênteses ao deus dos parênteses, em princípio, considero prejudiciais. Quando vemos que alguém comete um código de baixa qualidade, vale a pena entender por que ele está fazendo isso e resolver esse problema em um nível mais profundo. Naturalmente, você não precisa formatar o código com as mãos. Congratulo-me com os formadores automáticos de todas as formas possíveis, mas até que eles toquem a parte semântica do código de qualquer maneira. Se forçarmos a pessoa a levar o código aos padrões com um linter, então pintaremos essencialmente o tomate verde em vermelho. E será ainda mais difícil entender que é realmente verde. O que fazer em projetos de código aberto com um monte de pessoas diferentes, a questão é mais complicada, mas mesmo aqui você pode pensar no que fazer.

Vale dizer que minha atitude em relação ao linter foi formada há muito tempo, há mais de três anos, mas não pude encontrar um exemplo adequado na prática quando o linter fez uma piada cruel. E então eu o encontrei. O fato de eu procurá-lo há tanto tempo diz que o problema não é tão em larga escala ou quão difícil é perceber o efeito negativo, mas acho que este artigo será útil. Lembre-se, um linter é uma ferramenta e, como qualquer ferramenta, pode ser usado em detrimento e para o bem, e como às vezes você pode se cortar com qualquer ferramenta.

Source: https://habr.com/ru/post/pt440414/


All Articles