środa, 24 września 2008

Jak spieprzyć projekt?

może tak:
Project anti-patterns. How to make Your project fail

a może tak:
When Working Software Is Not Enough: A Story of Project Failure


//==============================
Dziś znalazłem 2 warte obejrzenia prezentacje. Myślę, że warto aby przynajmniej część z ponad 400 osób odwiedzających bloga je zobaczyła. Świat będzie dzięki temu lepszy;)

Pierwsza prezentacja jest pełna sarkastycznego humoru (taki lubię najbardziej), świetnie się ją ogląda.
Najbardziej przypadł mi do gustu rozdział 53. "Bob budowniczy" (wszystko rozpierniczy).
Druga prezentacja jest ciekawa, ale do połowy, później zaczyna się z niej wylewać osobiste rozgoryczenie, które radzę sobie darować.

niedziela, 21 września 2008

KomplikatorMode.ON

Gdyby ktoś z Was wpadł na genialny pomysł systemu podgrzewania rączek w rowerze to ostrzegam: nie ma on szans na komercyjny sukces w starciu z rękawiczkami!

Sam często łapię się na nieświadomym przełączeniu w tryb komplikatora. Szczególnie patrząc retrospektywnie na własne "dzieła". Jedynym pocieszeniem jest fakt iż istnieją więksi durnie;)

Czym jest działanie mózgu w trybie komplikatora? Jest to szukanie problemu w samym rozwiązaniu jakiegoś problemu. Czyli wyszukiwanie sobie meta-problemu - innymi słowy sztucznego problemu, tudzież dziury w całym.

Czym może się to objawiać?
Na poziomie architektury na ten przykład możemy popaść w paranoję i dążyć do unikania zależności od frameworków. W prostych/małych projektach należy się zdecydować. Albo opieramy się na jakimś frameworku albo nie. Jeżeli tak, to nie należy z nim walczyć. To bez sensu. Lepiej go wchłonąć i korzystać z wszystkich jego dobrodziejstw zamiast blokować sobie dostęp do ficzerów frameworka. W przeciwnym wypadku dochodzimy do paranoi pod tytułem Inner Platform Effect. Syndrom ten może przybrać ekstremalną formę od tytułem Not Invented Here.

Na czym może to polegać? Przykładowo na dodawaniu warstw abstrakcji w celu przykrycia API frameworka czy biblioteki. Idea jest szczytna: jesteśmy niezależni więc możemy dowolnie podmienić sobie implementację np warstwy dostępu do danych, warstwę prezentacji czy silnika reguł. Wystarczy pomyśleć racjonalnie (w kontekście przykładu dostępu do danych): czy kiedykolwiek wymienimy JPA (czy nawet Hibernate) na coś innego? Owszem fajnie jest mieć potencjał do testowania jednostkowego. Ale jakiego testowania?:P
Z czasem kończy się to tak, że nasza "fasada" powiela większość funkcjonalności frameworka - niestety powiela w sposób nieudolny bo jak tu przebić kilkudziesięcioosobowe community ekspertów;P

<nudny_przyklad_tylko_dla_uzytkownikow_hibernate>
Jako konkretny przykład, który często się pojawia (i nad którym sam mogę gorzko zapłakać) można podać doskonałe Criteria API z Hibernate. W prostych projektach aż się prosi aby Detached Criteria napełniać na poziomie GUI ekranu jakiegoś filtrowania. Niestety lęk przed couplingiem prezentacji z Hibernate prowadzi do tworzenia sztucznych protez (DTO) przenoszących kryteria wyszukiwania z GUI do DAO. W DAO mamy tłumaczenie protez na Criteria API.

Z czasem gdy komplikacja rośnie wprowadzamy wzorzec iterpretera (nieudolnie powielając API Hibernate:) przy pomocy którego implementujemy w DTO algorytmy już zawarte w Criteria API.

No ale dzięki temu zawsze możemy podmienić sobie framework persystencji - nawet dwa razy;)
</nudny_przyklad_tylko_dla_uzytkownikow_hibernate>


Na poziomie projektu natomiast możemy przesadzić np Wzorcami Projektowymi. Jest nawet takie schorzenie - zapadają na niego młodzi adepci, którzy się wzorcami zachłysnęli. Ciężko z niego wyjść. Cholernie ciężko... Wiem coś o tym:)
Często lepiej projektować w kierunku wzorca. Polega to na zostawianiu sobie możliwość rozbudowy w razie potrzeby do danego wzorce jednak jeszcze nie wprowadzając niepotrzebnej komplikacji.



//====================



My - programiści jesteśmy z natury umysłami ścisłymi (oby nie ciasnymi) - mamy więc niejako wbudowany detektor prostoty. Poszukujemy prostoty ponieważ jest piękna. Tak, wiem, to wyświechtany ogólnik - chodzi o coś głębszego: prosta forma zwalnia percepcję z zajmowania się rozpraszającymi detalami. Najlepiej gdy nie ma już czego odjąć niż nie miałoby być czego jeszcze dodać. I to właśnie pozwala dostrzec piękno.

Aby nie było tak prosto, jest jeden skomplikowany problem: należy umieć odróżnić rozwiązanie proste od prostackiego. Zgodnie z maksymą Einteina „Rzeczy powinny być tak proste jak to możliwe, ale nie prostsze”. Rozwiązanie proste nie zawsze jest nachalne i oczywiste. Często potrzeba wiele trudu i pracy mentalnej aby do niego dojść. Proste rozwiązanie może wymagać wypracowania poprzez wielokrotne próby i błędy. Przepraszam, nie ma błędów, są tylko rezultaty o niesprzyjającym wyniku:)

piątek, 19 września 2008

Nawróćcie się;)

Dzisiaj mały post (właściwie to wypychacz bo zbieram materiały na 2 większe) z serii ciekawych linków.
Allen Holub jest niestrudzonym ewangelizatorem Object Oriented i wzorców projektowych.
Co prawda część jego poglądów zamieściłem w jednej z prezentacji, ale teraz znalazłem ciekawe i godne polecenia kompendium dla młodych adeptów OO: Everything You Know is Wrong.

//=================

Myśli warte uwagi:

  • obiekty to nie dane+procedury zgromadzone w klasach aby nie rozsypywały się po pamięci
  • Gettery i settery są złe ponieważ naruszają enkapsulację (o zgrozo często wymienia się je jako definicję enkapsulacji!)
  • nie pytaj o dane, żądaj wykonania
  • dziedziczenie jest oczywiście złe:)
  • ciekawe połączenie modelu i GUI przy pomocy wzorca budowniczego (strona 7)
  • parę błędów projektowych w API Javy;P

I najważniejsze przesłanie Allena: Don’t confuse familiar with “right”.

poniedziałek, 15 września 2008

Programiści Enterprise nie gęsi i swój język mają

Zastanawialiście się kiedyś nad alternatywną składnią języka waszej matki? Na przykład taką, w której nie ma słowa być?

Jak to nie ma być? Przecież to podstawa? Da się w ogóle coś w nim powiedzieć? I po co się wydurniać? Przecież jestem w stanie się dogadać w sklepie i kupić sobie bułki więc jest git! I telewizor też jestem w stanie zrozumieć mogę też!

Jeżeli ktoś zdołał w sobie stłumić reakcję obronną przed dysonansem kognitywnym i temat wydał mu się intrygujący to warto zapoznać się z ideą języka E-Prime (ciekawe wprowadzenie tu: "Język E-Prime (English Prime) powstał jako swoisty dodatek do teorii niearystotelesowskiego systemu semantyki ogólnej autorstwa Alfreda Korzybskiego..."). Języka, który wręcz zachęca do formułowania subiektywnych wypowiedzi zależnych od kontekstu.

Znowu okazuje się, że to co wydaje się być naturalne, oczywiste i bezdyskusyjne jednak takie nie jest - niektórzy filozują nawet na takie, jak by się wydawać mogło, dawno zamknięte tematy. Oczywiście nie chodzi mi o to by od razu przestawiać się na nowy sposób mówienia i myślenia - po prostu nowe spojrzenie może otworzyć nową furtkę, przez którą ma szansę wedrzeć się struga świeżego powietrza rozrzedzając nieco stęchliznę.

Tyle tytułem wstępu - czas na mięcho...

Języki programowania ogólnego przeznaczenia wywodzą się z języków tworzonych na potrzeby matematyków. Przecież każdy "dinozaur" kodujący w szalonych latach 60 jest w stanie rozczytać kod klasy Javy, C# czy czegokolwiek co jest podobne do C.
Bo cóż takiego mamy do wyboru? Parę konstrukcji iteracji, parę konstrukcji selekcji, sekwencję oraz zestaw operatorów arytmetycznych. W starszych językach mogą być jeszcze technikalia związane z niskopoziomowymi szczegółami takimi jak zarządzanie pamięcią;)

/*
Żeby nie było, że należę lub sympatyzuję z nielicznymi (ale jednak) bezrefleksyjnymi i nieświadomymi niczego koderami, którzy twierdzą, że wszystkie języki programowania są takie same i są w stanie nauczyć się w ciągu paru dni dowolnego języka. Nie; chodzi mi po prostu o możliwość przeczytania kodu a nie o świadome jego tworzenie.
*/

Zatem praktycznie nie istnieje wsparcie dla logiki biznesowej w mainstreamowych językach (w niszowych nie wiem bo nie inwestygowałem). Jedyne co mamy to klasy, interfejsy, metody, pola i rozszerzanie (specjalnie nie piszę dziedziczenie, bo bez cech regresywnych nie ma co mówić o dziedziczeniu). Do tego instrukcje sterujące, operatory i radź sobie.



Od jakiegoś czasu przyglądam się Czi (przy okazji warto nadmienić, że Ojcem Założycielem jest nie byle kto, bo jeden z założycieli JBossa Rickard Öberg). Pora wrzeszczcie napisać coś bardziej konkretnego - najlepiej co nowego i dobrego to wnosi.

Qi ma szansę wypłynąć na fali rosnącej popularności Domain Driven Design. Widać, że swego rodzaju prąd myślowy DDD elektryzuje coraz większą grupę developerów. Będą oni w wkrótce potrzebować nowego frameworka wspierającego DDD aby wyżyć się w nowej przestrzeni.

No dobra, jak Qi wspiera DDD?
Przede wszystkim w Qi zachowanie (odpowiedzialność) zależy od kontekstu. Czyli idziemy bardziej w stronę świata rzeczywistego, w którym ta sama osoba może być w zależności od sytuacji programistą, mężem, motocyklistą...

Qi rozszerza standardowe "figury składniowe" o:

  • Mixins: Containing state, e.g. Name, Person, Adress
  • Concerns: Statelessm e.g. TransactionWrapper, Security
  • Constraints: Checking parameters, e.g. NotNullConstraint
  • SideEffects: Managing side effects, e.g. sending Mail

Oczywiście jest to rozszerzenie nieingerujące w składnię Javy 5 ponieważ opiera się na adnotacjach.

Jednym z głównych założeń Qi jest maksymalna reużywalność kodu. Jak wiadomo prawdopodobieństwo ponownego użycia rośnie gdy kod jest odpowiedzialny za jedną maksymalnie koherentną rzecz. Zatem w Qi składamy (komponujemy) wymienione powyżej fragmenty w większe części - kompozyty. Składanie kompozytów z części pozwala na zmianę ich zachowania - możemy zawsze spojrzeć na kompozyt z perspektywy jednej z części. Przykładowo możemy pozbyć się niezręczności wynikającej z "podczepienia" encji zawierającej metody biznesowe pod GUI. Po prostu w kontekście GUI encja jest np "prezenterem".

Qi zgodnie z DDD zakłada, że logika biznesowa jest aspektem, na który należy położyć największy nacisk, zatem zadaniem frameworka jest automagiczne przejęcie odpowiedzialności za technikalia takie jak persystencja czy transakcje. Pozwala to skupić uwagę na prawdziwym problemie stanowiącym rzeczywistą wartość systemu podczas gdy inne frameworki skupiają się jedynie na rozwiązywaniu problemów technicznych (zwykle przykrywając je kolejną warstwą abstrakcji zgodnie z zasadą Davida Wheelera "Any problem in computer science can be solved with one additional layer of indirection.").

Od strony technicznej QI zasadza się na AOP i IoC (DI w szczególności).


//====================


W sumie to sprytne stosowanie składni "subiektynej" (bez być) i "obiektywnej" (z być) jest jednym z głównych trików NLP czy w szczególności technik perswazji.

Przeglądając fora natknąłem się na krytykę Qi. Krytycy twierdzili jakoby twórcy Qi wzięli się za implementację swego pomysłu w nieodpowiednim języku. W skrócie: Java śmierdzi, Ruby jest sexi (heh żenada, język programowania jest sexi). Twórcy jednak ripostują:
- Composite Oriented Programming jest ideą, którą można zaimplementować w dowolnym języku
- Java jest standardem przemysłowym, posiada ugruntowaną pozycję i ogromne wsparcie społeczności.

I jeszcze jedno... kiedyś gdy miałem trochę zbyt dużo wolnego czasu zaczynałem nieśmiało zabawę z Pythonem i Ruby. O ile kojarzę to Ruby szczególnie charakteryzował się składnią, która jak teraz widzę mocno sprzyja COP. Szkoda, że autorzy tutoriali ograniczyli się do pokazania bzdurnych przykładzików prezentujących udziwnioną składnię nie pokazując, że nadaje się ona do implementacji idei szerszej niż tylko "hurra mój kod jest prawie tak paskudny jak bym go pisał w Perlu". A może sami wtedy jeszcze nie wiedzieli, że stworzyli potworka, który wspiera COP ;P

piątek, 5 września 2008

Wszechświaty równoległe

Wszechświaty równoległe...
Starożytna idea, która jakiś czas temu została wskrzeszona dzięki M-teorii. Teorii gdzie w 11, 12, 13 albo nawet 26 wymiarowej przestrzeni strun są rozpięte membrany. Brany "wiszące" w hiperprzestrzeni mogą w szczególności być dobrze znanymi nam 4-wymiarowymi wszechświatami rządzącymi się odrębnymi prawami przyrody. Brany mogą się zderzać/zlepiać niczym mokre gacie suszące się na równoległych sznurkach. Takie okresowe spotkania gaci wiążą się z pewnymi ciekawymi (i dosyć istotnymi z punku widzenia nagich małp biegających po trzecim kamieniu od słońca na peryferiach jakiejś prowincjonalnej galaktyki) zdarzeniami: zetknięcie dwóch bran to kolaps wszechświatów a następujące po nim oderwanie - wielki wybuch. I tak nieustannie... "A skądże to, jakże to, czemu tak gna?"

Mimo, że wiedzeni ciekawością póki co nie możemy (i być może nigdy nie będziemy mogli) zobaczyć membran rozpiętych na wielowymiarowej przestrzeni to jednak nie wszystko stracone...

Przecież nie ma takiego kuriozum, którego nie można by uświadczyć w programowaniu:)


Ostatnio było o kolejności. Kontynuując temat złej kolejności prowadzącej do paranoi czas na "GUI driven development". Co się dzieje, gdy zaczniemy od projektu ekranów (zwanego dumnie analizą)? Rozdzielenie ekranów pomiędzy programistów i wydanie rozkazu: RÓB (mylić z RUP) skutkuje tym, że każdy drąży swoją własną "studnię". Studnię, która schodzi w dół przez wszystkie warstwy: warstwę prezentacji (formularz i logika widoku), warstwę logiki biznesowej aż do persystencji i bazy danych (którą możemy niestety już mieć).

Czym to skutkuje? Każda studnia jest niezależnym wszechświatem równoległym - z własnym stylem, własną estetyką i własnym kodem biznesowym.

Kodem biznesowym, który jest powielany, ponieważ każdy jest tak zajęty kopaniem swojej studni, że nie ma czasu aby ogarnąć kod studni drążonych obok. Nie ma czasu ani co gorsza zasobów mentalnych - ograniczeń pojemności poznawczej nie przeskoczymy. Klapki na oczy, kilof w dłoń, kokodżambo i do przodu - yy właściwie to do dołu. Oczywiście zmiany w jednej studni są niespójne z działaniem innej więc mamy bugi. Te najbardziej paskudne - biznesowe, bo techniczne można łatwo zdiagnozować (działa albo nie).

GUI oczywiście się zmienia więc spaghetti nieuchronnie rośnie ponieważ ekrany nigdy nie są całkowicie niezależne. Logika biznesowa zmienią się nie mniej zatem mamy wiele miejsc na wykazanie się w refaktoringu tego samego:)


Po latach błędów i wypaczeń z odsieczą przychodzi na szczęście Domain Driven Design. Racjonalna kolejność nakazuje aby najpierw zająć się modelem domenowym. GUI jest jedynie zestawem perspektyw, które prezentują jakieś aspekty modelu domenowego. Więc zamiast studni mamy różne "okulary" przez które patrzymy na to samo - bez powielania.


//=========================
Analizowanie poprzez projektowanie ekranów jest oczywiście kuszące. Nie wymaga praktycznie żadnego skila (UML jest dla nerdów). Narysować ekran potrafi każdy. Zrozumieć też - klient szczególnie.

czwartek, 4 września 2008

Życia nie oszukasz

Kolejność to podstawa.
Jako przykład weźmy tę oto prozaiczną sytuację:
Wchodzisz do toalety, podnosisz deskę, siadasz, defekujesz, spuszczasz wodę, ściągasz spodnie.

Chyba oczyma wyobraźni widzimy jak zgubne w skutkach może być pomieszanie kolejności faz w nawet tak prostym procesie. A co dopiero musi się dziać w procesach bardziej złożonych... np podczas wytwarzania oprogramowania?
"... mnie oszukasz, przyjaciela oszukasz, mamusię oszukasz ale życia nie oszukasz ... "


Rebecca Brock zajmująca się "przeglądem" systemów i architektur w swej prezentacji dziwi się jak często na pytanie o analizę biznesową czy projekt domenowy zostaje jej radośnie przedstawiona baza danych.
J. B. Rainsberger jest bardziej radykalny. W swym felietonie opisuje doświadczenia z projektu, w którym zdecydował się na projektowanie bazy na koniec procesu wytwórczego.

/*
 * O ile zbytnio nie zachęcam do oglądania
 * prezentacji Pani Brock,
 * to felieton Rainsbergera polecam.
 */


Hmm czyli to, co od jakiegoś czasu podpowiada intuicja nie jest objawem jakiegoś schorzenia - inni też na to wpadli:)
Bo do czego prowadzi przedwczesne projektowanie bazy? Jeszcze nic nie wiemy o przyszłym systemie, wymagania wciąż się zmieniają a my już inwestujemy ogromną ilość czasu (zasobów w ogólności) w projekt bazy. Zaraz po tym piszemy zapytania (SQL, HQL, Criteria API), które po zmianach schematu bazy są do wyrzucenia albo przynajmniej gruntownego przepisania. Oczywiście o wiele taniej jest zmieniać model klas niż model klas, i bazy, i zapytania.

Co gorsza - z czasem gdy baza osiągnie masę krytyczną nikt nie odważy się na podjęcie decyzji o zmianie schematu! Przecież zbyt wiele DAO byłoby do przepisania! Zatem mamy piękną paranoję pod tytułem "DB driven development" - naciąganie rzeczywistości do istniejącego schematu bazy - schematu, który powstał gdy prawie nic nie wiedzieliśmy o wymaganiach; schematu, z którym po prostu musimy nauczyć się żyć:)

Rainsberger podaje jakże prostą i oczywistą metodykę: use a "dummy" persistence mechanism. Czyli jak długo się da (najlepiej do release) odwlekamy stworzenie bazy. Posługujemy się Mockowatymi implementacjami DAO albo Repozytoriów. Czyli najpierw (np. iteracyjne) rozwijamy model domenowy. Z czasem, gdy model domenowy okrzepnie możemy wreszcie przygotować tabele, które go będą utrwalać.


//======================


Rainsberger opisał sukces projektu opartego na Domain Driven Design. Czyli podejścia gdzie jesteśmy na takim poziomie świadomości, że rozumiemy iż Model Domenowy jest "sercem" systemu. To tam zawarte są reguły biznesowe, które sprawiają najwięcej problemów z utrzymaniem i rozbudową. Model domenowy modeluje byty biznesowe i interakcje pomiędzy nimi; baza jest tylko strukturą danych utrwalającą jakąś część modelu.

Pustkę po dobrym modelu domenowym można wypełnić tylko jednym: spaghetti:)
Spaghetti to wężowisko procedur (zapakowanych w klasy i dumnie nazywanych metodami) oplatających istniejącą strukturę bazy danych. Procedur, które powielają swą logikę, mieszają odpowiedzialności i zazwyczaj charakteryzują się wieloma zależnościami. Z czasem nikt nad nimi nie panuje, nie próbuje nawet refaktoryzowac; po prostu dolepia się kolejne:)
Spaghetti może i działa w wersji 1.0 ale z czasem osiągnie masę krytyczną uniemożliwiającą zmiany w jednym miejscu bez zniszczenia miejsc innych.

Przedstawione przez Rainsbergera podejście oczywiście nie sprawdzi się, gdy musimy często pokazywać działające wersje klientowi, który nie zadowoli się tym, że na jednym ekranie coś dodał/edytował a na ekranie z listą nie widzi zmian. No ale jeżeli klient nie potrafi unieść się na lekko wyższy poziom abstrakcji to może nie warto z nim robić interesów - zapowiadają się same problemy;P

Schemat bazy jakże często jest mylony z analizą czy modelem domenowym. Na schemacie widzimy co najwyżej strukturę danych, brak tam obrazu odpowiedzialności (dynamiki) czyli modelu biznesu.

I jeszcze jeden szczegół: dlaczego przechowywać byty ze świata obiektowego w relacyjnej bazie danych zamiast w obiektowej? :P

wtorek, 2 września 2008

Dobrze gada, polać mu wódki

Wróciłem właśnie z wakacji...
hehe bez obaw, nie będę zanudzał czerstwym sprawozdaniem z urlopu:)

Jednak zmęczenie podróżą nie pozwala mi na napisanie niczego poza wklejeniem linku do ciekawego posta o Composite Oriented (Qi w szczególności): Qi4J the next Java? Forget Scala.

//===========================
Myśli warte uwagi:
- wrzuty na Eckela:)
- business logic - kto programował komercyjnie i ma zdolność choćby do odrobiny refleksji ten pewnie rozumie, że to właśnie BL rozwala projekty (jeżeli jeszcze nie wersji 1.0 to na pewno w 3.0) i że wypasione GUI i baza w 5. postaci normalnej nic tu nie pomogą
- misterność i pomysłowość nie mają mają nic wspólnego z młotkiem