COME EVITARE GLI IF-ELSE NEL CODICE JAVA


Spaghetti code is a pejorative term for software code that has a complex and tangled control structure, much like a bowl of spaghetti. It is difficult to understand, read, or modify due to its lack of structure or design. This type of code often results from poor programming practices or shortcuts, and it can lead to numerous challenges, including increased debugging time, reduced performance, and decreased maintainability.  

L'IF Dilemma

Al centro della progettazione del software si trova uno strumento semplice ma potenzialmente pericoloso: l'istruzione condizionale "IF". Innegabilmente fondamentale, il suo utilizzo per gestire i cambiamenti in un contesto di crescita, può essere un sabotatore silenzioso, complicando il codice e intricando la logica. La strategia IF può portare a problemi di debug, storie utente mai consegnate, debito tecnico, progettazione intricata, attriti nel team e altre inefficienze. In sostanza, la strategia IF può aumentare i costi e ritardare i tempi di consegna del software, degradando al contempo la qualità interna. 

Perché evitare gli "if"?

Ecco alcune ragioni principali per cui l'abuso di if è nocivo:

  1. Difficoltà di manutenzione: Più if ci sono, più il codice diventa difficile da capire e modificare.
  2. Violazione del Principio Open/Closed (OCP): Quando un nuovo comportamento viene aggiunto, bisogna modificare codice esistente, aumentando il rischio di introdurre bug.
  3. Problemi di performance: Un gran numero di if nidificati porta a un codice meno efficiente e più difficile da ottimizzare.
  4. Difficoltà di test: Il codice con molti if ha una complessità ciclomatica elevata, rendendo i test più complessi.

Negli ultimi anni, si è diffuso il cosiddetto movimento anti-if, che propone strategie per ridurre al minimo il numero di istruzioni condizionali, migliorando così la qualità del codice. In questo articolo, vedremo tre alternative efficaci per eliminare gli if in Java: il Factory Pattern, lo Strategy Pattern e l'uso degli Enum.


1. Ottimizzazione con gli enum

Gli enum sono molto utili per eliminare if-else in certi scenari, fornendo un'implementazione più chiara e scalabile.

Esempio

enum Operation {
    ADD {
        @Override
        public int apply(int a, int b) {
            return a + b;
        }
    },
    SUBTRACT {
        @Override
        public int apply(int a, int b) {
            return a - b;
        }
    };
    
    public abstract int apply(int a, int b);
}

public class Main {
    public static void main(String[] args) {
        int result = Operation.ADD.apply(10, 5);
        System.out.println("Risultato: " + result);
    }
}

Vantaggi:

  • Elimina if-else e switch.
  • Aggiungere nuove operazioni è semplice e non modifica il codice esistente.

2. Ottimizzazione con il pattern Factory

Abbiamo già ampiamente discusso dell'utilizzo di questo pattern creazionale ed il cui vantaggio è quello di creare oggetti senza usare if o switch e deleganda la logica di creazione ad una classe apposita. Di seguito il classico esempio fornito anche dalla latteratura:

Esempio

interface Shape {
    void draw();
}

class Circle implements Shape {
    public void draw() {
        System.out.println("Disegnando un cerchio");
    }
}

class Square implements Shape {
    public void draw() {
        System.out.println("Disegnando un quadrato");
    }
}

class ShapeFactory {
    public static Shape getShape(String shapeType) {
        return switch (shapeType.toLowerCase()) {
            case "circle" -> new Circle();
            case "square" -> new Square();
            default -> throw new IllegalArgumentException("Forma non supportata");
        };
    }
}

public class Main {
    public static void main(String[] args) {
        Shape shape = ShapeFactory.getShape("circle");
        shape.draw();
    }
}

Vantaggi:

  • Evita la creazione di istanze con if-else.
  • Segue il principio Open/Closed: possiamo aggiungere nuove forme senza modificare il codice esistente.

3. Ottimizzazione con il pattern Strategy

Lo Strategy Pattern consente di sostituire if multipli con una serie di classi che incapsulano diversi comportamenti.

Esempio

interface PaymentStrategy {
    void pay(int amount);
}

class CreditCardPayment implements PaymentStrategy {
    public void pay(int amount) {
        System.out.println("Pagato " + amount + " con carta di credito");
    }
}

class PayPalPayment implements PaymentStrategy {
    public void pay(int amount) {
        System.out.println("Pagato " + amount + " con PayPal");
    }
}

class PaymentContext {
    private final PaymentStrategy strategy;
    
    public PaymentContext(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
    
    public void executePayment(int amount) {
        strategy.pay(amount);
    }
}

public class Main {
    public static void main(String[] args) {
        PaymentContext context = new PaymentContext(new CreditCardPayment());
        context.executePayment(100);
    }
}

Vantaggi:

  • Separazione dei comportamenti.
  • Possibilità di cambiare la strategia di pagamento senza modificare il codice principale.
  • Facile estensione.

4. Utilizzo delle Stream API

Lo Stream API di Java fornisce un modo elegante per evitare if utilizzando operazioni funzionali come filter, map e reduce.

Esempio

import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> names = List.of("Alice", "Bob", "Charlie", "David");
        names.stream()
             .filter(name -> name.startsWith("A"))
             .forEach(System.out::println);
    }
}

Vantaggi:

  • Codice più leggibile e conciso.
  • Semplifica la gestione dei dati senza if nidificati.
  • Migliora le performance sfruttando il parallelismo.

Conclusione

L'uso eccessivo di if rende il codice meno leggibile, difficile da testare e da mantenere. Adottando pattern come Factory, Strategy ed Enum, possiamo rendere il nostro codice più pulito, scalabile e manutenibile.

Seguire il principio anti-if non significa eliminare completamente gli if, ma usarli con consapevolezza e solo dove realmente necessario.


Comments

Popular posts from this blog

UNA PICCOLA INTRODUZIONE A DART

AGGIORNAMENTO INVESTIMENTI 2° TRIMESTRE 2024

AGGIORNAMENTO INVESTIMENTI 1° TRIMESTRE 2024