| 
View
 

Kata Message Handler - gruppo 3

Page history last edited by mt 16 years, 10 months ago

 

public class Main {

    public static void main(String[] args) {
        String msg1 = "giallo";
        String msg2 = "verde";
        String msg3 = "rosso";

        MessageHandler msgHander  = new MessageHandler();

        msgHander.onMessage(msg1);
        msgHander.onMessage(msg2);
        msgHander.onMessage(msg3);
    }
}

class MessageHandler {

    void onMessage(String msg) {
        if ("giallo".equals(msg)) {
            System.out.println("yellow");
        } else if ("rosso".equals(msg)) {
            System.out.println("red");
        } else if ("verde".equals(msg)) {
            System.out.println("green");
        }
    }
}

Innanzitutto dobbiamo introdurre dei test.
per fare ciò però abbiamo bisogno di un refactoring preliminare 

passo 1: estrarre i metodi che stampano a video

 


public void onMessage(String msg) {

    if ("giallo".equals(msg)) {

        printYellow();

    } else if ("rosso".equals(msg)) {

        printRed();

    } else if ("verde".equals(msg)) {

        printGreen();

    }

}

 

protected void printYellow() {

          System.out.println("yellow");

}      

protected void printRed() {

          System.out.println("red");

}      

protected void printGreen() {

          System.out.println("green");


 

passo 2

isolare la responsabilità di stampare ad una classe Printer 

public class MessageHandler {

    Pinter printer = new Pinter();

    public void onMessage(String msg) {

        if ("giallo".equals(msg)) {

            printer.printYellow();

        } else if ("rosso".equals(msg)) {

            printer.printRed();

        } else if ("verde".equals(msg)) {

            printer.printGreen();

        }

    }

}

 

class Pinter {

    public void printYellow() {

        System.out.println("yellow");

    }

    public void printRed() {

        System.out.println("red");

    }

    public void printGreen() {

        System.out.println("green");

    }

}


passo 3 Factory method per l'oggetto printer

 

public class MessageHandler {

    Pinter printer;

    public MessageHandler() {

        printer = getPinter();

    }

...

    protected Pinter getPinter() {

        return new Pinter();

    }

}


 

passo 4

Per testare la classe MessageHandler possiamo innanzitutto creare una classe stub della classe Printer

 

public class PrinterStub extends Printer {

    public String printedMsg = null;

    public void printYellow() {

        printedMsg = "yellow";

    }

    public void printRed() {

        printedMsg = "red";

    }

    public void printGreen() {

        printedMsg = "green";

    }

}

e poi creare un test 

public class MessageHandlerTest extends TestCase {

   

    public void testOnMessage() {

        final PrinterStub printerStub = new PrinterStub();

 

        MessageHandler instance = new MessageHandler() {

            protected Printer getPinter() {

                return printerStub;

            }

        };

 

        String msg = "giallo";

        instance.onMessage(msg);

        assertEquals("yellow", printerStub.printedMsg);

    }

}


rifattorizziamo il test in modo da rendere la creazione dell'istanza di MessageHandler più semplice.

facciamo diventare printerStub un membro della classe di test e aggiungiamo il factory method hetMessageHandler.

 

public class MessageHandlerTest extends TestCase {

   

    final PrinterStub printerStub = new PrinterStub();

    public void testOnMessage() {

        MessageHandler instance = getMessageHandler();

        String msg = "giallo";

        instance.onMessage(msg);

        assertEquals("yellow", printerStub.printedMsg);

    }

    private MessageHandler getMessageHandler() {

        return new MessageHandler() {

            protected Printer getPinter() {

                return printerStub;

            }

        };

    }

}


possiamo ora rinominare il test testOnMessage in testOnMessageGiallo e aggiungere i test per il caso 'verde' e 'rosso'

 

    public void testOnMessage_giallo() {

        MessageHandler instance = getMessageHandler();

        String msg = "giallo";

        instance.onMessage(msg);

        assertEquals("yellow", printerStub.printedMsg);

    }

    public void testOnMessage_verde() {

        MessageHandler instance = getMessageHandler();

        String msg = "verde";

        instance.onMessage(msg);

        assertEquals("green", printerStub.printedMsg);

    }

    public void testOnMessage_rosso() {

        MessageHandler instance = getMessageHandler();

        String msg = "rosso";

        instance.onMessage(msg);

        assertEquals("red", printerStub.printedMsg);

    }


definiemo le stringhe costanti

 

    public final String GIALLO = "giallo";

    public final String VERDE =  "verde";

    public final String ROSSO =  "rosso";

    public final String YELLOW = "yellow";

    public final String GREEN =  "green";

    public final String RED =    "red";

   

    final PrinterStub printerStub = new PrinterStub();

    public void testOnMessage_giallo() {

        MessageHandler instance = getMessageHandler();

        String msg = GIALLO;

        instance.onMessage(msg);

        assertEquals(YELLOW, printerStub.printedMsg);

    }

    public void testOnMessage_verde() {

        MessageHandler instance = getMessageHandler();

        String msg = VERDE;

        instance.onMessage(msg);

        assertEquals(GREEN, printerStub.printedMsg);

    }

    public void testOnMessage_rosso() {

        MessageHandler instance = getMessageHandler();

        String msg = ROSSO;

        instance.onMessage(msg);

        assertEquals(RED, printerStub.printedMsg);

    }


 

muoviamo le variabili statiche YELLOW, GREEN e RED nella classe Printer

public class Printer {

    public static final String YELLOW = "yellow";

    public static final String GREEN =  "green";

    public static final String RED =    "red";

    public void printYellow() {

        System.out.println(YELLOW);

    }

    public void printRed() {

        System.out.println(RED);

    }

    public void printGreen() {

        System.out.println(GREEN);

    }

}

 

quindi nella classe di test

 

public class MessageHandlerTest extends TestCase {

    public final String GIALLO = "giallo";

    public final String VERDE =  "verde";

    public final String ROSSO =  "rosso";

   

    final PrinterStub printerStub = new PrinterStub();

    public void testOnMessage_giallo() {

        MessageHandler instance = getMessageHandler();

        String msg = GIALLO;

        instance.onMessage(msg);

        assertEquals(Printer.YELLOW, printerStub.printedMsg);

    }

    public void testOnMessage_verde() {

        MessageHandler instance = getMessageHandler();

        String msg = VERDE;

        instance.onMessage(msg);

        assertEquals(Printer.GREEN, printerStub.printedMsg);

    }

    public void testOnMessage_rosso() {

        MessageHandler instance = getMessageHandler();

        String msg = ROSSO;

        instance.onMessage(msg);

        assertEquals(Printer.RED, printerStub.printedMsg);

    }

....

}

 

 

 

 

 

 

 

 

Comments (3)

Andrea Rosa said

at 2:29 am on Nov 8, 2009

Ciao Marco,

grazie mille per avere messo il materiale on-line, questo mi ha dato la possibilità di rivederlo e mi vine subito una domanda:
Abbiamo fatto il refactoring con la classe printer e con l'introduzione dello stub però siamo ancora dipendenti dagli "if", mi pare che stavamo discutendo della possibilità di eliminare questa catena di if:
public void onMessage(String msg) {
if ("giallo".equals(msg)) {
printer.printYellow();
} else if ("rosso".equals(msg)) {
printer.printRed();
} else if ("verde".equals(msg)) {
printer.printGreen();
}
}
..come lo si potrebbe fare?
Se non hai tempo di rispondere qui, ne parliamo alla prossima occasione.
Grazie ancora per la tua precisione, chiarezza e passione che metti all'interno del gruppo.
--
Andrea

Bruno Pasquali said

at 6:52 am on Nov 8, 2009

Ciao a tutti
Prima di tutto ringrazio anche io per il materiale on-line e per a serata.

Una soluzione per eliminare gli "if" c'è nel materiale messo on-line da Ivan Gelpi e corrisponde all'uso di una mappa (hasht able) di cui si era disscusso a inizio kata.

Bruno

Ivan Gelpi said

at 9:49 am on Nov 12, 2009

Esatto,
in effetti c'è un metodo ancora migliore, come suggerito anche dal mio collega Nicola Breda, che è alla base di molte tecnologie.
Questo metodo permette non solo di eliminare gli If, ma anche di fare a meno della mappa, istanziando direttamente gli handler in base al nome del messaggio. Per evitare doppioni lo spiego direttamente nella note della pagina http://bergamo-xpug.pbworks.com/Kata+Message+Handler+-+gruppo+2 .
Avevo deciso di scartare questo metodo per disaccoppiare gli handler istanziati rispetto al nome dei messaggi e rendere la cosa più configurabile (grazie alla mappa) ma in effetti nel nostro caso la cosa era perfettamente inutile dato cha abbiamo sempre una corrispondenza tra messaggio e handler. Vi rimando comunque all'altra pagina per la soluzione alternativa.

Ciao
Ivan

You don't have permission to comment on this page.