COOL:Gen

Pod koniec XX wieku pracowałem przez kilka lat nad systemem napisanym w środowisku COOL:Gen (wtedy jeszcze produkcji Sterling Software)[1]. Oryginalny pomysł nie był nasz, przejęliśmy projekt z całym dobrodziejstwem inwentarza. Wtedy sprawa była bardzo ciężka, klient (spora instytucja finansowa) po prostu zaczął pracować na systemie, którego jeszcze nikt nie zdążył napisać[2] — bagno po same uszy, nie jakieś lajcikowe grzęzawisko. Przez dłuższy czas pracowaliśmy oficjalnie po 12 godzin dziennie plus soboty. Jednak dziś, patrząc na to z dystansu jestem bardzo zadowolony, że takie coś mnie w życiu spotkało. Ze względu na COOL:Gena właśnie.

Dla mnie osobiście COOL:Gen to był (i jest, być może dlatego, że nie śledzę najnowszych osiągnięć w tej dziedzinie) niedościgniony wzór i mistrz wszelkich generatorów kodu. Zadziwiająco mało popularny i znany — liczba osób znających tą technologię w Polsce była wtedy szacowana na około 40 z czego 10 znałem osobiście. Nie dziwne zatem, że mało kto mi wierzył co potrafi to narzędzie, mało kto traktował mnie poważnie kiedy mówiłem, że nie obchodzi mnie platforma docelowa, nie obchodzi mnie silnik bazy danych, nie ma dla mnie znaczenia czy kod do kompilacji na powstać w języku C, w COBOLU czy (w późniejszych wersjach) w C++ albo w Javie. W COOL:Genie kod źródłowy powstaje automagicznie z modelu zapisanego w bazie danych w jakimś strasznie tajniackim formacie i uwidacznianego jako "action diagram"[3], czyli np. coś na kształt tego:

 SET e imh1 return_code TO 1

+= READ EACH post
| SORTED BY DESCENDING post timestamp
| WHERE DESIRED post is_posted_by SOME user
| AND THAT user id IS EQUAL TO i user id
|
| USE format_post
| WHICH IMPORTS: Entity View post TO Entity View i post
| Work View i sec1 TO Work View i sec1
| WHICH EXPORTS: Entity View l post FROM Entity View e post
| Work View l imh1 FROM Work View e imh1
| +- IF l imh1_component return_code IS NOT EQUAL TO 1
| | USE log_error
| | WHICH IMPORTS: Work View l imh1 TO Entity View i imh1
| | MOVE l imh1 TO e imh1
<------ESCAPE
| +- ELSE
| |
| | += READ EACH comment
| | | SORTED BY ASCENDING comment timestamp
| | | WHERE DESIRED comment is_posted_on CURRENT post
| | | ...
| | +--
| |
| | USE publish_post ...
| +--
+--

Z tego modelu COOL:Gen generuje kompletny kompilowalny i wykonywalny kod. Nie szkielet klas jaki wypluwa dzisiaj dowolne narzędzie CASE, nie coś co wymaga uzupełnienia i dopisania "bebechów", tylko normalny, w pełni funkcjonalny program. W dowolnym języku (no dobra, dowolnym z listy obsługiwanych) na dowolną platformę (z listy obsługiwanych). I to jeszcze wtedy była wersja COOL:Gen 5.1, zanim nastała era Advanced Gen, którego możliwości boję się nawet zgadywać..

Oprócz mnóstwa innych zalet (i mnóstwa wad, szczerze mówiąc), COOL:Gen miał jedną gigantyczną przewagę nad jakimkolwiek innym językiem programowania — nie dało się pomylić w kodowaniu. Pojęcie "syntax error" nie miało sensu ani racji bytu; co najwyżej można było "przepalcować" nazwę zmiennej, jeśli ktoś się bardzo postarał. Po prostu cały kod programu był budowany z "klocków" — jeden statement za drugim wybierany z menu, z listy możliwych w danym kontekście. W powyższym kodzie "z ręki" zostały wpisane przedrostki zmiennych (literki i, e, l) — reszta jest wyklikana myszką. Oczywiście same nazwy encji (post, comment, ...), relacji (is_posted_by, ...) i Action Blocków (format_post, ...) też ktoś musiał wpisać, ale to było raz przy ich tworzeniu/projektowaniu i więcej się do tego nie wraca. Z punktu widzenia kodera to raj na ziemi; z punktu widzenia programisty — szeroka, jasno oświetlona autostrada; dla projektanta — wymówka dla małej szczegółowości projektu ("jeśli wszystko zaprojektuję z detalami to już nic nie zostanie do roboty dla programistów")...

Oczywiście o obiektowości w COOL:Genie nie było w ogóle mowy. Fakt, że dało się wybrać język obiektowy jako język implementacji i w efekcie powstawały jakieś tam obiekty nie miał żadnego wpływu na projekt ani na "kodowanie". Architektura rozwiązania była również stosunkowo sztywna — do wyboru "trójwarstwowa" (klient — TE+serwer — baza) lub "dwuwarstwowa" (klient+TE+serwer — baza) plus kilka rodzajów "packagingu" w zależności od specyfiki docelowego systemu operacyjnego. Jednak zakładając przeznaczenie COOL:Gena do budowania systemów obsługi baz danych okazywało się to całkowicie wystarczające[4].

Z punktu widzenia architekta, projektanta systemu, czy choćby archeologa inżynierii oprogramowania COOL:Gen to był piękny w swej potędze przedstawiciel strukturalnych narzędzi CASE. Kto dzisiaj poza ośrodkami akademickimi pamięta jeszcze takie techniki jak Action Diagram, ERD, DML, ELC, hierarchie aktywności czy macierze CRUD? Dziś myślimy i mówimy inaczej — wszędzie tylko UML i najróżniejsze "markupy". A przecież cała analiza i projektowanie strukturalne jeszcze gdzieś tam istnieje, działa i generalnie ma się całkiem nieźle. Chociaż nie da się ukryć, że z dnia na dzień przechodzi do strefy "legacy systems"...

Starzeję się, wiem...

[1] COOL:Gen zmienił właściciela, skórę i właściwie wszystko co się dało, ale w swym kolejnym wcieleniu, jako Advantage Gen czy może już AllFusion Gen, trzyma się chyba całkiem nieźle.

[2] Byłem młody i naiwny — wydawało mi się jeszcze, że nie można pracować na systemie, który nie istnieje. Dziś mnie to jakoś specjalnie nie dziwi. Zresztą ten projekt istnieje do dziś, więc w dłuższej perspektywie znacznie spóźnione zaistnienie fizycznej postaci oprogramowania okazało się zupełnie nieistotnym szczegółem.

[3] Chyba gdzieś tutaj: James Martin, Carma McClure, "Diagramming techniques for analysts and programmers", 1985

[4] Określenie "całkowicie wystarczające dla obsługi baz danych" jest oczywiście względne — zdarzyło mi się napisać w COOL:Genie np. program komunikujący się "niskopoziomowo" po TCP/IP...

Komentarze

#1 | 2006.02.16 08:36 | buy vicodin

vladgondonpozornii

 

Uwaga: Ze względu na bardzo intensywną działalność spambotów komentowanie zostało wyłączone po 60 dniach od opublikowania wpisu. Jeżeli faktycznie chcesz jeszcze skomentować skorzystaj ze strony kontaktowej.