TDD_I_02: Znetvořené objekty

Obecný cyklus TDD vypadá takto:

  1. Napište test. Přemýšlejte o tom, jak vymyšlené operace převést na kód. Píšete příběh. Vymyslete rozhraní, které by se vám líbilo. Zahrňte všechny části příběhu, které vás napadnou a budou nezbytné k získání správných odpovědí.
  2. Spusťte test. Nejvyšší prioritu má zelený ukazatel průběhu. Je-li jasné a jednoduché řešení zřejmé, napište je. Jestliže je sice jasné a jednoduché řešení zřejmé, ale zabere nějaký čas, poznamenejte si to a vraťte se zpět k hlavnímu problému, jímž je pro vás v tuto chvíli zezelenání ukazatele průběhu. Tato změna estetiky je pro některé zkušené softwarové inženýry obtížná. Ti pouze vědí,jak dodržovat pravidla psrávného projektování. Zelený ukazatel ospravedlňuje všechnz prohřešky. Ale jen na chvilku.
  3. Opravte kód. Teď, když se systém chová správně, opusťte hříšnou cestu po níž jste dosud šli. Vraťte se na přímou a úzkou vestičku správné tvorby softwaru. Nyní odstraňte duplicitu kterou jste zavedli a zaměřte se na rychlé získání zeleného ukazatele.

Cílem je čistý kód, který funguje (díky Ronu Jeffriesovi za jeho pregnantní vyjádření). Čistý kód, který funguje, je občas mimo dosah i těch nejlepších programátorů a nejčastěji je mimo dosah většiny programátorů (jako jsem já). Rozděl a panuj, chlapče. Nejprve vyřešíme část "který funguje". Pak se teprve zaměříme na část "čistý kód". Jedná se o opačný postup než v případě architekturou řízeného vývoje. tam se nejprve řeší "čistý kód" a pak se honíte, abyste již do hotového návrhu začlenili poznatky, jež získáte při řešení části "který funguje".

$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?

Získali jsme jeden fungující test, ale při jeho vztváření jsme si všimli něčeho zvláštního: ldyž provedeme nějakou operaci s objektem Dolar, objekt se změní. Chci, aby bylo možné napsat:

	public void testNasobeni() {
		Dolar pet = new Dolar(5);
		pet.krat(2);
		assertEquals(10, pet.mnozstvi);
		pet.krat(3);
		assertEquals(15, pet.mnozstvi);
	}

Nedovedu si představit čistý způsob, jak tento test zprovoznit. Po prvním volání metody krat() už pět není pět, ale deset. Kdzž však metoda krat() vrátí nový objekt, můžeme násobit našich původních pět babek celý den a nikdy se nezmění. Touto změnou měníme rozhraní objektu Dolar, takže musíme změnit i test. To je v pořádku. Naše předpoklady ohledně správného rozhraní nejsou o nic dokonalejší než naše odhady správné implementace.

	public void testNasobeni() {
		Dolar pet = new Dolar(5);
		pet.krat(2);
		assertEquals(10, pet.mnozstvi);
		pet.krat(3);
		assertEquals(15, pet.mnozstvi);
	}

Nový test nepůjde zkompilovat, dokud nezměníme deklaraci metody krat():

Dolar

	Dolar krat(int nasobek) {
		mnozstvi =* nasobek;
		return null;
	}

Nyní lze test zkompilovat, ale nefunguje. Pokrok! Abychom ho zprovoznili, musíme vrátit nov objekt Dolar se psrávnou hodnotou:

Dolar

	Dolar krat(int nasobek) {
		return new Dolar(mnozstvi * nasobek);

$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?

Když jsme v první kapitole zprovoznili test, začali jsme falešnou implementací a postupně jsme ji převedli na skutečnou. V tomto okamžiku jsme zapsali to, o čem jsme předpokládali že je správná implementace, a modlili jsme se zatímco test běžel (samozřejmě jen krátkou modlitbičku, protože test trval jen několik milisekund). Protože jsme měli štěstí a test fungoval, můžeme přejít k dalšímu úkolu.

Následují dva ze tří postupů, které používám když se potřebuje rychle dobrat zeleného ukazatele:

Když používám TDD v praxi, obvykle přecházím mezi těmito dvěma způsoby implementace. Jde-li všechno hladce a já vím, co psát, používám jednu zřejmou implementaci za druhou (pokaždé spouštím test, abych se ujistil že to, co je zřejmé pro mě, je také zřejmé pro můj počítač). Jakmile někdy dojdu neočekávaně k červenému ukazateli, zazálohuji, přejdu k falešné implementaci a refaktoruji abych získal správný kód. Poté co se mi vrátí odvaha, přejdu zpět ke zřejmé implementaci.

Existuje ještě třetí styl TDD, triangulace, který si ukážeme ve třetí kapitole. Abychom si to však shrnuli:

Transformace pocitu (například zamyšlení se nad vedlejšími účinky) dp testu (například dvojí násobení téhož objektu Dolar je běžným tématem TDD. Čím déle to dělám, tím lépe mohu převést své estetické cítění na testy. Když to dokážu, ozvláštní to mé diskuze nad návrhem. Nejprve můžeme mluvit, zda systém tak či onak. Jakmile se rozhodneme pro správné chování, lze mluvit o nejlepším způsobu jak tohoto chování dosáhnout. Nad pivem lze sice meditovat o kráse a pravdě nebo o čemkoli jiném, ale při programování musíme opustit plané diskuze a mluvit k věci.

Vývoj řízený testy, Kapitola 1 | Dr3dweRkZ | Vývoj řízený testy, Kapitola 3