18 stycznia 2010

Przygotowywanie (się do) projektu z JAX-WS i Apache Maven - modularyzacja wychodzi sama

Po tych moich certyfikacyjnych wojażach i bojach z recenzjami (jeszcze jedna czeka w kolejce do napisania) wracam (na blogu) do tematu mojego obecnego projektu, którego pierwsze rezultaty można było "podziwiać" w Każdemu będzie w końcu dane - wreszcie Java EE 5 w projektach!.

Komentarzy posypało się co nie miara, za co wszystkim dziękuję, bo chciałbym móc powiedzieć, że to nie moje, albo że miałem jedynie 5-10 minut na poprawki przed publikacją, aby wybronić się z kilku, ale nic z tego. Wszystko, co opublikowałem było moje na bazie tego, co nie było moje :] Migracja miała na celu wypuszczenie działającego rozwiązania możliwie niewielkim nakładem pracy. Udało się. Jakkolwiek nie oznacza to zakończenia prac nad tym "dziwolągiem", ale przyświecał mi jeden cel - dzisiaj testuję prototyp, aby zweryfikować mój punkt widzenia, aby jutro i w kolejnych dniach wyciosać coś rzeczywiście przyzwoitego. Od niewielkiego tworu, ale działającego, do większego, bardziej naładowanego wzorcami i dobrymi praktykami, i wciąż działającego. Takie iteracyjne programowanie. Prace trwają.

Dzisiaj postanowiłem wprowadzić zmiany w obszarze zarządzania projektem, w którym można wyróżnić część serwerową (uruchomioną w centrali) oraz część kliencką. Ich zależność polega na interfejsie, z którego korzystają. W tym przypadku nie tylko interfejs programistyczny (w sensie programowania w Javie), ale również technologiczny (w sensie wykorzystania technologii/szkieletu aplikacyjnego w Javie) łączy oba moduły. Skorzystałem z technologii Web Services (JAX-WS), więc moduł centralny wystawia usługę sieciową, którą konsumuje moduł kliencki. Logiczne, co?

I tutaj natrafiłem na problem zdefiniowania zależności między modułami. Gdyby założyć, że część serwerowa jest aplikacją webową, to w jaki sposób określić zależność w module klienckim? Nie ma jak, bo war to podział technologiczny, a nie programistyczny i nie tędy droga. Potrzebuję zdefiniować SEI (ang. Service Endpoint Interfejs), abym na nim oparł technologiczny moduł serwerowy i programistyczny, kliencki. Moduł serwerowy to war, który zanurzy moduł SEI, z którego będzie mógł skorzystać moduł kliencki.

Teraz jest dla mnie jasny komentarz Artura Karazniewicza (aczkolwiek jego pierwszy "wyjazd" był do kosza, co się ostatecznie stało :)):

"Po drugie uniezależnienie samego WebService od implementacji endpointu w java (zastosowanie SEI oraz nazwanie poszczególnych elementów WSDL w adnotacjach WebService, WebMethod itd.)."

Początkowo pomyślałem "Kto by się tym przejmował?!", ale teraz samo rozczłonkowanie projektu na moduły wymusiło na mnie poćwiartowanie modułu serwerowego z wydzieleniem modułu z SEI. Inaczej po prostu nie dałoby rady. Do mnie przemawiają przykłady, co daje mi dane podejście i w tym przypadku samo stwierdzenie "Bo tak się robi. Bo to dobra praktyka." to zdecydowanie za mało. Potrzebuję konkretów, a nie kiwania głowami, że tak się robi, a kiedy zapytać "Dlaczego?", nikt nie jest skłonny wytłumaczyć.

Bardzo ucieszyłem się, kiedy pojawiły się komentarze wskazujące konkretne błędy z chociażby skromną, ale zawsze, próbą wytłumaczenia "Dlaczego nie". Niestety pojawiły się też takie ogólnikowe, zrób to, zrób tamto, bez jakiegokolwiek wyjaśnienia "Dlaczego". A szkoda, bo jestem w stanie wyobrazić sobie niedoświadczonych programistów, którzy postawieni w tej roli, w jakiej ja byłem przed chwilą - wystawienia ich kodu na publiczną krytykę - dostają multum dobrych rad, które są dobre jedynie z ich nazwy. Co mi po dobrej radzie, jeśli nie dostaję racjonalnego ich wytłumaczenia? Są dla mnie równie wartościowe, jak wskazanie palcem, co mam zrobić...milcząco.

Zestawiam projekt z pomocą Apache Maven, bo nie tylko wymusiło to na mnie poćwiartowanie (aka zmodularyzowanie) aplikacji, ale również uniezależni mnie od zależności środowiska programistycznego (IDE). Do tej pory w zespole królował Eclipse/RAD. Teraz, z wprowadzeniem mnie do zespołu, wszedł NetBeans IDE (bo jakoś łatwiej mi było stworzyć i przetestować Web Service), a ostateczny cel to uruchomienie narzędzia budowania aplikacji bez udziału ludków z zespołu. Bez wykorzystania Apache Maven, czy jemu podobnego rozwiązania, nie byłoby to możliwe.

Zastanawiam się, jak testować działanie usługi sieciowej? Czy w ogóle warto, skoro mogę przetestować implementację bez narzutu infrastruktury JAX-WS? To w końcu "oznakowane" POJO? A co z klientem? On jest zależny od wygenerowanego przez wsgen. Jak sobie z tym tematem poradzić? Może po prostu zaniechać testowania komunikacji usługa-klienta, bo to ma działać (jest poza moją kontrolą i jestem tego klientem), a przetestować metody, które otrzymają wynik wywołania przesłoniętego zaślepką (ang. mock object)? Rady mile widziane (zlitujcie się jednak nade mną i dodajcie słów kilka dlaczego, albo chociaż odnośniki do dokumentacji).