Introduzir prematuramente a complexidade implementando padrões de design antes que eles sejam necessários não é uma boa prática.
Mas se você seguir todos (ou até a maioria dos) princípios do SOLID e usar padrões de design comuns, introduzirá alguma complexidade à medida que os recursos e requisitos forem adicionados ou alterados para manter seu design tão fácil de manter e flexível quanto necessário.
No entanto, quando essa complexidade é introduzida e funciona como um campeão, quando você a remove?
Exemplo. Eu tenho um aplicativo escrito para um cliente. Quando originalmente criado lá, onde várias maneiras de dar aumentos aos funcionários. Usei o padrão de estratégia e a fábrica para manter todo o processo agradável e limpo. Com o tempo, certos métodos de aumento foram adicionados ou removidos pelo proprietário do aplicativo.
O tempo passa e o novo proprietário assume o controle. Este novo dono é um nariz duro, mantém tudo simples e só tem uma maneira única de dar um aumento.
A complexidade necessária para o padrão de estratégia não é mais necessária. Se eu codificasse isso a partir dos requisitos como estão agora, não introduziria essa complexidade extra (mas certifique-se de poder introduzi-lo com pouco ou nenhum trabalho, se necessário).
Então, removo a implementação da estratégia agora? Eu não acho que esse novo proprietário jamais mude como os aumentos são feitos. Mas o próprio aplicativo demonstrou que isso poderia acontecer.
É claro que este é apenas um exemplo em um aplicativo em que um novo proprietário assume e simplificou muitos processos. Eu poderia remover dezenas de classes, interfaces e fábricas e tornar todo o aplicativo muito mais simples. Observe que a implementação atual funciona muito bem e o proprietário está feliz com ela (e surpreso e ainda mais feliz por eu poder implementar suas alterações tão rapidamente devido à complexidade discutida).
Admito que uma pequena parte dessa dúvida é porque é altamente provável que o novo proprietário não me use mais. Realmente não me importo que outra pessoa assuma o controle, uma vez que não foi um grande gerador de renda.
Mas eu me importo com duas coisas (relacionadas)
Preocupo-me um pouco com o fato de o novo mantenedor ter que pensar um pouco mais ao tentar entender o código. Complexidade é complexidade e não quero irritar o psicopata maníaco que vem atrás de mim.
Mas ainda mais me preocupo com um concorrente vendo essa complexidade e pensando que apenas implemento padrões de design para manter minhas horas de trabalho. Então espalhei esse boato para ferir meu outro negócio. (Eu ouvi isso mencionado.)
Então...
Em geral, a complexidade necessária anteriormente deve ser removida, mesmo que funcione e haja uma necessidade historicamente demonstrada da complexidade, mas você não tem indicação de que será necessária no futuro?
Mesmo que a pergunta acima seja geralmente respondida "não", é aconselhável remover essa complexidade "desnecessária" se entregar o projeto a um concorrente (ou estranho)?
fonte
Um ditado comum é: "Se não está quebrado, não conserte".
Existem vários fundamentos por trás dessa regra. Alguns deles podem ser que a "simplificação" arrisca a introdução de novos bugs, diferentes e possivelmente maiores, pode levar uma quantidade crescente de tempo de desenvolvimento para longe de outros empreendimentos mais valiosos e pode ser completamente a mudança errada para alguma oportunidade de negócios futura inesperada que surge.
Se houver um valor comercial suficiente para esse código ser portátil e mais sustentável, decida se esse valor é realmente suficiente para considerar o código atual "quebrado". Pode ser que, se houver uma grande expansão de negócios planejada, ou você suspeite de um bug latente oculto na complexidade que poderia prejudicar os negócios.
fonte
Primeiro, se o aplicativo já foi assumido por um novo proprietário, isso pode acontecer novamente. E o próximo proprietário pode novamente começar a usar essa complexidade que não é beneficiada no momento.
Além disso, alterações não triviais no código de trabalho sempre envolvem um risco, portanto (como outros observaram) o cliente deve concordar com (e pagar) por eles. Se a complexidade "extra" atual não causar nenhuma desvantagem perceptível e mensurável (como problemas de desempenho), não há motivos fortes para removê-la.
Os clientes (potenciais) que (não) o contratam com base apenas nos boatos dos concorrentes não valem a pena ter de qualquer maneira, a menos que você esteja precisando desesperadamente de renda. Você tem razões boas e lógicas para implementar o aplicativo da maneira como implementou e qualquer cliente sério provavelmente entenderá isso. Alguém que não o faz - ou nem se incomoda em perguntar a você - provavelmente causará mais problemas ao longo do caminho do que vale a pena o trabalho.
fonte
Não.
Não. Por que desperdiçar seu tempo para corrigir a prioridade baixa funciona assim? Nenhum dano para o código ficar lá.
Quanto à sua pergunta: quando a complexidade deve ser removida?
Minha opinião é que, se não estiver quebrado, não conserte .
fonte
Para poder remover a complexidade, o seguinte deve ser verdadeiro:
fonte
Eu acho que há algo maior em ação aqui ... Escalabilidade
O que você está falando é chamado de escalabilidade . Não importa se o código é complexo, importa se o aplicativo pode evoluir com base em novas regras de negócios ou regras de negócios alteradas. O que acontece se o próximo proprietário quiser algo totalmente diferente.
Então, digo manter o código e documentá-lo. É uma característica de como o aplicativo pode ser utilizado.
fonte
Há um esforço e risco para remover a complexidade. Se isso for maior do que o esforço adicional e o risco de manter o código excessivamente complexo, mantenha-o. Caso contrário, você o remove. É difícil estimar esses riscos, no entanto.
Eu acrescentaria que você pode reduzir o risco de manutenção mais difícil documentando por que você usou o padrão de design Strategy em primeiro lugar, no código. Pessoalmente, acredito que qualquer padrão de design deve ser rastreável a um requisito explícito (funcional ou não funcional).
Seu cenário de ser criticado pela concorrência por horas de preenchimento é precisamente o motivo pelo qual você deve documentar a complexidade. Se você documentar e justificar (com um requisito específico do cliente) o uso de qualquer padrão, estará coberto. Se você não pode justificar um padrão com os requisitos de um cliente, parece um excesso de design ou padronização.
Se os requisitos forem alterados, você poderá justificá-lo, devido ao risco de poder quebrar o código (ou a quantidade de trabalho para remover cirurgicamente o padrão).
Eu acho que é bom distinguir entre complexidade acidental e complexidade essencial , já que os padrões geralmente envolvem ambos.
Ou seja, seu requisito para suportar algoritmos variados para decidir aumentos é uma complexidade essencial (parte do problema a ser resolvido). A manutenção do seu código é facilitada pelo padrão Estratégia, mas a alternativa codificada se / então à Estratégia ainda funcionará. Fiz exercícios nos meus cursos de mestrado, onde os alunos encontram oportunidades de aplicar a Estratégia em projetos de código aberto. A complexidade não é necessariamente melhor / pior ao aplicar a Estratégia (porque é uma complexidade essencial ). Às vezes, pode ser ainda mais difícil entender a estratégia, porque o código é dividido em várias classes com polimorfismo, em vez de um grande bloco if / then / else.
Idealmente, um padrão funciona quando os benefícios que ele supera o custo de suas desvantagens. Novamente, quantificar essas coisas é difícil. Freqüentemente, um padrão deixa o desenvolvedor feliz (não apenas porque facilita a adição de uma nova estratégia de aumento, mas também faz com que o desenvolvedor fique empolgado ao saber que um padrão foi aplicado). É difícil mostrar aos clientes como os beneficia.
O cliente não se importa ou mesmo entende os detalhes. No caso do novo proprietário aplicando o KISS em seus processos, é ela reduzindo a complexidade essencial , o que também deve ter um impacto na solução de software.
fonte