TDD_I_03: Rovnost pro všechny

Když mám proměnnou typu int a zvětším ji o 1, neočekávám, že se původní číslo změní, ale čekám, že se použije nová hodnota. Objekty se takto většinou nechovají. Kdzž mám smlouvu a její krytí zvětším o 1, tak se krytí smlouvy změní (vždyť já vím že je to téma nejrůznějších zajímavých obchodních pravidel, která se nás tu však vůbec netýkají).

Objekty můžeme použít jako hodnoty, stajně jako nzní používáme objekt Dolar. Vzorem pro to je hodnotový objekt (Value Object). Jedním z úskalí hodnotových objektů je, že jkmile je hodnota instance objektu nastavena v konstruktoru, už se nikdy nezmění.

Existuje jedna veliká výhoda výhoda používání hodnotových objektů: Nemusíte si dělat naprosto žádné starosti s problematikou aliasů. Řekněme, že mám jeden šek a nastavím jeho hodnotu na pět dolarů. Potom nastavím hodnotu jiného šeku na stejných pět dolarů. Jedna z nejhorších chyb v mé kariéře se stala, když jsem nechtěně zaměnil hodnotu prvního šeku s hodnotou druhého šeku. To jsou aliasy.

Máte-li hodnotový objekt, nemusíte si dělat starosti s aliasy. Jestliže mám pět dolarů, mám zajištěno, že to bude vždy pět dolarů. Chce-li někdo sedm dolarů, musí vytvořit úplně nový objekt.

$5 + 10 CHF = $10 je-li kurz 2:1

$5 * 2 = $10

Převést položku mnozstvi na soukromou

Vedlejší účinky třídy Dolar?

Zaokrouhlování peněz?

Metoda equals()

jedním důsledkem hodnotových objektů je, že všechnz operace musí vracet nový objekt, jak jsme to viděli v druhé kapitole. Dalším důsledkem je, že hodnotové objekty by měly překrýt metodu equals(), protože jedněch pět dolarů je stejně dobrých jako pět jiných.

$5 + 10 CHF = $10 je-li kurz 2:1

$5 * 2 = $10

Převést položku mnozstvi na soukromou

Vedlejší účinky třídy Dolar?

Zaokrouhlování peněz?

Metoda equals()

Metoda hashCode()

Používáte-li objekty Dolar jako klíč v hešovací tabulce a implementujete metodu equals(), potom musíte také implementovat metodu hashCode(). Přidáme ji do seznamu úkolů a vrátíme se k ní, až to bude nutné.

Že nepřemýšlíte o implementaci metody equals()? Dobře. Já také ne. Praštil jsem se přes ruce pravítkem a přemýšlím o tom, jak otestovat rovnost. Předně, pět dolarů by se mělo rovnat pěti dolarům:

	public void testRovnosti() {
		assertTrue(new Dolar(5).equals(new Dolar(5)));
	}

Ukazatel poslušně zčervená. Falešná implementace má vrátit pouze hodnotu true:

Dolar

	public boolean equals(Object object) {
		return true;
	}

Jak vy, tak já víme, že hodnota true znamená, že 5 == 5, což je ve skutečnosti mnozstvi == 5, což je ve skutečnosti mnozstvi == Dolar.mnozstvi. Kdybychom však tyto kroky prošli, nemohl bych vám ukázat třetí, nejkonzervativnější implementační postup: triangulaci.

Když dva přijímače ve známé vzdálenosti mohou oba měřit sílu a směr radiového signálu, pak máme dostatek informací k výpočtu umístění jiného zdroje signálu (pokud si ovšem z trigonometrie pamatujete více než já). Tento výpočet se nazývá triangulace.

Analogicky, kdž triangulujeme, pouze obměňujeme kód, pro který máme dva nebo více příkladů. Jednoduše ignorujeme duplicitu mezi kódem testu a modelu. Vyžaduje-li druhý příklad obecnější řešení, tehdy a jedině tehdy je čas na zobecňování. Takže k triangulaci potřebujeme druhý příklad. Co třeba $5 != $6?

	public void testRovnosti() {
		assertTrue(new Dolar(5).equals(new Dolar(5)));
		assertFalse(new Dolar(5).equals(new Dolar(6)));
	}

Teď je třeba zobecnit metodu equals():

Dolar

	public boolean equals(Object object) {
		Dolar dolar = (Dolar) object;
		return mnozstvi == dolar.mnozstvi;
	}

$5 + 10 CHF = $10 je-li kurz 2:1

$5 * 2 = $10

Převést položku mnozstvi na soukromou

Vedlejší účinky třídy Dolar?

Zaokrouhlování peněz?

Metoda equals()

Metoda hashCode()

Triangulaci jsme také mohli s úspěchem použít k zobecnění metody krat(). Pokud bychom měli $5 x 2 = $10 a $5 x 3 = $15, nemohli bychom už nikdy vracet konstantu.

Triangulace mi připadne směšná. Používám ji pouze tehdy kdzž vůbc nevím, jak refaktorovat. Když vidím, jak odstranit duplicitu mezi kódem a testy a vytvořit obecné řešení, tak to prostě udělám. Proč bych měl psát další test, který by mi umožnil napsat to, co bych mohl napsat hned?

Chybí-li však inspirace, poskytuje triangulace příležitost k zamyšlení se nad problémem z poněkud odlišného úhlu pohledu. Jaká měřítka variability se snažíte ve svém návrhu podporovat? Změňte některé z nich a odstanete jasnější odpověď.

$5 + 10 CHF = $10 je-li kurz 2:1

$5 * 2 = $10

Převést položku mnozstvi na soukromou

Vedlejší účinky třídy Dolar?

Zaokrouhlování peněz?

Metoda equals()

Metoda hashCode()

Rovnost s null

Rovnost objektů

A tak jsme se na chvíli vypořádali s rovností. A o takhle porovnání s hodnotou null nebo porovnání s dalšími objekty? To se běžně používá, ale v této chvíli to pro nás není nezbytné. Takže to přidáme na náš seznam úkolů.

Nyní, když máme metodu equals(), můžeme přímo vzájemně porovnávat objekty Dolar. To nám umožní změnit datovou pložku mnozstvi na soukromou, tak jak by tomu mělo být u každé správné instanční proměnné. Abychom si to zopakovali:

Vývoj řízený testy, Kapitola 2 | Dr3dweRkZ | Vývoj řízený testy, Kapitola 4