www.rozumim.cz

Nevolej tu metodu!

Objekt má metodu. Zavolám ji. Metoda vrací objekt. Ten objekt má metodu. Zavolám ji. Metoda vrací objekt. Ten objekt má metodu…

Co je na tom špatně? Překladač mi to přeloží, dělá to, co má, tak je to dobrý, ne?

Příklad:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ZpracovaniOdpovedi {

  public void zpracujOdpoved(PrubehDotazu prubeh){

    //(...)

    // objekt má metodu, ta vrátí objekt, ten má metodu, ta vrátí ...
    Mesto mesto = prubeh.getDotaz().getAutor().getAdresa().getMesto();
    
    // (...)
    
  }
}

Test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class ZpracovaniOdpovediTest {

  @Test
  public void zpracujOdpoved_pozitivni(){

    PrubehDotazu prubeh = new PrubehDotazu();
    
    Dotaz  dotaz = new Dotaz();
    prubeh.setDotaz(dotaz);
    
    Autor autor = new Autor();
    dotaz.setAutor(autor);
    
    Adresa adresa = new Adresa();
    autor.setAdresa(adresa);
    
    Mesto mesto = new Mesto();
    adresa.setMesto(mesto);

    //(...)

    ZpracovaniOdpovedi testovanaAkce = new ZpracovaniOdpovedi();

    testovanaAkce.zpracujOdpoved(prubeh);
    
    Assert.assertTrue(...)

  }
}

Vydíte problém? Jasně, getAutor() přece může vrátit null! Jenže o to mi teď nejde.

Problém je příliš silná závislost mezi třídou ZpracovaniOdpovedi a vnitřní implementací třídy Dotaz. Pokud ZpracovaniOdpovedi.zpracujOdpoved(PrubehDotazu) potřebuje instanci Mesto, měl by o ni požádat přímo parametr PrubehDotazu. Takový kód Vám zjednoduší budoucí změny a už teď se Vám budou lépe psát testy.

Lepší varianta:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ZpracovaniOdpovedi {

  public void zpracujOdpoved(PrubehDotazu prubeh){

    //(...)

    // zde nás nezajímá, jak PrubehDotazu instanci Mesto najde
    Mesto mesto = prubeh.getMestoAutoraDotazu();

    // (...)

  }
}

Test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class ZpracovaniOdpovediTest {

  @Test
  public void zpracujOdpoved_pozitivni(){

    final Mesto mesto = new Mesto();

    PrubehDotazu prubeh = new PrubehDotazu() {

      @Override
      public Mesto getMestoAutoraDotazu() {
        return mesto;
      }
    };

    //(...)

    ZpracovaniOdpovedi testovanaAkce = new ZpracovaniOdpovedi();

    testovanaAkce.zpracujOdpoved(prubeh);

    Assert.assertTrue(...)

  }
}

A kdybyste mi nevěřili, říká se tomu Law Of Demeter.

6. 2. 2014, kategorie: it
comments powered by Disqus