Quais são os piores anti-padrões que você encontrou em sua carreira como programador?
Estou envolvido principalmente com java, embora provavelmente seja independente da linguagem.
Eu acho que o pior é o que eu chamo de principal anti-padrão . Significa programa composto por uma classe extremamente grande (às vezes acompanhada de um par de turmas pequenas) que contém toda a lógica. Normalmente, com um grande loop no qual toda a lógica de negócios está contida, às vezes tendo dezenas de milhares de linhas de código.
language-agnostic
anti-patterns
стривігор
fonte
fonte
Vou acertar outro óbvio com "copy-pasta". Copiar código quase idêntico ao que você deseja e alterar algumas coisas (em vez de extrair para um método).
Isso é especialmente predominante em alguns códigos de teste funcionais e de API do final dos anos 90: literalmente centenas (ou até milhares) de casos de teste quase idênticos que poderiam ter sido divididos em algumas funções com três ou quatro parâmetros - ou, melhor ainda , algo orientado a dados. Meu primeiro emprego fora da faculdade foi, literalmente, oito meses reescrevendo e refatorando milhares de linhas de massas de cópia que usavam métodos obsoletos. Quando terminei, os arquivos de teste tinham menos de um décimo do tamanho original e eram muito mais fáceis de manter (e legíveis!).
fonte
Penso que posso escrever muito sobre o Pattern Mania e soluções que poderiam ser resolvidas com muito menos esforço, mas prefiro apontar para um ótimo artigo que li recentemente com um exemplo fantástico de como uma solução simples pode ser complicada demais .
Como (não) escrever o fatorial em Java, colocamos uma fábrica no seu algoritmo
fonte
Martelo de Ouro
fonte
Regiões
Em C #, você pode definir uma região de código que pode ser recolhida no IDE, ocultando-a, a menos que você queira lidar com esse código. Eu participei de um projeto em que as regiões abrangem centenas de linhas (gostaria de estar exagerando) e havia várias regiões em uma função de mil linhas (novamente, eu gostaria de estar brincando).
No lado positivo, o desenvolvedor que criou a região fez um trabalho muito bom na identificação de funções específicas dentro de uma região. Tanto que eu era capaz de fazer um método de extração na região e seguir em frente.
As regiões incentivam os desenvolvedores a "esconder" sua porcaria à vista.
fonte
DoNotUseRegions
.#region SQL Update
torna dobrável, portanto é necessária menos rolagem.Para mim, o pior padrão é Copiar / Colar .
fonte
Métodos que não sobrecarregam:
Mostra claramente que o programador não entendeu a sobrecarga.
fonte
Sequências de comutação de loop
http://en.wikipedia.org/wiki/Loop-switch_sequence
Eles me irritam sem fim e mostram realmente como o desenvolvedor era inexperiente
fonte
Codificação flexível , ou seja, quando os programadores se esforçam para evitar a codificação embutida e acabam do outro lado da escala - dependências "codificadas".
fonte
Mantenha o estado no cliente.
Uma vez trabalhado com um aplicativo da web em que todo o estado foi mantido no navegador. (Para garantir a escalabilidade sem problemas, todas as exceções foram ignoradas).
fonte
Checkins maciços
Odeio quando vejo que um desenvolvedor não faz o check-in há mais de uma semana. Isso significa que ele está preso e não procurou ajuda, ou está reunindo vários recursos em um grande check-in. (Eu deixei de lado o pior cenário, ele simplesmente não está fazendo nada. Isso é fácil de resolver ... duas palavras parecem que você foi contratado.)
Ao fazer um grande check-in, você perde muitos benefícios do SCM, como poder vincular um conjunto de alterações a um recurso específico. Além disso, é provável que você tenha muita fusão a fazer e isso não é necessariamente fácil de acertar.
fonte
Atualmente, estou trabalhando com um pedaço de código legado e adoro a maneira como o codificador anterior obtém o primeiro elemento de uma lista:
Mas o pior que vi neste código é definir páginas JSPs em linha de classes, escrever todo o HTML, CSS e Javascript usando scriptlet e out.println :-(
fonte
Um dos piores anti-padrões comportamentais que eu vi foi uma loja que só permitia que o código fosse verificado no controle de versão depois que ele estava em produção. Juntamente com checkouts exclusivos no VSS, isso levou a um processo complicado de desfazer checkouts, se um defeito de produção precisasse ser corrigido antes do próximo lançamento, muito menos mais uma pessoa precisando alterar um determinado arquivo para o próximo lançamento.
O fato de ser uma política departamental tornou ainda pior do que o caso de um único desenvolvedor se comportando dessa maneira.
fonte
Bloqueando um literal String
Nomes de classe muito longos. (no JRE)
Estrutura de herança insuficiente
Uma exceção que não é.
Manipulação de erro inútil e enigmática
Criação desnecessária de objetos
Lançando uma exceção para outros fins
Usando objetos de instância para métodos estáticos.
Sincronizando em um campo não final
Cópia inútil de uma String constante
Chamada inútil para String.toString ()
Chama System.gc () para liberar memória
Definir variável local como null para liberar alguma memória
Usando ++ i em vez de i ++ por razões de desempenho (ou qualquer outra micro-micro-otimização)
fonte
Código polvilhado com:
ou
sem informações adicionais.
fonte
Iterador para manequins:
Fábrica Singletono:
desenvolvimento orientado por if-else (também chamado de princípio de fechamento aberto - aberto para modificação próximo ao entendimento):
StringPattern (também chamado StringObject):
fonte
else if
entanto, muitas vezes é a única maneira de fazer as coisas. Estou pensando em cordas; não pode usar um interruptor. As condições devem ser iguais para que seja útil.getInstance
retorna a mesma instância. Tal suposição quebraria o encapsulamento e é de fato um dos anti-padrões mais comuns.Não é tanto um padrão de codificação, mas um padrão comportamental, é muito ruim: modificar algo no código (digamos que os requisitos mudaram) e depois ajustar todos os testes de unidade até que o código seja aprovado. Ajustando ou simplesmente removendo todo o código de teste do método de teste, mas deixando o método lá.
Isso está vinculado a um mais genérico, o padrão That'll Do , aqui está uma linha de código representativa para ele:
Funciona, afinal.
fonte
Eu absolutamente desprezo a inversão da abstração ou a reinvenção de primitivas de baixo nível em cima de primitivas de alto nível. Às vezes, porém, isso é causado por designers de linguagem ruim, não por programadores ruins. Exemplos:
Usando uma única classe de método sem variáveis de membro e uma interface correspondente (implementada em termos de tabelas de ponteiros de função), em vez de um ponteiro de função. Observe que em linguagens como Java, você pode não ter escolha.
Em MATLAB e R, a insistência de que tudo é um vetor / matriz e não um primitivo.
Enquanto estamos atacando o MATLAB, que tal o fato de ele não ter números inteiros? Portanto, quando você precisa de um número inteiro, deve usar um duplo.
Linguagens puramente funcionais, nas quais você precisa usar chamadas de função para escrever um loop.
fonte
Definitivamente seria copiar / colar, já vi muitos códigos ruins sendo feitos por causa disso, isso e codificação de cowboys e tudo o que deriva disso. (Classes de Deus, métodos extra grandes, algoritmos com más idéias, etc.)
E se os padrões de design forem permitidos, eu diria: Executando um projeto como um conjunto de ações de um plano, sem fazer nenhuma análise de design ou domínio.
fonte
Java multiuso -
Um java bean com muitas variáveis, usado em alguns tipos diferentes de operações. Cada operação usa algum subconjunto arbitrário das variáveis do bean e ignora as outras. Algumas variáveis para o estado da GUI, algumas variáveis usadas para passar entre componentes, algumas que provavelmente nem são mais usadas. Os melhores exemplos não têm documentação, o que dificultaria a apreciação do padrão.
Além disso, não pode esquecer o amado
fonte
Um ex-colega de trabalho tinha o hábito de reutilizar objetos substituindo suas propriedades, em vez de simplesmente criar novas. Eu nunca poderia imaginar a quantidade de problemas que isso causou ao implementar novos recursos.
fonte
Algo que me causou muita dor é o padrão "Grande mapa no céu". Jogando em torno de um mapa em vez de usar objetos adequados. Você não tem idéia de quais "variáveis" ele contém sem depuração e não sabe o que pode conter sem rastrear o código para trás. Normalmente mapeia Strings para objetos ou Strings para Strings, que você potencialmente deve analisar em primitivas.
fonte
Um dos meus antipadrões de desenvolvimento favoritos é o uso de um "design" de banco de dados que requer a adição contínua de colunas adicionais a uma ou mais tabelas programaticamente . Este é um primo do "design" que cria uma nova tabela para cada instância de uma entidade. Ambos atingem inevitavelmente as limitações do servidor de banco de dados, mas geralmente não até que o sistema esteja em produção há algum tempo.
fonte
Eu acho que um dos piores anti-padrões que eu já vi envolve o uso de uma tabela de banco de dados como armazenamento temporário em vez de usar a memória do computador.
O domínio do problema é proprietário, o que me impede de explicá-lo, mas não é necessário entender o problema básico. Este era um aplicativo GUI escrito em Java com um banco de dados back-end. Era para pegar certos dados de entrada, manipulá-los e depois confirmar os dados processados no banco de dados.
Nosso projeto possui um algoritmo bastante complicado que salva valores intermediários para processamento posterior. Em vez de encapsular os objetos temporários em ... objetos, uma tabela de banco de dados foi criada como "t_object". Sempre que um valor foi calculado, ele foi adicionado a esta tabela. Depois que o algoritmo terminasse seu trabalho, ele selecionaria todos os valores intermediários e os processaria em um objeto Map grande. Após o término de todo o processamento, os valores restantes marcados para serem salvos serão adicionados ao esquema real do banco de dados e as entradas temporárias na tabela "t_object" serão descartadas.
A tabela também foi usada como uma lista exclusiva, os dados só poderiam existir uma vez. Isso poderia ter sido um recurso decente do design se tivéssemos implementado restrições na tabela, mas acabamos iterando por toda a tabela para ver se os dados existiam ou não. (Não, nem usamos consultas que usavam cláusulas where com CONTAINS)
Alguns dos problemas que encontramos devido a esse design foram especificamente depuração. O aplicativo foi criado para pipeline de dados, para que houvesse várias GUIs que processariam os dados antes de chegarem nesse algoritmo. O processo de depuração foi processar um caso de teste e pausar logo após concluir a seção acima. Em seguida, consultávamos o banco de dados para ver quais dados estavam contidos nesta tabela.
Outro problema que descobrimos foi que os dados não estavam sendo excluídos corretamente dessa tabela temporária, o que interferiria com as execuções no futuro. Descobrimos que isso se deve ao fato de as exceções não serem tratadas adequadamente e, portanto, o aplicativo não sair corretamente e não excluir os dados na tabela em que estava sob controle.
Se tivéssemos usado o Design Orientado a Objetos Básico e mantivemos tudo na Memória, esses problemas acima nunca teriam ocorrido. Primeiro, a depuração seria simples, pois poderíamos configurar facilmente pontos de interrupção no aplicativo e depois inspecionar a memória na pilha e na pilha. Em segundo lugar, após uma saída anormal do aplicativo, a memória java teria sido limpa naturalmente sem ter que se preocupar em excluí-la do banco de dados.
NOTA: Não estou dizendo que esse padrão é inerentemente ruim, mas neste exemplo eu achei desnecessário quando os princípios básicos de OO seriam suficientes.
Não tenho certeza de um nome para esse anti-padrão, pois é a primeira vez que vejo algo assim sendo feito. Quaisquer bons nomes que vocês possam pensar para esse padrão?
fonte
Carrinho antes do cavalo - aka YouMightNeedIt
Por exemplo:
fonte
Na IMO, o pior antipadrão que já vi é o "Não precisamos de padrões fedorentos". Antipadrão: a ideia de que os padrões de design são desperdícios de tempo e você pode escrever código mais rapidamente, basta juntá-lo e copiar / colando conforme necessário.
Menção honrosa diz respeito ao código que carrega um objeto do banco de dados usando o antigo estilo VB6 de:
não é realmente um antipadrão, por si só, mas mostra uma falta de tirar proveito da arquitetura adequada e da separação de preocupações.
Além disso, coisas assim:
fonte