Ho ereditato 200.000 righe di codice spaghetti: e adesso?


470

Spero che questa non sia una domanda troppo generica; Potrei davvero usare alcuni consigli stagionati.

Sono appena assunto come unico "ingegnere SW" in una piccola bottega di scienziati che hanno trascorso gli ultimi 10-20 anni a mettere insieme una vasta base di codici. (È stato scritto in un linguaggio praticamente obsoleto: G2 - pensa a Pascal con la grafica). Il programma stesso è un modello fisico di un complesso impianto di trattamento chimico; il team che lo ha scritto ha una conoscenza del dominio incredibilmente profonda ma poca o nessuna formazione formale sui fondamenti della programmazione. Recentemente hanno imparato alcune lezioni difficili sulle conseguenze della gestione della configurazione inesistente. I loro sforzi di manutenzione sono inoltre fortemente ostacolati dal vasto accumulo di "fanghi" non documentati nel codice stesso. Ti risparmierò la "politica" della situazione (c'è sempre politica!), ma basti dire che non esiste un consenso di opinione su ciò che è necessario per il cammino da percorrere.

Mi hanno chiesto di iniziare a presentare al team alcuni dei principi dello sviluppo software moderno. Vogliono che introduca alcune delle pratiche e strategie standard del settore relative alle convenzioni di codifica, alla gestione del ciclo di vita, ai modelli di progettazione di alto livello e al controllo del codice sorgente. Francamente, è un compito abbastanza scoraggiante e non sono sicuro da dove cominciare.

Inizialmente, sono propenso a tutorarli in alcuni dei concetti centrali di The Pragmatic Programmer o Fowler's Refactoring ("Code Smells", ecc.). Spero anche di introdurre una serie di metodologie Agile. Ma alla fine, per essere efficace, penso che dovrò affinare su 5-7 fondamentali fondamentali; in altre parole, quali sono i principi o le pratiche più importanti che possono realisticamente iniziare ad implementare e che daranno loro il massimo "rapporto qualità-prezzo".

Ecco, questo è la mia domanda: Che cosa si includere nella vostra lista delle strategie più efficaci per contribuire a raddrizzare gli spaghetti (ed evitare che in futuro)?


124
Il libro di Michael Feather Funziona efficacemente con il codice legacy
MarkJ

13
Dato che G2 è come un non-codice, ma piuttosto un codice automatizzato scritto da una buona interfaccia grafica, penso che sia necessario specificare se si sta effettivamente eseguendo il refactoring in G2 o si sta rifando l'intera dannata cosa in qualcosa di sensato.
Erik Reppen,

101
Qualunque cosa tu faccia, non riscriverlo da zero. Sarebbe un grave errore. 20 anni di conoscenza chimica: sono cose che non potresti mai ricreare. E perderesti giustamente il rispetto da parte degli scienziati.
Francesco

13
Aggiungi il consiglio motivato di Joel Spolsky di non riscrivere il commento di @ Francesco: joelonsoftware.com/articles/fog0000000069.html .
Govert

16
Bella citazione che ho letto di recente che è in qualche modo correlata: "Il software è l'unico campo ingegneristico che riunisce i prototipi e quindi tenta di venderli come merce consegnata"
Chris S

Risposte:


466

Prefazione

Questo è davvero un compito scoraggiante, e c'è molto terreno da percorrere. Quindi sto umilmente suggerendo questo come una guida in qualche modo completa per il tuo team, con indicazioni su strumenti appropriati e materiale educativo.

Ricorda: queste sono linee guida e che come tali sono pensate per essere adottate, adattate o eliminate in base alle circostanze.

Attenzione: scaricare tutto questo in una squadra alla volta molto probabilmente fallirebbe. Dovresti provare a scegliere gli elementi che ti darebbero il miglior rapporto qualità-prezzo e presentarli lentamente, uno alla volta.

Nota: non tutto ciò si applica direttamente ai sistemi di programmazione visiva come G2. Per dettagli più specifici su come gestirli, vedere la sezione Addendum alla fine.


Riepilogo esecutivo per impaziente

  • Definire una struttura di progetto rigida , con:
    • modelli di progetto ,
    • convenzioni di codifica ,
    • sistemi di costruzione familiari ,
    • e serie di linee guida per l' utilizzo della tua infrastruttura e dei tuoi strumenti.
  • Installa un buon SCM e assicurati che sappiano come usarlo.
  • Indirizzali verso IDE validi per la loro tecnologia e assicurati che sappiano come utilizzarli.
  • Implementare controlli di qualità del codice e report automatici nel sistema di compilazione.
  • Associare il sistema di build a sistemi di integrazione continua e ispezione continua .
  • Con l'aiuto di quanto sopra, identificare "hotspot" di qualità del codice e refactor .

Ora per la versione lunga ... Attenzione, preparatevi!


La rigidità è (spesso) buona

Questa è un'opinione controversa, poiché la rigidità è spesso vista come una forza che lavora contro di te. È vero per alcune fasi di alcuni progetti. Ma una volta che lo vedi come un supporto strutturale, una struttura che toglie le congetture, riduce notevolmente la quantità di tempo e fatica sprecati. Fallo funzionare per te, non contro di te.

Rigidità = processo / procedura .

Lo sviluppo del software ha bisogno di buoni processi e procedure esattamente per le stesse ragioni per cui gli impianti o le fabbriche chimiche hanno manuali, procedure, esercitazioni e linee guida di emergenza: prevenire risultati negativi, aumentare la prevedibilità, massimizzare la produttività ...

La rigidità arriva con moderazione, però!

Rigidità della struttura del progetto

Se ogni progetto ha una sua struttura, tu (e i nuovi arrivati) siete persi e dovete riprenderli da capo ogni volta che li aprite. Non lo vuoi in un negozio di software professionale e nemmeno in un laboratorio.

Rigidità dei sistemi di costruzione

Se ogni progetto ha un aspetto diverso, ci sono buone probabilità che si costruiscano anche in modo diverso . Una build non dovrebbe richiedere troppe ricerche o troppe congetture. Si vuole essere in grado di fare la cosa canonica e non è necessario preoccuparsi di specifiche: configure; make install, ant, mvn install, ecc ...

Riutilizzare lo stesso sistema di build e farlo evolvere nel tempo garantisce anche un livello costante di qualità.

Hai bisogno di una rapida READMEindicazione delle specifiche del progetto e di guidare con garbo l'utente / sviluppatore / ricercatore, se presente.

Ciò facilita notevolmente anche altre parti della tua infrastruttura di costruzione, vale a dire:

Quindi mantieni aggiornato il tuo build (come i tuoi progetti), ma rendilo più rigoroso nel tempo e più efficiente nel segnalare violazioni e cattive pratiche.

Non reinventare la ruota e riutilizzare ciò che hai già fatto.

Lettura consigliata:

Rigidità nella scelta dei linguaggi di programmazione

Non puoi aspettarti, specialmente in un ambiente di ricerca, che tutti i team (e ancor meno tutti gli sviluppatori) utilizzino lo stesso linguaggio e lo stesso stack tecnologico. Tuttavia, è possibile identificare una serie di strumenti "supportati ufficialmente" e incoraggiarne l'uso. Il resto, senza una buona logica, non dovrebbe essere consentito (oltre alla prototipazione).

Mantieni il tuo stack tecnologico semplice e la manutenzione e l'ampiezza delle competenze richieste al minimo indispensabile: un nucleo forte.

Rigidità delle convenzioni e linee guida sulla codifica

Convenzioni e linee guida per la codifica sono ciò che ti consente di sviluppare sia un'identità di squadra, sia un linguaggio condiviso . Non vuoi sbagliare in terra incognita ogni volta che apri un file sorgente.

Norme insensate che rendono la vita più dura o vietano le azioni esplicitamente nella misura in cui i commessi vengono rifiutati sulla base di singole semplici violazioni sono un onere. Però:

  • un insieme di regole ben ponderato toglie molto al lamento e al pensiero: nessuno dovrebbe rompere in nessun caso;

  • e una serie di regole raccomandate fornisce ulteriori indicazioni.

Approccio personale: sono aggressivo quando si tratta di convenzioni di programmazione, alcuni addirittura dicono nazista , perché credo di avere una lingua franca , uno stile riconoscibile per la mia squadra. Quando il codice di merda viene registrato, si distingue come una ferita fredda sulla faccia di una stella di Hollywood: innesca automaticamente una recensione e un'azione. In effetti, a volte sono arrivato al punto di sostenere l'uso di hook pre-commit per rifiutare commit non conformi. Come accennato, non dovrebbe essere eccessivamente pazzo e ostacolare la produttività: dovrebbe guidarlo. Introducili lentamente, soprattutto all'inizio. Ma è preferibile spendere così tanto tempo a correggere il codice difettoso che non puoi lavorare su problemi reali.

Alcune lingue lo impongono persino in base alla progettazione:

  • Java aveva lo scopo di ridurre la quantità di schifezze noiose che puoi scrivere con esso (anche se senza dubbio molti riescono a farlo).
  • La struttura a blocchi di Python per rientro è un'altra idea in questo senso.

  • Vai, con il suo gofmtstrumento, che toglie completamente ogni dibattito e sforzo ( ed ego !! ) inerenti allo stile: corri gofmtprima di impegnarti.

Assicurati che il marciume del codice non possa scorrere. Convenzioni di codice , integrazione continua e ispezione continua , programmazione di coppie e revisioni del codice sono il tuo arsenale contro questo demone.

Inoltre, come vedrai di seguito, il codice è documentazione e questa è un'altra area in cui le convenzioni incoraggiano la leggibilità e la chiarezza.

Rigidità della documentazione

La documentazione va di pari passo con il codice. Il codice stesso è documentazione. Ma ci devono essere istruzioni chiare su come costruire, usare e mantenere le cose.

Utilizzare un unico punto di controllo per la documentazione (come un WikiWiki o un DMS) è una buona cosa. Crea spazi per progetti, spazi per battute e sperimentazione più casuali. Chiedi a tutti gli spazi di riutilizzare regole e convenzioni comuni. Cerca di renderlo parte dello spirito di squadra.

La maggior parte dei consigli che si applicano al codice e agli strumenti si applica anche alla documentazione.

Rigidità nei commenti sul codice

Anche i commenti sul codice, come menzionato sopra, sono documentazione. Agli sviluppatori piace esprimere i loro sentimenti riguardo al loro codice (principalmente orgoglio e frustrazione, se me lo chiedi). Quindi non è insolito per loro esprimerli in termini non incerti nei commenti (o persino nel codice), quando un pezzo di testo più formale avrebbe potuto trasmettere lo stesso significato con meno imprevisti o drammi. Va bene lasciarne passare alcuni per motivi storici e divertenti: fa anche parte dello sviluppo di una cultura di squadra . Ma è molto importante che tutti sappiano cosa è accettabile e cosa non lo è, e quel rumore di commento è proprio questo: rumore .

Rigidità nei log di commit

I log di commit non sono un "passo" fastidioso e inutile del ciclo di vita del tuo SCM: NON lo salti per tornare a casa in tempo o andare avanti con l'attività successiva o per incontrare gli amici che sono partiti per pranzo. Sono importanti e, come il (buon) buon vino, più passa il tempo più diventano preziosi. Quindi falli bene. Sono sbalordito quando vedo i colleghi scrivere una riga per impegni giganti o hack non ovvi.

I commit vengono eseguiti per un motivo e tale motivo NON è sempre chiaramente espresso dal codice e dall'unica riga del log di commit immessi. C'è di più.

Ogni riga di codice ha una storia e una storia . I diff possono raccontarne la storia, ma devi scriverne la storia.

Perché ho aggiornato questa linea? -> Perché l'interfaccia è cambiata.

Perché l'interfaccia è cambiata? -> Perché la libreria L1 che la definisce è stata aggiornata.

Perché la libreria è stata aggiornata? -> Perché la libreria L2, necessaria per la funzione F, dipendeva dalla libreria L1.

E qual è la funzione X? -> Vedi l'attività 3456 nel tracker dei problemi.

Non è una mia scelta SCM e potrebbe non essere la migliore per il tuo laboratorio; ma funziona Gitbene e cerca di forzarti a scrivere buoni registri più della maggior parte degli altri sistemi SCM, usando short logse long logs. Collega l'ID attività (sì, ne hai bisogno) e lascia un riepilogo generico per shortlog, ed espandi nel registro lungo: scrivi la storia del changeset .

È un registro: è qui per tenere traccia e registrare gli aggiornamenti.

Regola empirica: se stavi cercando qualcosa su questa modifica in un secondo momento, è probabile che il tuo registro risponda alla tua domanda?

Progetti, documentazione e codice sono VIVI

Tienili sincronizzati, altrimenti non formano più quell'entità simbiotica. Funziona a meraviglia quando hai:

  • cancella i log di commit nel tuo SCM, con collegamenti agli ID attività nel tracker dei problemi,
  • dove i ticket di questo tracker si collegano direttamente ai changeset nel tuo SCM (e possibilmente ai build nel tuo sistema CI),
  • e un sistema di documentazione che collega a tutti questi.

Il codice e la documentazione devono essere coerenti .

Rigidità nei test

Regole pratiche:

  • Ogni nuovo codice deve contenere (almeno) test unitari.
  • Qualsiasi codice legacy refactored deve contenere test unitari.

Naturalmente, questi hanno bisogno di:

  • per testare effettivamente qualcosa di prezioso (o sono una perdita di tempo ed energia),
  • per essere ben scritto e commentato (proprio come qualsiasi altro codice che si effettua il check-in).

Sono anche documentazione e aiutano a delineare il contratto del codice. Soprattutto se si utilizza TDD . Anche se non lo fai, ne hai bisogno per la tua tranquillità. Sono la tua rete di sicurezza quando incorpori il nuovo codice (manutenzione o funzionalità) e la tua torre di guardia per proteggerti dal marciume del codice e dai guasti ambientali.

Ovviamente, dovresti andare oltre e avere test di integrazione e test di regressione per ogni bug riproducibile che risolvi.

Rigidità nell'uso degli strumenti

Va bene per lo sviluppatore / scienziato occasionale voler provare un nuovo controllo statico sull'origine, generare un grafico o un modello usando un altro o implementare un nuovo modulo usando un DSL. Ma è meglio se esiste un set canonico di strumenti che tutti i membri del team dovrebbero conoscere e utilizzare.

Oltre a ciò, lascia che i membri usino ciò che vogliono, purché siano TUTTI:

  • produttivo ,
  • NON richiede regolarmente assistenza
  • NON adeguarsi regolarmente alla tua infrastruttura generale ,
  • NON interrompere la tua infrastruttura (modificando aree comuni come codice, sistema di compilazione, documentazione ...),
  • NON influisce sul lavoro degli altri ,
  • IN GRADO di eseguire tempestivamente qualsiasi attività richiesta .

In caso contrario, imporre che vengano ripristinati i valori predefiniti.


Rigidità vs versatilità, adattabilità, prototipazione ed emergenze

La flessibilità può essere buona. Consentire a qualcuno di usare occasionalmente un hack, un approccio rapido e uno strumento preferito per gli animali domestici per fare il lavoro va bene. Non lasciare MAI che diventi un'abitudine e MAI lasciare che questo codice diventi la base di codice effettiva da supportare.


Questioni di spirito di squadra

Sviluppa un senso di orgoglio nella tua base di codice

  • Sviluppa un senso di orgoglio nel codice
    • Usa i wallboard
      • classifica per un gioco di integrazione continua
      • wallboard per la gestione dei problemi e il conteggio dei difetti
    • Usa un tracker / bug tracker

Evita i giochi di colpa

  • Usa i giochi di integrazione continua / ispezione continua: promuove una competizione educata e produttiva .
  • Tieni traccia dei difetti: è solo un buon servizio di pulizia.
  • DO individuando cause di fondo : è solo processi a prova di futuro.
  • MA NON assegnare la colpa : è controproducente.

Riguarda il codice, non gli sviluppatori

Rendere gli sviluppatori consapevoli della qualità del loro codice, MA far loro vedere il codice come un'entità distaccata e non un'estensione di se stessi, che non può essere criticata.

È un paradosso: è necessario incoraggiare la programmazione senza ego per un ambiente di lavoro sano ma fare affidamento sull'ego per scopi motivazionali.


Dallo scienziato al programmatore

Le persone che non apprezzano e sono orgogliose del codice non producono un buon codice. Affinché questa proprietà emerga, devono scoprire quanto può essere preziosa e divertente. La semplice professionalità e il desiderio di fare del bene non bastano: ha bisogno di passione. Quindi devi trasformare i tuoi scienziati in programmatori (in senso lato).

Qualcuno ha sostenuto nei commenti che dopo 10 o 20 anni su un progetto e il suo codice, chiunque avrebbe sentito attaccamento. Forse mi sbaglio ma presumo siano orgogliosi dei risultati del codice, del lavoro e della sua eredità, non del codice stesso o dell'atto di scriverlo.

Per esperienza, la maggior parte dei ricercatori considera la programmazione come una necessità, o nella migliore delle ipotesi una distrazione divertente. Vogliono solo che funzioni. Quelli che sono già abbastanza esperti e che hanno un interesse per la programmazione sono molto più facili da convincere di adottare le migliori pratiche e cambiare le tecnologie. Devi prenderli a metà strada.


La manutenzione del codice fa parte del lavoro di ricerca

Nessuno legge documenti di ricerca scadenti. Ecco perché sono sottoposti a revisione paritaria, riletti, perfezionati, riscritti e approvati più volte fino a quando non saranno considerati pronti per la pubblicazione. Lo stesso vale per una tesi e una base di codice!

Metti in chiaro che il costante refactoring e aggiornamento di una base di codice impedisce la putrefazione del codice e riduce il debito tecnico e facilita il riutilizzo e l'adattamento futuri del lavoro per altri progetti.


Perché tutto questo??!

Perché ci preoccupiamo di tutto quanto sopra? Per la qualità del codice . O è un codice di qualità ...?

Queste linee guida mirano a guidare la tua squadra verso questo obiettivo. Alcuni aspetti lo fanno semplicemente mostrando loro la strada e lasciandoli fare (che è molto meglio) e altri li prendono per mano (ma è così che si educano le persone e si sviluppano le abitudini).

Come fai a sapere quando l'obiettivo è a portata di mano?

La qualità è misurabile

Non sempre quantitativamente, ma è misurabile . Come accennato, è necessario sviluppare un senso di orgoglio nella tua squadra e mostrare progressi e buoni risultati è la chiave. Misura regolarmente la qualità del codice e mostra i progressi tra gli intervalli e come conta. Fare retrospettive per riflettere su ciò che è stato fatto e su come ha migliorato o peggiorato le cose.

Ci sono ottimi strumenti per l' ispezione continua . Il sonar è popolare nel mondo Java, ma può adattarsi a qualsiasi tecnologia; e ce ne sono molti altri. Tieni il tuo codice al microscopio e cerca questi fastidiosi bug e microbi fastidiosi.


Ma cosa succede se il mio codice è già una schifezza?

Tutto quanto sopra è divertente e carino come un viaggio a Never Land, ma non è così facile da fare quando hai già (un mucchio di cazzate piene di vapore e puzzolente) e una squadra riluttante a cambiare.

Ecco il segreto: devi iniziare da qualche parte .

Aneddoto personale: in un progetto, abbiamo lavorato con una base di codice che pesava originariamente oltre 650.000+ Java LOC, oltre 200.000 righe di JSP, 40.000+ JavaScript LOC e oltre 400 MB di dipendenze binarie.

Dopo circa 18 mesi, sono 500.000 Java LOC (MOLTO PULITI) , 150.000 linee di JSP e 38.000 JavaScript LOC, con dipendenze fino a appena 100 MB (e queste non sono più nel nostro SCM!).

Come l'abbiamo fatto? Abbiamo appena fatto tutto quanto sopra. O provato duramente.

È uno sforzo di squadra, ma introduciamo lentamente nei nostri regolamenti e strumenti di processo per monitorare la frequenza cardiaca del nostro prodotto, mentre sbricioliamo in fretta il "grasso": codice di merda, dipendenze inutili ... Non abbiamo fermato tutto lo sviluppo per fai questo: abbiamo occasionali periodi di relativa pace e quiete in cui siamo liberi di impazzire sulla base di codice e di separarla, ma la maggior parte delle volte facciamo tutto di default in una modalità di "revisione e refactoring" ogni volta che ne abbiamo l'opportunità : durante le build, a pranzo, durante gli sprint di correzione dei bug, nei pomeriggi di venerdì ...

C'erano alcuni "lavori" di grandi dimensioni ... Il passaggio dal nostro sistema di generazione da una gigantesca build Ant di 8500+ XML LOC a una build Maven multi-modulo era uno di questi. Abbiamo quindi avuto:

  • moduli chiari (o almeno era già molto meglio e abbiamo ancora grandi progetti per il futuro),
  • gestione automatica delle dipendenze (per una facile manutenzione e aggiornamenti e per rimuovere deps inutili),
  • build più veloci, più facili e riproducibili,
  • rapporti giornalieri sulla qualità.

Un altro era l'iniezione di "utility tool-cinghia", anche se abbiamo cercato di ridurre le dipendenze: Google Guava e Apache Commons dimagrire il codice e ridurre la superficie e per il bug nel tuo codice di molto.

Abbiamo anche convinto il nostro dipartimento IT che forse usare i nostri nuovi strumenti (JIRA, Fisheye, Crucible, Confluence, Jenkins) era migliore di quelli in atto. Avevamo ancora bisogno di occuparci di alcuni che disprezzavamo (QC, Sharepoint e SupportWorks ...), ma è stata un'esperienza complessivamente migliorata, con ancora un po 'di spazio.

E ogni giorno, ora c'è un rivolo tra una e dozzine di impegni che si occupano solo di riparare e refactoring. Occasionalmente rompiamo le cose (hai bisogno di test unitari e è meglio scriverle prima di rimodellare le cose), ma nel complesso il vantaggio per il nostro morale E per il prodotto è stato enorme. Ci arriva una frazione di una percentuale di qualità del codice alla volta. Ed è divertente vederlo aumentare !!!

Nota: ancora una volta, la rigidità deve essere scossa per fare spazio a cose nuove e migliori. Nel mio aneddoto, il nostro dipartimento IT ha in parte ragione nel cercare di imporci alcune cose, e in altre sbagliato. O forse avevano ragione . Le cose cambiano. Dimostra che sono modi migliori per aumentare la tua produttività. Per questo sono disponibili prove di prova e prototipi .


Il ciclo di refactoring del codice spaghetti super-segreto incrementale per una qualità eccezionale

       +-----------------+      +-----------------+
       |  A N A L Y Z E  +----->| I D E N T I F Y |
       +-----------------+      +---------+-------+
                ^                           |
                |                           v
       +--------+--------+      +-----------------+
       |    C L E A N    +<-----|      F I X      |
       +-----------------+      +-----------------+

Una volta che hai degli strumenti di qualità a portata di mano:

  1. Analizza il tuo codice con controlli di qualità del codice.

    Linters, analizzatori statici o cosa hai.

  2. Identifica i tuoi hotspot critici E i frutti bassi .

    Le violazioni hanno livelli di gravità e le classi di grandi dimensioni con un numero elevato di classi ad alta gravità sono una grande bandiera rossa: come tali, appaiono come "punti caldi" su tipi di viste radiatore / heatmap.

  3. Correggi prima gli hotspot.

    Massimizza il tuo impatto in un breve lasso di tempo in quanto hanno il più alto valore aziendale. Idealmente, le violazioni critiche dovrebbero essere affrontate non appena compaiono, poiché sono potenziali vulnerabilità della sicurezza o cause di crash e presentano un alto rischio di indurre una responsabilità (e, nel tuo caso, cattive prestazioni per il laboratorio).

  4. Elimina le violazioni di basso livello con sweep di codebase automatizzati .

    Migliora il rapporto segnale-rumore in modo da poter vedere violazioni significative sul radar mentre appaiono. All'inizio c'è spesso un grande esercito di piccole violazioni se non sono mai state curate e la tua base di codice è stata lasciata libera in natura. Non presentano un vero "rischio", ma compromettono la leggibilità e la manutenibilità del codice. Risolvili mentre li incontri mentre lavori su un'attività o eseguendo grandi ricerche di pulizia con sweep di codice automatizzato, se possibile. Fai attenzione con le auto-sweep di grandi dimensioni se non hai una buona suite di test e un sistema di integrazione. Assicurati di concordare con i colleghi il momento giusto per gestirli per ridurre al minimo il fastidio.

  5. Ripeti fino a quando non sei soddisfatto.

    Che, idealmente, non dovresti mai essere, se questo è ancora un prodotto attivo: continuerà ad evolversi.

Suggerimenti rapidi per il buon mantenimento della casa

  • In modalità hotfix , in base a una richiesta di assistenza clienti:

    • Di solito è una buona pratica NON andare in giro a risolvere altri problemi, poiché potresti introdurne di nuovi senza volerlo.
    • Vanno esso SEAL-style: entrare, uccidere l'insetto, uscire , e spedire il vostro patch. È un colpo chirurgico e tattico.
  • Ma per tutti gli altri casi , se apri un file, prendi il tuo dovere di:

    • sicuramente: esaminalo (prendi appunti, segnala problemi di file),
    • forse: pulire esso (ripuliture stile e violazioni minori),
    • idealmente: riformattalo (riorganizza grandi sezioni e i loro vicini).

Basta non lasciarsi sfuggire a passare una settimana da un file all'altro e finire con un enorme cambiamento di migliaia di correzioni che coprono più funzionalità e moduli - rende difficile il tracciamento futuro. Un problema nel codice = un biglietto nel tracker. A volte, un changeset può influire su più ticket; ma se succede troppo spesso, probabilmente stai facendo qualcosa di sbagliato.


Addendum: gestione degli ambienti di programmazione visiva

I giardini murati di sistemi di programmazione su misura

Più sistemi di programmazione, come l'OP G2, sono bestie diverse ...

  • Nessun "codice" di origine

    Spesso non ti danno accesso a una rappresentazione testuale del tuo "codice" sorgente: potrebbe essere memorizzato in un formato binario proprietario, o forse memorizza le cose in formato testo ma le nasconde lontano da te. I sistemi di programmazione grafica su misura non sono in realtà rari nei laboratori di ricerca, in quanto semplificano l'automazione dei flussi di lavoro ripetitivi di elaborazione dei dati.

  • Nessuna attrezzatura

    A parte il loro, cioè. Spesso sei vincolato dal loro ambiente di programmazione, dal loro debugger, dal loro interprete, dai loro strumenti e formati di documentazione. Sono giardini recintati , tranne se alla fine catturano l'interesse di qualcuno abbastanza motivato da decodificare i loro formati e costruire strumenti esterni, se la licenza lo consente.

  • Mancanza di documentazione

    Abbastanza spesso, si tratta di sistemi di programmazione di nicchia, che vengono utilizzati in ambienti abbastanza chiusi. Le persone che li usano spesso firmano accordi di riservatezza e non parlano mai di ciò che fanno. Le comunità di programmazione per loro sono rare. Quindi le risorse sono scarse. Sei bloccato con il tuo riferimento ufficiale, e basta.

La parte ironica (e spesso frustrante) è che tutte le cose che fanno questi sistemi potrebbero ovviamente essere raggiunte usando linguaggi di programmazione tradizionali e generici, e probabilmente molto più efficacemente. Ma richiede una conoscenza più approfondita della programmazione, mentre non puoi aspettarti che il tuo biologo, chimico o fisico (per citarne alcuni) sappia abbastanza sulla programmazione e ancora meno che abbia il tempo (e il desiderio) di implementare (e mantenere) sistemi complessi, che possono essere o meno di lunga durata. Per lo stesso motivo per cui utilizziamo le DSL, disponiamo di questi sistemi di programmazione personalizzati.

Aneddoto personale 2:In realtà, ho lavorato su uno di questi da solo. Non ho fatto il collegamento con la richiesta del PO, ma il mio progetto era un insieme di grandi pezzi interconnessi di software di elaborazione e archiviazione dei dati (principalmente per la ricerca bioinformatica, sanità e cosmetici, ma anche per le imprese intelligence o qualsiasi dominio che implichi il monitoraggio di grandi volumi di dati di ricerca di qualsiasi tipo e la preparazione di flussi di lavoro di elaborazione dei dati e ETL). Una di queste applicazioni era, semplicemente, un IDE visivo che utilizzava le solite campane e fischietti: interfacce drag and drop, aree di lavoro di progetto con versione (utilizzando file di testo e XML per l'archiviazione dei metadati), molti driver collegabili a origini dati eterogenee e un oggetto visivo canvas per progettare pipeline per elaborare dati da N origini dati e alla fine generare M output trasformati, e possibili visualizzazioni brillanti e report online complessi (e interattivi). Il tuo tipico sistema di programmazione visiva su misura, che soffre di un po 'di sindrome NIH con la scusa di progettare un sistema adattato alle esigenze degli utenti.

E, come ci si aspetterebbe, è un sistema piacevole, abbastanza flessibile per le sue esigenze, anche se a volte un po 'esagerato, quindi ti chiedi "perché non utilizzare invece gli strumenti da riga di comando?", E purtroppo sempre all'avanguardia nelle medie dimensioni team che lavorano su grandi progetti a molte persone diverse che lo utilizzano con diverse "migliori" pratiche.

Fantastico, siamo condannati! - Cosa ne facciamo?

Bene, alla fine, tutto quanto sopra vale ancora. Se non è possibile estrarre la maggior parte della programmazione da questo sistema per utilizzare più strumenti e linguaggi tradizionali, è "solo" necessario adattarlo ai vincoli del proprio sistema.

Informazioni su controllo delle versioni e archiviazione

Alla fine, puoi quasi sempre eseguire le versioni , anche con l'ambiente più limitato e protetto. Il più delle volte, questi sistemi vengono ancora con il proprio versioning (che sfortunatamente spesso è piuttosto semplice, e offre solo di tornare alle versioni precedenti senza molta visibilità, mantenendo solo le istantanee precedenti). Non utilizza esattamente i changeset differenziali come potrebbe essere il tuo SCM preferito, e probabilmente non è adatto a più utenti che inviano le modifiche contemporaneamente.

Tuttavia, se forniscono tale funzionalità, forse la tua soluzione è quella di seguire le nostre amate linee guida standard del settore sopra e di trasporle in questo sistema di programmazione !!

Se il sistema di archiviazione è un database, probabilmente espone le funzionalità di esportazione o può essere eseguito il backup a livello di file system. Se utilizza un formato binario personalizzato, forse puoi semplicemente provare a versione con un VCS che ha un buon supporto per i dati binari. Non avrai un controllo accurato, ma almeno avrai la tua schiena coperta da catastrofi e avrai un certo grado di conformità al ripristino di emergenza.

Informazioni sui test

Implementare i test all'interno della piattaforma stessa e utilizzare strumenti esterni e processi in background per configurare backup regolari. Molto probabilmente, si accendono questi test allo stesso modo in cui si accenderebbero i programmi sviluppati con questo sistema di programmazione.

Certo, è un lavoro di hacking e sicuramente non all'altezza di ciò che è comune per la programmazione "normale", ma l'idea è quella di adattarsi al sistema mentre si cerca di mantenere una parvenza del processo di sviluppo software professionale.

La strada è lunga e ripida ...

Come sempre con ambienti di nicchia e sistemi di programmazione su misura, e come abbiamo esposto sopra, hai a che fare con strani formati, solo un insieme limitato (o totalmente inesistente) di strumenti probabilmente ingombranti e un vuoto al posto di una comunità.

La raccomandazione: cerca di attuare il più possibile le linee guida di cui sopra al di fuori del tuo sistema di programmazione su misura. Ciò garantisce che si possa fare affidamento su strumenti "comuni", che hanno un supporto adeguato e un impulso alla comunità.

La soluzione alternativa: quando questa non è un'opzione, prova ad aggiornare questo framework globale nella tua "scatola". L'idea è quella di sovrapporre questo modello delle migliori pratiche standard del settore al di sopra del vostro sistema di programmazione e trarne il meglio. Il consiglio è ancora valido: definire la struttura e le migliori pratiche, incoraggiare la conformità.

Sfortunatamente, questo implica che potrebbe essere necessario immergersi e fare un'enorme quantità di lavoro sulle gambe. Così...

Ultime parole famose e richieste umili:

  • Documenta tutto ciò che fai.
  • Condividi la tua esperienza.
  • Open Source qualsiasi strumento che scrivi.

Facendo tutto questo, dovrai:

  • non solo aumenta le tue possibilità di ottenere supporto da persone in situazioni simili,
  • ma fornisce anche aiuto ad altre persone e favorisce la discussione sul tuo stack tecnologico.

Chi lo sa, si potrebbe essere proprio all'inizio di una nuova comunità vibrante di Obscure Lingua X . Se non ce ne sono, iniziane uno!

Forse è bello dentro , ma finora nessuno ha la minima idea , quindi aiutate a abbattere questo brutto muro e date un'occhiata agli altri!


22
NOTA: i commenti su questo sono stati ripuliti mentre si stavano sfuggendo di mano. Haylem ha incorporato quelli più pertinenti e utili nella risposta. Inoltre, la risposta è molto vicina al limite di 30.000 caratteri per i post. Modifica con estrema cura.
ChrisF

3
Manca solo un pezzo di Integrazione continua, che è una distinzione importante: NON incolpare le persone per i check-in errati, NON biasimarli per non aver ripulito prontamente. Va bene fare un errore. Gli errori ti aiutano a imparare, ma lasciare che i tuoi colleghi soffrano per i tuoi errori fa perdere tempo, energia e, nel peggiore dei casi, insegna risentimento.
Jason,

96
Quando posso acquistare questa risposta in copertina rigida?
LarsH

5
Inizialmente sono stato disattivato da questa risposta. Non sono del tutto sicuro del perché, ma la formulazione mi ha sfregato nel modo sbagliato e mi è sembrato un po 'troppo alto livello. Tuttavia, dopo aver letto la guida sezione per sezione (al contrario di una seduta), l'ho trovata estremamente utile. Se trovi questa risposta scoraggiante e sei arrivato a questo commento senza leggerlo, torna indietro e leggi solo una sezione.
sdasdadas,

5
troppo rigido, a lungo tortuoso e affermando l'ovvio. Se questa è la tua agenda / strategia nessuno ti ascolterà più dopo circa un mese.
Joppe

101

Il primo passo sarebbe l' introduzione di un sistema di controllo versione (SVN, Git, Mercurial, TFS, ecc.). Questo è necessario per un progetto che avrà un factoring.

Modifica: riguardo a VSC - Ogni pacchetto di controllo del codice sorgente può gestire i binari, anche se con alcune limitazioni. La maggior parte degli strumenti sul mercato ha la capacità di utilizzare un visualizzatore e un editor delle differenze personalizzati, utilizzare questa funzionalità. I file sorgente binari non sono una scusa per non utilizzare il controllo versione.

C'è un post simile su come gestire il codice legacy , potrebbe essere un buon riferimento da seguire - Consigli su come lavorare con il codice legacy


19
Sfortunatamente, uno degli svantaggi del linguaggio G2 è che i file sorgente non sono leggibili dall'uomo (è fondamentalmente un linguaggio grafico, simile a LabView ), e quindi implementare Version Control non è affatto banale. Questo è, infatti, uno dei nostri maggiori ostacoli, attualmente (IMO).
kmote

4
@kmote: il produttore di G2 dispone di uno dei suoi strumenti speciali per il controllo della versione? Qualcun altro ha creato un tale strumento?
FrustratedWithFormsDesigner

39
Ogni pacchetto di controllo del codice sorgente può gestire i file binari, sebbene con alcune limitazioni. Ogni strumento che conosco ha la capacità di utilizzare un visualizzatore e un editor di differenze personalizzati, utilizzare questa funzionalità. I file sorgente binari non sono una scusa per non utilizzare il controllo versione.
Mattnz,

11
È possibile decodificare il formato di file G2 e creare un'utilità per scaricarlo in formato di testo diff-friendly. Può sembrare scoraggiante, ma per una base di codice così grande, varrebbe la pena (secondo la mia ingenua opinione).
Joey Adams,

6
@Erik: Usare il controllo versione SOLO come strumento di "rollback" è un po 'come comprare una Porsche per fare la spesa - Lo fa così come qualsiasi altra cosa, ma può fare molto di più per te .......
Mattnz,

43

Quando devo lavorare con il codice spaghetti, la prima cosa su cui lavoro è la modularizzazione . Trova i punti in cui puoi disegnare linee ed estrarre (più o meno) parti indipendenti della base di codice. Probabilmente non saranno molto piccoli, a causa di un alto grado di interconnessione e accoppiamento, ma emergeranno alcune linee di moduli se le cerchi.

Una volta che hai i moduli, non dovrai più affrontare il compito scoraggiante di ripulire un intero programma disordinato. Ora, invece, hai diversi moduli disordinati indipendenti più piccoli da ripulire. Ora scegli un modulo e ripeti su una scala più piccola. Trova i luoghi in cui puoi estrarre grandi funzioni in funzioni più piccole o persino in classi (se G2 le supporta).

Questo è molto più semplice se la lingua ha un sistema di tipi sufficientemente forte, perché puoi fare in modo che il compilatore esegua molto lavoro pesante per te. Apportate una modifica da qualche parte che interromperà (intenzionalmente) la compatibilità, quindi proverete a compilare. Gli errori di compilazione ti porteranno direttamente nei luoghi che devono essere modificati e quando smetti di ottenerli, hai trovato tutto. Quindi eseguire il programma e testare tutto! I test continui sono di fondamentale importanza per il refactoring.


17
Lavorare in modo efficace con il codice legacy è probabilmente un must per questo.
Oded,

3
Meglio ancora .. Piuttosto che eseguire semplicemente il programma, l'unità testa i tuoi nuovi moduli :)
Demian Brecht,

1
Questo è l'approccio migliore (insieme all'ovvio passo per ottenere l'intero lotto nel controllo della versione). Tutta la colpa delle grandi risposte è troppo generale e troppo grande per essere applicata in una volta sola. piccoli passi fino a quando non avrai un'idea del tutto. Una volta ho ereditato un progetto 50k (in realtà quattro versioni essenzialmente dello stesso 50k). Dopo un mese avevo una versione e mi ero sbarazzato di circa 10k linee attraverso il refactoring / ristrutturazione di base. 1-stick in repository, 2-assicurati di poterlo costruire, 3-refactor / ristrutturare, ripeti 3 fino al termine.

22

Non so se questa è un'opzione per te, ma inizierei a cercare di convincerli ad assumere sviluppatori più professionali . In questo modo potrebbero concentrarsi sui problemi di dominio (sono sicuro che ne hanno abbastanza lì).

Credo che siano persone molto intelligenti, ma diventare un buon sviluppatore richiede molto tempo. Sono pronti a passare così tanto tempo in un'attività che non è la loro attività principale? IMHO, questo non è il modo di ottenere i migliori risultati.


16
L'OP è il primo sviluppatore professionista. Il modo migliore per convincere l'OP a convincerli ad assumere di più è che l'OP fornisca un evidente valore aggiunto nei primi 6-12 mesi. Se ciò può essere ottenuto, l'OP avrà credibilità e potrebbe essere in grado di assumere di più.
MarkJ

20

Wow. Sembra che tu abbia una grande sfida davanti a te! Farei qualcosa seguendo le seguenti linee:

  • Prima di tutto: Priorità . Cosa vuoi ottenere per primo? Qual è il più importante per lo stato attuale del progetto? Cosa otterrai di più da vs quanto tempo ci vorrà per arrivarci.
  • Assicurarsi di disporre di un sistema di controllo della versione . Git o Mercurial per esempio.
  • Ottieni una sorta di sistema di integrazione continua (ad esempio Jenkins ) attivo e funzionante.
  • Ottieni un sistema di tracciamento dei bug attivo e funzionante. La mantide è piuttosto carina secondo me.
  • Esamina l' analisi del codice statico (se è disponibile qualcosa per la lingua con cui stai attualmente lavorando).
  • Cerca di ottenere la stessa coerenza in qualsiasi cosa, dalla denominazione delle variabili alle convenzioni di codice generali e alle linee guida nella base di codice.
  • Metti il ​​sistema in prova . Questo è estremamente importante per un grande sistema legacy come questo secondo me. Usa i casi di test per documentare il comportamento esistente , indipendentemente dal fatto che si senta strano o meno (di solito c'è una ragione per cui il codice sembra certo perché, potrebbe essere buono o cattivo, o entrambi; P). Michael Feathers Lavorare efficacemente con Legacy Code è una risorsa eccellente per questo.

10

Dicono che il primo passo per risolvere un problema è ammettere di averne uno. Con questo in mente, potresti iniziare generando un grafico delle dipendenze che illustra il vasto groviglio che è la tua base di codice attuale. Ottimo strumento per generare diagramma delle dipendenze? ha qualche anno ma contiene alcuni suggerimenti su strumenti che possono aiutare a creare tali grafici. Vorrei andare con un grafico grande, brutto che mostra il più possibile per guidare il punto a casa. Parla dei problemi che derivano da troppe interdipendenze e forse gettano una linea da Buckaroo Banzai :

Puoi controllare la tua anatomia tutto quello che vuoi, e anche se ci possono essere variazioni normali, quando arriva fino ad essa, così lontano all'interno della testa sembra tutto uguale. No, no, no, non tirarlo su. Non sai mai a cosa potrebbe essere collegato.

Da lì, introdurre un piano per iniziare a raddrizzare il pasticcio. Suddividere il codice in moduli il più autonomi possibile. Sii aperto ai suggerimenti su come farlo: le persone con cui stai parlando conoscono la storia e le funzionalità del codice meglio di te. L'obiettivo, tuttavia, è quello di prendere un grosso problema e trasformarlo in un numero di problemi minori che è quindi possibile stabilire le priorità e iniziare a ripulire.

Alcune cose su cui concentrarsi:

  • Crea interfacce pulite tra i moduli e inizia a usarli. Il vecchio codice potrebbe, per necessità, continuare a non usare quelle nuove e simpatiche interfacce per un po '- questo è il problema che stai iniziando a risolvere. Ma fai in modo che tutti accettino di usare solo le nuove interfacce in futuro. Se c'è qualcosa di cui hanno bisogno che non è nelle interfacce, correggi le interfacce, non aggirarle.

  • Cerca i casi in cui è stata ripetuta la stessa funzionalità. Lavora verso l'unificazione.

  • Ricorda a tutti di volta in volta che questi cambiamenti hanno lo scopo di rendere la vita più facile, non più difficile. La transizione può essere dolorosa, ma è per un buon scopo, e più tutti sono a bordo, più velocemente arriveranno i benefici.


1
@kmote Non ti avrebbero assunto se non avessero riconosciuto che hanno bisogno di aiuto e vogliono fare le cose meglio. La parte difficile potrebbe essere aiutarli a ricordare che il tuo lavoro non è quello di risolvere i problemi, ma è quello di aiutarli a risolvere i problemi. Buckaroo Banzai è piuttosto popolare tra i tipi scientifici di una certa età - forse può aiutarti a mantenere le cose leggere.
Caleb,

9

Dopo aver esaminato Gensym G2 per un po ', sembra che il modo in cui affrontare questo problema sarà fortemente dipendente da quanto della base di codice sia simile al seguente:

inserisci qui la descrizione dell'immagine

o questo:

inserisci qui la descrizione dell'immagine

al contrario, per gentile concessione di 99 Bottiglie di birra :

beer-bottles()

i:integer =99;
j:integer;
constant:integer =-1;

begin
for i=99 down to 1
    do
    j = (i+constant);
        if (i=1) then begin
            post"[i] bottle of beer on the wall";
            post" [i] bottle of beer";
            post" Take one down and pass it around ";
            post" No bottle of beer on the wall"; 
        end 
        else begin
            post"[i] bottles of beer on the wall";
            post" [i] bottles of beer";
            post" Take one down and pass it around ";
            if (i=2) then 
                post" [j] bottle of beer on the wall"
           else
                post" [j] bottles of beer on the wall"; 
           end
    end
end

Nel caso di quest'ultimo stai lavorando con il codice sorgente che è effettivamente una quantità nota e alcune delle altre risposte offrono alcuni consigli molto prudenti per gestirlo.

Se la maggior parte della base di codice è quest'ultima, o anche se è una porzione considerevole, ti imbatterai nell'interessante problema di avere codice che probabilmente non può essere refactored a causa dell'estrema specializzazione o, peggio ancora, di qualcosa che sembra può essere rimovibile, ma a meno che non sia adeguatamente documentato, non si sa se si sta rimuovendo il codice critico (pensare qualcosa lungo le linee di un'operazione di scram ) che non sembra essere così a prima vista.

Anche se ovviamente la tua prima priorità sarà ottenere una sorta di controllo di versione online, come ha sottolineato ElYusubov , e sembra che il controllo di versione sia supportato dalla versione 8.3 . Poiché G2 è una combinazione di un paio di metodologie linguistiche diverse, è probabile che sia più efficace utilizzare il controllo versione fornito con esso anziché cercare di trovare qualcos'altro e farlo funzionare.

Successivamente, anche se alcuni probabilmente supporteranno l'avvio di refactoring, sono un forte sostenitore di assicurarmi di comprendere appieno il sistema con cui stai lavorando prima di iniziare a toccare qualsiasi codice, specialmente quando hai a che fare con codice e diagrammi visivi sviluppati da sviluppatori senza formazione formale (o background) in metodologie di ingegneria del software. Il ragionamento per questo è più volte, ma la ragione più ovvia è che stai lavorando con un'applicazione che potenzialmente ha oltre 100 persone-anni di lavoro messo in esso e devi davvero assicurarti di sapere cosa sta facendo e quanto documentazione in esso contenuta. Poiché non hai detto in quale settore è distribuito il sistema, sulla base di ciò che ho letto su G2 sembra sicuro che si tratti di un'applicazione mission-critical che potrebbe anche avere un potenziale per avere anche implicazioni per la sicurezza della vita. Pertanto, capire esattamente cosa sta facendo sarà molto importante. Esiste un codice che non è documentato in collaborazione con gli altri membri del team per assicurarsi che venga messa a punto la documentazione per assicurarsi che le persone possano determinare cosa fa il codice.

Successivamente inizia a racchiudere i test di unità intorno alla base di codice e ai diagrammi visivi che puoi. Devo ammettere un po 'di ignoranza riguardo a come farlo con G2, ma potrebbe quasi valere la pena creare il proprio framework di test per metterlo in atto. Questo è anche il momento ideale per iniziare a presentare gli altri membri del team per abituarli ad alcune delle pratiche ingegneristiche più rigorose legate alla qualità del codice (ovvero tutto il codice deve avere unit test e documentazione).

Una volta che hai messo in atto test unitari su una discreta quantità di codice, puoi iniziare ad avvicinarti al refactoring secondo modalità come quella suggerita da haylem ; tuttavia, ricorda di tenere a mente che hai a che fare con qualcosa che è destinato allo sviluppo di sistemi esperti e al refactoring potrebbe essere una battaglia in salita. Questo è in realtà un ambiente in cui c'è qualcosa da dire per non scrivere codice estremamente generico a volte.

Infine, assicurati di prestare molta attenzione a ciò che dicono gli altri membri del team, solo perché la qualità del codice e del diagramma non è la migliore non riflette necessariamente male su di loro. In definitiva, per il momento è probabile che sappiano di più su ciò che l'applicazione fa di te, motivo per cui è tanto più importante sederti e assicurarti di capire cosa fa prima di apportare anche ampie modifiche.


1
@haylem - Nessuna idea, e potrebbe essere del tutto possibile che ci siano 200.000 LOC più n diagrammi di flusso e grafici nell'applicazione. Quindi 200.000 LOC potrebbero sottovalutare significativamente la complessità dell'applicazione.
rjzii,

9

Di solito i reclami che senti in anticipo non hanno nulla a che fare con i problemi importanti. Dopotutto, è del tutto normale ascoltare queste lamentele in qualsiasi progetto software.

Codice difficile da capire? Dai un'occhiata. Base di codice enorme? Dai un'occhiata.

Il vero problema è che le persone se ne vanno e quando la nuova persona si unisce all'organizzazione, c'è un tipico disorientamento. Inoltre, vi è un problema di aspettative non realistiche e problemi di qualità del codice.

Ecco cosa vorrei affrontare, in ordine:

  1. Backup, sia il server che la versione locale
  2. Imposta il tracker dei bug
  3. Configurare il sistema di controllo delle versioni
  4. Imposta FAQ / Wiki
  5. Primo debriefing di tutti gli scienziati / programmatori
    • Ricorda loro la regola 80/20. Il 20% dei bug è responsabile dell'80% dei problemi.
    • Concentrati sui problemi più importanti e mantieni le richieste di miglioramento ecc.
    • Lo scopo qui non è spaventare le persone con una grande lista, ma una lista di piccole vittorie ottenibili. Dopo tutto, devi dimostrare anche il tuo valore.
  6. Imposta il sistema di compilazione
    • Inizia a lavorare su come ottenere build affidabili (ciò potrebbe richiedere del tempo)
    • identificare e nominare ogni progetto
    • identificare dipendenze cicliche
    • se ci sono file binari da alcuni progetti open source, prova a ottenere fonti
  7. Identificare come il codice G2 può essere modulare, ad esempio API, servizi
  8. Identificare come il codice G2 può essere testato, documentato.
  9. Configurare il sistema di revisione del codice
  10. Secondo debriefing
  11. Identifica una squadra di migliori programmatori e lavora con loro per avvolgere i loro moduli.
  12. Le revisioni del codice sono presenti in questa fase per migliorare la comunicazione e la documentazione. Keep it easy in questa fase. Risolvi eventuali problemi di processo.
  13. Distribuire il sistema ad altri programmatori. Lascia che i membri del team di crack diventino mentori tra pari per il resto. Ricorda che il ridimensionamento è il problema qui. Sei effettivamente in un ruolo di gestione.

9

Domande come queste sono l'intera ragione per cui esiste il progetto Software Carpentry .

Negli ultimi 14 anni abbiamo insegnato a scienziati e ingegneri competenze di sviluppo software di base: controllo delle versioni, test, come modulare il codice e così via. Tutti i nostri materiali sono disponibili gratuitamente su licenza Creative Commons e ogni anno organizziamo un paio di dozzine di seminari gratuiti di due giorni per aiutare le persone a iniziare.

Sulla base di ciò, penso che il miglior punto di partenza sia probabilmente l'eccellente (breve) libro di Robert Glass Facts and Fallacies of Software Engineering : il suo approccio basato sull'evidenza è un buon modo per convincere gli scienziati che ciò che stiamo dicendo loro sulle buone pratiche di programmazione è più che una semplice opinione.
Per quanto riguarda le pratiche specifiche, le due che le persone sono più disposte ad adottare sono il controllo della versione e il test unitario; una volta che sono presenti, possono affrontare il tipo di refactoring sistematico descritto da Michael Feathers in Lavorare in modo efficace con il codice legacy .
Non raccomando più The Pragmatic Programmer (molta esortazione, difficile da mettere in pratica per i novizi), e penso che McConnell's Code Complete è troppo per cominciare (anche se è una buona cosa dargli sei mesi o un anno dopo aver imparato le basi).

Consiglio vivamente anche l'eccellente articolo di Paul Dubois "Mantenere la correttezza nei programmi scientifici" ( Informatica in scienza e ingegneria , maggio-giugno 2005), che descrive un approccio di "difesa in profondità" che combina una dozzina di pratiche diverse in un logico, coerente modo.


suggerimenti interessanti. Lo guarderò. (Nota: collegamento interrotto sul documento di Dubois)
kmote

7

Penso che prima di tutto devi cancellare la tua situazione. Cosa vogliono da te?

  • È molto improbabile che vogliano che tu impari una lingua antica, perché questo sembra ora un vicolo cieco: c'è una probabilità decrescente di trovare qualcuno che conosce o vuole imparare il G2, quindi la conoscenza sarà sepolta nel mucchio collasso di codice quando gli attuali scienziati se ne vanno o il codice con tutte le patch fallisce sempre più spesso.
  • Gli scienziati (o alcuni di essi) sono pronti ad imparare una nuova lingua e molti paradigmi di programmazione? O vogliono separare la programmazione e l'attività scientifica a lungo termine e forse hanno qualche programmatore in più se necessario? Sembra una separazione razionale ed efficiente delle competenze.

Penso che il requisito fondamentale qui sia "salvare la conoscenza nel sistema", quindi devi andare e scavare!

Il primo compito è scrivere una documentazione.

Analizza la struttura e i requisiti come se questo fosse un nuovo compito, ma con l'aiuto di un sistema esistente. Saranno contenti perché CHIEDI invece di INSEGNARE per primo - e otterrai rapidamente abbastanza, ma conoscenze di base più organizzate dal punto di vista di un programmatore: "cosa sta succedendo qui?" I documenti (struttura statica del sistema, flusso di lavoro, componenti, problemi) saranno immediatamente preziosi per loro, e forse mostreranno loro informazioni più pertinenti rispetto a te (alcuni dei ragazzi potrebbero avere "AHA!" E iniziare a correggere immediatamente alcuni codici ) ...

Dovresti quindi iniziare a chiedere dove vogliono andare?

Se sono pronti ad allontanarsi da G2, quale sistema vogliono vedere (piattaforma, lingua, interfaccia, struttura generale)? È possibile iniziare a scrivere un wrapper esterno attorno al sistema, se possibile, con la struttura di destinazione, ma mantenendo i componenti originali, avviando così lentamente una sorta di framework che consente l'implementazione di nuovi componenti in questo ambiente di destinazione. Devi trovare i servizi di base (connessioni dati permanenti e "toolkit": calcolo di base, disegno, ... librerie) e quindi fornire loro un ambiente familiare in una nuova piattaforma e linguaggio, che consenta la transizione da parte tua o loro: prendi i vecchi codici uno per uno, reimplementali (e PULISCI!) nel nuovo ambiente. Quando è pronto, conoscono la nuova lingua; e il livello di servizio (per lo più creato da te, scusa) è pronto per ospitare i nuovi componenti.

Se non si muovono , devi imparare G2 e creare lì la struttura modulare, in cui tu o loro dovresti spostare i componenti (con la pulizia). Ad ogni modo, il linguaggio è solo una serializzazione di dati e albero di algoritmi ...

Mentre analizzi e scrivi i documenti, leggi, usa e pubblicizza i modelli di GoF Design! :-)

... i miei 2 centesimi


Concordo sul fatto che il primo passo è capire cosa vogliono da te, ma il prossimo passo dovrebbe essere quello di farlo, e se il passo successivo non è quello di documentare lo stato delle cose, non farlo troppo. Se lo fai, non lo apprezzeranno.
Bill,

@bill: la domanda dice "non esiste un consenso di opinione su ciò che è necessario per il cammino da percorrere". Non lo sanno! Presumo che ci siano dibattiti seri senza intuizioni reali sul sistema che devono essere salvati "in qualche modo". Il compito di un programmatore in questa situazione è ovvio (almeno per me): fornire una corretta analisi dal punto di vista tecnico per aiutare a prendere una decisione razionale.
Lorand Kedves,

Ovviamente non sanno cosa vogliono, questa è la parte "risolvi tutto", che è diversa dal prendere semplicemente qualcosa come documentazione e schemi e dire di fare queste cose. Quelle cose sono buone cose, ma deve essere un processo che coinvolge il gruppo e se inizi con cose che non vedono prima il valore, avrai difficoltà a fare acquisti. - Saluti!
Bill,

@Bill: penso che tu abbia detto esattamente la stessa cosa che ho scritto sul contenuto e sulla creazione di quella documentazione ... ;-)
Lorand Kedves,

4

Ho appena finito di fare una serie di presentazioni sui principi SOLID di Robert Martin per i miei colleghi. Non so quanto bene questi principi si traducano in G2, ma dal momento che stai cercando 5-7 fondamentali fondamentali, questi sembrano un set consolidato per iniziare. Se vuoi arrotondare fino a 7, puoi iniziare con DRY e lanciare Fail-Fast.


1
ooh, ottimo suggerimento! Mi ha ricordato questa bella panoramica insieme a questo riepilogo eBook gratuito .
km

3

L'unico problema di produzione sembra un problema di gestione delle modifiche. Se questo è il caso e il software esegue diversamente lo scopo, il primo consiglio che darei è di resistere all'impulso di fare troppo in fretta.

Il controllo del codice sorgente, il refactoring e gli sviluppatori più esperti sono tutti buoni suggerimenti, ma se è la prima volta che devi affrontare questo tipo di problema muovendoti lentamente e facendo cambiamenti controllati non puoi essere abbastanza enfatizzato.

L'impulso di distruggere il caos a volte sarà grande, ma fino a quando non avrai abbastanza reverse engineering su di esso da sapere che puoi testare adeguatamente la tua versione sostitutiva, devi stare molto attento.


3

I principi più importanti per lavorare in una situazione del genere sono:

  1. Essere pazientare. Una buca che ha impiegato 20 anni per scavare non sarà riempita in poche settimane.

  2. Sii positivo. Resistere alla tentazione di lamentarsi e lamentarsi.

  3. Sii pragmatico. Guarda un cambiamento positivo che puoi realizzare in un giorno e fallo oggi. Hai ancora un sistema di controllo della versione? Implementalo e forma le persone. Quindi guarda e vedi se riesci ad automatizzare i test (Test unitari o qualcosa di simile). Risciacquare. Ripetere.

  4. Sii un modello. Mostra (non solo dire) alla gente come agile agisce. I primi tre punti sopra sono le chiavi per essere un bravo ragazzo, che è il predecessore per essere un efficace ragazzo agile. Secondo me, le persone che sono ammirevoli sviluppatori non sono solo intelligenti, ma anche brave, modellano impiegati e colleghi.

  5. Mappa il tuo territorio. Ho una tecnica per mappare basi di codice giganti legacy. Clono il repository, faccio una copia funzionante, quindi provo a cambiare qualcosa e vedo cos'altro si rompe. Studiando l'accoppiamento (tramite lo stato globale o le API rotte o la mancanza di API coerenti o eventuali astrazioni o interfacce da programmare) e leggendo il codice che si interrompe quando cambio cose, scopro l'innesto, faccio domande che portano a approfondimenti dal resto del team (Oh, l'abbiamo aggiunto perché Boss X 5 anni fa lo richiedeva, non ha mai funzionato!). Nel tempo, otterrai una mappa mentale del territorio. Una volta che sai quanto è grande, ne saprai abbastanza per creare la tua mappa e tornare a casa. Incoraggia gli altri a mappare il territorio della tua base di codice gigante e a sviluppare le conoscenze tecniche del team. Alcune persone si oppongono alla "documentazione" perché non è agile. Qualunque cosa. Lavoro anche in ambienti scientifici, e la documentazione è la cosa giusta per me, i manifesti agili sono dannati.

  6. Costruisci piccole app. Quando lavoro con una base di codice legacy, trovo che diventi una poltiglia. Ricupero il mio spirito costruendo piccole app di supporto. Forse quelle app ti aiuteranno a leggere, capire e modificare quella gigantesca base di codice G2. Forse puoi creare un mini IDE o uno strumento di analisi che ti aiuterà a lavorare nel tuo ambiente. Ci sono molti casi in cui la meta-programmazione e la costruzione di strumenti non solo ti aiuteranno a uscire dai giganteschi deadlock che le basi di codici legacy ti impongono, ma danno anche al tuo cervello la possibilità di volare senza restrizioni dal tuo linguaggio G2. Scrivi i tuoi strumenti e i tuoi aiutanti in qualsiasi lingua tu possa farli più velocemente e meglio. Per me, quelle lingue includono Python e Delphi. Se sei un ragazzo Perl o ti piace davvero programmare in C ++ o C #, allora scrivi i tuoi strumenti di supporto in quella lingua.


3
  1. Controllo delle revisioni : mostra agli esperti del dominio il vantaggio di essere in grado di ripristinare, vedere chi ha cambiato cosa, ecc. (Questo è più duro con i file tutto binari, ma se i contenuti sono davvero codice, sicuramente c'è una sorta di G2-to- convertitore di testo che può abilitare le differenze.)

  2. Integrazione e test continui : coinvolgere gli esperti del dominio nella creazione di test end-to-end (più semplice, poiché devono già avere input e output previsti da qualche parte) e test di piccole unità (più difficile, perché probabilmente il codice spaghetti coinvolge molte variabili globali) che copre quasi tutte le funzionalità e i casi d'uso.

  3. Rifattorizza il codice comune in routine e componenti riutilizzabili. Le persone non software senza controllo di revisione probabilmente copiano e incollano centinaia di righe alla volta per fare routine. Trovali e riformattali, dimostrando che tutti i test sono stati superati e il codice è stato ridotto. Questo ti aiuterà anche a imparare la sua architettura. Se sei fortunato nel momento in cui devi iniziare a prendere le difficili decisioni architettoniche, potresti arrivare a 100KLOC.

Politicamente , se in questo processo trovi resistenza dai vecchi timer, assumi un consulente per entrare e parlare della buona metodologia del software. Assicurati di trovarne uno valido con le quali sei d'accordo, e fai in modo che il management comprerà la necessità del consulente, anche se gli esperti del dominio non lo fanno. (Dovrebbero essere d'accordo - dopo tutto, ti hanno assunto, quindi evidentemente si rendono conto che hanno bisogno di competenze di ingegneria del software.) Questo è un trucco per sprecare soldi, ovviamente, ma il motivo è che se tu - il nuovo programmatore di giovani hotshot - dici loro hanno bisogno di fare qualcosa, possono ignorarlo. Ma se la direzione paga un consulente $ 5000 per entrare e dire loro cosa devono fare, riporranno più fiducia in esso. Punti bonus: chiedi al consulente di consigliare il doppio del cambiamento che desideri davvero, quindi puoi essere il "bravo ragazzo" e schierarti con gli esperti del dominio, compromettendo di cambiare solo la metà di quanto suggerito dal consulente.


3

"Il programma stesso è un modello fisico di un complesso impianto di lavorazione chimica ..."

"Dato che G2 è come un non-codice, ma piuttosto un codice automatizzato scritto da una fantastica GUI ..." - Erik Reppen

Supponendo che l'obiettivo principale del tuo software sia simulare (forse ottimizzare, eseguire stime dei parametri su) un complesso impianto chimico, o parti di uno ... quindi vorrei lanciare un suggerimento piuttosto diverso:

Potresti fare bene a considerare l'uso di un linguaggio di modellazione matematica di alto livello per estrarre l'essenza, i modelli matematici di base, da un software codificato a mano.

Quello che fa un linguaggio di modellazione è di separare la descrizione del problema dagli algoritmi utilizzati per risolverlo. Questi algoritmi sono generalmente applicabili alla maggior parte delle simulazioni / ottimizzazioni di una determinata classe (ad es. Processi chimici), nel qual caso non dovrebbero davvero essere reinventati e mantenuti internamente.

Tre pacchetti commerciali ampiamente utilizzati nel tuo settore sono: gPROMS, Aspen Custom Modeller e (se i tuoi modelli non includono fenomeni distribuiti lungo domini spaziali) ci sono pacchetti software basati su Modelica, come Dymola.

Tutti questi pacchetti supportano "estensioni" in un modo o nell'altro, in modo che se si hanno parti dei modelli che richiedono una programmazione personalizzata, possono essere incapsulati in un oggetto (ad esempio un .DLL) a cui si può fare riferimento dalle equazioni nella modello. Nel frattempo, la maggior parte del tuo modello rimane succinta, descritta in una forma facilmente leggibile direttamente dagli scienziati. Questo è un modo molto migliore per acquisire conoscenze e IP della tua azienda.

La maggior parte di questi programmi dovrebbe anche permetterti di "avviare piccoli" e portare piccole parti (sotto-modelli) del tuo codice monolitico nel loro formato, chiamando esternamente. Questo può essere un buon modo per mantenere un sistema funzionante e validarlo un pezzo alla volta.

Dichiarazione di non responsabilità completa: ho lavorato come ingegnere informatico presso la società dietro gPROMS per 8 anni. In quel periodo ho visto (e occasionalmente incorporato) esempi di software personalizzato (ad esempio proveniente dal mondo accademico) che era iniziato in piccolo e ordinato, implementando una soluzione o un algoritmo intelligente, ma poi è esploso nel corso degli anni con estensioni e modifiche - senza la guida utile di un ingegnere del software per tenerlo pulito. (Sono un grande fan dei team multidisciplinari.)

Quindi posso dire con una certa esperienza che alcune scelte chiave fatte male all'inizio dello sviluppo di un software (come una lingua o una libreria di chiavi) tendono a rimanere attaccate e causare dolore per molto tempo ... Hanno già "modellato" il software che li circonda. Mi sembra che potresti dover affrontare molti anni di pura pulizia del codice qui. (Sono riluttante a usare i numeri, ma sto pensando a più di 10 anni, forse molto di più se non riesci a ottenere il codice trasferito da G2 a qualcosa che supporti buoni strumenti di refactoring automatizzati come Eclipse / Java quick-smart.)

Mentre il mio stato predefinito è "refactoring e mantenere un sistema funzionante", penso anche che una volta che un problema diventa "troppo grande", un cambiamento / riscrittura più radicale diventa complessivamente più veloce. (E probabilmente porta ulteriori vantaggi, come passare a una tecnologia più moderna.) Lo dico con una certa esperienza porting su una nuova piattaforma software, ma da quello che raccolgo è ancora più drammatico con una porta a un pacchetto di modellazione matematica.

Per dare una prospettiva, potresti essere abbastanza sorpreso dalla riduzione delle dimensioni. Ad esempio, il 200.000 LoC potrebbe effettivamente essere rappresentato in qualcosa come 5.000 righe di equazioni (OK, sto indovinando qui, ma potrei provare a procurarti una vera testimonianza da amici nel settore); più alcuni moduli funzionali relativamente piccoli scritti in qualcosa come C (ad esempio, calcoli di proprietà fisiche - anche se a seconda del processo chimico potrebbero esistere pacchetti pronti all'uso. Questo perché letteralmente si getta via il codice della soluzione algoritmica e si lascia che uno "stack" generico di solutori matematici faccia il duro lavoro. Una volta eseguite le simulazioni, puoi fare molto di più con esse, come l'ottimizzazione del processo, senza modificare una riga di codice.

Infine direi: se l'unica documentazione affidabile dei vari modelli matematici (e algoritmi) è il codice stesso, vorrai l'aiuto degli scienziati e degli autori originali che ti aiuteranno a estrarre quei modelli, al più presto, non anni dopo quando alcuni potrebbero essere andati avanti. Dovrebbero scoprire che un linguaggio di modellazione matematica è un modo molto naturale per catturare quei modelli - possono persino (shock horror) divertirsi (ri) scriverlo.


Infine, poiché la mia risposta potrebbe non essere corretta, vorrei solo aggiungere un altro libro all'elenco dei buoni libri già citati qui: Clean Code di Robert Martin. Pieno di suggerimenti semplici (e giustificati) che sono facili da imparare e applicare, ma che potrebbero fare la differenza per le persone che sviluppano nuovo codice nella tua azienda.


2

Vorrei buttare giù il seguente:

  1. C'è un programmatore qui. Fanculo la politica. Conoscono il loro mestiere. Conosci il tuo. Segna quel territorio anche se devi pisciare su di esso. Sono scienziati. Possono rispettare quel genere di cose o dovrebbero, dal momento che fanno praticamente sempre lo stesso da soli. Con qualunque mezzo tu possa, segna i confini ora. Questo è quello che aggiusterò. Questo è ciò di cui non posso essere responsabile.

  2. Gli scienziati scrivono / testano gli algoritmi. Gli scienziati che vogliono scrivere i propri algoritmi in 1-3 lingue su cui tutti possono concordare per la conversione in codice di base. Ciò mette alla prova le loro cose su di loro. Oltre a ciò, dovranno aiutarti a isolare le importanti cose scientifiche rispetto al buon dio-sa-cosa hanno fatto per l'architettura. Il codebase è hosing. C'è un sacco di tagli e bruciature che dovranno essere fatti. Offri loro le opzioni per consegnarti versioni funzionanti di cose che impiegano ciò che sanno meglio in modo da poter fare ciò che sai fare meglio. Metti le loro conoscenze in una scatola di cui sono responsabili ma con cui puoi lavorare.

  3. Se possibile, usa un linguaggio orientato agli eventi con funzioni di prima classe. Quando tutto il resto fallisce, innescare un evento o lanciare una richiamata su un oggetto con un'interfaccia e un meccanismo di stato che ha effettivamente senso può essere un enorme risparmio di tempo quando sei nel profondo del codice del codice che non ha alcun senso sanguinante e molto probabilmente mai volontà. Python sembra apprezzare gli scienziati. Non è difficile incollare roba di livello C ad alta intensità matematica con quello. Sto solo dicendo

  4. Cerca qualcuno che abbia risolto questo o un problema simile. Dedica un po 'di tempo alla ricerca. Questi ragazzi hanno sentito parlare di G2 da qualcuno.

  5. Modelli di progettazione. Adattatori. Usali. Usali molto in situazioni come questa.

  6. Scopri cosa puoi della scienza. Più sai, meglio è possibile determinare l'intento nel codice.


13
MAI andare testa a testa con gli scienziati. MAI . Faranno della tua vita un inferno vivente. :)
haylem,

2

Fai prima l'analisi.

Vorrei fare qualche analisi prima di decidere cosa insegnare. Scopri dove sono i maggiori punti di dolore. Usa quelli per dare priorità alle pratiche da seguire.

Introdurre solo alcune modifiche alla volta (in una situazione simile ho fatto 2-3 pratiche ogni 2 settimane) .

Limiterei le pratiche a ~ 3 a seconda del livello di modifica dello stile di programmazione di SDLC; fino a quando non iniziano a sentirsi a proprio agio con loro (spingerei per introdurre 1 nuovo cambiamento ogni ~ 1-2 settimane man mano che si sentono più a proprio agio con l'idea di apprendere nuovi approcci). È anche una buona idea identificare quali sono i criteri per il successo. Cosa dovrebbe realizzare la pratica (anche se si tratta di un obiettivo morbido come il morale della squadra). In questo modo puoi mostrare se è efficace o no.

  • Perché limitare il numero di modifiche?

Anche se presumi che queste persone vogliano essere programmatori migliori e siano disponibili all'apprendimento, ci sono limiti a quanto e quanto velocemente le persone possono imparare nuovi concetti e applicarli; soprattutto se non dispongono di CS Foundation o hanno precedentemente partecipato a un ciclo di vita di sviluppo software.

Aggiungi una riunione di riepilogo settimanale per discutere di come le pratiche li hanno influenzati.

L'incontro dovrebbe essere usato per discutere di cosa è andato bene e di cosa ha bisogno di lavoro. Consenti loro di avere una voce e collaborare. Discutere e fare piani per affrontare i problemi che stanno incontrando e per visualizzare in anteprima le prossime modifiche in arrivo. Mantieni l'incontro focalizzato sulle pratiche e sulla loro applicazione. Fai un po 'di evangelizzazione sui benefici che dovrebbero iniziare a vedere dall'applicazione delle pratiche.

Alcune pratiche hanno la precedenza.

L'uso corretto di un sistema di controllo della versione (IMO) vince su tutto il resto. Dietro ci sono lezioni di modularizzazione, accoppiamento / coesione e tracciamento dei ticket funzione / bug.

Rimuovi le pratiche che non funzionano.

Non aver paura di sbarazzarti delle pratiche che non funzionano. Se c'è un costo elevato e poco o nessun beneficio, rimuovi la pratica.

Il miglioramento è un processo.

Trasmettere che un miglioramento costante e costante è un processo. Individua i maggiori punti di dolore, applica una soluzione, attendi / allena e ripeti. All'inizio si sentirà angosciosamente lento fino a quando non si accumula un certo slancio. Mantieni tutti concentrati sui miglioramenti che stanno arrivando e sui miglioramenti che hanno già successo.


0

Sembra che il primo passo che devi fare è vendere al team la necessità di investire in una nuova metodologia software. Secondo la tua affermazione, non c'è consenso nel team e ne avrai bisogno per poter avanzare lentamente con un "upgrade" lento del codice.

Vorrei (se posso) prendere personalmente le dure lezioni apprese e introdurrei ciascuno dei concetti chiave che desideri come soluzione al problema nel settore del software.

Ad esempio, due sviluppatori avevano copie diverse e hanno finito per distribuire una versione ibrida non testata -> Introdurre il controllo della versione, la ramificazione e il test.

Qualcuno ha rimosso alcune righe di codice che non ha capito e ha causato un'interruzione -> introdurre DDD.

Se le lezioni difficili non vengono condivise con te in modo sufficientemente dettagliato, mostra semplicemente i tuoi esempi di come le cose sono andate male quando questa disciplina non è stata rispettata.


0

Il controllo del codice sorgente è il passaggio 1 come già detto più volte. Mentre le persone con cui lavori potrebbero non essere sviluppatori professionisti e non risponderanno a molti jumbo mumbo aziendali o agili. Non sono nemmeno scimmie di codice di basso livello e cercare di trattarle in quel modo costringendole a fare le cose "a modo tuo" non volerà.

Devi esaminare cosa c'è là fuori. Se non hanno usato il controllo del codice sorgente, identificare semplicemente le versioni giuste del codice (se possibile) e quali saranno tutti i possibili risultati finali richiederà molto tempo. Quindi avrai il compito di insegnare ai tuoi colleghi come utilizzare il controllo del codice sorgente e convincerli che ne vale la pena. Inizia con i vantaggi!

Mentre lo stai facendo, trova altri frutti a bassa pendenza e risolvi questi problemi.

Soprattutto, ascolta ciò che hanno da dire e lavora per migliorare la loro situazione. Non preoccuparti di provare a mettere il timbro su ciò che fanno.

In bocca al lupo!

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.