Rzecz o myśleniu

I nadeszła ta chwila, zaczynamy nowy projekt, zespół skompletowany, sprzęt stoi, można zacząć kodować. Jednak jak to zwykle bywa, faktyczny start się opóźnia, ale i tak zespół nie marnuje czasu, spędza go na prototypowaniu. W zależności od klienta, zespół wybiera docelową platformę aplikacyjną, język, w którym będzie oddawał się twórczej pasji i kilka mniej istotnych rzeczy. I właśnie tym "pierdółkami" się zajmę.

Nie ważne jakie mamy narzucone ograniczenia, zawsze mamy możliwość wyboru. W moim przypadku muszę tworzyć aplikację na daną platformę, dany szkielet, nie mogę użyć różnych fajnych rzeczy ze świata Open Source. Mam dostępne tylko to co zostało zaaprobowane przez departament Architektury (i parę innych, kompletnie nie związanych z IT ;-).

Mimo ograniczeń, dalej mam wybór. Jeśli tak, to co będzie potrzebne do "upichcenia" aplikacji:

  • serwer aplikacyjny - jedyny słuszny u klienta
  • baza danych - lokalnie HSQL a na produkcji DB2 lub Oracle
  • szkielet www - JSP albo jedyny słuszny wspierany przez jedynie słuszny serwer aplikacyjny
  • szkielet persystencji danych - czyste JDBC lub Hibernate - wybór oczywisty (czy aby na pewno?)
  • dynamiczna walidacja modelu - to co dostarcza szkielet www (jak sama nazwa wskazuje) nie jest wystarczające i często ma się nijak do wymagań walidacji modelu i logiki biznesowej
  • IDE - wybór dowolny, włącznie z preferowanym przez klienta (ktoś to będzie musiał wspierać później)
  • narzędzie do zarządzania projektem - wyboru nie ma, klient narzuca swoje i trzeba się dopasować

Patrząc na powyższą listę, wybór sprowadza się do bazy danych, która i tak będzie taka sama jak na produkcji. Jedynie na potrzeby testów jednostkowych zespół wykorzysta HSQL. Ktoś oczywiście będzie zaskoczony "że przecież lokalnie też należy używać HSQLa", a ja powiem, że to proszenie się o problemy. Jeśli tylko można, należy używać środowiska jak najbardziej zbliżonego do produkcyjnego.

Szkielet www - nikt nie ma ochoty na "rzeźbienie" w czystym JSP, więc cokolwiek ponad to i tak będzie super. Zresztą i tak taki szkielet w dużej mierze przekształcimy do naszych potrzeb, bo od tego jest szkielet, ma być rusztowaniem dla pomysłów zespołu. Łatwość rozbudowy to podstawowe kryterium dla szkieletu www. Reszta to marketing ;-)

Persystencja - tu też wybór jest oczywisty, na pierwszy rzut oka. Kto chciałby się "babrać" w czystym JDBC? Pisanie tych wszystkich SQLi, tworzenie połączeń, więc Hibernate jest niczym Święty Graal. I w tym miejscu większość zespołów zapomina o tym elemencie, aż zaczną się problemy ;-) Przyjęcie, że Hibernate zrobi za nas wszystko jest dużym błędem. Decydując się na jego użycie musimy również spełnić założenia, które nakłada na aplikację ten szkielet. Podam tylko dwa problemy, które należy rozwiązać - implementację metod equals() i hashCode().

Dynamiczna walidacja - jeśli dynamiczna to znaczy potrzebujemy jakiegoś języka dynamicznego, coś co będzie można poprawić bez restartowania aplikacji i bez kompilacji. Jakiś język skryptowy będzie odpowiedni, wyszukujemy wśród zaaprobowanych języków skryptowych i jest, mamy język X (podstaw dowolny język skryptowy z jakim miałeś styczność i który pozwala wprost na interakcję z kodem napisanym w Javie). Gotowe, pozostaje tylko napisać generyczny mechanizm, który pozwoli wywoływać nam zapisane walidacje w plikach i wstrzykiwać model aplikacji do kontekstu przetwarzania skryptu. Teraz to już z górki!

IDE - wybór możliwości jest szeroki, od darmowych Eclipse i NetBeans po komercyjne IntelliJ IDEA, każdy z członków zespołu znajdzie coś dla siebie. Wymóg jest jeden, kod napisany za pomocą IDE musi się dać zbudować za pomocą narzędzia do zarządzania projektem klienta. Można to porównać do Mavena, który pozwala zarządzać projektem niezależnie od używanego IDE. Problemu nie ma, wszyscy kochają swoje zabawki ;-)

I gotowe, projekt rusza pełną parą, a że piszę o projekcie, który potrwa tak na oko z dwa lata, więc czasu mamy sporo. Jeśli nawet coś przeoczyliśmy, to będzie czas aby to naprawić, zmienić, dostosować. I znów zespół sam wprowadza się w błąd, zaczyna budowę na niesprawdzonych fundamentach. Nie ma pełnej wiedzy o problemach jakie mogę przysporzyć poszczególne elementy aplikacji - serwer aplikacyjny (zarządzanie wątkami), baza danych (wspierane typy indeksów), szkielet www (przechowywanie stanu w środowisku rozproszonym), szkielet persystencji danych (struktura tabel jest ważniejsza, niż łatwe mapowanie na encje), narzędzie zarządzania projektem (po dodaniu nowych zależności, należy zainicjować projekt od nowa).

Nie ma znaczenia, czy zespół sam wybrał dane rozwiązanie, czy zostało ono narzucone. Musi znać ograniczenia i wymagania każdego elementu, czas na początku projektu musi być temu poświęcony. To nie tylko skompletowanie "teczki z papierami", to również zaznajomienie się z tym "papierami" i ich zrozumienie. Temu właśnie ma służyć prototypowanie, poznawaniu możliwości i ograniczeń wybranych składowych aplikacji.

Najważniejszym kryterium pod względem którego należy sprawdzić każdy element to jak się zachowa w przypadku zmian, jedynej pewnej rzeczy, która na 100% wydarzy się w trakcie trwania projektu i to wiele razy. Wymagania zawsze będą się zmieniać.

Dość tych "wynurzeń", teraz trochę konkretnej wiedzy, która wynika z powyższych założeń. Skupię się na IDE i języku dynamicznym, gdyż oba są ze sobą połączone.

Użycie danego IDE powinno być przemyślane nie tylko pod względem łatwości użycia, czy znajomości przez członków zespołu. Również aspekt łatwości rozwiązywania problemów związanych z IDE i łatwość dostosowania do wymogów projektu musimy być rozważony. Dotyczy to wsparcia dla wybranych technologii - Hibernate , język dynamiczny, szkielet www. Podam prosty przykład: zmieniamy nazwę klasy Java za pomocą IDE, czy wszystkie odwołania, również z języka dynamicznego czy też z plików *.hbm.xml zostaną zmienione? Jeśli nie, to będziemy musieli wyszukiwać wszystkie przypadki użycia ręcznie i za każdym razem pamiętać o tym procesie. IDE zostanie sprowadzone do poziomu Notatnika.

W przypadku IDE dużą rolę odgrywa przyzwyczajenie członków zespołu, może dobrze jest je odłożyć na bok i nauczyć się obsługiwać nowe IDE, zwłaszcza jeśli będziemy go używać przez kilkanaście miesięcy? Szczególnie jest to istotne, gdy reszta zespołu używa wspólnego IDE a my jesteśmy wyjątkiem. Sprowadza się to do utrzymywania różnych plików projektu wymaganych przez dane IDE i przechowywanie ich w repozytorium. Z drugiej strony przechowywanie plików w projektowych IDE w repozytorium uważam za błąd. Do tego dochodzi rozwiązywanie różnych drobnych problemów związanych z danym IDE, jeśli jesteśmy wyjątkiem, to nie mamy za bardzo kogo zapytać.

Język dynamiczny - czy aby na pewno jest nam potrzebny? Łatwość dokonywania zmian i brak potrzeby kompilacji są zachęcające, ale co z poprawnością typów? co w przypadku gdy element na ścieżce (model.scenariusz.nazwa) jest nullem ? Jeśli wybraliśmy nasz język dynamiczny tylko ze względu na łatwość zmian w locie i braku kompilacji, możemy być w dużych tarapatach, zwłaszcza kiedy nasze IDE nie wspiera tego języka. I oczywiście takie problemy zaczynają się pojawiać, gdy projekt jest w bardzo zaawansowanym stadium i zmiana mechanizmu walidacji dotknie połowy aplikacji. Bez odpowiedniego rozpoznania we wstępnej fazie projektu, będzie to naprawdę dużą bombą z opóźnionym zapłonem. Pierwszym znakiem ostrzegawczym będzie brak wsparcia ze strony IDE. Reszta musi zostać wykryta w trakcie prototypowania.

Na końcu pasuje umieścić jakąś puentę, ale chyba tytuł tego wpisu robi za nią: trzeba myśleć i nie zdawać się na cudze opinie i przyzwyczajenia. Każdy projekt jest inny, jest procesem twórczym a nie produkcją samochodów na linii montażowej.

Pozdrawiam
--
Łukasz
http://www.lenart.org.pl

Comments

Opcje przeglądania komentarzy

Wybierz preferowany sposób wyświetlania komentarzy i klinij na "Zapisz ustawienia", aby aktywować zmiany.

IDE

Za bardzo doceniacie wagę IDE. Chyba zapomnieliscie, ze aplikacje mozna tworzyc uzywajac zwyklego VIMa..
Osobiscie uzywam IntelliJ IDEA tylko i wylacznie z przyzwyczajenia z Javy oraz posiadania bardzo dobrej integracji z Subversion. Nawet brak refaktoringu dla Pythona nie jest problemem uzywajac Pythona (jedynie)...

Moze mowicie o przypadkach, gdzie _programujecie_ w IDE, i bez niego aplikacja nie dziala, albo konfiguracja reczna (aka VIM) bylaby tak trudna, ze rece opadają - wtedy tylko wspolczuc :-)

Przykladowo: IDEA nie wspiera Pythona i narzedzi webowych dla niego, ale to nie jest _zadna_ przeszkoda, aby nie [u]tworzyc aplikacje w Pythonie. W koncu kod zrodlowy to przeciez ciag znakow. I to jest smrod, jesli potrzebujesz IDE, aby moc komfortowo pisac w danej platformie (jezyk + zbior narzedzi). Duzy smrod... ja zwylke uciekam daleko.

Czas wracac do kolejnego sprintu... :)
T.

Łukasz Lenart's picture

Można pisać nawet w Notatniku

Można pisać nawet w Notatniku (VIM daje za dużo ;-) ale ja mówię o zmianach, jak VIM wspomaga implementację ciągłych zmian w projekcie? Wiem, że można tworzyć makra, czy inne zaawansowane wyrażenia w VIMie (nie jestem ekspertem a kolega wyszedł, więc piszę z pamięci :-) ale chyba nie oto chodzi, żeby za każdym razem odkrywać koło. IDE ułatwia takie operacje, które są na porządku dziennym, ciągły refaktoring.

IDE to nic więcej jak edytor (VI) plus klika dodatkowych narzędzi (M) == VIM ;-) Duży smród ... hmm ... z twojego stwierdzenia wynika, że jakikolwiek (poza VIM) warsztat to smród, jakoś to do mnie nie przemawiam.

Pozdrawiam
--
Łukasz

Hehe, daleko mi do

Hehe, daleko mi do ekstremizmu w stylu "VIM rulez". Przeciez mowie, ze jesli integracja z np Subversion to koniecznie IDEA. A dopiero jesli nie potrzebujesz svn, to vim ;)

A tak na serio, to chcialem sie troche posmiac z tego nacisku na IDE. Nawet jak pracowalem w Javie, to IDE mozna bylo wymienic w moim projekcie na inne i nie bylo ani wymogu, ani obowiazku..
Natomiast koledzy z innego projektu (w EJB) to chyba faktycznie pracowali na IBMowym Websphere i tam by sie raczej nie dalo bez IDE obejsc, ale nie znam szczegolow.

Z tymi "ciaglymi" zmianami w projekcie to jest roznie. W zaleznosci od stylu prowadzenia projektu. U nas to jest na porzadku dziennym, ale to nie oznacza, ze praca programisty to w wiekszosci refaktoring. Jesli by tak bylo, tzn. ze panuje chaos i cos jest nie tak, albo z wymaganiami, albo z programista ;)
U nas zreszta te zmiany to jesli wystepuja, to na poczatku sprintow (1-2 tyg), gdzie sie okazuje, ze wymagania sie zmienily (uprecyzowaly). Ale, zeby "ciagle" to z pewnoscia nie.
Moze masz tyle plikow do zmiany, ze ten proces przeciaga sie w nieskonczonosc ;-))))

W zwiazku z tym, ze to Python, to od razu na wejsciu ucieklo wiele codziennych w Javie potrzeb. I dlatego twierdze, ze nawet C-A-M (extract method?), C-A-R (rename method?) -- wlasciwie, to nawet pozapominalem o tych zaletach (i skrotach) IDE...

Mysle, ze powoli trzeba konczyc te komentarze o IDE ;)
Wazne, aby pisac kod, ktory da sie ze zrozumieniem przeczytac przez osoby trzecie..

AGO

moje 5 groszy do IDE:
jest niezbędne do _szybkiego_ i sprawnego szeroko pojętego dewelopmentu.
Pewnie, że można pisać w jakimś prymitywnym narzędziu ... ale po co?
Podpowiedzi, JavaDoc, wizardy, refaktoring, etc, etc. są na wagę złota.
Liczy się szybkość i wygoda. Nie ulega, że kod trzeba rozumieć i teksty w stylu "IBMowy Websphere" albo śmierć ozn. tylko ze koledzy dopiero co rozpoznawali temat.

Koledze T. proponuje natywną przejażdżkę rowerem z Zakopanego do Szczecina bo po co używać samochodu jak jest rower ?!? ba nogi są :) czasu bedzie duzo na przemyslenia

bez urazy ; pozdrawiam
AGO

BTW: bylem kiedyś w takiej firmie na rozmowie kwalifikacyjnej. Zrezygnowałem jak koleś (kierownik techników) wyskoczył z tekstem, ze on pisze TYLKO w edytorze a la notatnik ... firmy już nie ma, zbankrutowała :))))

Łukasz Lenart's picture

Małe nieporozumienie

Język dynamiczny nie jest podstawowym językiem w projekcie, używamy języka Java i starego poczciwego J2EE. Myślałem, że jest to oczywiste. Język dynamiczny jest używany tylko jako dodatek na potrzeby łatwości pisania walidacji logiki biznesowej. Czy nikt nigdy nie używał takiej konfiguracji? Mi już zdarzyło się kilka razy, więc piszę z doświadczenia ;-) Więc cały twój akapit na temat Groovy i Grails pominę ;-)

Nie bardzo rozumiem twój wywód nt. IDE i jego wsparcia dla języków dynamicznych. Czy użył byś w projekcie (który jak napisałem będzie trwał dwa lata) języka X tylko dlatego, że łatwo i szybko piszę się w nim kod, ale żadne posiadane przez ciebie IDE nie wspiera tego języka? Wątpię ;-)

Przyzwyczajenia programisty to jego największy wróg. Przez długie lata używałem Eclipse'a (a dokładnie wersji komercyjnej MyEclipse), jednak obecnie pracuję z IntelliJ IDEA dlatego, że cały zespół z nim pracuje, jest domyślnie wspierane przez klienta, etc. Oczywiście miałem możliwość dalszej pracy z Eclipsem ale stwierdziłem, że zmiana przyzwyczajeń będzie z pożytkiem dla projektu i produktywności całego zespołu.

Piszesz o testach i bardzo dobrze, tylko nie rozumiem, co do trudności pisania testów ma język, którego używamy? W większości przypadków jest to problem stylu kodowania przez danego programistę (kolejne przyzwyczajenie) i jeśli programista nie będzie pisał testów, to taki czy inny język tego nie zmieni. Groovy nie jestem tu wyjątkiem, co z tego że wygeneruje za nas prostą "wydmuszkę", jeśli programista nie doda tam kodu, który wykona faktyczny test?

Testy nie zapewnią, że np. w ostatniej chwili okazuje się, że schemat bazy danych jest zły i należy spełnić wymagania klienta. I tłumaczenie "bo tak to się robi za pomocą Hibernate'a" nie jest tu argumentem. To brak rozpoznania przed projektem. Testy pozwalają wykryć błędy w toku myślenia danego programisty ale nie zapewnią myślenia globalnie.
Testy nie są gwarantem bezpieczeństwa projektu jak piszesz, pozwalają zabezpieczyć się, że zmiany które przeprowadzasz zostaną zweryfikowane i nie zepsują działającej aplikacji. Gwarancją bezpieczeństwa jest tylko myślenie, znanie ograniczeń i możliwości każdego elementu tworzącego projekt. A sukces projektu zależy od definicji sukcesu, która jest określana przez klienta i znana zespołowi. Bez tej wiedzy to co jest sukcesem dla zespołu będzie porażką dla klienta. Aplikacji nie tworzy się dla własnej przyjemności ale aby zaspokoić potrzeby klienta.

I zdecydowanie typ języka czy wsparcie IDE nie ma znaczenia - kompletnie się z tym nie zgodzę, właśnie przez pomijanie takich szczegółów jak IDE i jego wsparcie dla danego języka, jest proszeniem się o wielkie BOOM! To jak stwierdzenie, że można zbudować Porsche tylko za pomocą młotka ;-) Do wykonania każdego zadania należy mieć odpowiednie do tego zadania narzędzie.

Mój komentarz nie wyjaśnia wszelkich zawiłości projektu, ale mam nadzieję, że nadaje głębszy kontekst moim wypowiedziom. No i raczej nie jestem FUDem jak napisałeś ale tylko zwróceniem uwagi, że na każdym etapie projektu należy używać "szarych komórek". Wykorzystanie takiego czy innego szkieletu, nie zwalnia nas z myślenia.

Pozdrawiam
--
Łukasz
http://www.lenart.org.pl/

Języki dynamiczne zmuszają do testowania

Nie za bardzo rozumiem, co chciałeś wyrazić w tym artykule? Nie zgodzę się z większością tutaj promowanych spostrzeżeń i skłaniam się ku zakwalifikowaniu ich jako FUD. Skupię się na części dotyczącej wpływu języka skryptowego w projekcie i jego ułatwieniom (utrudnieniom?), a szczególnie zdaniu "Jeśli wybraliśmy nasz język dynamiczny tylko ze względu na łatwość zmian w locie i braku kompilacji, możemy być w dużych tarapatach, zwłaszcza kiedy nasze IDE nie wspiera tego języka.".

Nie potrafię wyrazić, dlaczego dla mnie Groovy wydaje się być przyjemniejszy i bardziej zachęca do pracy niż Java (być może znudzenie i potrzebowałem odświeżenia, które daje mi Groovy, a dodając do tego wszechobecny zachwyt tym językiem, może i mi się udzieliło - a może nawet fakt, że gdzieś w głębi duszy, ja (każdy?) jestem bałaganiarzem/raptusem, a Groovy pozwala mi na pewien "bałagan" - w dobrym tego słowa znaczeniu, chociaż trudno sobie wyobrazić dobre znaczenie słowa "bałagan"). Fakt faktem, dzięki Groovy rozwiązania na nim oparte, np. Grails, mogą wykonać większość pracy za nas - patrz: rozszerzanie klas dziedzinowych bez żadnych specjalnych konstrukcji wymagających od programisty specjalnej wiedzy. To jest zdecydowanie na plus dla naszej produktywności.

Z łatwością, z jaką możemy rozszerzać nasze obiekty dynamicznie idzie ryzyko ich zbytniego rozbudowania w *pewnym* miejscu podczas działania aplikacji, co niechybnie wpłynie na późniejsze jego utrzymanie - będzie trudniej. Tym razem policzę to na minus. Biorąc jednak pod uwagę fakt, że takie rozbudowanie wymaga znacznej wiedzy programistycznej, ufam, że taki gość podzieli się swoimi umiejętnościami z zespołem i podniesie ogólną jego produktywność, a to już liczę na plus. Dodatkowo, zakładam, że "dynamiczne triki" są dokumentowane testami, o czym za moment.

Wsparcie IDE dla języków dynamicznych jest jak wsparcie IDE dla każdego innego języka. Jeśli producent IDE jest zainteresowany nim, to będzie. Dla przykładu, NetBeans IDE, IntelliJ IDEA, TextMate oraz jEdit mają wsparcie dla Groovy, więc czy to Java, czy Groovy nie ma już tak na prawdę znaczenia. Dla mnie wybór IDE ma znaczenie nie dla projektu, ale dla człowieka, który w projekcie uczestniczy. Jednemu NetBeans, innemu Eclipse, a jeszcze innemu Notatnik. Niech każdy używa tego, co mu sprawia przyjemność, zakładając, że idzie tu ku dobru projektu. Wszystko zależy od umiejętności i pewnej ciekawości członków zespołu projektowego. Możliwości IDE nie muszą iść w parze z produktywnością jego użytkownika (często mogą go nawet przytłaczać swoją wszechstronnością). Nie widzę, więc powodów, aby twierdzić "Jeśli wybraliśmy nasz język dynamiczny tylko ze względu na łatwość zmian w locie i braku kompilacji, możemy być w dużych tarapatach, zwłaszcza kiedy nasze IDE nie wspiera tego języka.". Zwłasza "zwłaszcza" uderzyło mnie najbardziej. Powtarzam, testy, testy i jeszcze raz testy. O czym za moment. I jeszcze nie doceniasz wpływu błędów w mechaniźmie refaktoryzacji w IDE. To w końcu też oprogramowanie, czyż nie?

Ową moc języka dynamicznego dobrze wyraża następujące powiedzenie Człowieka-Pająka (aka Spiderman): "Whatever life holds in store for me, I will never forget these words: "With great power comes great responsibility." This is my gift, my curse. Who am I? I'm Spider-man.". To o nas, pajęczarzach! ;-)

I na koniec, uwaga dotycząca akapitu "I oczywiście takie problemy zaczynają się pojawiać, gdy projekt jest w bardzo zaawansowanym stadium i zmiana mechanizmu walidacji dotknie połowy aplikacji. Bez odpowiedniego rozpoznania we wstępnej fazie projektu, będzie to naprawdę dużą bombą z opóźnionym zapłonem. Pierwszym znakiem ostrzegawczym będzie brak wsparcia ze strony IDE. Reszta musi zostać wykryta w trakcie prototypowania.". Jedną z cech języków dynamicznych jest prostota tworzenia konstrukcji projektowych - klas, interfejsów, modułów, ich dynamicznych rozszerzeń, itp. W tym jest również tworzenie testów jednostkowych czy integracyjnych. W Grails przy każdorazowym tworzeniu nowego bytu aplikacyjnego tworzony jest również właściwy test. Testowanie narzuca się na każdym kroku i podkreśla się jego znaczenie właśnie z powodów, które wymieniłeś. Nie ma mowy o "bombie z opóźnionym zapłonie" - testy zadbają o wczesne jej rozbrojenie. Testować trzeba, testowanie jest obowiązkowe, ale w Javie jakoś mi się nie chciało, było trudniej. W przypadku Grailsów mam w tym jakąś uciechę, zabawę. Czy to wpływ mody, czy prostoty Groovy, czy czegoś jeszcze innego - nie ma to znaczenia, chce mi się testować i robię to (a jeśli jeszcze nie tak intensywnie, jak powinienem, to i tak myślę o tym intensywniej - mam świadomość mojego błędu przy ich braku). I nie muszę się martwić o zmiany, w dowolnym momencie i w dowolnym wydaniu. Czy to będzie Java, czy Groovy, czy jeszcze inny język - testy są gwarantem bezpieczeństwa projektu. Nie masz ich, za niedługo się przekonasz ile straciłeś - bez względu na zastosowany język programowania.

Ciągła integracja, bezkres testów i niekończący się refaktoring w każdym momencie projektu gwarantem jego sukcesu, o jakości nie wspominając. I zdecydowanie typ języka czy wsparcie IDE nie ma znaczenia.