Come si misura significativamente la manutenibilità?

22

Contesto: sono uno sviluppatore di impresa in un negozio di MS.

Qualcuno può raccomandare un buon metodo di misurare oggettivamente la manutenibilità di un pezzo di codice o un'applicazione?

Perché manutenibilità : sono stanco delle metriche di "qualità" nel mio gruppo che ruotano attorno al numero di bug e alla copertura del codice. Entrambe le metriche sono facili da giocare, specialmente quando non stai misurando la manutenibilità. La perspicacia e le scadenze comportano enormi quantità di debito tecnico che non vengono mai realmente affrontate.

Perché la capacità di misurare obiettivamente : lavoro in un grande gruppo di imprese. Se non puoi misurarlo oggettivamente, non puoi renderlo responsabile o farlo migliorare. Le misurazioni soggettive non si verificano o non si verificano in modo coerente.

Sto osservando le metriche del codice VS2010 , ma mi chiedo se qualcuno ha eventuali altri consigli.

    
posta nlawalker 24.01.2011 - 23:10
fonte

11 risposte

7

The caveat with measuring maintainability is that you are attempting to predict the future. Code coverage, bug count, LOC, cyclomatic complexity all deal with the present.

La realtà è che a meno che tu non abbia prove concrete del fatto che il codice non è manutenibile poichè ... un errore di correzione ha causato N ore di tempo non necessario a causa di codice non gestibile; quindi avere una gamba su cui stare sarà intrinsecamente difficile. In questo esempio potrebbe essere stato causato dal fatto che è stata utilizzata una metodologia eccessivamente complessa quando sarebbe bastato qualcosa di molto più semplice. Camminare in un'area in cui si tenta di misurare metodologie, paradigmi e migliori pratiche diventa sempre più difficile con un guadagno minimo o nullo a lungo termine.

Scendere questa strada è, purtroppo, una strada verso il nulla. Concentrati sull'individuazione di problemi di base che hanno un merito sostanziale e non sono legati a sentimenti personali su un problema come la mancanza di convenzioni di denominazione attraverso il codice base e trovare un modo per misurare il successo e gli insuccessi intorno a tale problema di root. Ciò ti consentirà quindi di iniziare a mettere insieme una serie di blocchi da cui puoi iniziare a formulare soluzioni.

    
risposta data 24.01.2011 - 23:34
fonte
7

Bene, la misura che uso, o mi piace pensare di usare, è questa:

Per ogni requisito funzionale indipendente, a una sola riga, prendere o lasciare, è necessario eseguire un'istantanea del codice prima di implementarlo. Quindi implementalo, incluso trovare e correggere eventuali bug introdotti nel processo. Quindi esegui un diff tra il codice base prima e dopo. Il diff ti mostrerà un elenco di tutti gli inserimenti, le eliminazioni e le modifiche che hanno implementato la modifica. (Come inserire 10 righe consecutive di codice è one modificare.) Quanti cambiamenti ci sono stati? Il numero più piccolo è, in genere, il codice più gestibile è.

Io chiamo la ridondanza del codice sorgente, perché è come la ridondanza di un codice che corregge gli errori. L'informazione era contenuta in 1 blocco, ma era codificata come N pezzi, che devono essere tutti fatti insieme, per essere coerenti.

Penso che questa sia l'idea alla base di DRY, ma è un po 'più generale. Il motivo per cui è buono che il conteggio sia basso è, se occorrono N modifiche per implementare un tipico requisito, e come programmatore fallibile hai solo ottenuto il N-1 o il N-2 in modo corretto all'inizio, hai inserito 1 o 2 bug. Oltre allo sforzo di programmazione O (N), questi bug devono essere scoperti, localizzati e riparati. Ecco perché la piccola N è buona.

Mantenibile non significa necessariamente leggibile, per un programmatore che non ha imparato come funziona il codice. L'ottimizzazione di N potrebbe richiedere alcune operazioni che creano una curva di apprendimento per i programmatori. Ecco un esempio. Una cosa che aiuta è se il programmatore cerca di anticipare le modifiche future e lascia indicazioni su come fare nel commento del programma.

Penso che quando N viene ridotto abbastanza (l'optimum è 1) il codice sorgente è più simile a un dominio specifico della lingua (DSL). Il programma non "risolve" il problema in quanto "afferma" il problema, perché idealmente ogni requisito viene semplicemente rideterminato come un singolo pezzo di codice.

Sfortunatamente, non vedo le persone che imparano a fare così tanto. Piuttosto sembrano pensare che i nomi mentali dovrebbero diventare classi, ei verbi diventano metodi, e tutto ciò che devono fare è girare la manovella. Ciò si traduce in codice con N di 30 o più, nella mia esperienza.

    
risposta data 25.01.2011 - 03:28
fonte
5

La manutenibilità non è davvero misurabile. È una visione soggettiva di un individuo in base alle sue esperienze e preferenze.

Per un pezzo di codice dare un'idea di un design perfetto .

Quindi, per qualsiasi deviazione del codice reale da quella perfetta, diminuire il valore di 100 di un numero. Da cosa dipende esattamente dalle conseguenze di un approccio scelto non perfetto.

Un esempio:

Un pezzo di codice legge e importa alcuni formati di dati e potrebbe mostrare un messaggio di errore se qualcosa non va.

Una soluzione perfetta (100) avrebbe i messaggi di errore conservati in un posto comune. Se la tua soluzione li ha codificati come costanti di stringa direttamente nel codice, prendi, diciamo 15 off. Quindi il tuo indice di manutenibilità diventa 85.

    
risposta data 24.01.2011 - 23:35
fonte
4

Un risultato di codice difficile da mantenere è che ti richiederà più tempo (in "media") per correggere i bug. Quindi, a prima vista, una metrica sembra essere il tempo necessario per correggere un bug da quando viene assegnato (vale a dire che la correzione viene avviata) a quando è "pronto per il test".

Ora, funzionerà davvero solo dopo aver risolto un numero ragionevole di bug per ottenere il tempo "medio" (che cosa mai significhi). Non è possibile utilizzare la figura per un bug particolare, poiché quanto è difficile rintracciare non dipende solo dalla "manutenibilità" del codice.

Ovviamente, mentre correggi più bug il codice diventa "più semplice" da mantenere mentre lo stai migliorando (o almeno dovresti esserlo) e acquisisci maggiore familiarità con il codice. Contrastare questo è il fatto che i bug saranno tendenzialmente più oscuri e quindi ancora più difficili da rintracciare.

Questo soffre anche del problema che se le persone tendono ad affrettare correzioni di bug per ottenere un punteggio più basso, causando nuovi bug o non correggendo correttamente quello esistente che porta a un altro lavoro e forse anche un codice peggiore.

    
risposta data 24.01.2011 - 23:30
fonte
2

Trovo che le metriche del codice di Visual Studio siano abbastanza decenti per fornire una rapida metrica di "manutenibilità". 5 metriche primarie vengono acquisite:

  • Complessità ciclomatica
  • Profondità dell'eredità
  • Couling di classe
  • Linee di codice (per metodo, per classe, per progetto, qualunque sia, a seconda del tuo livello di roll-up)

L'indice di manutenibilità è quello che trovo utile. È un indice composito, basato su:

  1. Dimensione totale (linee di codice)
  2. N. di classi o file
  3. N. di metodi
  4. Complessità ciclomatica superiore a 20 (o 10 - configurabile, 10 è la mia preferenza)
  5. Duplicazione

Occasionalmente esaminerò i miei metodi con un basso indice di manutenibilità (basso = cattivo per questo). Quasi senza fallire, i metodi nel mio progetto con il più basso indice di manutenibilità sono quelli che hanno più bisogno di una riscrittura e sono i più difficili da leggere (o mantenere).

Consulta il white paper per ulteriori informazioni sui calcoli.

    
risposta data 25.01.2011 - 22:04
fonte
2

huge amounts of technical debt that never really get addressed

Che dire del debito tecnico che è "superato dagli eventi"?

Scrivo codice scadente e lo porto in produzione.

Osservi - correttamente - che non è gestibile.

Quel codice, tuttavia, è l'ultimo ciclo di funzionalità per una linea di prodotti che verrà ritirato perché il contesto legale è cambiato e la linea di prodotti non ha futuro.

Il "debito tecnico" è eliminato da una modifica legislativa che rende tutto obsoleto.

La metrica "manutenibilità" passò da "cattiva" a "irrilevante" a causa di considerazioni esterne.

Come si può misurare?

    
risposta data 25.01.2011 - 01:13
fonte
1

Due che saranno significativi sono complessità ciclomatica e accoppiamento di classe. Non puoi eliminare la complessità, tutto ciò che puoi fare è dividerlo in parti gestibili. Queste 2 misure dovrebbero darti un'idea di dove può essere localizzato il codice difficile da mantenere, o almeno dove cercare il più difficile.

La complessità ciclomatica è una misura di quanti percorsi ci sono nel codice. Ogni percorso dovrebbe essere testato (ma probabilmente non lo è). Qualcosa con una complessità superiore a circa 20 dovrebbe essere suddiviso in moduli più piccoli. Un modulo con una complessità cycomatica di 20 (uno potrebbe duplicare questo con 20 blocchi if then else successivi) avrà un limite superiore di 2 ^ 20 percorsi da testare.

L'accoppiamento di classe è una misura di quanto siano strettamente legate le classi. Un esempio di codice errato con cui ho lavorato presso il mio precedente datore di lavoro include un componente "livello dati" con circa 30 elementi nel costruttore. La persona per lo più "responsabile" di quel componente continuava ad aggiungere parametri di business e di interfaccia utente al costruttore / aprire le chiamate fino a quando non si trattava di una vera e propria palla di fango. Se la memoria mi serve correttamente, c'erano circa 15 diverse chiamate nuove / aperte (alcune non più utilizzate), tutte con set di parametri leggermente diversi. Abbiamo istituito revisioni del codice al solo scopo di impedirgli di fare più cose del genere - e per evitare che sembrasse come se lo stessimo individuando, abbiamo rivisto il codice di tutti sulla squadra, quindi abbiamo sprecato circa mezza giornata per 4-6 persone ogni giorno perché non volevamo ferire i sentimenti di un idiota.

    
risposta data 25.01.2011 - 02:03
fonte
1

Nella linea di fondo, la manutenibilità può essere misurata solo dopo richiesta, non prima . Cioè, puoi solo dire, se un pezzo di codice è gestibile, quando devi mantenerlo.

È relativamente ovvio misurare quanto sia stato facile adattare un pezzo di codice alle mutevoli esigenze. È quasi impossibile misurare in anticipo, in che modo risponderà ai cambiamenti dei requisiti. Ciò significherebbe che devi prevedere cambiamenti nei requisiti. E se puoi farlo, dovresti ottenere un prezzo nobile;)

L'unica cosa che puoi fare, è essere d'accordo con il tuo team, su una serie di regole concrete (come i principi SOLID), che tutti ritieni generalmente aumentino la manutenibilità.
Se i principi sono ben scelti (penso che andare con SOLID sarebbe una buona scelta per iniziare), puoi chiaramente dimostrare che sono stati violati e ritenere gli autori responsabili per questo.
Avrai un momento molto difficile, cercando di promuovere una misura assoluta per la manutenibilità, mentre convincere in modo incrementale la tua squadra ad attenersi a una serie concordata di principi consolidati ti sembra realistico.

    
risposta data 25.01.2011 - 02:25
fonte
0

La prossima cosa migliore di un peer code review è creare un'architettura adattabile prima di codificare un'unità o un prodotto. Red-Green-Refactor è un modo molto carino per farlo. Chiedi a un ragazzo suor di mettere insieme un'interfaccia funzionante e di dividere il lavoro. Tutti possono prendere il loro pezzo del puzzle e diventare rosso-verde la loro strada verso la vittoria. Dopo questo, una revisione e un refact del peer code sarebbero in ordine. Questo ha funzionato molto bene su un importante prodotto del passato su cui ho lavorato.

    
risposta data 24.01.2011 - 23:38
fonte
0

Questionario

Che ne pensi di fare un questionario anonimo per gli sviluppatori, da compilare una volta al mese? Le domande sarebbero andate come:

  • Quanto tempo hai speso il mese scorso sul progetto X (approssimativamente) [0% ... 100%]
  • Come giudicheresti lo stato della base di codice in termini di manutenibilità [davvero scadente, povero, neutro, ok, buono, veramente buono].
  • Quanto complesso valuteresti il codice base rispetto alla complessità del progetto [troppo complesso, giusto, troppo semplificato].
  • Quante volte ti sei sentito in difficoltà a risolvere i tuoi compiti a causa dell'eccessiva complessità della base di codice? [niente affatto, una volta ogni tanto, spesso, costantemente].

(Sentiti libero di aggiungere altre domande che ritieni siano utili per misurare la manutenibilità nei commenti e io le aggiungerò.)

    
risposta data 25.01.2011 - 08:48
fonte
0

Posso pensare a due modi per considerare la manutenibilità (sono sicuro che ci sono più speranze che altri possano trovare delle buone definizioni.

Modifica senza comprensione.

Un bug fixer può entrare nel codice e risolvere un problema senza dover capire come funziona l'intero sistema.

Ciò può essere ottenuto fornendo test unitari completi (test di regressione). Dovresti essere in grado di verificare che qualsiasi modifica al sistema non cambi il modo in cui il sistema si comporta con qualsiasi input valido specifico.

In questa situazione un bug fixer dovrebbe essere in grado di entrare e correggere un (semplice) bug con una conoscenza minima del sistema. Se la correzione funziona, nessuno dei test di regressione dovrebbe fallire. Se qualche test di regressione fallisce, allora devi passare allo stadio 2.

maintainabilty1 = K1 . (Code Coverage)/(Coupling of Code) * (Complexity of API)

Modifica con comprensione.

Se una correzione di bug diventa non banale e devi capire il sistema. Quindi qual è la documentazione del sistema. Siamo non che comunichiamo la documentazione dell'API esterna (sono relativamente inutili). Quello che dobbiamo capire è come funziona il sistema dove qualsiasi trucco intelligente (leggi hack) usato nelle implementazioni ecc.

Ma la documentazione non è sufficiente, il codice deve essere chiaro e comprensibile. Per misurare la comprensibilità di un codice possiamo usare un piccolo trucco. Dopo che lo sviluppatore ha terminato la codifica, dategli un mese per lavorare su qualcos'altro. Quindi chiedere loro di tornare indietro e documentare il sistema in modo che un molo possa ora comprendere il sistema. Se il codice è relativamente facile da capire, dovrebbe essere veloce. Se è scritto male impiegheranno più tempo a capire cosa hanno costruito e scritto la documentazione.

Quindi forse potremmo inventarci un po 'di questo:

maintainability2 = K2 . (Size of doc)/(Time to write doc)
    
risposta data 25.01.2011 - 09:10
fonte