Sabotar os padrões de codificação [fechados]

35

Existem vários padrões de codificação aplicados em empresas de software que têm o objetivo de aumentar a confiabilidade, portabilidade e, o mais importante, legibilidade no código escrito em conjunto por diferentes desenvolvedores.

Dois exemplos notáveis ​​são o MISRA C e o padrão C ++ desenvolvido para o projeto JSF .

Eles geralmente estão na seguinte forma, depois de especificar cuidadosamente o que as palavras "devem", "devem", "devem", "podem" etc. significam:

Exemplo:

Regra 50: Variáveis ​​de ponto flutuante não devem ser testadas quanto à exata igualdade ou desigualdade.

Justificativa: Como os números de ponto flutuante estão sujeitos a erros de arredondamento e truncamento, a igualdade exata pode não ser alcançada, mesmo quando esperado.

Esses padrões de codificação impõem restrições, geralmente em código que seria legal do ponto de vista do compilador, mas é perigoso ou ilegível e, portanto, é "considerado prejudicial".

Agora vamos abusar disso!

Você é aceito como membro de um pequeno comitê de padronização da sua empresa, cujo objetivo é criar os novos padrões de codificação que todos os desenvolvedores da empresa deverão usar. Sem o conhecimento dos outros, você está secretamente empregando uma organização sinistra e tem como missão sabotar a empresa. Você precisa propor uma ou mais entradas para o padrão de codificação que mais tarde prejudicará os desenvolvedores. No entanto, você deve tomar cuidado para não tornar isso imediatamente óbvio, caso contrário, corre o risco de não ser aceito no padrão.

Em outras palavras, você deve introduzir regras no padrão de codificação que pareçam legítimas e com boas chances de serem aceitas pelos outros membros do comitê. Depois que os projetos são iniciados e inúmeras horas-homem são investidas no código, você deve poder abusar dessas regras (por exemplo, por um detalhe técnico ou muitointerpretação literal) para sinalizar códigos normais e de boa qualidade como contrários ao padrão. Portanto, eles devem se esforçar muito para reformulá-lo, e as regras os impedirão a partir de agora, mas, como as regras estão ativas há algum tempo, o momento puro manterá essas funções vivas e há conflitos significativos de interesses entre os diferentes níveis de administração, os outros gerentes provavelmente manterão as regras vivas (eles seriam tolos em admitir seu erro!), prejudicando a empresa! Mwahahahahaaa!

Pontuação

A resposta mais votada após aproximadamente duas semanas da primeira entrada válida vence. Eu tenho uma idéia para uma boa resposta, mas vou publicá-la apenas alguns dias depois, pois outra pessoa pode ter a mesma idéia e não quero roubá-la do prazer. Obviamente, minha própria resposta não será aceita acima de nenhuma outra, independentemente da pontuação.

Os eleitores são incentivados a obter respostas com base em quão bem as brechas estão ocultas e quão frustrantes para os desenvolvedores seriam.

Regras e regulamentos

  • A regra ou regras devem ter uma aparência profissional, como no exemplo acima
  • As regras devem parecer genuínas (portanto, coisas como "todas as variáveis ​​devem conter pelo menos um sublinhado, uma letra maiúscula, uma letra minúscula e dois números" não são aceitas. Elas realmente atrapalhariam os desenvolvedores, mas provavelmente não seriam aceitas por comitê) e, se o mérito deles não for imediatamente óbvio, você deve dar uma boa justificativa.
  • Você deve encontrar uma maneira de usar / abusar de suas regras para sabotar os desenvolvedores posteriormente. Você pode abusar de qualquer ambiguidade em outras regras ou usar várias regras que são inofensivas por si mesmas, mas diabólicas uma vez combinadas!
  • Você deve postar uma explicação em tags de spoiler no final de sua postagem sobre como você pode abusar das regras
  • O idioma usado não deve ser um idioma esotérico. Uma linguagem amplamente usada em projetos reais deve ser escolhida, para que as línguas com sintaxe do tipo C (em vez de coisas como o Golfscript) sejam preferidas.
vsz
fonte
4
Python, Ruby, Haskell, Makefile, XML, etc. são algumas linguagens usadas em muitos projetos reais que não possuem uma sintaxe semelhante a C.
Kennytm # 30/14
7
Esta pergunta parece estar fora de tópico porque não é um concurso de programação.
Peter Taylor
5
@ PeterTaylor: a definição inclui "quebra-cabeças de programação", o que não significa que a resposta deva ser um código de software. Em nenhum lugar da definição do site está escrito que se trata apenas de "concursos de programação". A definição é: "Código de golfe / Quebra-cabeças de programação / Outros concursos ou desafios de programação" "
vsz 30/10/14
7
@ PeterTaylor, parece um concurso de programação para mim; em policiais e ladrões desafia os ladrões não codificam quer (e se o seu argumento é que o comentário ladrões, então certifique-se de comentário no post meta que sugere policiais divisão e desafios ladrões a duas questões separadas)
John Dvorak
5
Eu votei para reabrir. Parece que ainda temos algumas perguntas em que não podemos concordar se elas estão no tópico. Isso me lembra aquele relacionado à arte que foi fechado e reaberto duas vezes. Eu tenho uma idéia para uma resposta para esta pergunta e é definitivamente relacionada à programação. Essa pergunta se encaixa até em duas das tags do site.
hmatt1

Respostas:

40

C / C ++

Regra 1: constantes octais não devem ser usadas

Justificativa: as constantes octais podem causar confusão. Por exemplo, um olhar casual sobre a linha const int coefficients[] = {132, 521, 013, 102};
pode deixar de notar que um dos números da matriz está definido em octal.

Se você quer ser ainda mais mal, adicione o seguinte:

Regra 2: constantes hexadecimais devem ser usadas apenas no contexto de manipulação de bits.

Justificativa: se uma constante representa um valor numérico, é mais legível se estiver em decimal. Uma constante hexadecimal deve indicar que representa uma máscara de bit, não um valor numérico.

Como pode ser abusado:

Pegue o programa simples a seguir, que adicionará os 10 primeiros elementos de uma matriz. Este código não seria compatível com o padrão.

sum = 0;
for (i = 0; i < 10; i++) 
{
    sum += array[i];
}

Observe que 0, por definição, uma constante octal. Pela regra 1, exigir que ele seja gravado como 0x00 em todo o código é frustrante. Pela regra 2, ainda mais frustrante.

vsz
fonte
11
Você poderia vincular à definição padrão de codificação que diz que 0é uma constante octal? Presumo que é porque começa com o personagem 0. Isso reforçaria o argumento do seu hipotético pedante.
Xnor
16

Python

Regra 1: Todo o código deve ser compilado em bytes usando o -OOsinalizador, que otimiza o bytecode. Queremos um bytecode otimizado para tamanho e eficiência!

Regra 2: Os testes devem ser executados com o mesmo "artefato" de código que será colocado em produção. Nossos auditores exigem isso.

Usar -OOremove assertinstruções. Combinado com a regra 2, isso proíbe efetivamente o uso de assertinstruções em testes. Diverta-se!

ErlVolton
fonte
Isso também remove as instruções, o que significa que você não obtém nada help()no REPL, e o teste informal do REPL ainda está sendo testado.
21715 Kevin
Não. Se você escrever uma estrutura de teste adequada, ela usará o unittestmódulo ou, que implementa suas próprias asserções, não dependendo do __debug__sinalizador. No entanto, os testes não serão executados silenciosamente. Sorrateiro!
Pppery # 29/16
15

Isto é para um projeto Node.JS.

Seção 3 - Velocidade e eficiência são essenciais

Regra 3.1: Os arquivos devem ser mantidos no máximo 1kb. Arquivos maiores que isso demoram muito para serem analisados.

Regra 3.2: Não aninhe funções com mais de 3 níveis de profundidade. O mecanismo V8 deve acompanhar muitas variáveis ​​e fechamentos profundos como esse tornam o trabalho mais difícil, diminuindo a interpretação geral.

Regra 3.3: Evite require()desvios.

Regra 3.3.1: Qualquer módulo require()d não deve ter require()uma profundidade superior a 3. require()Cadeias profundas são caras tanto em termos de uso de memória quanto de velocidade.

Regra 3.3.2: Os módulos principais contam como um único require(), não importa quantas vezes eles require()internamente.

Regra 3.3.3: Módulos externos contam no máximo 2 require()s. Não podemos pagar a mesma clemência que os módulos principais, mas podemos supor que os autores dos módulos estejam escrevendo código eficiente.

Regra 3.4: Evite chamadas síncronas a todo custo. Isso geralmente leva muito tempo e impede que todo o loop de eventos continue.

Como pode ser abusado:

As regras 3.1 e 3.3 não funcionam bem juntas. Ao manter um máximo de 1kb e 3s require()na cadeia, eles serão pressionados para obter sucesso.
As regras 3.2 e 3.4 são quase incompatíveis. 3.4 proíbe chamadas síncronas; O 3.2 torna difícil o trabalho assíncrono avançado, limitando o número de retornos de chamada.
A regra 3.4 é, com toda a honestidade, uma regra que é boa de seguir de verdade. 3.1, 3.2 e 3.3 são falsos completos.

Scimonster
fonte
11

JavaScript (ECMAScript)

7.3.2: Literais de expressão regular

Literais de expressão regular não devem ser usados. Especificamente, o código-fonte não deve conter nenhuma substring correspondente ao não-terminal RegularExpression definido abaixo.

RegularExpression     :: '/' RegularExpressionBody '/'
RegularExpressionBody :: [empty]
                         RegularExpressionBody [any-but-'/']

[vazio] corresponde à sequência vazia e [any-but - '/'] corresponde a qualquer sequência de caracteres únicos, exceto a que contém '/' (barra U+002F).

Fundamentação

Expressões regulares são frequentemente desencorajadas por razões de legibilidade. Muitas vezes, é mais fácil entender o código com operações tradicionais de strings do que recorrer a expressões regulares. Mais importante, porém, muitos mecanismos de expressão regular oferecem desempenho abaixo da média. Expressões regulares também foram associadas a problemas de segurança no contexto do JavaScript.

No entanto, a Organização ™ reconhece que expressões regulares ocasionalmente são a melhor ferramenta para o trabalho. Portanto, o RegExppróprio objeto não é proibido.

(A sintaxe do trecho gramatical em si [não a que ela define] corresponde à da especificação ECMAScript. É claro que isso seria definido com mais rigidez em outro ponto da especificação hipotética.)

O truque

O seguinte programa não está em conformidade:

// sgn(x) is -1 if x < 0, +1 if x > 0, and 0 if x = 0.
function sgn(x) {
  return x > 0?  +1
       : x < 0?  -1
       :          0
}

As produções para o não terminal RegularExpressionBody, dadas acima, mostram uma maneira comum de expressar listas no BNF, contando com recursão explícita. O truque aqui é que eu "acidentalmente" permito a string vazia como RegularExpressionBody , de forma que a string //seja proibida no código-fonte. Mas quem precisa de comentários de linha única, afinal? C89 e CSS parecem fazer tudo certo enquanto permitem apenas /* */comentários de bloco.

FireFly
fonte
15
Na verdade, é ainda mais ruim do que isso: o código também não pode conter comentários em bloco, nem mais de um operador de divisão por arquivo.
Chromatix
Oh sim, você está certo. Eu nem pensei nisso. : P
FireFly
5

C #

12.1 Métodos estáticos que afetam o estado do programa são proibidos

Isso ocorre porque é difícil testar com segurança os resultados de um método estático, especialmente um que altera algum estado.

12.2 Os métodos estáticos devem ser determinísticos

Se o método estático pegar uma entrada e fornecer uma saída, o resultado deverá ser o mesmo sempre que o método estático for chamado com a mesma entrada.

Por quê

O ponto de entrada para um programa C # é o método estático privado 'main'. Pela primeira regra, isso agora é proibido porque a regra esquece de declarar que somente métodos públicos, protegidos ou internos devem seguir essa regra. Se o teste realmente é a preocupação, apenas os métodos públicos devem seguir a regra 1. Principal também pode violar a regra 2, pois o programa fornecerá um código de erro se o programa falhar, isso pode ocorrer independentemente dos parâmetros de entrada. Por exemplo, o programa pode não encontrar um arquivo ou pode ter dependências em outros sistemas que não estão configurados corretamente.

sydan
fonte
4

JAVA / PRIMAVERA

4.2 Uso da reflexão no código de produção

Como o Reflection pode ser usado para acessar partes restritas do código-fonte, o uso da reflexão no Código de produção é estritamente proibido.

O truque

O Spring tecnicamente usa a reflexão para instanciar e gerenciar os objetos que ele suporta. Ao impor esta regra, todo o utilitário Spring precisaria ser removido.

tfitzger
fonte
3

Codificação de site

666.13 O UTF-8 não deve ser usado e deve ser substituído pelo UTF-7.
Justificativa: O UTF-7 é mais eficiente do que o UTF-8, especialmente ao direcionar usuários de países árabes que o fazemos.

Como pode ser abusado:

O HTML5 desaprova especificamente o UTF-7. Isso significa que os navegadores modernos não suportam isso. Se todos os testes forem feitos em um navegador como o IE 11, ninguém notará isso até que seja tarde demais.

Stefnotch
fonte
2

Operadores JavaScript bit a bit

1.9 Você não deve usar multiplicação, divisão ou piso, a menos que sejam consideravelmente mais rápidos que seus pares em bits. Eles devem ser substituídos pelos operadores bit a bit <<, >> e ~~ respectivamente.
Justificativa: Os operadores bit a bit são mais eficientes.

Como pode ser abusado:

Usar << ou >> em vez de multiplicação ou divisão causará problemas ao lidar com números grandes. Além disso, eles ignoram a precedência da operação e os pontos decimais. O til duplo retornará valores diferentes quando você der um número negativo.

Stefnotch
fonte
2
Acho que já é óbvio que x = (x<<10) + (x<<8) + (x<<5) + (x<<4) + (x<<3) + (x)é inferior em todos os aspectos (possivelmente até velocidade) x *= 1337e que substituir a divisão por uma não potência de dois por somas de deslocamento de bits é ainda pior.
precisa saber é o seguinte
@ Thomas Kwa Eu editei minha resposta adequadamente. Obrigado por apontar isto. Eu sou novo nos operadores bit a bit.
21415 Stefnotch
1

JavaScript (ECMAScript)

7.3.1: Convenções de identificador

Restrições são colocadas nos identificadores, dependendo do tipo de identificador. Os identificadores são divididos nos tipos Variável , Constante , Função e Construtor ; ver 5.3. As restrições são dadas abaixo.

  • Variável: o primeiro caractere deve ser um caractere de letra minúscula. Camel-case (ver 1.3) deve ser usado para separar palavras dentro de um identificador.

  • Constante: O identificador deve consistir apenas em caracteres de letras maiúsculas e sublinhados ('_', U+005F). Os sublinhados devem ser usados ​​para separar as palavras em um identificador.

  • Função: As funções devem seguir as mesmas regras que o tipo Identificador .

  • Construtor: O primeiro caractere deve ser um caractere de letra maiúscula. Camel-case (ver 1.3) deve ser usado para separar palavras dentro de um identificador.

Fundamentação

Nomes de identificadores legíveis são muito importantes para a manutenção. Restringir os identificadores a convenções conhecidas também facilita a transição entre diferentes bases de código. Essas convenções específicas são modeladas após as convenções padrão da linguagem de programação Java ™ [1] .

O truque

Lamento informar a equipe do jQuery que o nome mais comum para o "objeto jQuery global" entra em conflito com essa convenção de nome. Felizmente, eles já pensado nisso e fornecer tanto $e jQuerycomo nomes globais referindo-se ao mesmo objeto. Imagino que a base de usuários possa não estar tão interessada em mudar de $para jQueryqualquer lugar.

FireFly
fonte
2
»As funções devem seguir as mesmas regras que o tipo Identificador .« - você quer dizer »como o tipo Variável «?
Pa Elo Ebermann 03/04