Część 0
Część 1
Część 2

Z głośników spokojnie tym razem. Era. Swoją drogą przypominają mi się stare dobre czasy gdy przy „Ameno” przerąbywałem się przez kolejne poziomy w Diablo: Hellfire.
Wspomnienia, wspomnieniami czas jednak zająć się trzecią z zasad Jeff’a Bay’a.

Opakowuj wszystkie prymitywy i Stringi(w klasy o specyficznej dla zastosowania nazwie)

Rozejrzyj się wokoło. Zobacz jak zbudowany jest świat. Szybko stwierdzisz, że świat składa się z obiektów, które wchodzą w interakcje. Tak mniej więcej zaczyna się jakieś 99% kursów dotyczących programowania obiektowego. Pozostałe 1% zaczyna się mniej więcej tak: php jest językiem obiektowym.
Rzecz w tym, że w realnym świecie nie występują liczby, znaki czy stringi. Służą one do opisania jakiś konkretnych przedmiotów są ich cechami i wartościują je według określonego wzorca. W Javie liczby są przedstawione jako typu proste, a autoboxing jest tylko dodatkiem pozwalającym na łatwiejszą pracę z nimi. Swoją drogą powoduje to cholernie wiele problemów jeżeli chcemy używać typów liczbowych w metodach przyjmujących Object i przez przypadek podamy z palca prymitywa. To jednak zupełnie inny temat.

Program opisuje świat

Tak jak w realnym świecie tak i w aplikacji nie powinno używać się typów prostych i stringów. W ich miejsce należy wprowadzać niewielkie klasy reprezentujące atomową jednostkę „czegoś”. Klasa taka powinna mieć znaczenie biznesowe ponieważ reprezentuje pewną małą istotę żyjącą w ramach systemu.

Na początek pewien prosty przykład.

Listing 1. Typ prymitywny i „ciekawy błąd”

package pl.koziolekweb.eowp3;

public class MoneyExample {

	public static void main(String[] args) {
		Konto konto = new Konto();
		print(konto.stan());
		konto.uznaj(10);
		print(konto.stan());
		konto.obciąż(5);
		print(konto.stan());
		konto.uznaj(-3);
		print(konto.stan());
		konto.obciąż(-5);
		print(konto.stan());
	}

	private static void print(int stan){
		System.out.println("Stan konta to " + stan);
	}
}

class Konto {

	private int stan = 0;

	public void uznaj(int wartość) {
		stan += wartość;
	}

	public void obciąż(int wartość) {
		stan -= wartość;
	}
	
	public int stan(){
		return stan;
	}
}

Błąd widać na pierwszy rzut oka. Prymitywne typy danych prowokują do tego typu „ekscesów”. Oczywiście można wprowadzić dodatkowy walidator i bawić się w sprawdzanie czy przekazywana wartość nie jest mniejsza od 0. Jeżeli jednak operacje na danej wartości przeprowadzamy w różnych miejscach w aplikacji warto wprowadzić klasę zamiast typu prymitywnego. Jeff Bay idzie dalej i mówi, iż skoro w świecie realnym nie istnieją typy proste jako samodzielne twory to nie należy ich używać w aplikacji.

Typy prymitywne

Oczywiście trochę inaczej należy traktować typy proste, a inaczej String. Trochę lepsze rozwiązanie:

Listing 2. Typ prymitywny i obejście

package pl.koziolekweb.eowp3;

public class MoneyExampleWithType {

	public static void main(String[] args) {
		Konto2 konto = new Konto2();
		print(konto.stan());
		konto.uznaj(new Kwota(10));
		print(konto.stan());
		konto.obciąż(new Kwota(5));
		print(konto.stan());
		konto.uznaj(new Kwota(-3));
		print(konto.stan());
		konto.obciąż(new Kwota(-5));
		print(konto.stan());
	}

	private static void print(Stan stan) {
		System.out.println("Stan konta to " + stan);
	}

}

class Konto2 {

	private Stan stan = new Stan(0);

	public void uznaj(Kwota kwota) {
		stan.uznaj(kwota);
	}

	public void obciąż(Kwota kwota) {
		stan.obciąż(kwota);
	}

	public Stan stan() {
		return stan;
	}
}

class Kwota implements Wartość<Integer> {

	private final int wartość;

	public Kwota(int wartość) {
		if (wartość 
<p>Przykład działa w tym przypadku całkiem nieźle, ale... no właśnie. Jest sobie interfejs <samp>Wartość</samp>, który tan naprawdę psuje nam wszystko. Z dwóch powodów. Pierwszy to ujawnia jak trzymana jest implementacja typu prostego w klasie <samp>Kwota</samp>. Drugi nadal operujemy bezpośrednio na typie prostym. Czas wyciągnąć naszą ulubioną broń, czyli dziedziczenie.</p>
<p class="listing">Listing 3. Typ prymitywny i dobre podejście</p>java
package pl.koziolekweb.eowp3;

public class MoneyExampleWithExtends {
	public static void main(String[] args) {
		Konto3 konto = new Konto3();
		print(konto.stan());
		konto.uznaj(new KwotaBazowa(10));
		print(konto.stan());
		konto.obciąż(new KwotaBazowa(5));
		print(konto.stan());
		konto.uznaj(new KwotaBazowa(3));
		print(konto.stan());
		konto.obciąż(new KwotaBazowa(15));
		print(konto.stan());
	}

	private static void print(StanKonta stan) {
		System.out.println("Stan konta to " + stan);
	}
}

class Konto3 {

	private StanKonta stan = new StanKonta(0);

	public void uznaj(KwotaBazowa kwota) {
		stan = stan.uznaj(kwota);
	}

	public void obciąż(KwotaBazowa kwota) {
		stan = stan.obciąż(kwota);
	}

	public StanKonta stan() {
		return stan;
	}
}

class KwotaBazowa {

	protected final int wartość;

	public KwotaBazowa(int wartość) {
		if (wartość 
<p>Oczywiście ten kod wymaga jednej rzeczy. Testów (oraz synchronizacji, ale to inna inszość). Tych nie prezentuję, bo są nudne, ale trzeba je napisać. OK, ale co się stało? Przede wszystkim <samp>StanKonta</samp> reprezentuje kwotę (klasa nazywa się <samp>KwotaBazowa</samp>, bo siedzi w jednym pakiecie z poprzednimi przykładami i się kompilator burzy). Rozszerzyliśmy jednak zachowanie tej klasy w ten sposób, że poza zawsze dodatnią kwotą ma jeszcze flagę <samp>Debet</samp>. Flaga ta mogła być typu <samp>Boolean</samp>, ale... nie można by było wtedy uzyskać efektu wartości oraz metody <samp>czyDebet</samp> - <samp>Boolean</samp> jest <samp>final</samp>. To rozwiązanie ma pewne wady. Przede wszystkim rozwlekło kod. Wymaga też testów, ale... pierwotne rozwiązanie nadal wymaga testów w dodatku jest znacznie bardziej podatne na błędy (spróbujcie wrzucić do stanu konta np. zrzutowany <samp>char</samp>). Z drugiej strony uzyskaliśmy kod odporny na durne błędy. Łatwy w testowaniu. Jeżeli dodatkowo odpowiednio go popaczkujemy to będzie przenośny pomiędzy projektami.</p>
<h5>Typ String</h5>
<p>Podobnie jak typy proste typ <samp>String</samp> nie występuje w naturze z jednym wyjątkiem:<br></br><figure aria-describedby="caption-attachment-2286" class="wp-caption aligncenter" id="attachment_2286" style="width: 610px"><a href="https://i0.wp.com/koziolekweb.pl/wp-content/uploads/2011/11/object.toString.jpg"><img alt="getStringFromObject" class="size-full wp-image-2286" data-recalc-dims="1" height="761" sizes="(max-width: 610px) 100vw, 610px" src="https://i0.wp.com/koziolekweb.pl/wp-content/uploads/2011/11/object.toString.jpg?resize=610%2C761" srcset="https://i0.wp.com/koziolekweb.pl/wp-content/uploads/2011/11/object.toString.jpg?w=610&ssl=1 610w, https://i0.wp.com/koziolekweb.pl/wp-content/uploads/2011/11/object.toString.jpg?resize=240%2C300&ssl=1 240w" title="object.toString" width="610"></img></a><figcaption class="wp-caption-text" id="caption-attachment-2286">getStringFromObject</figcaption></figure></p>
<p>i tego wyjątku się trzymajmy.</p>
<p>Generalnie typ znakowy jest używany dość często jako nośnik informacji. Począwszy od dupereli typu imię i nazwisko, poprzez hasła, loginy, kończąc na adresach URL czy adresach usług. Przesłanianie tego typu ma jednak dwie zalety.</p>
<p>Po pierwsze pozwala na wprowadzenie dodatkowych walidacji na etapie tworzenia obiektu. Tym samym mamy kontrolę nad tym co tworzymy i nie posypie się np. <samp>MalformedURLException</samp> czy nie otrzymamy pustego napisu.<br></br>
Po drugie znacznie łatwiej jest zarządzać kodem mając konkretny typ, a nie enigmatyczny <samp>String</samp>. Przykłady wymyślcie sobie sami.</p>
<h4>Inne typy proste</h4>
<p>Że co? Czy w Javie  jeszcze jakieś inne typy proste poza prymitywami(plus ich obiektowe wersje) oraz <samp>String</samp>? To zależy jak na to spojrzymy. Jeff Bay mówi o typach prostych, ale ja osobiści zalecam dodanie do listy typów prostych takich, które pochodzą z różnych narzędzi. Przykładowo jeżeli tworzymy XMLa i mamy schemę to warto poza walidacją ze schemą rozszerzyć klasy typu <samp>Node</samp> by uzyskać efekt wstępnej walidacji np. by nie wstawić nieprawidłowej nazw elementu.<br></br>
Podobnie ma się rzecz z usługami sieciowymi. Tu wartą rozszerzenia jest klasa <samp>QName</samp>, szczególnie jeżeli wywołujemy usługi w sieci z ograniczonym dostępem. Można wtedy wprowadzić dodatkową walidację by sprawdzać już na wstępie czy dana usługa jest osiągalna. Pozwoli to na kontrolowane wyłapanie baboli.</p>
<h4>Podsumowanie</h4>
<p>Zasada ta jest dość trudna w zastosowaniu. Wymaga umiejętnego użycia zarówno interfejsów jak i dziedziczenia. Tworząc taki kod warto zadawać sobie pytanie "Czy A to B?". Pozwoli to na uproszczenie kodu i wczesne wyłapanie pewnych abstrakcji. Rozwiązanie tego typu pociąga za sobą pewne niedogodności. Przede wszystkim uzyskujemy prawdziwą enkapsulację. Innymi słowy łatwo wyeliminować tu gettery/settery, co pociąga za sobą spore problemy natury prezentacyjnej. Ten problem poruszę jednak w ostatniej części. Na razie można używać getterów 😀</p>