Hermetyzacja i błąd

0

Trafiłem na kilka źródeł dotyczących hermetyzacji, większośc z nich mówi to samo: brak hermetyzacji może powodowować błędy i trzeba robić getery i setery.
Nic konkretnego, jakie niby błędy ? Założmy że nasze pole w klasie jest publiczne, więc nie ma hermetyzacji, jaki błąd może wystąpić ? Przecież i tak tworzymy obiekt i na nim operujemy, więc co za różnica czy po stworzeniu instancji klasy wywołamy naszObiekt.setName("name") czy naszObiekt.name = "name" ?
Co takiego źle zrozumiałem :D ?

0

Hermetyzacja pozwala na to, żeby te zmienne nie byłby widoczne dla klientów. To są zmienne danej instancji klasy dlatego też inne obiekty nie powinny mieć odstępu do tych zmiennych. Gettery tworzy się tylko w ostateczności.

2

Twoje @watpliwosci są słuszne.
TL;DR;
Opisywanie hermetyzacji na przykładzie getterów i setterów to słaby przykład. Gettery i settery to są janusze hermetyzacji.
Hermetyzacja to robienie tylko tego publiczne, co obiecujemy, że jest dopieszczone i będzie działać dobrze również w przyszłych wersjach.

Wersja długa

Hermetyzacja służy oszczędzeniu nam pracy..
Jak coś jest jest public to to trzeba o to bardziej dbać - inni z tego korzystają. Nawet jesli inni to nadal Ty tylko w innej klasie, w następnym tygodniu.
W metodach public często warto sprawdzać argumenty, nazwy (metody i argumentów) muszą być sensowne. Najlepiej nie za wiele zmieniać, bo zmiana może zamieszać we wszystkich częściach kodu, które z tej metody korzystają. Metody publiczne warto testować.

Po prostu jak z jajkiem... bo inni moga już z tego korzystać. Czyli dużo pracy.

NIe chcemy tak przy wszystkich metodach i polach się męczyc i myśleć o konsekwencjach każdej zmiany.
Dlatego co jest **private ** to jest moja sprawa, mogę w każdej chwili zmienić zasady działania, inni mają nie tykać.

To trochę jak w domu, przychodzą goście sprzątasz w salonie , i jest tam ładnie (public) , ale prosisz żeby nie wchodzili do tego małego pokoju przy balkonie, bo tam właśnie masz swój gabinecik (private) i zamiotłeś cały syf. To twój syf, Ty się w nim ogarniasz, ale jak ktoś wejdzie to nie dość, że będzie zniesmaczony, to jeszcze może Ci coś poprzestawiać i będzie dramat. .

Z polami klasy sprawa jest taka, że zależy.
Najczęściej warto je mieć prywatne, szczególnie jeśli to pole jest modyfikowane w klasie. Szczególnie jeśli klasa jest częścią jakiegoś API - robisz bibliotekę, moduł, z którego korzysta inny zespół.

Pole prywane, które ma gettery i settery publiczne, jest praktycznie publiczne. Nie ma żadnej sensownej hermetyzacji.
I jeśli masz to w małym projekcie, który robisz z kolegą, albo dwoma, to w zasadzie nie ma po co bawić sie w te akscesory.

Uzasadnieniem kiedyś jeszcze było, że wtedy jak coś zmienisz w logice np. settera (np. będziesz dodatkowo zapisywał do loga, co zostało zmienione), to majac taki setter, możesz to łatwo zrobić, a z polem nie.
To jest obecnie bzdura, bo od 15tu lat mamy dobre narzędzia do szybkiego refaktoringu. Widzimy, że takie pola trzeba zmienić na setter to robimy to jednym (dwoma) klikami i mamy. Wprowadzamy ten getter lub setter dopiero kiedy trzeba. (Podkreślam ,ze tak jest, kiedy klasa jest częścią wewnętrzna projektu i to nie jest API do jakiejś biblioteki).

Polecam generalnie nie stosować javabeanów (i tych nieszczęsnych getterów i setterów).
Jak chcesz mieć obiekt opisujący jakies dane, wynik obliczeń, transfer object itp., to zrób tak:

public class Person {
    public final String fistName;
    public final String lastName;
    public final int age;

    public Person(String fistName, String lastName, int age) {
        this.fistName = fistName;
        this.lastName = lastName;
        this.age = age;
    }
}

Tu pola są publiczne, ale final, nikt ich nie zmieni i Ci nie pomiesza - to od razu jest przewaga nad setterami, java beanami.
A ponieważ sensem tej klasy jest dostarczanie danych o osobie, z konkretnymi polami (pewnie zaraz i tak będzie wrzucona do bazy danych lub jsona), to jak najbardziej te pola są publicznym interfejsem.

2

Generalnie trzeba pamiętać że są 2 rodzaje obiektów w Javie.

  1. To takie prawdziwe obiekty z jakąs logiką. Np. masz CartService który ma logikę związaną z dodawaniem produktów do koszyka i ma jakieś referencje do obiektów DAO itd. Nie musisz wiedziec co on przechowuje, tylko masz jakieś metody addToCart itp
    2)Pojemniki na dane (takie coś jak @jarekr000000 opisał). One nie są de facto takimi obiektami z OOP, stąd de facto nie ma w nich hermetyzacji. Niemniej takie obiekty najlepiej robić niemutowalnymi (chyba że to encje JPA to wtedy sprawa sie troche rypie) -> walić przez konstruktor albo przez buildera. W buildierze akurat settery moga miec sens jeśli zwracają referencje do tegoż buildera, np.
PersonBuilder setLastName(String lastName) {
 this.lastName = lastName;
 return this;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1