Progettare modifiche future o risolvere il problema a portata di mano [chiuso]


37

Durante la scrittura del codice o durante la progettazione si tenta di generalizzare il problema nella prima istanza stessa o si tenta di risolvere quel problema molto specifico.

Lo sto chiedendo perché cercare di generalizzare il problema tende a complicare le cose (il che potrebbe non essere necessario) e d'altra parte sarà molto difficile estendere la soluzione specifica in caso di modifica del requisito.

Immagino che la soluzione sia trovare la via di mezzo che è più facile a dirsi che a farsi. Come affrontate questo tipo di problema? Se inizi a generalizzarlo in quale momento sai che è sufficiente questa generalizzazione?



Ciò pone una domanda molto importante: puoi davvero prevedere come cambieranno i requisiti?
user16764,

Molte persone ti diranno YAGNI. Quelle sono le persone che disprezzi quando devi assumere il loro lavoro.
Martin Maat,

Risposte:


60

Troppo spesso quando si tenta di progettare per il futuro, le previsioni sulle esigenze future si rivelano errate. Di solito è meglio effettuare il refactoring quando si sa effettivamente come sono cambiate le esigenze piuttosto che sovrascrivere il proprio sistema il primo giorno. Allo stesso tempo, non spararti nemmeno ai piedi. C'è sicuramente una via di mezzo e sapere dove si trova è più arte che scienza.

Per ridurlo a una regola empirica: less is more.


17
+1 "Il futuro non è più quello di una volta."
Dan Lyons,

19

Conosci Agile? Uno dei grandi principi di Agile è YAGNI . Trovo che sia il modo migliore per avvicinarsi alle cose.

"Non ne avrai bisogno" ... è un principio di programmazione estrema (XP) che afferma che un programmatore non dovrebbe aggiungere funzionalità fino a quando ritenuto necessario. Ron Jeffries scrive: "Implementa sempre le cose quando ne hai davvero bisogno, mai quando prevedi che ne hai bisogno."

... YAGNI è un principio alla base della pratica XP di "fare la cosa più semplice che potrebbe funzionare" (DTSTTCPW). È pensato per essere utilizzato in combinazione con diverse altre pratiche, come il refactoring continuo , il test automatico continuo delle unità e l' integrazione continua . Utilizzato senza refactoring continuo, potrebbe portare a codice disordinato e rilavorazioni di massa. Il refactoring continuo a sua volta si basa su test di unità automatizzati come rete di sicurezza (per rilevare bug imprevisti) e integrazione continua per prevenire problemi di integrazione più ampi ...

YAGNI non è universalmente accettato come un principio valido, anche in combinazione con le pratiche di supporto. La necessità di combinarlo con le pratiche di supporto, piuttosto che utilizzarlo autonomamente, fa parte della definizione originale di XP ...


3
Mentre sono più o meno d'accordo con YAGNI, non riesco a trovarlo nei principi agili: agilemanifesto.org/principles.html
Jens Schauder,

"La semplicità - l'arte di massimizzare la quantità di lavoro non svolto - è essenziale", si applicherebbe a YAGNI e ad altre pratiche agili.
tvanfosson,

1
Anche se non indica specificamente "YAGNI" nel manifesto, penso che siano molto in linea tra loro.

2
@Jens e @Matt, YAGNI, sono in Agile per mezzo di XP in bundle come metodologia "agile". Come menzionato nell'articolo di Wikipedia, il principio YAGNI è stato sviluppato da Ron Jeffries come parte delle pratiche di base di XP.

1
Può essere vero che YAGNI sia il linguaggio degli sviluppatori, ma TDD è quello che applica questo dilemma abbastanza bene. Nel passaggio in cui si dice che dovresti scrivere solo abbastanza codice per superare il test e non di più. E TDD fa parte di agile.
Robert Koritnik,

12

Questa è probabilmente una delle parti più difficili dello sviluppo del software perché è necessario percorrere la linea tra "YAGNI" e "PYIAC" (Paint Yourself Into A Corner).

È abbastanza facile dire "non scrivere una funzione se non ne hai bisogno". La parte difficile è progettare il tuo codice in modo da poter aggiungere facilmente funzionalità in seguito quando ne hai bisogno.

La chiave è essere in grado di progettare un'architettura estensibile in cui non si scrive più codice di quello che è attualmente necessario. La capacità di farlo bene proviene davvero da molta esperienza (e dolore).


7

Passo un po 'di tempo in anticipo a pensare alla direzione generale del design - non troppo, ma abbastanza per delineare sostanzialmente una panoramica di alto livello. Seguo quindi una metodologia agile basata su storie usando TDD per sviluppare soluzioni per storie individuali. Mentre sto implementando tramite TDD, tengo presente la mia panoramica di alto livello e (a) dirigo le mie implementazioni particolari a seguire la panoramica di alto livello o (b) refactoring (e migliorare) la mia comprensione / direzione di alto livello basata su cosa imparo durante i test / l'implementazione.

Penso che sia un errore non pianificare in anticipo, ma probabilmente è più grande fare troppo. Per quanto possibile, mi piace lasciarmi guidare dall'esperienza nel quadro generale e quindi lasciare che il design cresca organicamente secondo le linee che ho definito nella mia mente su come si svilupperà l'applicazione. Utilizzando TDD trovo che il design stesso sia costretto a principi di progettazione migliori (disaccoppiati, responsabilità singola, ecc.) Ed è più malleabile rispetto ai cambiamenti che se provassi a concepire il tutto e ad adattare lo sviluppo ad esso.


3

Un buon design accoglie cambiamenti futuri e vale sicuramente la pena andare. Considera il sistema operativo UNIX e il suo "tutto è una filosofia di file". Tale decisione progettuale è stata presa non per soddisfare alcune esigenze immediate ma in vista di requisiti futuri. Uno rabbrividisce per pensare a come sarebbe un sistema operativo basato su un design "agile".


2

Ciò che stai cercando di affrontare ha a che fare con il riutilizzo (ovvero la generalizzazione di un problema che stai affrontando ora in modo da poter riutilizzare il lavoro (codice) in futuro). L'ho già detto e lo collegherò di nuovo.

Penso di aver sentito altre persone dire qualcosa sull'effetto di:

Risolvo il problema la prima volta. Quando ripeto la mia soluzione per la prima volta, la noto. Quando lo ripeto di nuovo, rifletto.


2

Progettare per "ora + 1". Ciò significa, risolvere il problema immediato a portata di mano e integrare funzionalità sufficienti in modo che la prossima volta che chiedano un cambiamento, lo abbia già fatto a metà (o più) e abbia la scelta di a) risolverlo immediatamente e refactoring in seguito, oppure b) risolvendo nuovamente "ora + 1" (con la metà "ora" eseguita)

Questo dipende dal progetto e, in breve, l'esperienza ti insegnerà qual è il "+1".


1

La filosofia di YAGNI , You Ain't Gonna Need It, può essere sintetizzata con (dall'articolo):

Secondo coloro che sostengono l'approccio YAGNI, la tentazione di scrivere codice che al momento non è necessario, ma che potrebbe essere in futuro, presenta i seguenti svantaggi:

  • Il tempo impiegato viene impiegato per aggiungere, testare o migliorare le funzionalità necessarie.
  • Le nuove funzionalità devono essere sottoposte a debug, documentate e supportate.
  • Qualsiasi nuova funzionalità impone vincoli su ciò che può essere fatto in futuro, quindi una funzione non necessaria ora può impedire l'implementazione di una funzione necessaria in un secondo momento.
  • Fino a quando la funzionalità non è effettivamente necessaria, è difficile definire completamente cosa dovrebbe fare e testarla. Se la nuova funzionalità non è definita e testata correttamente, potrebbe non funzionare correttamente, anche se alla fine è necessaria.
  • Porta a codice gonfio; il software diventa più grande e più complicato.
  • A meno che non ci siano specifiche e un qualche tipo di controllo di revisione, la funzione potrebbe non essere nota ai programmatori che potrebbero farne uso.
  • L'aggiunta della nuova funzionalità può suggerire altre nuove funzionalità. Se anche queste nuove funzionalità saranno implementate, ciò potrebbe tradursi in un effetto a palla di neve verso il featurism strisciante.

0

Sono fermamente convinto di progettare il problema in questione e di non far esplodere il tuo progetto cercando di indovinare tutti i casi che devi affrontare perché "un giorno potremmo averne bisogno".

Fondamentalmente, dato un elenco di requisiti specifici, progettare contro ciò, tuttavia, ciò non significa che non si dovrebbe:

  • rendere configurabili gli aspetti del proprio progetto piuttosto che codificarli in modo rigoroso nella propria soluzione. Tramite parametri passati in fase di esecuzione o tramite una configurazione esterna letta all'avvio (o dopo HUP'ing).
  • allaccia il tuo codice con numeri magici,
  • evita di dare un'occhiata per vedere se c'è già qualcosa che puoi riutilizzare, forse dopo aver adattato la soluzione esistente per fornire un approccio adatto alla situazione esistente e ai nuovi requisiti.

Il problema principale con la progettazione di "possibili futuri" è che indovini sempre. Probabilmente fare ipotesi colte, ma "quando arriva la spinta" è ancora solo una serie di ipotesi.

In questo modo hai anche la reale possibilità di spremere la tua soluzione per adattarla ai casi generali piuttosto che risolvere il problema specifico a portata di mano come definito dai tuoi requisiti noti.

Cosa sta dicendo? "Quando tutto ciò che hai è un martello, tutto inizia a sembrare un chiodo."

Vorrei avere una sterlina per ogni volta che ho sentito qualcuno dire: "Ma è una soluzione che è più adattabile per quei casi generali che potremmo vedere in futuro".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.