Come si fa a passare un programma da in-development a release?

67

Ad un certo punto un programma è in fase di sviluppo. Le funzioni vengono aggiunte o rimosse o modificate continuamente. Ogni versione non è altro che un prototipo. Quindi non spreco molto tempo a scrivere codice super pulito a quel punto perché non so mai per quanto tempo duri qualcosa. Certo che cerco di mantenere la qualità del codice su determinati standard, ma il tempo è sempre un problema.

Poi arriva il punto in cui il programma è finito e il / i decisore / i dire / e "è così". A questo punto ho un prototipo funzionante, ma il codice all'interno è un po 'disordinato da tutto il back and forth durante la fase di sviluppo. Dovrei iniziare a testare / eseguire il debug finale ma il mio istinto dice che ora dovrei pulire e / o riscrivere le cose per dargli un'architettura corretta che faciliti la manutenzione ecc.

Una volta che le cose sono state testate e approvate, allora non ha senso riscriverle. Mi trovo regolarmente con un prototipo "finito" funzionante e ottengo un bug durante i test e vedo che è il risultato di una codifica non intelligente che è il risultato dell'intero processo di sviluppo. Sono nel bel mezzo dei test e il bugfix sarebbe una riscrittura ... è un casino!

Ci sono modi migliori / da manuale, ne sono sicuro. Ma devo lavorare in un ambiente di lavoro reale dove non tutto è un libro di testo.

Quindi, come faccio a passare il mio prototipo funzionante a una versione di rilascio con una base di codice stabile? Forse non dovrei considerare lo sviluppo finito una volta che lo faccio e in effetti lo vedo come la fase di pulizia ... Non lo so, ho bisogno di aiuto qui.

Modifica

Voglio chiarire alcune cose.

  • Sono al 100% dalla parte di farlo subito prima e non dopo, codice pulito e leggibile. Ma devo anche fare le cose e non posso sognare la bellezza del codice tutto pulito e brillante. Devo trovare un compromesso.

  • spesso una nuova funzionalità è in realtà solo qualcosa che vogliamo provare e vedere se ha senso implementare qualcosa di simile. (specialmente nelle app mobili, per avere un aspetto reale su un dispositivo reale) Quindi è qualcosa di piccolo che (imho) non giustifica troppo lavoro in una prima iterazione "vediamo". Tuttavia a volte sorge la domanda QUANDO pago questo tech.debt? Ecco di cosa tratta questa domanda.

Se so che metà delle funzionalità verrà eliminata un giorno dopo (abbastanza esperienza nella nostra azienda ormai), trovo davvero difficile credere che il modo migliore per affrontare il mio problema sia quello di investire ancora tempo in più per scrivere tutto pulito anche se la maggior parte di essa verrà eliminata poco dopo. Mi sembra di risparmiare tempo se faccio una grande pulizia una volta che la cosa è solida, quindi la mia domanda.

    
posta NikkyD 09.03.2016 - 13:55
fonte

7 risposte

98

So I don't waste much time on writing super clean code at that point because I never know how long something lasts.

Non sapendo quanto durerà qualcosa non dovrebbe mai essere una scusa per la sciatteria, anzi. Il codice più pulito è IMHO quello che non ti viene in mente quando devi cambiare qualcosa. Quindi la mia raccomandazione è: cerca sempre di scrivere il codice più pulito che puoi - specialmente durante la codifica di un prototipo. Perché sarà molto più facile adattarlo quando qualcosa deve essere cambiato (cosa che sicuramente accadrà).

Non fraintendermi - la mia comprensione del "codice più pulito" non ha nulla a che fare con la creazione di codice bello per bellezza. Questo è davvero qualcosa che può rallentare. Dal mio punto di vista, il codice pulito è un codice che è principalmente auto-esplicativo (non c'è bisogno di scrivere così tanti documenti - causa l'accelerazione), facile da capire (meno errori, quindi meno debug necessari - velocità, meno tempo necessario per trovare il corretto posto per alterare - velocizzare), risolve il problema dato con la minor quantità di codice necessario (meno codice per eseguire il debug - evidente velocità), è DRY (solo un posto dove cambiare quando qualcosa deve essere cambiato - accelerazione - e meno rischi per introdurre nuovi bug dimenticando di cambiare un secondo posto), segue gli standard di codifica (cose meno ingombranti a cui pensare - accelerazione), utilizza piccoli elementi di costruzione riutilizzabili (che possono essere riutilizzati per molte funzionalità o addirittura prototipi - accelerazione), e così via.

I am expected to start testing/final debugging but my gut says I should now somehow clean up and or rewrite stuff to give it proper architecture that makes maintenance etc easier

In seguito "pulizia" non funziona mai. Considera di ripulire prima di implementare una nuova funzione o di iniziare a implementarla, ma non in seguito. Ad esempio, ogni volta che si inizia a toccare un metodo per una funzione e si nota che dura più di 10 righe, prendere in considerazione il refactoring in metodi più piccoli - immediatamente , prima di completare la funzione. Ogni volta che rilevi una variabile o un nome di funzione esistente non sai esattamente cosa significhi, scopri a cosa serve e rinomina la cosa prima facendo qualsiasi altra cosa. Se lo fai regolarmente, mantieni il tuo codice almeno in uno stato "abbastanza pulito". E tu inizi a risparmiare tempo perché hai bisogno di molto meno tempo per il debug.

I am in the middle of testing and the bug fix would be a rewrite

... che è la prova effettiva di ciò che ho scritto sopra: essere "sporchi" ti perseguita immediatamente quando inizi a eseguire il debug del tuo codice e ti renderai più lento.

Puoi evitarlo quasi completamente se esegui immediatamente la pulizia. Quindi correzioni di bug significheranno per lo più piccole modifiche al codice, ma mai un cambiamento architettonico importante. Se rilevi davvero prove per un miglioramento dell'architettura durante i test, ritarda la procedura, inseriscila nel tuo sistema di tracciamento dei problemi e implementala la prossima volta che devi implementare una funzionalità che benefici di tale modifica ( prima tu inizia con quella funzione).

Questo richiede un po 'di disciplina e, naturalmente, un'esperienza di programmazione. È un'idea simile all'idea alla base dello "sviluppo guidato da test", che fa queste cose in anticipo invece di farle successivamente (anche TDD può aiutare, ma ciò che ho scritto funziona anche quando non si usa TDD). Quando lo fai di conseguenza, non avrai bisogno di alcuna speciale "fase di pulizia" prima di rilasciarlo.

    
risposta data 09.03.2016 - 14:32
fonte
22

Hai due problemi separati, entrambi con lo stesso sintomo (codice sciatto):

Problema 1: controllo dei requisiti insufficiente Non voglio dire che i tuoi stakeholder cambiano troppo spesso le tue esigenze, voglio dire che stai permettendo modifiche ai requisiti durante un bugfix / ciclo di test. Persino le metodologie agili non lo supportano; costruisci, collaudi, consegni, immetti nuovi requisiti.

Problema n. 2: ritieni che le cose che stai scrivendo siano "solo per ora" Nello sviluppo del software "just for now" il codice è davvero estremamente raro. Ti sei accorto che una volta soddisfatto un requisito dell'utente, i rigori della domanda e dell'offerta rendono molto difficile giustificare il ritorno e la riattivazione di una funzionalità "completata". Quindi, cosa fare a riguardo? Scrivi sempre codice di produzione. Funzionalmente per te, significa che le tue stime per i tuoi stakeholder devono essere sostanzialmente più grandi in modo da avere un po 'di tempo per farlo nel modo giusto.

Inoltre, ti preghiamo di comprendere che stai lavorando nella posizione più difficile come sviluppatore: Leggi Joel Spolsky di assumere la vita di uno sviluppatore interno . Quindi, devi essere più vigile se vuoi mantenere intatto il tuo equilibrio mentale.

    
risposta data 09.03.2016 - 18:23
fonte
21

Si tratta di un problema comune, specialmente quando si crea essenzialmente un fumetto di prova .

Esistono numerosi approcci che possono aiutare. In primo luogo, l'approccio TDD può aiutare a ridurre la base del codice a quella strettamente necessaria. Se i tuoi test vanno di pari passo con il tuo codice, puoi avere almeno una certa sicurezza che il tuo codice si comporta come dovrebbe.

Dedica tempo al refactoring mentre vai. Una volta che hai un prototipo e il cliente è super-desideroso di metterlo tra le mani, è difficile vendere per dire che hai bisogno di tempo per lucidare ciò che (per loro) è completo. Mi piace fare il check-in tutti i giorni seguito da un refactoring ma YMMV.

Gli sviluppatori che scrivono codice velocemente sono spesso richiesti - abbiamo avuto un tale sviluppatore nel mio ultimo dipartimento. Ogni squadra lo voleva perché lavorava in maniera super veloce. Una volta giunto il momento di testare e rilasciare il suo codice, tuttavia, le ruote si staccarono rapidamente. Roba codificata, hack e scorciatoie ovunque. Le sue azioni presto caddero - in modo massiccio.

Tagliare il codice di produzione dall'inizio può sembrare un trascinamento ma, a seconda dell'ambiente, ci sono molti strumenti che possono eliminare lo sviluppo come Ghostdoc e Stylecop .

Vale la pena entrare nella giusta mentalità di sviluppo sin dall'inizio. Sareste sorpresi dal fatto che molti sistemi back-of-a-fag-pack che dovevano essere solo soluzioni stop-gap diventino applicazioni cardine.

    
risposta data 09.03.2016 - 14:29
fonte
11

continua

La velocità di sviluppo è la ragione principale per scrivere codice pulito, leggibile e verificabile; non è fatto per la bellezza, né altri valori astratti. Perché dovrei negarlo a me stesso e farlo solo in seguito per qualche futuro programmatore?

Certo potrebbero esserci dei cambiamenti che sono per lo più cosmetici e quindi non essenziali; Direi che è molto più utile avere un codice moderatamente bello in questo momento, durante lo sviluppo, piuttosto che avere un pasticcio adesso e sperare di renderlo perfetto in seguito (il che, ammettiamolo, non accadrà mai, anche se tu avessi l'ora).

    
risposta data 10.03.2016 - 11:14
fonte
4

Lo fai differenziando tra "Sto solo provando questo per vedere come funziona" codice e "questo è diretto nel codice del prodotto". Ci sono diversi modi per farlo.

Uno è ramificato o qualunque sia la parola nel tuo sistema di controllo del codice sorgente. Si crea un ramo per il nuovo report o il nuovo layout di importazione o altro. Se le persone lo apprezzano, il compito di riportarlo nel ramo principale è un lavoro separato e tracciabile. Può essere assegnato a qualcuno e segnalato e non è previsto che si verifichi semplicemente in modo magicamente il giorno in cui la gestione (o le vendite) concorda che la funzione appartiene al prodotto.

Un altro è picchi. Non si fa questo cambiamento nel prodotto. Vai in qualche app separata, super semplice, che esiste solo per te per avere un posto dove mettere il codice. Puoi essere disordinato quanto vuoi perché stai semplicemente esplorando la nuova API o qualsiasi altra cosa. E ancora, se torni a riferire "sì, possiamo farlo, ho capito come" c'è un compito tracciabile, referibile, assegnabile di scrivere codice pronto per il prodotto nel prodotto per fare ciò che vuoi.

In entrambi i casi, i prodotti pronti per l'uso sono leggibili, ordinati, seguono gli standard di denominazione, con i test e aderiscono allo stile del codice e agli obiettivi prestazionali. In entrambi i casi, rendi visibile quel lavoro. Sono d'accordo sul fatto che non si vuole fare tutto ciò che funziona ogni volta che qualcuno è in grado di strappare la funzionalità dal prodotto. Ma non vuoi lasciare che quel lavoro diventi invisibile. Lavorare in copie separate del prodotto o in un prodotto non correlato che è appena più di un'imbracatura di prova consente di far emergere il lavoro per creare codice pronto per il prodotto quando qualcuno decide di volere qualcosa.

Il rovescio della medaglia è che non possono decidere di volere qualcosa e spedirlo (ovvero la semi-assediata, disordinata, non testata, non documentata, possibilmente lenta semiautomatica che hai implementato come prova del concetto) domani. La prima volta che si ottiene un respingimento su questo fronte, è sufficiente chiedere se si dovrebbe fare il lungo (più costoso) modo ogni volta nel caso in cui, rallentando il percorso verso le funzionalità rifiutate. Se chiedi correttamente, riceverai un "no".

    
risposta data 10.03.2016 - 23:00
fonte
1

Credo davvero che tu capisca il problema già. Il problema è che il tuo stile di codifica richiede che tu esegua troppe rilavorazioni. Il motivo per cui è necessario troppe rilavorazioni è perché (a) è combinato con previsione e pianificazione insufficienti e (b) le patch incrementali a breve termine regolarmente inserite durante lo sviluppo combinatoricalmente aumentano la complessità di qualsiasi rielaborazione richiesta.

La risposta quindi è

(a) sposta il tuo stile di sviluppo un po 'più verso la cascata e un po' meno agile. Non andare fino in fondo, perché la cascata classica ha le sue insidie. C'è un equilibrio sano da avere. So che può riguardare solo il pensare a qualcosa per qualche giorno, a volte, come se nessuno sviluppo venisse fatto, ma devi fidarti del processo. Nel settore dell'ingegneria non si possono solo inchiodare le cose e quindi inchiodare le cose e sperare di ottenere una soluzione elegante. Se non c'è nessuno che fa architettura e progettazione tecnica di livello superiore, significa che è il tuo lavoro. Hai pagato il prezzo di trascurare quel lavoro.

(b) cerca di evitare di aggiustare le cose. Non pensare a lungo termine solo quando arriva il momento di fare QA. Davvero dovresti testare ogni piccolo pezzo che costruisci, sempre e coprendo tutti i casi di input, anche quelli che non sono sul sentiero felice. Una patch / hack è quasi per definizione una correzione a breve termine, che potrebbe avere un costo a lungo termine, colpisce il costo totale di proprietà del cliente nel sistema. Ancora una volta, la pressione è su per ottenere il codice, quindi ci deve essere equilibrio. Ma prova a non mettere a posto correzioni a breve termine, esp. quelli che accoppiano strettamente componenti che dovrebbero essere accoppiati liberamente. Ci sarà un ri-lavoro, quindi fai in modo PRECEDENTE per renderlo molto più facile, per evitare gli hack e le patch che si accumuleranno nel tempo e diventeranno ingestibili.

    
risposta data 09.03.2016 - 16:35
fonte
0

Scrivi:

Every version is nothing but a prototype. So I don't waste much time on writing super clean code at that point because I never know how long something lasts. ...

Then comes the point where the program is finished and the decision maker(s) say "that's it". I do have a working prototype at this point, but the code inside is a bit messy from all the back and forth during the development phase.

Una versione verificata può essere un "prototipo" in quanto manca funzionalità o alcune funzionalità non sono arricchite, ma tutto il codice archiviato dovrebbe essere un codice di qualità di produzione che non ha bisogno di essere ripulito.

Penso che stai rimandando la tua "pulizia" a molto.

La mia regola empirica è:

  • Inizia con (sotto) funzione
  • sentiti libero di scrivere cose incomplete e incomplete, magari qualche c & p per avere un'idea di ciò che sto implementando o se devo grattare l'ultima ora o le ore di codifica (nota che questo può vanno di pari passo con TDD / test, è solo che tutto si attenua un po 'per ottenere un rapido riscontro dello spazio di implementazione che sto esplorando)
  • La funzione secondaria "funziona" abbastanza bene per ora
  • Ora effettua la pulizia: prima di un commit SCC .
    • Guarda il codice per vedere cosa è ovvio
    • Esegui un commit diff contro l'ultimo per rivedere le modifiche e forse rilevare alcuni problemi
    • Correggere le cose che ho annotato sul mio scratchpad
  • Ora eseguo il commit - questa qualità del codice è pronta per essere spedita

A questo punto, il codice impegnato potrebbe ancora contenere alcuni workaround o "debito tecnico" che sarebbe bello ripulire, e forse lo pulirò quando è la cosa naturale da fare per una seguente sotto-funzionalità , ma sarà OK se quel codice è rilasciato così com'è.

    
risposta data 10.03.2016 - 01:25
fonte

Leggi altre domande sui tag