Home > English > Primitives w javie

Primitives w javie

Trochę mnie nie było, ale i tematy się pozbierały. Jak pokonam na dobre lenia to opiszę wszystko co mi na wątrobie leży i w kajecie zanotowałem. Zaczynamy od tematu lekkostrawnego: primitives.

Od jakiegoś czasu, przeglądając zasoby sieci można wywnioskować, że jednym z większych niepowodzeń Javy, jest nie w pełni obiektowy model. Mianowicie Java posiada typy takie jak int, boolean, float, etc. Dalej można doczytać, że na szczęście nadchodzą języki, które uratują nas od tego przekleństwa (Scala, Groovy, Clojure i pewnie wiele innych).

Ale czy primitives (tak, nie wiem jak to się na PL tłumaczy) są aż tak złe?

Są trochę niebezpieczne, jako że Java je auto (un)boxuje (od 1.5), na podstawie czego Joshua Bloch stworzył kilka Java Puzzlers. Nie są też obiektami, przez co nie pasują do obiektowego modelu. Jednak mają przynajmniej dwie zalety z powodu których powstaje ten wpis i z których można korzystać do woli.

  1. Każdy primivitive ma wartość domyślną
  2. Nigdy nie mogą być nullem

Dlaczego jest to według mnie istotne? A szczególnie istotne w kontekście warstwy danych?

Weźmy najprostszą flagę Boolowską, powiedzmy, że oznacza ona czy email usera został zwalidowany (kliknął jakiś link w @ or sth). Korzystając z Hibernate Criteria API tworzycie zapytanie wykorzystując ją jako warunek. Zapytanie ma wyciągnąć wszystkie nieaktywne konta użytkowników. Wyglądało by to mniej więcej tak:  (Pseudokod pewnie idealnie się kompiluje, jeśli nie to proszę nie informujcie mnie o tym ;))

public class Email {//nasza encja
 ...//adnotacje i inne potrzebne pierdoły
 private Boolean active;

 public void setActive(Boolean active){
 this.active = active;
 }
 public Boolean isActive(){
 return active;
 }
 .... // pola inne i metody
}
public class JakiesDaoEmail {
 public List<Email> mojaMetodaSzukajacaMaili(Boolean active){
 Criteria inactiveEmails = createCriteria().addRestriction(Restriction.eq("active", active));
 ...
 }
}

No i dobra, co jest tu nie tak i dlaczego primitive miałby nam zrobić dobrze, a przynajmniej trochę pomóc?

Zacznijmy od tego co jest źle a później dopiero o rozwiązaniach. W przykładzie, tak jak jest zdefiniowany ten wihajster, użytkownik może mieć maila aktywnego, nie aktywnego i ch..olera go wie jakiego. O tym co oznacza null pogadamy przy okazji kolejnego wpisu na temat null object pattern (ten się za bardzo rozrósł i musiałem dzielić). Zapytanie więc zwróci nam nie pełną listę nieaktywnych userów.

Oczywiście nie w ciemię bity  programista może zacząć zabezpieczać się przed nullem, w końcu wystarczy zainicjalizować pole w momencie deklaracji i w seterze sprawdzać czy nie dostaliśmy nulla. Korzystając z hiberneta można w restrykcjach na sztywno umieścić or by szukał też nulli, dołożyć jeszcze adnotację notnull i column z deklaracją default value dla kolumny i  … o rly?

Jeśli macie team dość zdyscyplinowany to pewnie można. Jeśli nie, to łatwiej przekonać wszystkich by korzystali z primitives.  Jak wspomniałem każdy typ podstawowy (czy jak się je oficjalnie nazywa), posiada wartość domyślną. No tak, obiektowe wersję też ją mają, ale null nie jest kandydatem z moich snów i marzeń.

Korzystając z prymitywów zostanie nam wprawdzie jeden problem: unboxing, ale to już problem wyższej warstwy. W każdym bądź razie tworząc statystyki nie odkryjecie, że w systemie macie tak naprawdę jeszcze raz tyle userów o nie aktywowanych mailach ;)

I … to jeszcze nie koniec :) Obiektowe odpowiedniki primitivów zazwyczaj widziałem ‘czyszczone’ poprzez setActive(null). Powodzenia w debuggowaniu tak wyczyszczonej flagi. Mały bool może nie da 100% gwarancji, że NPE nie poleci (przekazanie Booleanu = null jako parametru w połączeniu z unboxem zrobią nam ała), ale znacząco utrudni psucie nam innych fragmentów kodu czy zaśmiecanie ich przez kod szukający nulli.

I tak, wiem, że opisuję haki na bad practices, ale gdzie bym nie pracował to się z tym spotykam. Praktyka wstawiania siedzi tak mocno w nas, że ostatnio i Koziołek prezentując testy posłużył się nullem miast wstawiać zera. Na dzonie przeglądając example kody tu i ówdzie nulla też się znajdzie. No i niby nic, bo większość wie o co chodzi, koncepcja przekazana. Tyle że młodzież co jeszcze NPE nie szukała, się szybko uczy. A później będzie, że jak Koziołki tak robią to i oni powinni.

Od dziś z powyższej przyczyny postaram się walczyć w moich pseudokodach z nullami. Amen. Rozejść się można, koniec wpisu (bosz z 2 tyg go produkowałem :/ Jeśli coś nie ma sensu to sorry, ale z 2x go dzieliłem. Feedback mile widziany :))

Advertisements
Categories: English
  1. 13/09/2011 at 20:07

    Soł tró. W tamtym poście chodziło o dodatkowe warunki brzegowe i użycie NULL było po prostu wygodne. Zgadzam sie jednak w pełni NULL=Zło

  2. mk
    15/09/2011 at 10:38

    Co to jest za dzona, o której piszesz ? chodzi to : http://java.dzone.com/, czy coś jeszcze innego ?

    Same korzystanie z nulli rzeczywiście nie jest zbyt dobrą praktyką, ale nie wyeliminujemy tego tylko poprzez podstawianie ‘prymitywów’. Chyba, że traktujemy prymitywy jako wspomniane NullObjects i w każdym innym przypadku także korzystamy z tych obiektów

    • 25/09/2011 at 22:13

      Tak, chodziło dokładnie o ten serwis. Założyłem, że jeżeli ktoś trafia na tak małego bloga jak mój, to jeden z większych serwisów javowych zna. Na przyszłość postaram się nie pozostawić wątpliwości, dzięki za uwagę.

      Tak, są lepsze sposoby by wyeliminować nulla, ale wymagają wysiłku. Nie znam programistów którzy lubili by się wysilać, wprowadzam więc prosty sposób by uniknąć nulli i nie wymuszać null objecty.
      Taka alternatywna furtka w javie jedynie dostępna, mało problemów powodująca. A z ewentualnymi exceptionami, wynikającymi z wprowadzenia prymitives, to już każdy programista będzie umiał walczyć.

      Ostatnia rzecz: nie uważam że prymitives są złe. Koniec końców i tak zawsze opakować je wypada w własne obiekty, podnosząc trochę poziom abstrakcji, ale to już temat na inną dyskusję

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: