Il refactoring dovrebbe essere l'eccezione o la regola? [chiuso]

1

Ho avuto una discussione con un collega ieri sulla filosofia del design. L'altro programmatore è più esperto di me, e ammetto pienamente che probabilmente è molto più bravo a automatizzare correttamente i suoi test, che sto solo cercando di rompere con le abitudini sbagliate. Tuttavia, sembra che alcune delle nostre controversie siano questioni filosofiche in cui non sono disposto a cedere semplicemente alla sua maggiore esperienza.

Generalmente è un programmatore regista, che segue tutti gli approcci formali. Ha interfacce per quasi tutte le classi e ha eseguito test automatici per tutto fino a getter e setter su oggetti POJO di base. Vede il refactoring come una parolaccia che è un segnale che le cose non sono state scritte / progettate correttamente dall'inizio, è inevitabile e fatto come necessario ma tutto dovrebbe essere fatto per evitare di doverlo fare e dovresti sentirti male quando devi .

Sento di essere un programmatore più flessibile / abilitante. Ritengo che le interfacce debbano essere utilizzate come necessario, ma non lanciate fino a quando non sono necessarie (KISS), e che è abbastanza facile estrarre un'interfaccia da un oggetto esistente mediante refactoring se si decide che un'interfaccia / polimorfismo ha più senso in seguito. Sentivo anche che, mentre ammetto che devo essere più bravo a fare i test, al momento, il livello dei test automatici che ha suggerito sembravano troppo rigidi poiché ci sarebbe voluto così tanto tempo per implementare e, cosa più importante, rendere il refactoring un incubo dato che non avrei essere liberi di modificare il comportamento di qualsiasi metodo non privato. Man mano che le mie esigenze crescono e cambiano, mi ritrovo a dover eseguire pesantemente il refactoring e quel livello di test sembra che possa uccidere la mia flessibilità. Il suo punto di vista è che non dovrei essere refactoring, quindi non importa se i test lo rendono più difficile da fare.

In definitiva tutte le altre discussioni filosofiche sembravano ridursi alla parola "refactoring". Adoro il refactoring, penso che dovrebbe essere usato liberamente ogni volta che senti che qualcosa non è così pulito e bello come dovrebbe essere, e che il corso naturale per far crescere un programma o aggiungere nuovi requisiti richiederà il refactoring per abilitare meglio il codice riutilizzare, spostare la logica verso nuove classi / pacchetti man mano che diventa più complessa, e sì fissando gli inevitabili errori di progettazione che avverranno da un approccio flessibile allo sviluppo agile (e non è sempre male se il tuo codice è scritto per consentire modifiche!). Non è d'accordo con tutto ciò.

Mi chiedo quali sono i pensieri degli altri sul refactoring. Quanto comune dovrebbe essere? Scrivere codice con una filosofia di "Lo sto facendo in modo semplice ora, posso rifattenerlo in seguito se la logica più complicata si rivela necessaria" intrinsecamente imperfetta / pericolosa? L'accettabilità del refactoring dipende dall'approccio e dallo stile del programma? Generalmente sono sulla prototipazione rapida o "ripulisci questo brutto, ma lavorando, prototipo di alcuni non-ingegneri hanno scritto", mentre sembra che possa effettivamente fare una programmazione formale con requisiti ufficiali che non cambiano; Non ho mai avuto un lavoro del genere nemmeno io!

    
posta dsollen 09.04.2014 - 15:26
fonte

4 risposte

4

Penso che la risposta risieda tra voi due.

Le modifiche devono essere previste mentre il software si evolve. Non importa quanto sei competente, non puoi prevedere il futuro con una precisione del 100%. E anche se fosse possibile, potrebbe non corrispondere alle previsioni o al gusto del cliente. Dal momento che è lui a pagare (più sfortunatamente :)) ha voce in capitolo. Quindi, a meno che non sia semplice, è quasi impossibile progettare un'applicazione con tutto nel posto giusto fin dal primo giorno.

D'altra parte, hai ancora la responsabilità di essere, in ogni momento, il più vicino possibile a quello. Devi pianificare e pensare in anticipo ai requisiti in modo che sia meno probabile dipingerti in un angolo e rendere quasi impossibile che il tuo codice si adatti alle nuove esigenze (e credici, sarà richieste).

Quindi, mentre sono pienamente d'accordo con te sul fatto che il refactoring è una cosa grandiosa da fare ogni volta che senti che le cose potrebbero andare meglio, chiamarla una "regola" non mi sembra del tutto giusta. Se il codice di refactoring è qualcosa che fai quotidianamente, allora chiaramente qualcosa non va nel modo in cui stai codificando le tue app.

Su questa domanda:

Is writing code with a philosophy of "I'm doing it simple now, I can refactor
it later if more complicated logic proves necessary" inherently flawed/dangerous?

Se ti aspetti - o anche solo sospetti - alla fine sarà necessaria una logica più complicata, la risposta è sicuramente sì. In caso contrario, dipende davvero dall'utilità del codice, dalla profondità della tua app, dalle scadenze del progetto e, cosa forse più importante, dal buon senso.

Se il tuo cliente è un laboratorio di biciclette nel Wisconsin è molto improbabile che abbia bisogno di un'app che supporti i numeri di telefono internazionali. Pertanto è ragionevole progettare una classe PhoneNumber che sia in realtà un codice area di tre cifre e un numero di sette cifre. Nel caso improbabile che diventi necessario per i tuoi clienti memorizzare dati sui motociclisti francesi, il refactoring potrebbe essere utile.

Questo è ovviamente solo un esempio ma ti viene l'idea: mentre all'inizio potrebbe avere senso scrivere codice piuttosto semplice, con il passare del tempo e le modifiche dei requisiti potresti scoprire che il modo in cui la tua applicazione si basa su di esso potrebbe essere un problema. Questo è il tipo di scenario che dovresti normalmente cercare di evitare, ma a meno che tu non sia Dio, non sarai in grado di evitarli tutti. A volte non sarà nemmeno colpa tua; i clienti del software tendono ad essere molto fantasiosi quando si tratta di trasformare un'applicazione di gestione di officine di biciclette in un sistema di ordinazione di pizza.

In ogni caso, dovresti comunque scrivere sempre il codice nel modo in cui pensi che dovrebbe essere al momento del rilascio. Pensa al refactoring come un modo per sistemare le cose su cui hai fatto supposizioni sbagliate.

    
risposta data 09.04.2014 - 15:51
fonte
4

Abbraccia il refactoring. Abbraccia il fatto che puoi creare codice che funziona, e hai dei test che lo fanno funzionare, e poi puoi cambiare gli interni avendo fiducia che non stai infrangendo nulla. E come dici, KISS.

Riguardo alla visione di non aver scritto / progettato correttamente dall'inizio, per me la risposta è che non ho lavorato in un progetto in cui non ci sono stati cambiamenti ad un certo punto (o piuttosto, molto spesso). Anche se qualcuno ha trascorso un mese a "progettare" la soluzione. Cambiamenti che introducono la duplicazione, che introducono la generalizzazione, che introducono nuovi casi d'uso. Per tutti loro dovrai refactoring.

Anche se stai scrivendo una soluzione completamente "progettata", scoprirai che c'è un codice duplicato, che ci sono generalizzazioni non prese in considerazione. La codifica sta progettando e finché non hai terminato la codifica, non hai terminato la progettazione.

Un'altra cosa da aggiungere: YAGNI .

    
risposta data 09.04.2014 - 16:00
fonte
1

Tutto si riduce a chi scrive codice migliore relativamente alla quantità di tempo. La tua azienda / squadra dovrebbe definire cosa significa "meglio". Anche i clienti hanno qualcosa da dire su questo.

Assicurati di avere una definizione solida di Refactoring. Sembra che tu lo faccia, ma lo menzioni insieme ai cambiamenti comportamentali del codice molto vicini tra loro nella tua domanda. Stai attento. Voi due non potete mantenere questo dibattito se non siete d'accordo sulla definizione.

Fuori da tutto ciò che voi due state reclamando, il problema più grande è la sua affermazione di essere in grado di scrivere codice in modo corretto nella "prima" volta. Questo si verifica quando il codice viene registrato per la prima volta o prima che entri in produzione? Ovviamente la successiva ti dà un po 'più di tempo per sistemare le cose. Forse ha lavorato su questo particolare progetto per così tanto tempo che è in grado di farlo perché comprende il codice e le persone che chiedono funzionalità. Potrebbe essere aggiunto un nuovo PM che non crea una descrizione dettagliata delle specifiche o potrebbe non comprendere il dominio tanto quanto quello attuale. Il tuo metodo potrebbe renderti più adattabile.

Prende una quantità sproporzionata di tempo per raggiungere lo stesso obiettivo con un minor numero di bug / necessità di migliorare? Il codice può essere migliorato in una certa misura per sempre, ma viene spedito un codice veramente buono. Introduci più bug nel sistema? Gli utenti vogliono presto nuove funzionalità e correzioni, ma c'è un punto in cui si sentono troppo frustrati da troppi bug che spuntano troppo spesso. Ogni volta che aggiorniamo ...

I tuoi argomenti filosofici sono solo preferenze personali finché non puoi determinare chi è lo sviluppatore più efficace . Il tuo programmatore Direttivo sarebbe in grado di farlo su un nuovo progetto? Stai usando "Posso rifattorizzarlo più tardi" come una stampella?

    
risposta data 09.04.2014 - 15:51
fonte
0

Direi l'eccezione.

Ogni volta che fai refactoring, stai sostanzialmente cambiando il modo in cui appare il codice piuttosto che come funziona (ad esempio puoi estrarre un blocco di codice in un metodo o cambiare un passaggio in una chiamata di funzione polimorfica, in tutti i casi la funzionalità non è cambiata, l'hai appena modificata).

Ora, mentre ciò può essere utile per rendere il codice più facile da mantenere o capire, sta comunque apportando grandi cambiamenti che influenzeranno davvero il modo in cui il codice viene visualizzato nei registri di controllo del codice sorgente. Non puoi ora guardare le differenze e vedere un bug a causa di un cambio di codice, poiché il codice è radicalmente diverso. È lo stesso problema quando si modifica l'aspetto del codice perché si desidera ottimizzarlo (ad esempio, modificare le posizioni di controvento o rinominare le variabili).

Quindi il refactoring dovrebbe essere davvero conservato per i casi in cui è veramente utile, solo così puoi tenere a mente cosa fa il codice. Lavoravo con un ragazzo che ha cambiato il codice in modo drammatico - sarei entrato dopo un weekend e ho scoperto che il codice base era praticamente un prodotto diverso. Ha reso il lavoro estremamente difficile, dato che ho dovuto prendermi il tempo per capire dove fossero andati a finire i pezzi che conoscevo.

C'è anche la sensazione che il refactoring sia abusato al giorno d'oggi, la sensazione che i programmatori debbano incidere qualcosa che funzioni rapidamente, e poi riordinarlo per renderlo più bello più tardi (o anche solo rimetterlo in ordine mentre lo fai). Penso che questa sia una cattiva pratica. Dovresti pensare a cosa stai cercando di ottenere prima di farlo. Se questo è stato fatto prima, non dovresti aver bisogno di un refactoring. Nei vecchi tempi in cui il design-first era molto più diffuso, il refactoring era usato esclusivamente per il codice legacy, mai per il lavoro quotidiano.

Ne conosco uno però - 'la bellezza è negli occhi di chi guarda'. Puoi fare il refactoring per far sembrare le cose più belle, ma poi qualcun altro può venire di nuovo e refactoring di nuovo per renderlo bello per loro (nel libro di Fowler Refactoring ci sono dei refactoring che sono degli opposti!). Non ti fermerai mai, passerai tutto il codice di refactoring per tutto il giorno e nessuno in realtà scriverà le caratteristiche del prodotto.

    
risposta data 09.04.2014 - 15:51
fonte

Leggi altre domande sui tag