Il tuo codice può sentire l'odore! Come sistemarlo

Il tuo codice può sentire l'odore! Come sistemarlo / Programmazione

UN odore di codice è un frammento di codice o schema generale di codifica che sembra che potrebbe indicare un problema più profondo nella struttura generale e nella progettazione di una base di codice.

Pensa a un odore di codice come qualsiasi segno che suggerisce che una sezione di codice dovrebbe essere refactored. Non è che il codice sia bacato o non funzionale - spesso i tempi, il codice malefico funziona bene - ma il codice maleodorante è spesso difficile da mantenere ed estendere, il che può portare a problemi tecnici (specialmente su progetti più grandi).

In questo articolo, metteremo in evidenza 10 dei più comuni odori di codice, cosa cercare e come deodorarli. Se sei un nuovo programmatore Come imparare la programmazione senza tutti gli stress Come imparare la programmazione senza tutti gli stress Forse hai deciso di perseguire la programmazione, sia per una carriera che per un semplice hobby. Grande! Ma forse stai iniziando a sentirti sopraffatto. Non così eccezionale. Ecco l'aiuto per facilitare il tuo viaggio. Leggi di più, evita questi e il tuo codice sarà notevolmente migliore!

1. Accoppiamento stretto

Il problema
L'accoppiamento stretto è quando due oggetti sono così dipendenti dai dati e / o dalle funzioni di un altro che modificando uno richiede la modifica dell'altro. Quando due oggetti sono accoppiati in modo troppo stretto, apportare modifiche al codice può essere un incubo ed è più probabile che introducano bug ad ogni cambio.

Per esempio:

class Worker Bike bike = new Bike (); public void commute () bike.drive (); 

In questo caso, Worker e Bike sono strettamente accoppiati. E se un giorno volessi guidare una macchina invece di una bicicletta per i tuoi spostamenti? Dovresti entrare nella classe Worker e sostituire tutto il codice relativo alla moto con il codice relativo all'auto. È disordinato e soggetto a errori.

La soluzione
Puoi allentare l'accoppiamento aggiungendo uno strato di astrazione. In questo caso, la classe Worker non vuole solo guidare Bikes, ma anche Cars, e forse Trucks, possibilmente anche Scooter. Questi sono tutti i veicoli, no? Crea quindi un'interfaccia Vehicle, che ti permetta di inserire e sostituire diversi tipi di Veicoli come desiderato:

classe Operaio Veicolo veicolo; public void changeVehicle (Vehicle v) vehicle = v;  public void commute () vehicle.drive ();  interface Vehicle void drive ();  classe Bike implements Vehicle public void drive ()  classe Car implementa Vehicle public void drive () 

2. God Objects

Il problema
Un oggetto God è una classe / modulo enorme che contiene troppe variabili e funzioni. esso “sa troppo” e “fa troppo,” che è problematico per due ragioni. Innanzitutto, altre classi / moduli diventano eccessivamente dipendenti da questo per i dati (accoppiamento stretto). In secondo luogo, la struttura complessiva del programma diventa fangosa poiché tutto viene stipato nello stesso posto.

La soluzione
Prendi un oggetto di Dio, separa i suoi dati e le sue funzioni in base a quali problemi esistono per risolverli, quindi trasforma quei raggruppamenti in oggetti. Se hai un oggetto di Dio, potrebbe essere meglio come una composizione di molti oggetti più piccoli.

Ad esempio, supponiamo di avere una classe utente mostruosa:

class User nome utente String pubblico; password stringa pubblica; indirizzo di stringa pubblico; codice di accesso pubblico a stringa; public int age; ... public String getUsername () return username;  public void setUsername (String u) username = u; 

Potresti convertirlo in una composizione di quanto segue:

utente di classe credenziali credenziali; Profilo profilo; ... credenziali di classe nome utente stringa pubblico; public String password; ... public String getUsername () return username;  public void setUsername (String u) username = u; 

La prossima volta che è necessario modificare le procedure di accesso, non è necessario eseguire la scansione attraverso una massiva classe utente perché la classe Credentials è più gestibile!

3. Funzioni lunghe

Il problema
Una funzione lunga è esattamente ciò che sembra: una funzione che è cresciuta troppo a lungo. Mentre non c'è un numero specifico per quante linee di codice è “troppo lungo” per una funzione, è una di quelle cose in cui lo sai quando lo vedi. È praticamente una versione più ristretta del problema oggettuale di Dio: una lunga funzione ha troppe responsabilità.

La soluzione
Le funzioni lunghe devono essere suddivise in numerose sottofunzioni, in cui ciascuna sottofunzione è progettata per gestire un singolo compito o problema. Idealmente, la funzione long originale si trasformerà in una lista di chiamate sub-function, rendendo il codice più pulito e più facile da leggere.

4. Parametri eccessivi

Il problema
Una funzione (o costruttore di classi) che richiede troppi parametri è problematica per due motivi. Innanzitutto, rende il codice meno leggibile e rende più difficile il test. Ma in secondo luogo, e soprattutto, può indicare che lo scopo della funzione è troppo ambiguo e sta cercando di gestire troppe responsabilità.

La soluzione
Mentre “troppi” è soggettivo per un elenco di parametri, si consiglia di diffidare di qualsiasi funzione che abbia più di 3 parametri. Certo, a volte ha senso avere una singola funzione con 5 o anche 6 parametri, ma solo se c'è davvero una buona ragione per farlo.

Il più delle volte, non ce n'è uno e il codice sarebbe meglio spezzando quella funzione in due o più funzioni diverse. non mi piace il “Funzioni lunghe” odore di codice, questo non può essere risolto semplicemente sostituendo il codice con sotto-funzioni - la funzione stessa deve essere divisa e suddivisa in funzioni separate che coprono responsabilità separate.

5. Identificatori con nome errato

Il problema
Nome variabile a una o due lettere. Nomi di funzioni non descrittive. Nomi di classe eccessivamente ornati. Contrassegnare i nomi delle variabili con il loro tipo (ad es. B_isCounted per una variabile booleana). E, peggio ancora, mescolando diversi schemi di denominazione in un'unica base di codice. Tutto ciò si traduce in codice difficile da leggere, difficile da capire e difficile da gestire.

La soluzione
Scegliere buoni nomi per variabili, funzioni e classi è un'abilità difficile da imparare. Se stai partecipando a un progetto esistente, esegui il controllo e scopri come vengono denominati gli identificatori esistenti. Se c'è una guida di stile, memorizzala e rispettala. Per i nuovi progetti, prendi in considerazione la possibilità di formare la tua guida di stile e attenerci ad essa.

In generale, i nomi delle variabili dovrebbero essere brevi ma descrittivi. I nomi delle funzioni dovrebbero in genere avere almeno un verbo e dovrebbe essere immediatamente ovvio ciò che la funzione fa solo dal suo nome, ma evitare di stipare troppe parole. Lo stesso vale per i nomi delle classi.

6. Numeri magici

Il problema
Stai sfogliando un codice che (si spera) abbia scritto qualcun altro e hai individuato dei numeri codificati. Forse fanno parte di un'istruzione if, o forse parte di alcuni calcoli arcani che non sembrano avere senso. Devi modificare la funzione, ma non puoi dare un senso a cosa significano i numeri. Graffiare la testa del cue.

La soluzione
Quando si scrive codice, questi cosiddetti “numeri magici” dovrebbe essere evitato a tutti i costi. I numeri hardcoded hanno senso nel momento in cui vengono scritti, ma possono perdere rapidamente ogni significato, specialmente quando qualcun altro cerca di mantenere il proprio codice.

Una soluzione è lasciare commenti che spieghino il numero, ma l'opzione migliore è convertire numeri magici in variabili costanti (per calcoli) o enumerazioni (per istruzioni condizionali e istruzioni switch). Dando un numero magico a un nome, il codice diventa infinitamente più leggibile a colpo d'occhio e meno incline a modifiche buggy.

7. Nidificazione profonda

Il problema
Ci sono due modi principali per finire con codice profondamente annidato: cicli e istruzioni condizionali. Il codice profondamente annidato non è sempre male, ma può essere problematico perché può essere difficile da analizzare (specialmente se le variabili non sono ben definite) e anche più difficile da modificare.

La soluzione
Se ti ritrovi a scrivere un ciclo for double, triple, o anche quadruplo, allora il tuo codice potrebbe tentare di raggiungere troppo lontano da se stesso per trovare i dati. Invece, fornire un modo per i dati da richiedere attraverso una chiamata di funzione su qualsiasi oggetto o modulo contiene i dati.

D'altra parte, le dichiarazioni condizionali a nidificazione profonda sono spesso un segno che stai cercando di gestire troppa logica in una singola funzione o classe. Infatti, la nidificazione profonda e le funzioni lunghe tendono ad andare di pari passo. Se il tuo codice contiene istruzioni switch di grandi dimensioni o istruzioni nidificate if-then-else, potresti invece voler implementare una macchina a stati o un modello di strategia.

Il nesting profondo è particolarmente diffuso tra programmatori di giochi inesperti 5 Strumenti software di sviluppo giochi gratuiti per creare i tuoi giochi 5 Strumenti software di sviluppo giochi gratuiti per creare i tuoi giochi Ecco i migliori software e strumenti di sviluppo di giochi gratuiti che puoi utilizzare per iniziare a realizzare il tuo sogno oggi. Leggi di più !

8. Eccezioni non gestite

Il problema
Le eccezioni sono potenti ma facilmente abusate. I programmatori pigri che usano in modo errato le dichiarazioni throw-catch possono rendere il debugging esponenzialmente più difficile, se non impossibile. Ad esempio, ignorare o seppellire le eccezioni rilevate.

La soluzione
Invece di ignorare o seppellire le eccezioni scoperte, almeno stampare la traccia dello stack dell'eccezione in modo che i debugger abbiano qualcosa su cui lavorare. Permettere al tuo programma di fallire silenziosamente è una ricetta per i futuri mal di testa, garantito! Inoltre, preferisci rilevare eccezioni specifiche rispetto alle eccezioni generali. Ulteriori informazioni nel nostro articolo su come gestire le eccezioni nel modo giusto Come gestire le eccezioni Java nel modo giusto Come gestire le eccezioni Java nel modo giusto In questo articolo, imparerai quali sono le eccezioni Java, perché sono importanti, come usali e errori comuni da evitare. Leggi di più .

9. Codice duplicato

Il problema
Esegui la stessa logica esatta in più aree non correlate del tuo programma. Più tardi, ti rendi conto che è necessario modificare quella logica, ma non ricordare tutti i punti in cui è stata implementata. Finisci per cambiarlo solo in 5 su 8 luoghi, con conseguenti comportamenti buggy e inconsistenti.

La soluzione
Il codice duplicato è un candidato ideale per essere trasformato in una funzione. Ad esempio, supponiamo tu stia sviluppando un'applicazione di chat e scrivi questo:

String queryUsername = getSomeUsername (); boolean isUserOnline = false; for (String username: onlineUsers) if (username.equals (queryUsername)) isUserOnline = true;  if (isUserOnline) ...

Da qualche altra parte nel codice, ti rendi conto che è necessario eseguire lo stesso “questo utente è online?” dai un'occhiata. Invece di copiare il ciclo, puoi estrarlo in una funzione:

public booleano isUserOnline (String queryUsername) for (String username: onlineUsers) if (nomeutente.equals (queryUsername)) return true;  return false; 

Ora ovunque nel tuo codice, puoi usare il controllo isUserOnline (). Se è necessario modificare questa logica, è possibile modificare il metodo e verrà applicato ovunque venga chiamato.

10. Mancanza di commenti

Il problema
Il codice non ha assolutamente commenti da nessuna parte. Nessun blocco di documentazione per le funzioni, nessuna panoramica di utilizzo per le classi, nessuna spiegazione degli algoritmi, ecc. Si potrebbe sostenere che il codice ben scritto non ha bisogno di commenti, ma la verità è che anche il codice scritto meglio richiede ancora più energia mentale per capire che l'inglese.

La soluzione
L'obiettivo di una base di codice di facile manutenzione dovrebbe essere il codice scritto abbastanza bene da non farlo bisogno commenti, ma li ha ancora. E quando scrivi dei commenti, cerca i commenti che spiegano perché esiste uno snippet di codice invece di spiegare che cosa sta facendo I commenti vanno bene per l'anima e la sanità mentale. Non trascurarli.

Come scrivere codice che non sembri

Per quanto possa sembrare ovvio, la maggior parte degli odori di codice derivano da un fraintendimento o un'abbandono di buoni principi e schemi di programmazione 10 Principi di programmazione di base Ogni programmatore deve seguire 10 principi di programmazione di base Ogni programmatore deve seguire Scrivi sempre codice che può essere mantenuto da chiunque possa terminare lavorare sul tuo software. A tal fine, qui ci sono diversi principi di programmazione per aiutarti a ripulire il tuo atto. Leggi di più . Ad esempio, una solida adesione al principio DRY elimina la maggior parte della duplicazione del codice, mentre la padronanza del principio di Responsabilità Unica rende quasi impossibile creare mostruosi oggetti di Dio.

Si consiglia inoltre di leggere il nostro articolo su come scrivere codice più pulito 10 Suggerimenti per scrivere Cleaner & Better Codice 10 Suggerimenti per scrivere Cleaner e Better Code Scrittura di codice pulito sembra più facile di quanto non sia in realtà, ma ne valgono i benefici. Ecco come iniziare a scrivere codice più pulito oggi. Leggi altro, che esamina un aspetto più pratico della programmazione. Se non riesci a leggere il tuo codice e comprenderlo a colpo d'occhio, come farà qualcun altro? Il codice pulito è codice inodore.

Che cosa combatti di più quando si tratta di programmazione? Condividi con noi giù nei commenti qui sotto!

Immagine di credito: SIphotography / Depositphotos

Scopri di più su: Programmazione.