Quando dovresti riscrivere? [duplicare]

17

Nel famoso (o famigerato) articolo di Joel Spolsky Thins che non dovresti mai fare, parte I , egli fa il caso che fare una riscrittura è sempre una mossa sbagliata perché:

  1. Ti mette automaticamente dietro (i tuoi concorrenti / programma / ecc.)
  2. Probabilmente il codice non è così male come credono i programmatori (tutto ciò che qualcun altro ha scritto è sempre un casino, anche se alcuni sono pasticci più grandi di altri - e anche allora)
  3. Probabilmente è più facile / più veloce / meno costoso risolvere ciò che c'è di veramente sbagliato in esso che riscrivere da zero.
  4. Nella riscrittura da zero, probabilmente stai per reintrodurre bug corretti nelle versioni precedenti del codice originale.

Invece, consiglia di correggere cosa c'è di sbagliato nel codice.

Presumo che questo sia un buon riassunto del suo post, e postulerò che è generalmente vero.

Sto cercando di raccogliere un insieme di regole / linee guida per il mio team, e uno di questi (basato sull'articolo di Joel) è

We don’t re-write ... ever! 
- But we can refactor large portions of the code.
  (this exception takes care of ugly/problematic code issues)

Una domanda che è saltata fuori è "Che dire di quando la tecnologia cambia e non puoi più ottenere il supporto per le versioni precedenti?". Questo è quello che penso come Sisyphean Upgrade path.

Ad esempio, ricordo quando Oracle si è trasferito da SQL * Forms 2.x / 3.x a Forms 6i e oltre, Forms che erano originariamente sviluppati nel vecchio formato .inp non erano più supportati con la versione corrente di Oracle e Oracle Forms.

Quindi hai avuto la possibilità di attaccare un database non supportato con strumenti non supportati o di riscrivere i moduli da zero (o convertiti con strumenti di terze parti e poi ripassati con un pettine a denti fini). Che chiamerò porting, in particolare quando si esegue una riga fedele per riga / funzione per traduzione di funzione nella nuova tecnologia e non si aggiunge alcuna funzionalità.

La regola è diventata:

We don’t re-write ... ever!
- But we can refactor large portions of the code.
- And we can port the code to a new platform when we *truly* have no other 
  choice.

(e in realtà voglio dire, non puoi nemmeno comprare la tua via d'uscita dal problema per 2 volte il costo del porting)

Ci sono altre eccezioni che mi sono perse?

    
posta BIBD 12.08.2011 - 20:41
fonte

5 risposte

14

Come per qualsiasi affermazione dura e veloce che Joel Spolsky sputa fuori ...

Non dovresti prenderlo alla lettera!

Gli piace dipingere un argomento drammatico per un problema comune e una situazione comune, ma come qualsiasi cosa nel mondo reale c'è sempre quell'area grigia, non importa quanto piccola.

Intende convincere la gente a pensare e a creare un'avversione per essere "riscritta felice" che sono completamente d'accordo. Il 95% delle situazioni di riscrittura non lo giustifica, ma ovviamente avrai questo caso eccezionale in cui "il nostro cliente si sta spostando su server Linux e non installerà Mono. Dovremmo riscrivere questa app .NET in qualche altra tecnologia. "

Il fatto che ciò che ha detto ti abbia preoccupato abbastanza da pubblicare una domanda significa che fa bene il suo lavoro. Ti ha fatto pensare e questo è il suo obiettivo finale, credo.

    
risposta data 12.08.2011 - 21:30
fonte
11

La mia vista è questa: dovresti riscrivere quando sarebbe più facile iniziare da zero che a refactoring. Ad esempio, se lo sforzo di refactoring implicherebbe mesi di retrofitting del codice OOP proceduralmente scritto all'OPO corretto prima ancora di poter iniziare a rifattorizzare il codice, allora una riscrittura è l'opzione migliore perché devi cambiare < em> tutto . Un altro esempio potrebbe essere se non ci sono test unitari e l'infrastruttura non supporta il test delle unità (cioè codice strettamente accoppiato, nessuna separazione dei problemi), non è possibile iniziare a rifattorizzare il codice senza una suite di test, ma la creazione della suite di test richiede prendendo il coraggio dell'applicazione e apportando alcune modifiche piuttosto serie per consentire la creazione di tali test in primo luogo. È un ciclo infinito, di tipo: non puoi refactoring senza i test, ma i test non possono esistere senza refactoring.

Non sono d'accordo con veemenza sull'articolo di Joel sulla riscrittura, perché sono stato in molte situazioni in cui un serio refactoring non può accadere perché letteralmente NOTHING è fatto correttamente per supportare il refactoring a tutti. In una situazione come questa, le scelte sono spesso: 1) Riscrivi l'applicazione, oppure 2) Non toccare nulla e continua a far scorrere il codice.

Dovresti anche prendere in considerazione una riscrittura quando devi introdurre alcune modifiche architettoniche del codice che non possono essere adattate, di nuovo l'esempio per eccellenza potrebbe funzionare su un'app che è stata lanciata insieme senza virgola o motivo, nessun test unitario , nessuna separazione, SQL codificato, numeri magici ovunque ... hai un'idea. Cercare di cambiare una bestia del genere è come Sisyphus che cerca di spingere il masso, soprattutto se vuoi introdurre concetti di progettazione appropriati come SOLID, o introdurre un ORM appropriato, o dire di passare a ASP.NET MVC quando tutto è WebForm con tutta la logica in code-code ad esso.

Per rimanere con l'intero tema del "debito tecnico", ho esposto questo:

Refactoring sta attraversando un consolidamento (tecnico) del debito e lentamente restituendo il debito per un periodo di tempo (solitamente lungo).

Riscrivere è una bancarotta (tecnica).

Proprio come nelle finanze reali, a volte il tuo debito è così grande che la bancarotta è la migliore (se non la sola) opzione per cancellare tutto pulito e ricominciare da capo, a patto di non ripetere gli stessi errori.

    
risposta data 12.08.2011 - 21:35
fonte
3

Probabilmente ... ma

Ci sono probabilmente ulteriori eccezioni - ad un certo punto "refactoring su larga scala" e "riscrittura" sono indistinguibili - quando cambia ogni riga di codice!

Ma quello che mi chiedo è: qual è lo scopo di creare regole rigide per situazioni che devi ancora incontrare? L'esempio di Joel era un caso estremo (NetScape) non comune Astuccio. Se hai una progettazione sbagliata o hai superato l'architettura o cambiato piattaforme e altri, riscrivere potrebbe essere un'opzione valida. Se la tua squadra non arriva mai a quel punto, allora il dibattito sulle regole è uno spreco di respiro. Quando arrivi a quel punto, la situazione potrebbe essere così diversa che le regole combattute con cui ti trovi oggi non si applicano più.

    
risposta data 12.08.2011 - 20:58
fonte
3

Ho letto il suo articolo, e 1,2 e 4 sono buoni punti, ma 3 è un argomento circolare. Inoltre, i suoi esempi di codice non sono nemmeno close per il codice peggiore che ho visto. Sicuramente, a un certo punto, ci deve essere un codice che riscrive da zero? Una cosa è dire che non farlo mai, ma sarebbe più utile cercare di trovare un modo per decidere in modo ragionevole dove tracciare la linea.

Che cosa succede se qualcuno vuole aggiornare uno stack software obsoleto che utilizza file invece di un database, è scritto in una lingua privata con un compilatore buggy personalizzato in COBOL, non ha commenti, non ha test di alcun tipo e non usa nient'altro che GOTO per flusso di controllo e variabili globali per lo stato, ed è un'intera applicazione aziendale in un livello con tutto dipende da tutto il resto (ma gli utenti lo adorano)? Ci sto riuscendo, ma in quella situazione, sarebbe davvero più economico sistemare che riscrivere?

Penso che il punto numero 3, sia più economico ricominciare da capo a riparare (compreso qualsiasi porting), è il punto chiave. Nel tuo caso, se una porta linea per riga non funzionasse, forse potresti ammettere la tua riscrittura e pianificare di conseguenza.

    
risposta data 12.08.2011 - 21:16
fonte
2

Se il tuo progetto si trasforma in spaghetti non mantenibili (problema comune con un programmatore singolo / piccoli progetti di code-base) e sei ancora all'inizio del progetto (o la parte interessata è abbastanza piccola) è meglio eliminare la spazzatura e riavviare

ma è praticamente l'unica ragione per cui dovresti riscrivere

e quando inizi a riscrivere fai un piano chiaro su quale sarà il nuovo design e STICK TO IT, dovresti già avere un'idea di cosa è necessario e dove è andato male la prima volta e creare un disegno da quello senno di poi (mantieni vecchie segnalazioni di bug e ricrea le circostanze con il nuovo progetto coughunittestscough per correggere i bug di respawning

se vuoi ricreare un progetto precedente esistente come la prossima versione principale mantienilo come un progetto collaterale e mantenere attivo e supportato il progetto principale per un backup quando la riscrittura fallisce e spedisci solo la riscrittura quando soddisfa i requisiti che il vecchio ha raggiunto o lo getta quando fallisce; L'articolo di Joel menzionava che M $ provava a riscrivere la parola, ma non funzionava, ma mantenevano attivo il vecchio codice base, quindi andava bene oltre al tempo di sviluppo perduto.

    
risposta data 12.08.2011 - 21:27
fonte

Leggi altre domande sui tag