3 potenti tecniche di codifica per eliminare condizionali disordinati
Introduzione a tre potenzi tecniche di codifica per ottimizzare e semplificare strutture condizionali complesse, migliorando la qualità e la manutenibilità del codice.
Introduzione a tre potenzi tecniche di codifica per ottimizzare e semplificare strutture condizionali complesse, migliorando la qualità e la manutenibilità del codice.
Nel sviluppo software, spesso ci troviamo di fronte a logiche di codice che devono gestire più scenari. Se non gestite correttamente, queste logiche possono facilmente evolversi in lunghe catene di if-else o enormi strutture switch. Questo articolo introdurrà diverse tecniche efficaci per ottimizzare queste strutture, migliorando la qualità e la manutenibilità del codice.
Supponiamo di sviluppare un sistema di autenticazione utente che deve verificare vari stati dell'utente prima di consentire l'accesso:
Questo codice ha evidenti problemi strutturali. Utilizza strutture if-else profondamente annidate, rendendo il codice difficile da leggere e manutenere. Man mano che il numero di controlli sulle condizioni aumenta, aumenta anche il livello di indentazione del codice, formando un cosiddetto codice "a forma di freccia". La logica di gestione degli errori è sparsa in diversi livelli di annidamento, il che non favorisce una gestione unitaria. Più importante, la logica principale del codice - il caso in cui l'accesso è consentito - è sepolta in profondità all'interno di più strati di giudizi condizionali, mancando di intuitività. Questo stile di codifica non solo riduce la leggibilità del codice, ma aumenta anche il rischio di errori e rende difficile l'espansione del codice.
Possiamo ottimizzare questo codice utilizzando l'approccio del "ritorno anticipato":
Adottando la strategia del "ritorno anticipato", abbiamo ottimizzato con successo la struttura originale del codice.
Questo metodo porta diversi miglioramenti:
Spesso ci imbattiamo in scenari in cui è necessario restituire risultati diversi in base a input diversi. Se non gestite adeguatamente, queste logiche possono facilmente evolversi in lunghe catene di if-else o enormi strutture switch. Ad esempio, in una piattaforma di e-commerce, è necessario restituire le descrizioni dello stato corrispondenti in base a diversi stati dell'ordine:
Questo è uno scenario tipico di restituzione di risultati diversi in base a diversi casi. Man mano che il numero di casi aumenta, la dichiarazione switch o i giudizi if-else diventano lunghi. Inoltre, in questo scenario, se gli utenti devono tradurre questi contenuti di stato in altre lingue, sarebbe necessario modificare il corpo della funzione o aggiungere nuove funzioni, il che comporterebbe costi di manutenzione significativi.
In questo caso, possiamo utilizzare il metodo della tabella di ricerca per ottimizzare il codice:
Prima di tutto, utilizzando un oggetto Map per memorizzare la relazione di mapping tra stati e descrizioni, il codice diventa più conciso. Abbiamo anche reso facile spostare le descrizioni dello stato nei file di configurazione, fornendo comodità per l'internazionalizzazione e gli aggiornamenti dinamici. Quando vengono aggiunti nuovi stati, non è necessario modificare il codice logico principale; basta aggiungere le coppie chiave-valore corrispondenti nella configurazione.
Quando si sviluppano grandi sistemi software, spesso è necessario supportare più fornitori di servizi o moduli funzionali. Possiamo considerare l'uso della programmazione orientata alle interfacce nella fase di progettazione del software per facilitare le espansioni successive, eliminando così la complessità di molteplici giudizi condizionali portata dalla programmazione "hard-coded" nei sistemi complessi.
Supponiamo di sviluppare un sistema di traduzione multilingue che deve supportare diversi fornitori di servizi di traduzione. Se non si considera la programmazione orientata alle interfacce dalla fase di progettazione, le espansioni successive diventeranno molto difficili:
Questa implementazione utilizza una struttura semplice e grezza di if-else per selezionare i fornitori di traduzione, rendendo il codice difficile da mantenere e espandere. Quando si aggiungono nuovi fornitori di traduzione in futuro, il codice esistente deve essere modificato e, man mano che è necessario supportare più fornitori di traduzione, il codice diventerà sovraccarico e difficile da mantenere. Allo stesso tempo, questo metodo complesso è anche difficile da testare con unità perché non è facile simulare diversi fornitori di traduzione.
Per risolvere questi problemi, possiamo utilizzare la programmazione orientata alle interfacce per ottimizzare il codice. La programmazione orientata alle interfacce è un modo importante per implementare il polimorfismo, consentendo a diversi oggetti di rispondere diversamente allo stesso messaggio.
Processo di implementazione:
Definendo l'interfaccia TranslationStrategy e introducendo la programmazione orientata alle interfacce, abbiamo ottenuto i seguenti vantaggi:
TranslationService può utilizzare strategie di traduzione diverse per ciascuna chiamata.TranslationService.TranslationService, il servizio diventa più privo di stato e thread-safe.Ottimizzare le strutture delle istruzioni condizionali è un mezzo importante per migliorare la qualità del codice. I tre metodi introdotti in questo articolo - programmazione difensiva, metodo della tabella di ricerca e programmazione orientata alle interfacce (combinata con il polimorfismo) - hanno ciascuno i loro scenari applicabili:
Nello sviluppo reale, spesso dobbiamo scegliere i metodi appropriati in base a situazioni specifiche e talvolta è necessario applicare in modo completo più tecniche. L'importante è bilanciare la semplicità, la leggibilità e la manutenibilità del codice, scegliendo la soluzione che meglio si adatta al problema attuale.
Ricorda, l'ottimizzazione eccessiva può portare a codice eccessivamente complesso. Mantenere il codice semplice e leggibile è sempre il principio primario. Quando applichi queste tecniche, dovrebbero essere fatte scelte sagge basate sulle esigenze specifiche del progetto e sul livello tecnico del team.