Projete para futuras alterações ou resolva o problema em questão [fechado]

37

Ao escrever o código ou durante o design, você tenta generalizar o problema na primeira instância ou tenta resolver esse problema muito específico.

Estou perguntando isso, porque tentar generalizar o problema tende a complicar as coisas (o que pode não ser necessário) e, por outro lado, será muito difícil estender a solução específica se houver uma alteração no requisito.

Eu acho que a solução é encontrar o caminho do meio que é mais fácil dizer do que fazer. Como você lida com esse tipo de problema? Se você começar a generalizá-lo em que momento você sabe que essa generalização é suficiente?

Naveen
fonte
Isso gera uma pergunta muito importante: você pode realmente prever como os requisitos mudarão?
user16764
Muita gente vai te dizer YAGNI. Essas são as pessoas que você despreza quando precisa assumir o trabalho deles.
Martin Maat

Respostas:

60

Muitas vezes, quando você tenta projetar para o futuro, suas previsões sobre necessidades futuras acabam erradas. Geralmente é melhor refatorar quando você realmente sabe como as necessidades mudaram do que projetar demais o sistema no primeiro dia. Ao mesmo tempo, também não atire no próprio pé. Certamente existe um meio termo, e saber onde é isso é mais arte do que ciência.

Para resumir a uma regra de ouro: menos é mais.


fonte
17
+1 "O futuro não é mais o que costumava ser."
Dan Lyons
19

Você conhece o Agile? Um dos grandes princípios do Agile é o YAGNI . Acho que é a melhor maneira de abordar as coisas.

"Você não vai precisar" ... é um princípio de programação extrema (XP) que afirma que um programador não deve adicionar funcionalidades até que seja considerado necessário. Ron Jeffries escreve: "Sempre implemente as coisas quando você realmente precisa delas, nunca quando você apenas prevê que precisa delas".

... YAGNI é um princípio por trás da prática do XP de "fazer a coisa mais simples que poderia funcionar" (DTSTTCPW). Ele deve ser usado em combinação com várias outras práticas, como refatoração contínua , teste de unidade automatizado contínuo e integração contínua . Usado sem refatoração contínua, pode levar a códigos confusos e retrabalho maciço. A refatoração contínua, por sua vez, conta com testes de unidade automatizados como uma rede de segurança (para detectar bugs imprevistos) e integração contínua para evitar problemas de integração mais amplos ...

O YAGNI não é universalmente aceito como um princípio válido, mesmo em combinação com as práticas de apoio. A necessidade de combiná-lo com as práticas de suporte, em vez de usá-lo de maneira independente, faz parte da definição original do XP ...

Matt Grande
fonte
3
Embora concorde com YAGNI mais ou menos, eu não posso encontrá-lo nos princípios ágeis: agilemanifesto.org/principles.html
Jens Schauder
"A simplicidade - a arte de maximizar a quantidade de trabalho não realizado - é essencial", se aplicaria ao YAGNI e a algumas outras práticas ágeis.
tvanfosson
11
Embora não diga especificamente "YAGNI" no manifesto, acho que eles estão muito alinhados um com o outro.
2
@Jens e @Matt, YAGNI, estão no Agile por meio do XP sendo empacotado como uma metodologia "ágil". Conforme mencionado no artigo da Wikipedia, o princípio YAGNI foi desenvolvido por Ron Jeffries como parte das principais práticas do XP.
11
Pode ser verdade que YAGNI é o idioma dos desenvolvedores, mas é o TDD que aplica esse dilema de maneira bastante agradável. Na etapa em que diz que você deve escrever apenas código suficiente para passar no teste e não mais. E o TDD faz parte do ágil.
Robert Koritnik 28/03
12

Essa é provavelmente uma das partes mais difíceis do desenvolvimento de software, porque você precisa seguir a linha entre "YAGNI" e "PYIAC" (pinte-se em um canto).

É muito fácil dizer "não escreva um recurso a menos que você precise". A parte difícil é projetar seu código para que você possa adicionar recursos facilmente mais tarde, quando precisar deles.

A chave é poder projetar uma arquitetura extensível em que você não escreva mais código do que o necessário no momento. A capacidade de fazer isso bem provém de muita experiência (e dor).

17 de 26
fonte
7

Passo algum tempo adiantado pensando na direção geral do design - não muito, mas o suficiente para basicamente esboçar uma visão geral de alto nível. Em seguida, sigo uma metodologia ágil baseada em histórias usando TDD para desenvolver soluções para histórias individuais. Enquanto estou implementando via TDD, lembro de minha visão geral de alto nível e (a) direcionei minhas implementações específicas para seguir a visão geral de alto nível ou (b) refatorou (e melhorou) meu entendimento / direção de alto nível com base em o que aprendi durante o teste / implementação.

Eu acho que é um erro não fazer nenhum planejamento antecipado, mas é provavelmente um erro maior fazer muito. Na medida do possível, gosto de me deixar experimentar me guiar no cenário geral e, em seguida, deixar o design crescer organicamente, de acordo com as linhas que eu expus em minha mente para saber como o aplicativo será desenvolvido. Usando o TDD, acho que o próprio design é forçado a adotar melhores princípios de design (dissociado, responsabilidade única, etc.) e é mais maleável em relação às mudanças do que se eu tentar pré-conceber o todo e ajustar o desenvolvimento a ele.

tvanfosson
fonte
3

Um bom design acomoda mudanças futuras e definitivamente vale a pena. Considere o sistema operacional UNIX e seu "tudo é uma filosofia de arquivo". Essa decisão de projeto foi tomada não para atender a uma necessidade imediata, mas tendo em vista requisitos futuros. Alguém estremece ao pensar em como seria um sistema operacional baseado em um design "ágil".


fonte
2

O que você está tentando lidar tem a ver com a reutilização (ou seja, a generalização de um problema com o qual está lidando agora, para poder reutilizar o trabalho (código) no futuro). Eu já disse isso antes e vou ligar para ele novamente.

Acho que ouvi outras pessoas dizerem algo para o efeito de:

Eu resolvo o problema pela primeira vez. Quando repito minha solução pela primeira vez, percebo. Quando repito, refatoro.

Jason Punyon
fonte
2

Design para "agora + 1". Isso significa resolver o problema imediato em mãos e criar funcionalidades suficientes para que, da próxima vez em que solicitem uma alteração, você já tenha feito a metade (ou mais) e tenha a opção de a) resolvê-lo imediatamente e refatorando mais tarde, ou b) resolvendo "agora + 1" novamente (com o "agora" meio pronto)

Isso depende do projeto e, em resumo, a experiência ensinará o que é o "+1".

Richard Levasseur
fonte
1

A filosofia de YAGNI , Você não vai precisar, pode ser resumida com (a partir do artigo):

De acordo com aqueles que defendem a abordagem do YAGNI, a tentação de escrever código que não é necessário no momento, mas que pode ser no futuro, tem as seguintes desvantagens:

  • O tempo gasto é gasto na adição, teste ou aprimoramento da funcionalidade necessária.
  • Os novos recursos devem ser depurados, documentados e suportados.
  • Qualquer novo recurso impõe restrições sobre o que pode ser feito no futuro; portanto, um recurso desnecessário agora pode impedir a implementação de um recurso necessário posteriormente.
  • Até que o recurso seja realmente necessário, é difícil definir completamente o que ele deve fazer e testá-lo. Se o novo recurso não for definido e testado corretamente, ele pode não funcionar corretamente, mesmo que eventualmente seja necessário.
  • Isso leva ao inchaço do código; o software se torna maior e mais complicado.
  • A menos que haja especificações e algum tipo de controle de revisão, o recurso pode não ser conhecido pelos programadores que poderiam fazer uso dele.
  • Adicionar o novo recurso pode sugerir outros novos recursos. Se esses novos recursos também forem implementados, isso poderá resultar em um efeito de bola de neve no sentido de uma característica arrepiante.
JeffH
fonte
0

Eu acredito muito em projetar o problema em questão e não estourá-lo, tentando adivinhar todos os casos que você precisa atender porque "um dia poderemos precisar dele".

Basicamente, dada uma lista de requisitos específicos, projete contra isso, no entanto, isso não significa que você não deve:

  • torne aspectos do seu design configuráveis ​​em vez de codificá-los na sua solução. Através de parâmetros passados ​​no tempo de execução ou de uma configuração externa lida na inicialização (ou após o HUP'ing).
  • amarre seu código com números mágicos,
  • evite dar uma olhada para ver se há algo já escrito que possa ser reutilizado, talvez depois de adaptar a solução existente para fornecer uma abordagem adequada à situação existente e aos novos requisitos.

O principal problema ao projetar para "futuros possíveis" é que você está sempre adivinhando. Possivelmente fazendo palpites, mas "quando o assunto é empurrar" ainda é apenas uma série de palpites.

Ao fazer isso, você também tem a possibilidade muito real de espremer sua solução para se adequar aos casos gerais, em vez de resolver o problema específico em questão, conforme definido por seus requisitos conhecidos.

O que está dizendo isso? "Quando tudo que você tem é um martelo, tudo começa a parecer um prego."

Eu gostaria de ter uma libra por cada vez que ouvi alguém dizer: "Mas é uma solução mais adaptável aos casos gerais que poderemos ver no futuro".

Rob Wells
fonte