03 czerwca 2009

Kontynuacja relacji z rozdziału 3. "Groovy for the Java eyes" z "Programming Groovy"

Skończyłem moją ostatnią relację z lektury "Programming Groovy: Dynamic Productivity for the Java Developer" Venkata Subramaniama na stronie 32. rozdziału 3. "Groovy for the Java eyes" (zajrzyj do Rozpoczynam lekturę "Programming Groovy: Dynamic Productivity for the Java Developer" Venkata Subramaniama).

Na kolejnych stronach wciąż zagłębiamy się w te cechy Groovy, które pozwalają programistom Java uzmysłowić sobie paradoks swojej produktywności - pisaliśmy wiele, szybciej, ale w dużej mierze niepotrzebnie. Akurat ten rozdział dostępny jest bezpłatnie ze strony książki (na dole w sekcji Contents and Extracts znajduje się odnośnik do PDFa), więc można w ten sposób wyrobić sobie własny pogląd na sprawę.

Przykłady cech Groovy, które programiści javowi mogą z początku nazwać udziwnieniami mogą być:
  • Słowo kluczowe return jest opcjonalne i przez to prawie nieużywane, podobnie średnik
  • Metody i klasy są domyślnie publiczne
  • Operator bezpiecznego odczytu ?. wykona metodę następującą po nim, jedynie jeśli poprzedzająca referencja nie jest null
  • Wprowadzono mechanizm nazwanych parametrów inicjalizacyjnych, więc POJO (a teraz POGO - ang. Plain Old Groovy Object) konstruujemy z konstruktorami, które akceptują mapę parametrów i ich wartości
  • Obsługa wyjątków jest opcjonalna - bez względu na rodzaj - kontrolowane czy nie, nieprzechwycone idą wyżej, do wywołującego
  • this w bloku statycznym jest wskazaniem na obiekt typu Class, więc możemy stworzyć ciąg wywołań statycznych (zwanych fluent API)
Deklarując właściwość w klasie Groovy dostarczy dla nich metodę odczytu i zapisu (ang. getter/setter) - podobnie jak z domyślnym konstruktorem w Javie, jeśli nie zdefiniowaliśmy żadnego. Deklaracja właściwości jako final jest wskazaniem dla Groovy, że ma "dołożyć" wyłącznie metodę odczytu. Właściwość jest wciąż do zmiany, ale wyłącznie z innych metod klasy, do której należy. Deklaracja właściwości może być nietypowana (bez określenia typu) z def albo podobnie jak w Javie ze wskazaniem typu.
 $ groovysh
Groovy Shell (1.6.3, JVM: 1.6.0_13)
Type 'help' or '\h' for help.
---------------------------------------------------------------------------------------------------------------
groovy:000> class Pracownik
groovy:001> {
groovy:002> def imie, nazwisko
groovy:003> final def pewnaDanaStala
groovy:004> }
===> true
groovy:000> p = new Pracownik(imie: 'Jacek', nazwisko: 'Laskowski')
===> Pracownik@9abce9
groovy:000> p.imie
===> Jacek
groovy:000> p.nazwisko
===> Laskowski
groovy:000> p.pewnaDanaStala = 'Zabronione, ale próbujemy'
ERROR groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: pewnaDanaStala for class: Pracownik
at Pracownik.setProperty (groovysh_evaluate)
at groovysh_evaluate.run (groovysh_evaluate:2)
...
groovy:000> quit
Właściwości klasy można odczytywać bez konieczności uruchamiania metod odczytu, a po prostu wskazać ją po kropce. Uwaga na class, która odpowiada metodzie getClass(), ale dla pewnej grupy typów, np. java.util.Map czy budowniczych (ang. builders) w Groovy jest niczym specjalnym, np. w mapie jest traktowane jako...klucz. Zaleca się używanie metody getClass() zamiast class, gdzie interesuje nas dostęp do typu java.lang.Class.

Groovy pozwala na deklarację opcjonalnych parametrów wejściowych metody/konstruktora, jednakże muszą one być końcowymi parametrami. Ostatni parametr wejściowy metody będący tablicą jest również traktowany przez Groovy jako opcjonalny. Tym samym programiści C++ mogą wrócić do swoich przyzwyczajeń, których wyzbywali się przez tyle lat programowania w Javie.
 $ groovysh
Groovy Shell (1.6.3, JVM: 1.6.0_13)
Type 'help' or '\h' for help.
-------------------------------------------------------------------------------------------
groovy:000> def wypisz(nazwa, String[] tablica) { println "$nazwa - tablica: $tablica" }
===> true
groovy:000> wypisz 'Tablica podana', 'Pierwszy parametr', 'drugi parametr tablicy'
Tablica podana - tablica: [Pierwszy parametr, drugi parametr tablicy]
===> null
groovy:000> wypisz 'Brak tablicy'
Brak tablicy - tablica: []
===> null
groovy:000> def dajPodwyzke(kwota=10000) {
groovy:001> println "Masz podwyzke o $kwota PLN"
groovy:002> }
===> true
groovy:000> dajPodwyzke()
Masz podwyzke o 10000 PLN
===> null
groovy:000> dajPodwyzke(300)
Masz podwyzke o 300 PLN
===> null
groovy:000> quit
Realizacja interfejsu to często tworzenie metod-zaślepek, gdzie jedynie pojedyncza metoda interfejsu nas interesuje, a parametry wejściowe często wcale. Znany i (nie)lubiany przypadek to klasy wewnętrzne do obsługi zdarzeń w GUI. Jak to ujął Venkat: "Groovy brings a charming idiomatic difference here" (strona 39 u dołu). Wystarczy zdefiniować domknięcie i zrzutować na odpowiedni typ konstrukcją as [typ], np.
 button.addActionListener(
{ JOptionPane.showMessageDialog(frame, "You clicked!") } as ActionListener
)
Zadaniem dla wytrwałych i dociekliwych byłoby napisanie podobnej konstrukcji w Javie.

Możemy również tak:
 displayMessage = { JOptionPane.showMessageDialog(frame, "You clicked!") }
button.addActionListener(displayMessage as ActionListener)
W końcu Groovy udostępnia domknięcia - bloki z kodem do wykonania - i możemy je traktować jak zmienne.

Co powoduje, że realizacja interfejsów w Groovy staje się jeszcze bardziej pikantna, to opcjonalna implementacja metod interfejsu (w przypadku próby wykonania niedostarczonej metody z interfejsu Groovy zgłosi NullPointerException!) oraz ich definicja w postaci mapy - nazwa metody i domknięcie - jej ciało.
 handleFocus = [
focusGained : { msgLabel.setText("Good to see you!") },
focusLost : {msgLabel.setText("Come back soon!") }
]
button.addFocusListener(handleFocus as FocusListener)
Realizacja interfejsu może być dynamiczna, tzn. poznamy realizowany interfejs w trakcie działania programu. Pomocne jest wykorzystanie metody asType().
 events = ['WindowListener', 'ComponentListener'] // listę budujemy dynamicznie, np. podane przez użytkownika

handler = { msgLabel.setText("$it") }

for (event in events) {
handlerImpl = handler.asType(Class.forName("java.awt.event.${event}))
frame."add${event}"(handlerImpl)
}
Nie powinniśmy mieć złudzeń - tyle, ile zabawy mamy podczas programowania, tyle będziemy mieli podczas utrzymania takiego kodu. To musi być niezwykle interesujące dla obu stron :)

Jako podsumowanie wiadomości nt. obsługi interfejsów w Groovy autor przedstawia kompletny przykład aplikacji okienkowej zbudowanej na bazie JFC/Swing API. Kompletny kod źródłowy tej i pozostałych programów dostępny jest pod adresem ze strony książki.

Groovy nie wymaga podania wyrażenia boolowskiego explicite, tzw. prawda Groovy (ang. Groovy truth). Referencja null to false, a nie null to...zależy. Jeśli dotyczy kolekcji, wtedy niepusta kolekcja daje true. Bardzo intuicyjnie będzie z innymi typami, np. Character to niezero, Enumeration to niepusta lista, Iterator podobnie, Map posiada przynajmniej jedną parę, itd. Warto zajrzeć do dokumentacji, aby...nie rozpisywać się (ja teraz, Ty w trakcie programowania w Groovy). Pora przetrawić to Groovy.

20 komentarzy:

  1. Operator bezpiecznego odczytu wydaje mi się fajny, nieraz w Ruby wpadałam na ''you have nil object ...''

    OdpowiedzUsuń
  2. Szczerze powiedziawszy nie widzę zbyt wiele zalet Groovy. Domknięcia to chyba jedyna rzecz jakiej brakuje obecnie Javie.

    Używanie ? oznacza, że tworzymy tak naprawdę zaśmiecony kod. Moim zdaniem null powinno nie istnieć i wtedy takie konstrukcję są zbędne.
    Uproszczona składnia klas jest w Javie, to wszelakie szkielety (Hibernate, Spring, JPA, JSF, etc.) wymusiły używanie getter/setter do pól klasy, co stoi na przeszkodzie przed używaniem public przy definicji pola?
    A uproszczone konstruktory? Mam nadzieję, że można to zablokować, bo całą hermetyzację diabli biorą ;-)
    Wyjątki? Zawsze można używać RuntimeException?

    W wielu przypadkach to głównie polityka Suna doprowadziła do pewnych konstrukcji a nie ograniczenia języka :P

    I chyba podałeś najlepszy argument czemu nie używać Groovy:
    "Nie powinniśmy mieć złudzeń - tyle, ile zabawy mamy podczas programowania, tyle będziemy mieli podczas utrzymania takiego kodu" - naprawdę nie życzę nikomu utrzymywania takiego kodu :P

    PS. Możesz używać innego formularza do komentarzy? To co jest teraz kompletnie nie nadaje się do pisania :-(

    OdpowiedzUsuń
  3. "co stoi na przeszkodzie przed używaniem public przy definicji pola?" - A to nie łamie enkapsulacji? W jaki sposób kontrolujesz dostęp do pola skoro jest publiczne? Pewnie na to i na inne tego typu pytania odpowiada Mariusz w Jest rozdział "Zagadnienia programowania obiektowego". Właśnie pojawił się nowy rozdział o OO. Nie czytałem, ale spodziewałbym się odpowiedzi tam. Szkielety aplikacyjne nie wymuszają stosowania set/get-terów. Można dodawać adnotacje przy polach, jednakże to właśnie możliwość związania ich z metodami daje możliwość dołożenia dodatkowych sprawdzeń i funkcjonalności.
    Jakby na zaprzeczenie swoich słów o publicznych polach piszesz "A uproszczone konstruktory? Mam nadzieję, że można to zablokować, bo całą hermetyzację diabli biorą ;-)" ;-)

    Języki wyższego poziomu nakładają na nas pewne ograniczenia i przyzwyczajają do nich, jakby były niezbędne. Czym niżej, aż do assemblera, masz więcej narzędzi, aby zrobić sobie krzywdę. Czy ją sobie zrobisz, czy nie, to już inna bajka. Nie daje się ostrych narzędzi małym dzieciom, mimo, że bez ostrych narzędzi nie dalibyśmy sobie rady w życiu. Po prostu dzieciaka trzeba nauczyć się nimi posługiwać. Podobnie z Groovy. Zapomniałeś jak wyglądały Twoje aplikacje w javie na początku kariery programisty? Utrzymywanie tego pewnie nie należałoby do przyjemności. Czy to jest argument, aby dać Ci po łapach i powiedzieć: "Wypad z baru. Koniec z programowaniem. Nie nadajesz się do tego"?! I co byś dzisiaj robił? Szydełkował? :D Wolę programowanie.

    OdpowiedzUsuń
  4. Właśnie o to mi chodzi, w Groovym używanie publicznych pól jest ok, ale w Javie już nie. Właśnie takie myślenie jest problemem a nie używany język.

    Nie ma co mówić o enkapsulacji w przypadku zwykłego POJO, to tylko wiaderko na dane, które nosimy tam i nazad. A jeśli już mamy bardziej złożoną klasę, to dostęp przez "uproszczony konstruktor" do wszystkich pól jest już łamaniem enkapsulacji.

    Adnotacje przy polach pojawiły się dopiero nie dawno (z tego co się orientuję). Druga spraw, to co jeśli używamy XML do konfiguracji i nie mamy getterów / setterów, zadziała? Wątpię. Zresztą co to za enkapsulacja, gdy metoda przypisuje wartość wprost polu.

    Sprawdzanie przy polach? To nadaje się tylko w najprostszych przypadkach, danych z formularzy www, czy ktoś wpisał imię, albo data jest w zakresie. I zresztą łamie to zasadę Pojedynczej Odpowiedzialności klas. Klasa reprezentuje pewną wartość biznesową i wykonuje walidację danych. Może co najwyżej definiować jakie wartości są poprawne.

    Faktyczna walidacja będzie w osobnej klasie, która sprawdzi, czy taki obiekt jest poprawny w danym kontekście, w stosunku do całego modelu aplikacji. Sama poprawność danych nie oznacza, że obiekt jest poprawny.

    Od dłuższego czasu widzę taki trend, w którym sam uczestniczyłem (ale już otwarły mi się oczy ;-), definiuje się pewną zasadę i potem dostosowuję się do niej język, tworząc wymyślne szkielety. I nikt się nie zastanowi, że zasada jest zła i to ją trzeba zmienić.

    Ile waszych klas to zwykłe wiaderka z danymi, gdzie gettery / settery dają dostęp do pola? Założę się, że 50% kodu :-(

    OdpowiedzUsuń
  5. Właśnie o to mi chodzi, w Groovym używanie publicznych pól jest ok, ale w Javie już nie. Właśnie takie myślenie jest problemem a nie używany język. Czekaj, czy Ty sądzisz, że w Groovy konstrukcja klasa.pole jest równoznaczne z wywołaniem klasa.pole w Javie?! Tak nie jest. Pamiętam, jak tłumaczyłeś OGNL przy Struts2. Podobnie jest w Groovy - zapis przypomina bezpośredni dostęp do pola, ale tak na prawdę jest wywołaniem metody zapisu/odczytu. Możesz je sobie stworzyć, albo możesz polegać na tym, co stworzy Ci Groovy dynamicznie.

    Uproszczony konstruktor to jedynie taka konstrukcja, która sprowadza się do wykonania stworzonego (znowu dynamicznie) konstruktora. Co za różnica, czy Ty go tworzysz, czy język?! A czy domyślny, bezargumentowy konstruktor w Javie jest czymś innym?! Nie dotyka się pól, ale one są i tak inicjowane do swoich domyślnych wartości. Tak jest w Javie, a Groovy rozszerza tą myśl.

    Kontrola przez metody to jedynie kontrola znana klasie - nie łamie to żadnej z zasad, a wręcz przeciwnie pozwala na zapewnienie, że nikt poza samą zainteresowaną - klasą - będzie wiedział, co jest właściwe z jej punktu widzenia. Bardziej złożone sprawdzenie poprawności będzie i tak musiało być wyniesione poza klasę, bo ona sama niewiele wie. To dobrze. Mam nadzieję, że to ma związek z Groovy, bo nie widzę.

    Odnośnie zakładu - pewie byś go ze mną przegrał :) Wystarczy, że sprawdzisz archiwum na moim blogu, gdzie pisząc o JPA pisałem, że to nie mają być jedynie klasy z getami i setami, ale właśnie klasy-pojemniki z możliwościami uruchomienia pewnej, nieskomplikowanej funkcjonalności na niej - najczęściej będzie to niewielka, acz potrzebna kontrola poprawności. Tworzyłem klasy z getami/setami i nadal pewnie będę to robił, ale nie jestem przykładem na osobę, która mogłaby pretendować do miana zaawansowanego programisty przestrzegającego dobrych praktyk. Po prostu śledzę, co się dzieje na rynku i weryfikuję swoje poglądy. W zależności od nastroju, upodobań, itp. jedno mi się podoba, a inne nie. Właśnie dlatego, kiedy mam wolną chwilę próbuję się z...Clojure. Nigdy nie programowałem (więcej niż na zaliczenie) w języku funkcyjnym i wciąż nie wiem, czy mi to potrzebne. Groovy, jak i inne języki, próbuje coś rozwiązać. Owe coś mnie intryguje. Badam, sprawdzam, czytam i dyskutuję. Groovy nie nada się do wszystkiego, ale dla niektórych rozwiązań będzie więcej niż cacy. Uważam, że Groovy może wiele, a pogłoski jakoby Gosling był nim zachwycony mają nieznaczny, ale z pewnością niezerowy wpływ na jego wykorzystanie przeze mnie. Niektórzy klienci już są przekonywani do mojego poglądu, jakoby Groovy/Grails mogło więcej (czasowo) niż odpowiedni stos czystojavowy, np. Seam, a potrzebna wiedza nie jest tak rozległa, więc wejście w temat następuje z uśmiechem na twarzy (który wierzę, że nie zniknie do końca projektu :))

    OdpowiedzUsuń
  6. Wiem jak to działa w Groovym, ale to niczego nie zmienia z publicznym dostępem do pól w Javie. Wygenerowany czy wpisany z palca getter / setter nic tu nie zmienia.

    Co do uproszczonego konstruktora, to moje pytanie było czy można to wyłączyć, np. definiując własny konstruktor? Tak jak to jest w Javie, zdefiniowanie własnego konstruktora "wyłącza" domyślny konstruktor.

    Kontrola poprawności przez klasę-wiaderko, moim zdaniem, łamię zasadę S(OLID). Przypuszczam, że w Groovym kontrola jest wykonywana nie przez klasę, ale przez szkielet, na bazie zdefiniowanych ograniczeń i komunikaty błędów są wstrzykiwane do klasy też przez szkielet.

    JPA bazuje na doświadczeniach Hibernate więc dlatego już to tam działa. Hibernate 2 raczej nie miał takich możliwości.

    Ja nie mówię, żeby nie poznawać nowych rzeczy, tylko poznawać je ze zrozumieniem. To nie powinien być kolejny wytrych do problemów jakie mamy z danym rozwiązaniem i wieszczenie, że to jest Święty Graal na wszystkie problemy.

    Druga sprawa, programiści zbyt często przykładają zbyt dużą wagę do technologii, zamiast skupić się na tworzeniem pięknego kodu, który działa niezależnie od użytego wytrychu. Powinniśmy tworzyć kod, który rozwiązuje / obrazuje / modeluje pewien aspekt biznesowy, a nie tworzyć aplikacje po daną technologię, szkielet.

    OdpowiedzUsuń
  7. @Łukasz
    Groovy nie definiuje publicznego pola! ale o tym za chwile...

    a)
    Gettery nie są potrzebne by używać xml w konfiguracji. W zwykłym Hibernate/JPA możesz też ustawić by pola były używane bezpośrednio. Działa to nawet jeśli są prywatne, refleksją dostaniesz się wszędzie.

    b)
    gettery i settery powstały ponieważ korzystanie z publicznego pola było uznane za złą praktykę, bo:
    - nie ma osobnej kontroli nad zapisem i odczytem
    - nie możesz zdefiniować pola w interfejsie
    - tracisz zgodność binarną jeśli musisz zmień logikę ustawiania/pobierania pola
    - dobrze to działało w visual edytorach, które refleksyjnie sobie oglądały co w klasie da się ustawić

    Koncepcyjnie "properties" muszą być elementem nowoczesnego języka, problemem Java jest, że nie uwzględniono ich za pomocą składni ale konwencji(C# już nie popełnił tego błędu).

    Groovy nie definiuje publicznego pola!
    Properties zdefiniowane w przykładach Jacka kompilują się do pola, gettera i settera. Getter i setter możesz podmienić, możesz zmienić ich widoczność itp.

    POJO znane z Hibernate rzeczywiście daleko stoi od poprawnego OOD.

    c)
    Grzechem głównym Groovy jest pełna dynamiczna typizacja, bez możliwości statycznej typizacji.

    Co gorsza używanie "nazwanych typów" w Groovy powoduje spowolnienie kodu (runtime zajmuje się dodatkowo sprawdzaniem typów).

    Osobiście jestem silnym zwolennikiem statycznej typizacji(z elementami dynamicznymi w języku), a moim idealnym językiem byłoby coś między C# 4, a Scala tylko ze składnią bliżej Groovy.

    Groovy jest o tyle piękny co niebezpieczny. Mimo, że Scala zawsze będzie szybsza i bezpieczniejsza to Groovy już teraz ma wsparcie (SpringSource) i ma najmniejszą stromą krzywą nauki ze wszystkich języków na JVM.

    To powiedziawszy odradzałbym wykorzystanie produkcyjnie Groovy jeśli ktoś nie jest w pełni przekonany, że wie co robi.
    Moim zdaniem w dużych projektach Groovy/Grails wymaga wysokiej dyscypliny i dobrego procesu. Praktyki jak testowanie i ciągła integracją muszą być we krwi wszystkich programistów. Jeśli to jest to odpłaca się produktywnością i przejrzystością budowy.

    Z drugiej strony nie ma lepszego języka skryptowego dla programisty Java. Polecałbym wypróbować Groovy właśnie w pisaniu skryptów czy testów. Trudno wytłumaczyć to "aha!" jakie występuje z powodu dobrego API, składni pozbawionej szumu i elementów funkcyjnych w użyciu.

    Pozdrawiam,
    Krzysztof Kowalczyk

    OdpowiedzUsuń
  8. "gettery i settery powstały ponieważ korzystanie z publicznego pola było uznane za złą praktykę"
    i o tym właśnie pisałem, ktoś uznał to za złą praktykę i zaczęto budować koło tego cały kościół wiernych, że tak ma być. A wystarczyło powiedzieć, że się pomyliliśmy, i dostęp do publicznego pola jest ok. Tak właśnie zrobił Groovy, zresztą po cichu wszystkie szkielety zrobiły to samo, wstrzykiwanie wartości do prywatnych pól z zewnątrz. I jakoś nikt się nie oburza, że tak nie wolno!

    OdpowiedzUsuń
  9. Łukasz, ale publiczne pola są złą praktyką nie bez powodu, część z nich wymieniłem. W wielu sytuacjach są po prostu nie akceptowane (interfejsy!), a koncepcja properties jest po prostu lepsza.

    Pewnie, że sam gdy robiłem sobie sieć neuronową to używałem publicznych pól, ale to było w algorytmicznym problemie, gdzie nawet jednego interfesu czy dziedziczenia nie było (w warstwie logiki).

    Groovy nie ma powiedział, że dostęp do publicznego pola jest ok, on po prostu implementuje w specyfikacji języka koncepcje Properties, która jest lepsza od koncepcji pola w większości przypadków i jest jawnym bytem w porównaniu do konwencji jaką są settery.

    Brak properties jest brakiem Java załatanym przez get/set, ale to jest dalej łata, którą Groovy stara się ulepszyć.

    Pozdrawiam,
    Krzysztof Kowalczyk

    OdpowiedzUsuń
  10. Użycie "property" dalej nic nie zmienia, przełam tą konwencję. Jeśli jest to tylko zapis i odczyt wartości pola, nawet wygenerowany, to pole może być publiczne i wszystko jest ok. Jeśli potrzebujesz kontrolować zapis, dodajesz setter, chcesz kontrolować odczyt, dodajesz getter. Chcesz kontrolować zapis i odczyt, dodajesz setter i getter. Groovy nic tu więcej nie robi.

    Powody które wymieniłeś, to tak jak wzorce J2EE są antywzorcami, tak te są antypowodami.

    Pierwszy już opisałem, chcesz mieć kontrolę, to dodajesz gettery i settery a pole robisz prywatne.

    Interfejsy definiują zachowanie i reprezentują abstrakcję, więc definiowanie w nich pól powoduje, że przestają być abstrakcyjne (nawet jeśli robisz to za pomocą gettera i settera).

    Z tą zgodnością binarną można długo dyskutować. Jeśli projektujesz API to powinno ono być jak najbardziej abstrakcyjne, więc bazujesz na interfejsach a nie na rzeczywistych klasach. W innym przypadku zawsze będziesz miał problem ze zgodnością binarną.

    A co przeszkadzało wizualnym edytorom operować na polach? Refleksja działa tak samo w obu przypadkach, i pola i metody da się odczytać.

    OdpowiedzUsuń
  11. "Jeśli potrzebujesz kontrolować zapis, dodajesz setter, chcesz kontrolować odczyt, dodajesz getter. Chcesz kontrolować zapis i odczyt, dodajesz setter i getter"

    I musisz refaktoryzować cały kod oraz tracisz zgodność we wszystkich bibliotekach. Jak masz od razu gettery i settery, to przynajmniej część zmian możesz ukryć przed użytkownikiem implementując je w w nich i nie używasz dwóch różnych konwencji do tych samych bytów. To jeszcze nie problem...

    Polimorfizm w Java dotyczy wyłącznie odwołań do metod, czyli nie jesteś w stanie przechwycić odwołań do pól w potomkach, ani w żaden sposób zmienić ich zachowania, wzorce jak dekorator przestają w połowie działać.

    "Interfejsy definiują zachowanie i reprezentują abstrakcję, więc definiowanie w nich pól powoduje, że przestają być abstrakcyjne"

    Nie mogę się zgodzić. Interfejs jest kontraktem, mówi co jest dostępne w danym typie dotyczy to za równo zachowania jak i właściwości. Poza tym właściwości - properties wcale nie muszą być oparte o istniejące pole - mogą być wyliczane, mogą w nowej wersji być wyliczane choć w starej nie były...
    Ważne jest, że dany obiekt posiada zadeklarowane cechy i metody.

    To zwiększa abstrakcje a nie zmniejsza.

    Nie uważam, że konwencja get/set jest udana ale jest potrzebna. Można używać pól publicznych ale gdy się wie co się robi, inaczej psuje to projekt i utrudnia wykorzystanie bardziej zaawansowanych technik.

    Na samych polach nie działa leniwe ładowanie, nie działają aspekty, nie można zaprojektować wzorca proxy ani wykorzystać interceptora, nie można użyć porządnego beans binding. Inne wzorce też się psują bo potrzebują polimorfizmu, lub wywołań wirtualnych.

    Aspekty i leniwe ładownie wymagają wykorzystania DynamicProxy albo zmian w bytecode. Do pierwszego potrzebne są wywołania virtualne a więc metody - stąd kiepska ale potrzebna konwencja get/set. Nawet w drugim przypadku w teorii można zamiast zmieniać jedną metodę, modyfikować każdy kod, który korzysta z naszego pola, myślę, że możesz sobie wyobrazić do czego to prowadzi.

    Pojo to dość uproszczona wersja specyfikacji JavaBeans i tak zajmujemy Jackowi bloga, więc pominę rozwijanie dlaczego get i set w tym powstało.

    Mówiąc krótko, set/get realizuje "Open/closed principle".

    Pozdrawiam,
    Krzysztof Kowalczyk

    OdpowiedzUsuń
  12. Szkoda zaśmiecać blog Jacka taką dyskusją, zapraszam na piwko, gdzie będzie można dalej dyskutować. To gdzie i kiedy?

    OdpowiedzUsuń
  13. Dobre. Wy mi zaśmiecacie?! Żartujecie? Właśnie takich dyskusji mi trzeba było. Ja odpadłem, od kiedy Krzysiek wszedł na scenę. Od tego momentu siedzę i czytam z otwartą buzią. To się nazywa dyskusja - połowy w ogóle nie rozumiem (!) Tzn. rozumiem, ale tylko teoretycznie - za słabo, aby zająć stanowisko. Groovy ma łączyć, a nie dzielić.

    OdpowiedzUsuń
  14. Zaśmiecamy, bo odchodzimy od tematu, to taka typowa dyskusja barowa ;-) Miło porozmawiać, ale jak wrócisz do domu to o wszystkim zapomnisz :P

    OdpowiedzUsuń
  15. Hm, jeśli piszę nie zrozumiale to raczej moja wina ;)

    @Łukasz
    Można mnie znaleźć we Wrocławiu, kończę magisterkę w przerwach szukam sobie powoli pracy, więc z czasem trochę trudno :/
    Może na konferencjach się w końcu zacznę pojawiać.

    @Jacek
    Jak to jest, że akurat gdy Ty będziesz we Wrocławiu przemawiał (przynajmniej taką plotkę słyszałem ;) ) to ja będę w Warszawie? No i nie wiem czy zdążę wrócić na czas...

    Pozdrawiam,
    Krzysztof Kowalczyk

    OdpowiedzUsuń
  16. Czyli jednak będziesz w Warszawie, daj znać to się jakoś zgadamy.

    OdpowiedzUsuń
  17. W drodze do albo z Mazur, na przystankach kończąc artykuł na CEE-SET...

    Następnym razem :)

    OdpowiedzUsuń
  18. Krzysiek, będę we Wrocku w pon za tydzień z Groovy i Grails. Dobrze słyszałeś. Muszę przyznać, że byłoby niezwykle wartościowe móc się z Tobą spotkać. Wydajesz się posiadać nieprzeciętną wiedzę i aż dziw bierze, że jeszcze się z nią nie ujawniłeś na JUGu czy konferencji w PL. Zdumiewające. Postaraj się przyjechać na Javarsovię 4.lipca. Będzie tam wiele osób, które z przyjemnością chciałyby zamienić z Tobą słówko.

    A to CEE-SET to http://www.cee-set.agh.edu.pl/? A ja tu wspominam o wystąpieniach. O czym będzie Twoje?

    OdpowiedzUsuń
  19. @Jacek
    hm, może szerokie horyzonty ale brak specjalizacji i doświadczenia komercyjnego (brak spring w CV to straszna sprawa dzisiaj ;)), to też jeszcze nie uważam, że mam o czym opowiadać z zakresu tematów popularnych.

    Zakładając, że a) zdążymy z artykułem, b)przyjmą go na konferencje, c) będzie wybrany do prezentacji, to tak, to CEE-SET.

    Artykuł dotyczy "model-driven software modernisation".
    W teorii chodzi o pokazanie jak automatyzować proces modernizacji oprogramowania (ew. migracji) z wykorzystaniem narzędzi przeznaczonych do MDA/MDSD.

    W praktyce oznacza to migrację projektu z Java 1.4, hibernate 2 i xml na Java 1.5 z generics, hibernate 3 i adnotacje, w jakieś 15 sek. z wykorzystaniem kilku projektów z Eclipse modeling i bardzo wielu akronimów. Tyle marketingu, w praktyce tak różowo nie ma.

    Postaram się dotrzeć na prezentację we Wrocławiu :)

    Pozdrawiam,
    Krzysiek

    OdpowiedzUsuń
  20. Ale fajna konferencja, człowiek nawet nie wiedział. Może warto się wybrać?

    OdpowiedzUsuń