Come gestisci il brutto codice che hai scritto? [chiuso]


88

Quindi il tuo cliente ti chiede di scrivere un po 'di codice, così fai. Quindi cambia le specifiche su di te, come previsto, e tu implementi diligentemente le sue nuove funzionalità come un bravo ragazzo. Tranne ... le nuove funzionalità sono in conflitto con le vecchie funzionalità, quindi ora il tuo codice è un casino. Vuoi davvero tornare indietro e aggiustarlo, ma continua a richiedere nuove cose e ogni volta che finisci di pulire qualcosa, finisce di nuovo un casino.

cosa fai? Smetti di essere un maniaco del disturbo ossessivo compulsivo e accetti semplicemente che il tuo codice finirà per fare casino, qualunque cosa tu faccia, e continui a concentrarti sulle caratteristiche di questa mostruosità? Salvare la pulizia per la versione 2?


15
Questa è un'ottima domanda.
Walter,

3
Penso che questo sia un buon posto per applicare la regola 80/20 .
Marco C,

umm..non scrivi brutto codice in primo luogo ?!
Roopesh Shenoy,

8
@Roopesh: Non è brutto in primo luogo, è quando continui a puntare sulle cose che diventa brutto. Con le funzionalità aggiunte, ti rendi conto che la struttura principale avrebbe potuto essere progettata in modo diverso per supportare meglio tali funzionalità. E a quel punto puoi tornare indietro e riscrivere grossi pezzi di fondotinta o semplicemente aggiungere la funzione. Di solito non c'è abbastanza tempo per tornare indietro e riscrivere metà del programma.
Aprire il

Quindi "progetta pensando al cambiamento" dici. Certo, facile da dire, ma quando alcune cose fondamentali cambiano perché il tuo cliente non sa davvero cosa vuole e ti dà solo una mezza specifica in anticipo, è un po 'difficile.
Aprire il

Risposte:


41

Trova un altro lavoro e consenti ad altre persone di affrontarlo. Muahahahhahahaa.

.....

Solo scherzando. :)

Ma in tutta serietà: il riempimento di stima è tuo amico. In genere faccio una stima realistica decente, quindi la raddoppio. Questo potrebbe sembrare eccessivo, e talvolta lo è, ma è meglio sopravvalutare un po 'e persino sembrare un po' lento a volte - piuttosto che lasciare cattive impressioni rivelando il codice buggy e saltando sempre le tue stime. E, naturalmente, si incorre in un debito tecnico lasciando che il codebase diventi confuso.

Un altro suggerimento (correlato): stimare sempre attività apparentemente minuscole, senza sforzo in un blocco di dimensioni decenti. Supponiamo, ad esempio, che un elemento di cui sei quasi sicuro sarà solo un semplice cambio di 30 secondi di una riga: dagli 1 ora (o forse qualunque sia il periodo di tempo più basso sul tuo foglio presenze o sul tuo sistema CR, ad esempio 15 minuti / 0,25 ore) . E dai blocchi di mezza giornata o 1 giorno per gli oggetti leggermente più grandi ma ancora relativamente banali.

La ragione di ciò è principalmente psicologica: trovo che se prendi l'abitudine di fare rapidamente piccoli cambiamenti, il lavoro sembra affrettato, e non finisci mai per rilassarti, fare il punto e rifattorizzare le cose che devono essere rifattorizzate. Inoltre, a livello pratico: a volte esplodono piccoli ma non banali cambiamenti, e non vuoi sentirti costantemente come se fossi in ritardo e spegni bug. Fa parte del perché le basi di codice diventano confuse nel tempo.

Infine, ricorda sempre che le persone non devono sapere che stai riempiendo un po 'le tue stime. Finché sei uno sviluppatore competente e stai lavorando a un ritmo decente, questa imbottitura non sarà evidente. cioè non dire al PHB "La mia stima iniziale è che ci vorranno due ore, ma dammi mezza giornata". Digli semplicemente "Penso che ci vorrà circa mezza giornata." e lasciarlo lì.


12
+1 Per essere malvagio. ;)for(printf("MUHU"); 1; printf("HA"));
Mateen Ulhaq,

1
@muntoo: Mi ci è voluto un secondo per capire cosa facesse ... non ho visto il for. Carino;)
mpen

4
Sono sicuro che questo dipende dal manager, ma non devi necessariamente mentire. Il CTO e io abbiamo una comprensione; sa che posso dare una stima ragionevole ma solo con una confidenza di circa il 50%; se inserisco un fattore di sfumatura, posso dare la stessa stima con un livello di confidenza del 90%. E si scopre che, per un lungo periodo di tempo, la maggior parte delle persone preferisce stime affidabili a quelle ingenuamente ottimistiche, anche se non lo ammettono o non lo realizzano, quindi dà la stima pessimistica al suo capo a meno che non sia un'emergenza.
Aaronaught,

2
Il punto che assolutamente nulla richiede meno di circa mezz'ora è molto ben fatto. Anche se una singola modifica al codice richiede 5 minuti, c'è una zattera di spese generali che ne deriva.
Murph,

2
@Murph - spot on. Rifiuto qualsiasi stima commerciale inferiore a mezza giornata. Quando lo sviluppatore ha acquisito il codice giusto, apportato la modifica, eseguito i test delle unità, superato la build per testare e testare la sanità mentale, NULLA richiede 5 minuti.
Jon Hopkins,

66

Sopravvalutare deliberatamente il tempo necessario per le prossime funzionalità. Usa quel tempo in più per pulire.

Non sarai mai in grado di giustificare la manutenzione e il cliente ne ha bisogno a prescindere, quindi dai loro la medicina amara (costi leggermente aumentati per le prossime funzionalità) in modo che possano migliorare.


+1 per questo. Stima imbottitura FTW. E davvero, lo stesso consiglio vale per giustificare quanto tempo richiede la correzione e la manutenzione dei bug (comunque internamente: giustificare il PHB, non i clienti, come dici che non importa ai clienti).
Tavoli Bobby,

5
Penso che sia un modo ragionevole di gestire anche il problema. Il dolore che sottopongono agli sviluppatori deve essere restituito come costo aggiuntivo. Anche la direzione e la forza vendita devono accettare questa filosofia, altrimenti gli sviluppatori otterranno il controllo e saranno sottoposti a basi di codice sempre peggiorate.
Tin Man,

1
Oh, inoltre: assolutamente, l'ideale è una comunicazione aperta e onesta. Suggerisco un meccanismo di coping solo quando ciò non è perfettamente realizzabile. È una medicina a lungo termine come inganno.
Frank Shearar,

3
Questa imbottitura di stima? Sembra il momento di implementare una nuova funzionalità, pur mantenendo la qualità del codice per me.
David Thornley,

2
Penso che questo sia principalmente l'approccio giusto, ma lo caratterizzerei in modo diverso. Ti stanno assumendo per sviluppare un codice di qualità professionale. Ciò significa che è necessario integrare i tempi delle stime per "farlo nel modo giusto". Non fare stime in base al tempo che impiegheresti se restassi sveglio tutta la notte a hackerare e dichiarassi "completo" non appena funzionava correttamente la prima volta. Ciò può significare che in una situazione competitiva verrai a volte sottovalutato. Va bene. Svilupperai una reputazione per offrire qualità e coerenza e alla fine vincerai. Gioca al gioco lungo.
Brandon DuRette

11

Prova a riprogettare correttamente integrando nuove funzionalità. Non c'è più tardi. Senza la riprogettazione si aggiunge costantemente sempre più attrito per ulteriori modifiche e nuove funzionalità.

Ad un certo punto arriverete a una macinatura quasi ferma dove tutto sembra richiedere secoli. La maggior parte delle aziende probabilmente preferisce la grande riscrittura a questo punto, versione 2. Ha un'economia piuttosto scadente ed è un buon momento per i tuoi clienti di provare un partito di sviluppo diverso se si sentono propensi.

Una corretta riprogettazione / refactoring può proteggere gli investimenti dei vostri clienti e mantenere le cose sostenibili. Devi integrarlo. Ottimizza per il cambiamento, viaggiare leggero.


6

Con tutti i commenti sulla sopravvalutazione, penso che ci sia una modesta quantità di punti (ben opportunità) da perdere.

Non si tratta di stimare il tempo impiegato per apportare la modifica (solo) e quindi aggiungerne un po ', si tratta di stimare il tempo necessario per modificare il codice (refactor!) Per portarlo a un punto in cui la modifica può essere effettuata in modo sicuro e quindi effettuare il cambiamento (probabilmente un po 'insieme). Ok, questo equivale alla stessa cosa ... ma non si tratta di confondere o allungare o sopravvalutare, si tratta semplicemente di dire che per fare questo devo prima farlo e questo è quanto tempo ci vorrà in totale. La chiave qui è che lavori su quelle parti del sistema da cui dipende la modifica e non di più - se c'è un codice orribile altrove ... difficile, prendilo quando sei lì.

Ritornare un po 'alla domanda originale - dopo molti anni si riduce a questo per me, quando si implementa qualcosa a meno che non si sappia (non si creda, non ci si aspetti (sospetto?), Non si pensi ma si sappia ) che roba aggiuntiva è Inoltre, è necessario fare ciò che è necessario per implementare tale requisito e non più nel modo più ordinato ed elegante possibile.

Quando arrivate a implementare la cosa successiva - qualche tempo dopo - prendete le misure necessarie per portare la base di codice (e il database e quant'altro) allo stato necessario per implementare quella funzionalità nel modo più ordinato ed elegante possibile. Questo refactoring è il punto in cui si affronta il disordine che si presenta naturalmente all'evolversi di un progetto e si spera di evitare di creare più disordine (o almeno mantenere il livello coerente).

Una delle aree di discussione qui è "Debito tecnico" - è come uno scoperto, devi ripagarlo e più lo lasci, più interessi (in questo caso è necessario il tempo per correggere) che matureresti - il che ti dà una buona argomento per passare un po 'del tuo tempo a minimizzare il debito tecnico.

Questo è anche il punto in cui iniziano i test unitari e altri test automatizzati (se potessi fare così come dico, sono abbastanza sicuro che sarei una persona più felice!) In combinazione con un server di build adeguato (che può eseguire almeno alcuni dei tuoi test). Combinati con quelli - ma di valore in sé stessi - sono schemi come l'iniezione di dipendenza e l'inversione del controllo (mai abbastanza sicuri di quanto siano gli "stessi" quei due) perché rendono più facile cambiare l'impianto idraulico e quindi gestire i cambiamenti in solitudine.

Infine, ricorda, se non è rotto non aggiustarlo. Riordinare il codice semplicemente per motivi di riordino potrebbe essere soddisfacente, ma è anche un'opportunità per introdurre errori, quindi può essere doloroso se non è necessario modificarlo e non ci si basa su di esso, potrebbe essere meglio lasciare alcuni grumi da solo - la possibilità di riparare o sostituire andrà alla fine!


4

1) Il controllo delle modifiche corretto è tuo amico

Se il cliente modifica le specifiche, va bene, è un suo diritto, tuttavia si tratta di una modifica e deve essere addebitata (o pagata in qualsiasi modo appropriato alla struttura / relazione del progetto).

La stima per tale modifica dovrebbe includere il costo del refactoring necessario . Il cliente potrebbe anche fare a meno di quello che sembra essere un costo elevato, ma a quel punto è necessario spiegargli che, poiché il codice è già scritto per metà, ci sono elementi che devono essere riscritti per garantire che sia solido e sostenibile in futuro e che se non viene fatto, è probabile che abbia problemi con il supporto futuro o che le modifiche diventino ancora più costose.

2) Il refactoring deve essere eseguito in modo tale da fornire al cliente un vantaggio reale a lungo termine

Quando si considera il refactoring è sempre necessario considerare ciò che è effettivamente necessario e ciò che è importante e assicurarsi che il lavoro di refactoring offra un autentico valore a lungo termine.

Dopotutto, dovremmo fare queste cose in modo che il codice rimanga estendibile e sostenibile a medio / lungo termine per garantire che l'investimento del cliente rimanga valido piuttosto che fuori da qualsiasi spinta per la perfezione teorica. Il lavoro di refactoring (e le stime corrispondenti) dovrebbe essere fatto con questo come scopo, e non solo perché ora pensi che potrebbe esserci un modo leggermente migliore per farlo.


3

Alcuni programmatori suggeriscono che un modo per controllare quel problema con i client sia avere il segno del cliente e autorizzare la specifica iniziale. ALLORA, quando richiedono una modifica del requisito che non è nella specifica iniziale, si dice loro che è necessario passare attraverso il contratto e l'orario del progetto al fine di calcolare costi aggiuntivi e ritardi, quindi fare un allegato al contratto. Apparentemente fa miracoli nel impedire ai clienti di insistere su nuove funzionalità (non previste).


2
+1; Può funzionare, tuttavia corre anche il pericolo di alienare il cliente essendo troppo flessibile. In una certa misura, la possibilità di farlo o meno dipende dal tipo (dimensione) del progetto e dalle aspettative del cliente.
Ken Henderson,

3

Ho il seguente commento in una base di codice su cui sto attualmente lavorando:

/*
 * Every time I see this function, I want to take a shower.
 */

Conosco molto bene la situazione che stai descrivendo. Quello che faccio è cercare (il mio meglio) di aspettare che le cose si stabilizzino e ogni tipo di "creep" ha "insinuato" tutto ciò che sta per fare. A quel punto, probabilmente hai rilasciato qualcosa di utilizzabile e puoi dedicare del tempo per ripulire le cose e implementare le cose in modo leggermente diverso.

Non puoi andare in giro a ripulire ripetutamente molti piccoli pasticci. Questo triplica il tuo lavoro e la tua frustrazione. Aspetta che diventi un disastro più grande, ma difficilmente commovente e quindi puoi fare qualcosa al riguardo.


2

La mia preferenza è quella di evitare questa situazione in primo luogo.

Tutto dipende da come leggi le specifiche. È facile pensarli come tavolette di pietra, ma in realtà la maggior parte delle specifiche cambia. Quando progetti il ​​tuo codice, dai un'occhiata alla probabilità che ogni parte delle specifiche cambi. Nel tempo, diventerai abbastanza bravo a prevederlo.

Essere nel caos, esperienza e giudizio è molto importante. Stai scrivendo nuovi bug a causa di questo codice spaghetti? ci vuole più tempo per implementare? questi indicherebbero a fare un rifattore tattico.

per il futuro, sembra che tu debba lavorare in collaborazione con il tuo cliente. Dicendo loro, "guarda questo prodotto si sta espandendo in modo significativo oltre le specifiche originali. Mentre il design originale era buono per quel livello, espandendolo in direzione X e direzioni Y necessitavano di qualche ristrutturazione nel design" gestito bene, e otterrai anche il tuo cliente a pagare per questo.


Non so se li considererei "bug" o no. Sto apportando alcuni grandi cambiamenti e naturalmente tutto inizia a sfaldarsi quando inizi a strappare le basi. È tutto risolvibile però. Ricordo al mio cliente i costi per apportare modifiche come questa su base regolare, ma desidera "stime" immediate che semplicemente non posso dare. Il parcheggio con la palla non è nemmeno possibile fino a quando non pensi davvero a tutte le modifiche al design che devi apportare, ma non lo capisce. Comunque, sta pagando e non si lamenta troppo.
mpen

2

Addebita ogni ora e se vuole dei cambiamenti dì che va bene ma incorpora il tempo necessario per scrivere un buon codice nell'equazione. Ricorda anche che scrivere codice più ordinato paga a lungo termine quando devi mantenerlo. Risparmiare tempo ora potrebbe costarti in seguito.


Sto caricando per ora, ma il fatto è che, anche quando mi prendo il tempo per scrivere "buon codice", diventa così obsoleto così in fretta, mi chiedo se ci sia un punto. Penso di aggiungere costi pulendo costantemente prima ancora che il progetto si sia stabilizzato.
mpen

1

Penso che la scrittura di software debba andare di pari passo con le esigenze aziendali. Se si tratta di un progetto usa e getta (come un prototipo che deve essere costruito in una settimana, con nuovi input in arrivo ogni giorno), non è necessario preoccuparsi della manutenibilità del codice e di altre cose: il tempo è cruciale e devi solo spingere il codice fuori dalla porta il più velocemente possibile.

Ma se stai scrivendo un'app a lungo termine, ha senso considerare tutto questo, perché c'è un impatto considerevole su quanto tempo ci vuole per costruire nuove funzionalità, correggere bug esistenti, integrarsi in altre applicazioni e altre cose - e questo si traduce in impatto sul business (a causa di più tempo richiesto in seguito e più costi).

Quindi è meglio sensibilizzare il decisore ai costi effettivi di non refactoring del codice ogni volta che è necessario - nella mia esperienza, se i costi e l'impatto sul tempo di entrambe le opzioni sono spiegati in termini misurabili al proprietario della decisione, allora la decisione può essere un una follia. Non aspettarti che la gente ti dica "sì, vai avanti a scrivere un bellissimo codice, anche se ci vuole il doppio del tempo e non mi dà alcun vantaggio extra". Semplicemente non funziona in questo modo.


1

Rendilo parte del tuo processo, lo chiamo "refactoring estremo" e sarà grande! ;) Basta fare le cose rapidamente e quando sono state aggiunte abbastanza nuove funzionalità che ci sono tessuto cicatriziale, refactor. Chiediti continuamente "Ora se avessi iniziato da zero, come avrei fatto"

Le persone che pensano di poter progettare e pensare a tutto ciò che è in anticipo si stanno prendendo in giro da sole, tu (e il tuo cliente) imparate sempre le cose mentre andate avanti. Usa quelle lezioni.

Dato che sei un buon programmatore, sarai in grado di eseguire il refactoring abbastanza rapidamente e man mano che lo fai, il codice inizierà a prendere la sua "forma corretta", il che significa che diventerà più flessibile con meno dipendenze.

I clienti potrebbero essere seccati se sapessero che stavi "perdendo tempo" a rielaborare le cose, quindi aiuta a non chiedere / raccontare ed essere molto veloce al riguardo.

Il codice sviluppato in questo modo ti farà risparmiare un sacco di tempo alla fine e renderà sempre più facile l'aggiunta di nuove funzionalità.

Direi anche che uno dei maggiori motivi del cattivo codice è la paura che alcuni programmatori hanno di fare un refactoring strutturale più ampio, e più a lungo aspetti e peggiora.


1

Affidati a una potenza superiore

Non intendo pregare. Voglio dire, assicurati che ci sia un uomo d'affari (cioè project manager o equivalente) che puoi inserire come imbottitura tra te e il cliente. Se il cliente richiede troppo, lascia che l'uomo d'affari metta piede e sii pronto a esercitare il "è fattibile, ma non sono sicuro che si adatti allo scopo delle specifiche, vedi [uomo d'affari]".

In un normale flusso di progetto, le specifiche generali dovrebbero essere congelate prima che avvenga un serio sviluppo.

Molti clienti continueranno a guidare per cambiamenti / miglioramenti / miglioramenti fino a quando li lascerai. Molti abuseranno al massimo di questa capacità perché li fa sentire come se stessero ottenendo il massimo per i loro soldi (anche se sabota il tuo progetto).

Chiedi a una persona dedicata a perfezionare e congelare le specifiche all'inizio e farle rispettare in seguito.

Non c'è niente di sbagliato nel fare un piccolo extra per un po 'di buon karma con il cliente, ma sii pronto a rinviare a un potere superiore quando sfuggono di mano. Se la specifica richiede una quantità ridicola di modifiche, forse è il momento di tornare indietro nel ciclo economico e rivalutare il contratto e / o aggiungere aggiunte al contratto (con un equo compenso monetario).

Il fatto che stai riscontrando questo problema ha poco a che fare con il modo in cui il codice. È un segno che il tuo project manager è sottoutilizzato sul progetto (che sia colpa tua, colpa sua o entrambi).

Come altri hanno già detto in molte risposte, è necessario aggiungere un time buffer per le contingenze su qualsiasi progetto, ma determinare che dovrebbe essere deciso a porte chiuse prima che la specifica venga congelata e consegnata al cliente dal PM.


0

Una corretta progettazione iniziale non può aiutare a evitare il problema. Ed è quasi impossibile (o molto molto difficile) considerare tutti i futuri requisiti "forse". Quindi dopo qualche tempo arriverà il Big Re-factoring. E la soluzione migliore è riscrivere tutto.

In poche parole: invece di montare una torretta sulla Ferrari rossa, riconsidera i requisiti e costruisci un serbatoio.


0

Uccidilo col fuoco.

Aka refactor il più presto possibile: ad esempio quando il codice brutto proviene dalla corsa per una scadenza, farei refactoring dopo la scadenza perché non puoi (o non dovresti almeno) aggiungere più funzionalità fino a quando il codice esistente non è mantenibile, altrimenti renderà molto più difficile il debug dei codici futuri.


0

Scrivi unit test per i tuoi progetti che testano lo stato corrente e poi refactoring quando hai tempo, in questo modo eviti di interrompere il tuo progetto mentre stai provando a ripulirlo.


0

Risposta più semplice. Smetterei di scrivere codice di qualsiasi tipo, fino a quando non avrà una specifica finale per quello che vuole ora.

Quindi devono dare la priorità a quell'elenco di funzionalità ecc., Per confermare quali elementi devono avere adesso e quali possono essere fatti in seguito ...

Usando le tue esperienze per determinare quale sia il tempo / costo di ogni funzione, e poi dire loro, se lo vogliono, ci vorrà x quantità di tempo e denaro.

Stai affrontando il grande crimine dell'ambito delle funzionalità, e continueranno continuamente ad aggiungere funzionalità, fino a quando nulla verrà mai fatto o fatto così male.

Dì loro una volta che avrai un elenco finale, che apporterai modifiche future, come preferiscono, ma devi concentrarti sui primi 15/20 che devono avere in questo momento.

Quindi, in base al tempo di completamento, di 'loro che dopo che questo sarà stato rilasciato, sarai aperto a discutere / fare brainstorming sulla prossima versione.

Una volta presa la decisione finale su cosa fare per la versione attuale, tutte le discussioni / idee / suggerimenti devono essere fermati al 100%.

Se ottiene idee all'infinito, digli di scriverle, nel loro elenco di funzionalità per la prossima versione, e di concentrarti sulla fornitura delle funzionalità più importanti che desiderano in questo momento.

Se continuano a perdere tempo, continua a cambiare idea. Quindi smetterei di lavorare sul progetto e di lavorare su altri progetti, fino a quando non avranno finalizzato le loro decisioni.

È difficile da fare, ma il creep di portata delle caratteristiche è così distruttivo di tempo, energia, motivazione e pensiero chiaro.


0

Da una prospettiva completa del progetto:

Impara dal codice con il tuo team, vedi cosa può essere refactored e riutilizzato la prossima volta, quindi vai a bere una birra.

Dal punto di vista dello sviluppo:

Spiega pazientemente perché lo sviluppo si è fermato e spiega perché non può continuare fino a quando tutte le specifiche sono sul tavolo e capite. Quindi vai a bere una birra.

Dal punto di vista della pianificazione:

Richiedi tutte le specifiche in anticipo e lavora con tutti per avere una chiara comprensione del percorso di sviluppo. Coinvolgi il cliente / le parti interessate il più vicino possibile per assicurarti che tutti siano sulla stessa pagina. Più tardi quella sera, prendi tutte le birre. Domani inizia il progetto.

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.