Mistrz programowania.
Zwiêksz efektywnoœæ
i zrób karierê
Autor: Neal Ford, David Bock
ISBN: 978-83-246-2650-2
Tytu³ orygina³u:
The Productive Programmer
Format: 168×237, stron: 216
Poznaj efektywne narzêdzia oraz mistrzowskie techniki pracy!
Jak efektywnie zarz¹dzaæ cyklem ¿ycia obiektów?
Jak upraszczaæ trudne zadania przy u¿yciu technik metaprogramowania?
Jak wykorzystaæ m¹droœæ staro¿ytnych filozofów w programowaniu?
Ka¿dy profesjonalista marzy o tym, aby w jak najkrótszym czasie zrobiæ i zarobiæ
jak najwiêcej — dotyczy to równie¿ programistów. Autor niniejszej ksi¹¿ki, Neal Ford,
wychodzi naprzeciw tym marzeniom i stawia tezê, ¿e kluczem do sukcesu jest
mistrzostwo w pos³ugiwaniu siê dostêpnymi narzêdziami… w po³¹czeniu z okreœlon¹
metodologi¹ pracy, opart¹ na m¹droœci staro¿ytnych myœlicieli. Jak uzyskaæ tê
wyrafinowan¹ efektywnoœæ i tworzyæ wydajne programy, dowiesz siê podrêcznika,
który trzymasz w rêkach.
Ksi¹¿ka
„
Mistrz programowania. Zwiêksz efektywnoœæ i zrób karierê
”
zawiera mnóstwo
bezcennych porad, dotycz¹cych korzystania z narzêdzi zwiêkszaj¹cych produktywnoœæ,
które mo¿esz zastosowaæ natychmiast! Dowiesz siê z niej, jak unikaæ najczêstszych
pu³apek oraz w jaki sposób pozbyæ siê czynników dekoncentruj¹cych, zd¹¿aj¹c
w kierunku wydajnej i efektywnej pracy. Nauczysz siê tworzyæ kod o jednolitym
poziomie abstrakcji, pisaæ testy przed napisaniem testowanego kodu, zarz¹dzaæ cyklem
¿ycia obiektów i stosowaæ techniki metaprogramowania. Dziêki temu podrêcznikowi
zdobêdziesz potrzebn¹ wiedzê i przyswoisz sobie najlepsz¹ metodologiê pracy
— a to szybko doprowadzi Ciê do mistrzostwa w Twoim zawodzie.
Tworzenie p³yty startowej
Rejestrator makr
Makra klawiszowe
Wyszukiwanie zaawansowane
Widoki zakorzenione
Automatyzacja interakcji ze stronami WWW
Mapy danych
Projektowanie oparte na testowaniu
Generowanie metryk kodu
Metaprogramowanie
Zostañ najbardziej poszukiwanym i najlepiej op³acanym programist¹!
3
Spis treļci
Przedmowa .................................................................................................................... 7
Wstýp .............................................................................................................................9
1. Wprowadzenie ............................................................................................................ 13
Dlaczego ksiñĔka o produktywnoĈci programistów
14
O czym jest ta ksiñĔka
15
Co dalej
17
I Mechanika ..............................................................................................19
2. Przyspieszenie ............................................................................................................. 21
Päyta startowa
22
Akceleratory
31
Makra
44
Podsumowanie
46
3. Skupienie ......................................................................................................................47
PozbñdĒ siö czynników rozpraszajñcych
48
Wyszukiwanie przebija nawigowanie
50
Wyszukiwanie zaawansowane
52
Widoki zakorzenione
54
Ustawianie atrybutów trwaäych
56
Skróty do wszystkich zasobów projektu
57
UĔywaj kilku monitorów
57
Porzñdkowanie miejsca pracy na wirtualnych pulpitach
57
Podsumowanie
59
4
_
Spis treļci
4. Automatyzacja ............................................................................................................ 61
Nie wynajduj ponownie koäa
63
Zapisuj zasoby na dysku
63
Automatyzacja interakcji ze stronami internetowymi
64
Kanaäy RSS
64
Wykorzystanie Ant do zadaþ niezwiñzanych z kompilacjñ
66
Wykorzystanie narzödzia Rake do codziennych zadaþ
67
Wykorzystanie Selenium do odwiedzania stron internetowych
68
UĔyj basha do zliczania wyjñtków
70
Zastñp pliki wsadowe interpreterem Windows Power Shell
71
UĔywaj Automatora z Mac OS X do usuwania starych plików
72
Oswajanie wiersza poleceþ Subversion
73
Pisanie rozdzielacza plików SQL w jözyku Ruby
74
Argumenty za automatyzacjñ
75
Nie strzyĔ jaka
76
Podsumowanie
77
5. Kanonicznoļë ............................................................................................................... 79
Kontrolowanie wersji
80
Kanoniczny komputer kompilujñcy
82
PoĈrednioĈè
83
Niedopasowanie falowe
90
Podsumowanie
102
II Praktyka ................................................................................................105
6. Projektowanie oparte na testowaniu ....................................................................... 107
Ewolucja testów
109
7. Analiza statyczna ....................................................................................................... 117
Analiza kodu bajtowego
118
Analiza kodu Ēródäowego
120
Generowanie metryk kodu za pomocñ programu Panopticode
122
Analiza jözyków dynamicznych
124
8. Dobry obywatel ..........................................................................................................127
ã
amanie zasady hermetyzacji
128
Konstruktory
129
Metody statyczne
129
Zachowania patologiczne
134
Spis treļci
_
5
9. Nie býdziesz tego potrzebowaë ............................................................................... 135
10. Starożytni filozofowie ...............................................................................................141
Arystotelesowskie wäasnoĈci akcydentalne i istotne
142
Brzytwa Ockhama
143
Prawo Demeter
146
Tradycje programistyczne
147
11. Kwestionuj autorytety .............................................................................................. 149
WĈciekäe maäpy
150
Päynne interfejsy
151
Antyobiekty
153
12. Metaprogramowanie ................................................................................................ 155
Java i refleksja
156
Testowanie Javy za pomocñ jözyka Groovy
157
Pisanie päynnych interfejsów
158
Dokñd zmierza metaprogramowanie
160
13. Metody i SLAP .............................................................................................................161
Wzorzec composed method w praktyce
162
SLAP
166
14. Jýzykoznawstwo ........................................................................................................ 171
Jak do tego doszäo
172
Dokñd zmierzamy
175
Piramida Oli
179
15. Dobór odpowiednich narzýdzi ...................................................................................181
Poszukiwanie idealnego edytora tekstu
182
Wybór wäaĈciwego narzödzia
186
Pozbywanie siö niechcianych narzödzi
192
16. Podsumowanie — kontynuujmy dyskusjý ............................................................... 195
Dodatki .................................................................................................. 197
A Elementy skĥadowe ................................................................................................... 199
Skorowidz .................................................................................................................. 207
117
ROZDZIAĤ 7.
Analiza statyczna
118
_
Rozdziaĥ 7. Analiza statyczna
JeĈli uĔywasz jözyka programowania o statycznej kontroli typów (jak Java lub C#), masz
do dyspozycji doskonaäe narzödzie umoĔliwiajñce znalezienie takich rodzajów bäödów,
które bardzo trudno wykryè za pomocñ przeglñdów kodu i innych standardowych technik.
Mowa o analizie statycznej — metodzie wyszukiwania w kodzie okreĈlonych oznak wystö-
powania nieprawidäowoĈci.
Narzödzia do analizy statycznej moĔna podzieliè na dwie kategorie: narzödzia przeszukujñce
skompilowane artefakty (tzn. pliki klas lub kod bajtowy) i narzödzia analizujñce pliki Ēró-
däowe. W rozdziale tym opiszö przykäadowe aplikacje kaĔdego z tych rodzajów, a jako przy-
käadowego jözyka uĔyjö Javy, poniewaĔ zestaw dostöpnych narzödzi jest w tym przypadku
bardzo bogaty. NaleĔy jednak pamiötaè, Ĕe nie jest to technika przeznaczona wyäñcznie do
stosowania w Javie. Z podobnych narzödzi moĔna korzystaè we wszystkich najwaĔniejszych
jözykach programowania o statycznej kontroli typów.
Analiza kodu bajtowego
Analizatory kodu bajtowego szukajñ w kodzie Ēródäowym okreĈlonych oznak wystöpowania
bäödów. Wynikajñ z tego dwa wnioski: po pierwsze, niektóre jözyki programowania zostaäy
juĔ na tyle dobrze poznane, Ĕe w ich skompilowanym kodzie bajtowym moĔna wyszukiwaè
czösto wystöpujñce wzorce oznaczajñce bäödy, a po drugie, narzödzia te nie znajdujñ wszyst-
kich bäödów, lecz tylko takie, których wzorce zostaäy zdefiniowane. To nie oznacza, Ĕe na-
rzödzia te sñ maäo przydatne. Niektóre znajdowane przez nie bäödy sñ niezwykle trudne do
wykrycia innymi metodami (tzn. przez wielogodzinne bezproduktywne wlepianie wzroku
w ekran programu diagnostycznego).
Jednym z tego typu narzödzi jest otwarty program FindBugs, bödñcy projektem przygotowanym
na Uniwersytecie Maryland. Program ten moĔe dziaäaè w kilku trybach: z poziomu wiersza
poleceþ, zadania Ant lub Ĉrodowiska graficznego. Graficzny interfejs uĔytkownika aplikacji
FindBugs przedstawiono na rysunku 7.1.
FindBugs dziaäa w kilku obszarach, do których naleĔñ:
PoprawnoĈè
Program okreĈla prawdopodobieþstwo wystñpienia bäödu.
Zäa praktyka
Wykrywa przypadki zäamania jednego z podstawowych zaleceþ dotyczñcych pisania
kodu (na przykäad przesäoniöcia metody
equals()
i jednoczesnego nieprzesäoniöcia
metody
hashCode()
).
Podejrzane elementy
Znajduje niejasne fragmenty kodu, przypadki dziwnych zastosowaþ, anomalie, kod säabej
jakoĈci.
W celu zilustrowania sposobu dziaäania programu musiaäem znaleĒè ofiarö. Padäo na otwarty
szkielet sieciowy Struts. Odkryäem kilka prawdopodobnie faäszywych alarmów z kategorii
zäych praktyk, które zostaäy opisane nastöpujñco: „W metodzie
equals
nie powinno przyj-
mowaè siö Ĕadnych zaäoĔeþ dotyczñcych typu jej argumentów”. Zalecanñ praktykñ definio-
wania metody
equals()
w Javie jest sprawdzenie rodowodu przekazywanego do niej obiektu
w celu upewnienia siö, Ĕe operacja porównywania ma sens. Oto fragment kodu Struts, który
sprawia te problemy. Znajduje siö on w pliku ApplicationMap.java:
Analiza kodu bajtowego
_
119
Rysunek 7.1. Graficzny klient aplikacji FindBugs
entries.add(new Map.Entry() {
public boolean equals(Object obj) {
Map.Entry entry = (Map.Entry) obj;
return ((key == null) ? (entry.getKey() == null) :
key.equals(entry.getKey())) && ((value == null) ?
(entry.getValue() == null) :
value.equals(entry.getValue()));
}
UwaĔam, Ĕe to moĔe byè faäszywy alarm, poniewaĔ mamy tu do czynienia z definicjñ ano-
nimowej klasy wewnötrznej, wiöc autor prawdopodobnie zawsze zna typy argumentów.
Mimo wszystko coĈ tu jest nie tak.
PoniĔej przedstawiono oczywisty bäñd znaleziony przez FindBugs. Ten fragment kodu znaj-
duje siö w pliku IteratorGeneratorTag.java:
if (countAttr != null && countAttr.length() > 0) {
Object countObj = findValue(countAttr);
if (countObj instanceof Integer) {
count = ((Integer)countObj).intValue();
}
else if (countObj instanceof Float) {
count = ((Float)countObj).intValue();
}
else if (countObj instanceof Long) {
count = ((Long)countObj).intValue();
}
else if (countObj instanceof Double) {
count = ((Long)countObj).intValue();
}
120
_
Rozdziaĥ 7. Analiza statyczna
Przyjrzyj siö uwaĔnie ostatniemu wierszowi tego kodu. Znajdujñcy siö tam bäñd, naleĔñcy do
kategorii poprawnoĈci programu FindBugs, zostaä okreĈlony jako „niemoĔliwe rzutowanie”.
Ostatni wiersz powyĔszego listingu zawsze bödzie powodowaä wyjñtek rzutowania klas.
W istocie nie ma takiej sytuacji, w której uruchomienie tego kodu nie wywoäa problemu.
Programista sprawdza, czy obiekt o nazwie
countObj
jest typu
Double
, i od razu rzutuje go
na typ
Long
. Aby dowiedzieè siö, jak to siö staäo, wystarczy spojrzeè na znajdujñcñ siö wyĔej
instrukcjö
if
: to jest bäñd kopiowania i wklejania. Tego typu bäñd trudno jest znaleĒè metodñ
przeglñdania kodu — bardzo äatwo go przeoczyè. NajwyraĒniej w bazie kodu Struts nie ma
testu jednostkowego pokrywajñcego ten wiersz kodu, poniewaĔ w przeciwnym razie na-
tychmiast by go wykryto. Co gorsza, ten bäñd wystöpuje w trzech miejscach kodu Struts: we
wspomnianym pliku IteratorGeneratorTag.java i dwa razy w pliku SubsetIteratorTag.java. Powód?
Nietrudno zgadnñè. Kod ten zostaä skopiowany i wklejony we wszystkich tych trzech miejscach
(FindBugs tego nie wykryä, sam zauwaĔyäem, Ĕe te fragmenty sñ do siebie podejrzanie podobne).
Dziöki moĔliwoĈci zautomatyzowania uruchamiania programu FindBugs przez Ant lub Maven
jako czöĈci procesu kompilacji aplikacja ta peäni funkcjö bardzo taniej polisy ubezpieczenio-
wej na wypadek wystñpienia rozpoznawanych przez niñ bäödów. OczywiĈcie nie moĔna za-
gwarantowaè w ten sposób, Ĕe kod bödzie caäkowicie wolny od bäödów (i nie zwalnia to z obo-
wiñzku pisania testów jednostkowych), ale program ten moĔe Ciö uratowaè przed paroma
nieprzyjemnymi wpadkami. Potrafi on nawet znaleĒè takie bäödy, które trudno wykryè w testach
jednostkowych, na przykäad problemy z synchronizacjñ wñtków.
Narzödzia do analizy statycznej stanowiñ äatwy sposób weryfikacji.
Analiza kodu Śródĥowego
Narzödzia do analizy kodu Ēródäowego przeszukujñ kod Ēródäowy w celu znalezienia okre-
Ĉ
lonych oznak wystöpowania bäödów. W zaprezentowanym przykäadzie uĔyäem otwartego
narzödzia Javy o nazwie PMD. Program ten dziaäa z poziomu wiersza poleceþ, Ant oraz ma
wtyczki do wszystkich najwaĔniejszych Ĉrodowisk programistycznych. Aplikacja ta znajduje
nastöpujñce typy nieprawidäowoĈci:
Potencjalne bäödy
Na przykäad puste bloki
try…catch
.
Martwy kod
NieuĔywane zmienne lokalne, parametry i zmienne prywatne.
Nieoptymalny kod
Marnotrawne uĔycie äaþcuchów.
Nadmiernie skomplikowane wyraĔenia
Wielokrotne uĔycie kodu spowodowane kopiowaniem i wklejaniem.
Duplikaty kodu (obsäugiwane przez pomocnicze narzödzie o nazwie CPD)
Wielokrotne uĔycie kodu spowodowane kopiowaniem i wklejaniem.
Analiza kodu Śródĥowego
_
121
PMD moĔna okreĈliè jako coĈ pomiödzy zwykäym narzödziem do sprawdzania stylu (takim
jak CheckStyle, które weryfikuje, czy kod zostaä napisany zgodnie z wytycznymi dotyczñcymi
stylu, na przykäad czy zostaäy zastosowane odpowiednie wciöcia) a programem FindBugs,
który analizuje kod bajtowy. Rodzaje bäödów, w wykrywaniu których specjalizuje siö PMD,
pokaĔö na przykäadzie metody napisanej w jözyku Java:
private void insertLineItems(ShoppingCart cart, int orderKey) {
Iterator it = cart.getItemList().iterator();
while (it.hasNext()) {
CartItem ci = (CartItem) it.next();
addLineItem(connection, orderKey, ci.getProduct().getId(),
ci.getQuantity());
}
}
PMD poinformuje, Ĕe metodö tö moĔna zoptymalizowaè przez dodanie do pierwszego
parametru (
ShoppingCart cart
) modyfikatora
final
. Dziöki zastosowaniu siö do tej rady
moĔna zmusiè kompilator do wykonania za nas wiökszej iloĈci pracy. PoniewaĔ w Javie
wszystkie obiekty sñ przekazywane przez wartoĈè, nie moĔna zmiennej
cart
przypisaè refe-
rencji do nowego obiektu wewnñtrz tej metody, a próba zrobienia tego spowoduje wystñpienie
bäödu. PMD oferuje kilka tego typu wskazówek, które pomagajñ zoptymalizowaè dziaäanie
róĔnych narzödzi (na przykäad kompilatora).
Program PMD ma równieĔ funkcjö wykrywania podejrzanie wyglñdajñcych skopiowanych
i wklejonych fragmentów kodu (jak wczeĈniej pokazany kod Struts) o nazwie CPD (ang. Cut-Paste
Detector). Interfejs uĔytkownika CPD zostaä zbudowany przy uĔyciu biblioteki Swing. Sñ w nim
wyĈwietlane stan i problematyczny fragment kodu (rysunek 7.2). Sposób jego dziaäania oczy-
wiĈcie równieĔ jest zwiñzany z zasadñ DRY, którñ opisaäem w rozdziale 5.
Rysunek 7.2. Narzödzie Cut and Paste Detector programu PMD
122
_
Rozdziaĥ 7. Analiza statyczna
WiökszoĈè podobnych narzödzi do analizy kodu Ēródäowego ma API dajñce siö dostosowaè
do indywidualnych potrzeb, w którym moĔna utworzyè wäasne zestawy reguä (takie API ma
zarówno FindBugs, jak i PMD). WiökszoĈè z nich oferuje ponadto tryb interaktywny i, co
jeszcze waĔniejsze, pozwala uruchamiaè siö jako czöĈè zautomatyzowanych procesów, na
przykäad ciñgäej integracji. Uruchamianie tych narzödzi przed kaĔdym wysäaniem plików do
repozytorium jest bardzo prostym sposobem na unikniöcie typowych bäödów. KtoĈ zadaä
sobie trud zidentyfikowania bäödów, a Ty moĔesz z tego skorzystaè.
Generowanie metryk kodu
za pomocé programu Panopticode
Zagadnienia zwiñzane z metrykami kodu wykraczajñ poza zakres tematyczny tej ksiñĔki, ale
produktywnoĈè w ich generowaniu nie. JeĈli chodzi o jözyki o statycznej kontroli typów (jak
Java i C#) jestem wielkim zwolennikiem ciñgäego gromadzenia metryk, aby mieè pewnoĈè, Ĕe
problem zostanie rozwiñzany moĔliwie jak najszybciej. Oznacza to, Ĕe zwykle mam caäy ze-
staw narzödzi do mierzenia jakoĈci kodu (wäñcznie z programami FindBugs i PMD/CPD),
które uruchamiam w ramach procesu ciñgäej integracji.
Konfigurowanie tych wszystkich programów w kaĔdym projekcie jest käopotliwe. Podobnie
jak w przypadku programu Buildix (zobacz podrozdziaä „Nie wynajduj ponownie koäa” w roz-
dziale 4.) chciaäbym mieè wstöpnie skonfigurowanñ caäñ infrastrukturö. W tym wäaĈnie naj-
lepszy jest Panopticode.
Podobny problem miaä kiedyĈ jeden z moich kolegów (Julias Shaw), ale on zamiast narzekaè
jak ja, wziñä siö do roboty. Panopticode
1
to program typu open source zawierajñcy mnóstwo
wstöpnie skonfigurowanych narzödzi do generowania metryk kodu. Jego jñdro stanowi plik
kompilacji Ant, zawierajñcy wiele projektów open source i ich wstöpnie skonfigurowanych
plików JAR. Wystarczy podaè ĈcieĔkö do swoich plików Ēródäowych, ĈcieĔkö do bibliotek
(innymi säowy, ĈcieĔkö do wszystkich plików JAR potrzebnych do skompilowania projektu)
oraz katalog testów, a nastöpnie uruchomiè plik kompilacyjny Panopticode. Program zajmie
siö resztñ.
Emma
Narzödzie typu open source do mierzenia pokrycia kodu testami (zobacz podrozdziaä
„Pokrycie kodu” w rozdziale 6.). Zmieniajñc jeden wiersz w pliku kompilacji Panoptico-
de, moĔna z tego narzödzia przeäñczyè siö na narzödzie Cobertura (kolejny program open
source do mierzenia pokrycia kodu Ēródäowego Javy).
CheckStyle
Otwarty weryfikator stylu kodu. MoĔna utworzyè dostosowane do wäasnych potrzeb
zestawy reguä za pomocñ jednego wpisu w pliku kompilacji Panopticode.
JDepend
Otwarte narzödzie zbierajñce metryki numeryczne na poziomie pakietów.
1
Do pobrania pod adresem http://www.panopticode.org.
Generowanie metryk kodu za pomocé programu Panopticode
_
123
JavaNCSS
Otwarte narzödzie do mierzenia zäoĔonoĈci cyklomatycznej (zobacz podrozdziaä „ZäoĔo-
noĈè cyklomatyczna” w rozdziale 6.).
Simian
Komercyjny program säuĔñcy do znajdowania powtarzajñcych siö fragmentów kodu.
Wersjö dostöpnñ w Panopticode moĔna bezpäatnie testowaè przez 15 dni. Po upäywie tego
czasu naleĔy usunñè program lub za niego zapäaciè. Planowane jest umoĔliwienie jego
wymiany na CPD.
Panopticode Aggregator
Narzödzie przedstawiajñce raporty wszystkich narzödzi Panopticode w formie tekstowej
i graficznej (w postaci schematów).
Po uruchomieniu Panopticode przez jakiĈ czas przeĔuwa kod Ēródäowy, a nastöpnie wypluwa
raport zawierajñcy informacje o jego jakoĈci. Program ten tworzy takĔe bardzo äadne sche-
maty w postaci zaawansowanych obrazów w formacie SVG (wiökszoĈè przeglñdarek potrafi
wyĈwietlaè tego typu grafikö). Schematy te majñ dwie zalety. Pierwszñ z nich jest to, Ĕe sta-
nowiñ graficzny obraz wartoĈci okreĈlonej metryki. Na przykäad na rysunku 7.3 zostaäa
przedstawiona zäoĔonoĈè cyklomatyczna projektu CruiseControl. Zacienione obszary repre-
zentujñ róĔne przedziaäy wartoĈci dla okreĈlonej metody. Grube biaäe linie oznaczajñ granice
pakietów, a cienkie linie — granice klas. KaĔde pole odpowiada jednej metodzie.
Drugñ zaletñ schematów jest ich interaktywnoĈè. To nie jest tylko äadny obrazek — to obra-
zek interaktywny. JeĈli rysunek ten zostanie wyĈwietlony w przeglñdarce internetowej, klik-
niöcie dowolnego pola spowoduje wyĈwietlenie po prawej stronie metryk odpowiadajñcej mu
metody. Schematy te umoĔliwiajñ przeanalizowanie kodu w celu znalezienia metod i klas,
które sprawiajñ problemy.
Panopticode wyĈwiadcza programiĈcie dwie bardzo istotne przysäugi. Po pierwsze, nie trze-
ba w kaĔdym projekcie ciñgle konfigurowaè tych samych rzeczy. W typowym projekcie kon-
figuracja programu trwa nie wiöcej niĔ 5 minut. Po drugie, program umoĔliwia tworzenie
schematów, które säuĔñ jako agregatory informacji. W projektach zwinnych agregator infor-
macji (ang. information radiator) to reprezentacja stanu projektu umieszczona w jakimĈ wi-
docznym miejscu (na przykäad w pobliĔu ekspresu do kawy). Dziöki niemu czäonkowie
zespoäu nie muszñ otwieraè Ĕadnych zaäñczników, aby sprawdziè stan projektu, poniewaĔ
mogñ to zrobiè, idñc po kawö.
Jeden z rodzajów schematów, jakie moĔna tworzyè za pomocñ Panopticode, to ilustracje po-
krycia kodu (zobacz podrozdziaä „Pokrycie kodu” w rozdziale 6.). JeĈli metryka wyglñda jak
wielka czarna plama, nie jest dobrze. Zwiökszanie pokrycia kodu zacznij od znalezienia naj-
wiökszej moĔliwej kolorowej drukarki i wydrukuj na niej swój schemat (wäaĈciwie za pierw-
szym razem zwykle wystarcza biaäo-czarna, poniewaĔ i tak wydruk jest caäy czarny). PowieĈ
ten wydruk w widocznym miejscu. Po zakoþczeniu jakiegoĈ waĔnego etapu pisania testów
wydrukuj nowy schemat i powieĈ go obok poprzedniego. Jest on bardzo skutecznym moty-
watorem wszystkich czäonków zespoäu — nikt nie chce byè Ĉwiadkiem ponownego pogrñĔa-
nia siö projektu w ciemnoĈci. Jest to takĔe dobry sposób na pokazanie kierownikowi, Ĕe po-
krycie kodu testami jest coraz wiöksze. Kierownicy lubiñ takie obrazy z rozmachem, a ten na
dodatek zawiera uĔyteczne informacje!