Wstęp do DSL

Po przeczytaniu komentarza Jacka Laskowskiego na temat sposobów popularyzacji zadadnień tworzenia narzędzi eclipsowych, koncepcji MDD (Model Driven Development) czy DSM/DSL (Domain Specific Modeling) postanowiłem coś zrobić w tym temacie. Myślę że dobrym początkiem może być prosty tutorial.

Co jednak zaprezentować by jednocześnie wytłumaczyć podstawy zagadnienia a przy okazji wzbudzić zainteresowanie tematem? Jedno jest pewne - nie może to być generacja pustych interfejsów :) W internecie można znaleźć setki prostych kursów jak wygenerować schemat klas, bazy danych z modelu etc. Nuda. Postanowiłem pokazać coś innego, co moim zdaniem pozwoli lepiej reprezentować powyższe koncepcje. Zamiast modelować kod strukturalny stwórzmy kod logiki. Naszym zadaniem będzie utworzenie miniaturowego systemu który biznesowy opis (reguły rozsyłania wiadomości) przekształci w działający kod.

Wymagania dla zadania wyglądają następująco. Musimy utworzyć narzędzie pracujące na poziomie problemu (biznesowy opis zachowania) które będzie potrafiło generować coś zrozumiałego dla maszyny (kod wykonywalny). Czy to możliwe? Zobaczymy...

Jako platformę docelową wybrałem prosty silnik świadczący usługę rozsyłania wiadomości pomiędzy nazwanymi kolekcjami (taki uproszczony wzorzec rozsyłania wiadomości z EAI). Nasz silnik oczekuje jako swojej konfiguracji klas reprezentujących zasady działania (interfejs IRule). Reguły te modelowane będą za pomocą edytora pracującego według zasad opisanych poprzez pewien model (meta-model). Żeby nie komplikować wykorzystamy dynamiczny edytor Ecore. Nie jest to oczywiście rozwiązanie produkcyjne jednak na potrzeby prostego tutoriala wystarczy. Osoby zainteresowane tematem budowy własnych edytorów DSL odsyłam do swojej prezentacji z EclipseCamp 2008 (trzeba jakoś reklamować swojego bloga).

Przykładowy meta-model naszego języka zawiera zaledwie dwie proste reguły:
- skopiuj wszystko z kolekcji źródłowej do kolekcji docelowej
- rozbij kolekcję źródłową na podzbiory na podstawie wartości parametru.



Jak widać model nie jest zbyt zaawansowany. Fragment opisujący wyrażenie można nazwać co najwyżej "edukacyjnym", całość pozbawiona jest też nadrzędnego kontekstu. Podział oraz integracja modeli to temat złożony, wykraczający poza ramy tego kursu. Myślę jednak że na nasze potrzeby prosty meta-model w zupełności wystarczy.

Korzystając z edytora dynamicznego (opcja "Create Dynamic Instance") tworzymy dwie proste reguły:
- pobierz listę z kolekcji 'src' do kolekcji 'dst'
- pobierz listę klientów z kolekcji 'customers' i dorosłych umieść na 'adults', dzieci na 'children', nieprawidłowe elementy na 'unknown'



W trybie tekstowym utworzona instancja modelu powinna wyglądać następująco:



Ostatni krok to utworzenie szablonu generacji kodu. Nie jest to trudne. Kod który zostanie wygenerowany musi wykonywać operacje opisane przez meta-model. Utworzona instancja zawiera przykładowe wartości parametrów których użyjemy podczas testów. W naszym przypadku musimy zaimplementować prosty interfejs reguły (IRule) naszego silnika.



Pisanie szablonu rozpoczynamy od utworzenia testów. Ważne jest by nie starały się one weryfikować formatowania generowanego kodu ale logikę jego wykonania. Kod ten wielokrotnie może ulegać zmianom (optymalizacja etc.) jednak kontrakt z pozostałymi elementami systemu powinien być zachowany. W związku z tym w testach opisujemy tylko zasady interakcji z otoczeniem (nie tworzymy implementacji silnika etc.) Przykładowy test wygląda następująco:



Tworzenie testów pomaga nam lepiej zrozumieć problem jaki staramy się rozwiązać. Są one także niezmiernie pomocne w tropieniu literówek etc. Mając testy oraz przykładową instancję modelu bez trudu tworzymy prosty szablon kodu.



Testy zadziałały - zadanie zakończone ;D

Bardziej szczegółowe informacje znaleźć można na stronach www.eclipse.org/modeling. Jeżeli temat kogoś zainteresował fajnie byłoby gdyby dodał jakiś komentarz, będę wiedział czy warto go kontynuować (polecam także tutorial z AST jako wstęp do zagadnienie budowy notacji tekstowej dla modeli).

8 komentarze:

Krzysiek pisze...

Witam!

Jest ktoś zainteresowany tematem ;) Przyznam jednak, że przykład średnio mi się spodobał. Cieszy mnie za to wykorzystanie Xpand, bo myślałem, że komponenty oAW są w Polsce nieznane.
W ramach sportu stworzyłem sobie tekstową notację (w Xtext) dla przedstawionego modelu (najnowszy Xtext pozwala na korzystanie z istniejącego modelu). Nie zauważyłem wykorzystania atrybutu SimpleFieldExpression::type, czy to spadek po rzeczywistym modelu?

Pozdrawiam,
Krzysztof Kowalczyk
http://toolsmatter.blogspot.com/

Grzegorz Białek pisze...

Przykład miał być tak prosty jak to tylko możliwe.

Model oczywiście jest czysto edukacyjny. W normalnym rozwiązaniu taka reguła składałaby się minimum z czterech współpracujących modeli (kontekst, reguła, wyrażenie, dane). Współpraca to istota całego tematu nie bardzo jednak nadaje się na tutoriale. Raczej by to ludzi straszyło niż wzbudzało zainteresowanie ;D

Swoja drogą uprzedziłeś mojego kolejnego posta. Chciałem napisać kilka słów o notacjach i przy okazji zaprezentować xText. Notacja tekstowa w tak prostym przypadku jest po prostu idealna, dodatkowo za darmo dostajesz pracę grupową. Żyć nie umierać. ;D

Grzegorz Białek pisze...

Zapomniałem odpowiedzieć na pytanie:

"Nie zauważyłem wykorzystania atrybutu SimpleFieldExpression::type"

Pole 'type' używane jest w tym przykładzie do generacji nazwy klasy (getTypeJavaName). Metoda definiowana jest poprzez xtend dlatego nie widać jej w modelu.

Krzysiek pisze...

A już myślałem, że to funkcja metamodelu EMF, którego za dobrze jeszcze nie znam. Na razie generowałem odrobinę z UML, a naturalnym odruchem po zderzeniu z jego metamodelem jest zwrócenie się do DSL / DSM, co właśnie ma u mnie miejsce :)

Xtext 4.3 ma eksperymentalną genialną funkcjonalność - importowanie gotowych gramatyk. Kluczowa według mnie funkcjonalność, na razie czeka na mojej liście rzeczy do przetestowania. Sprawdzałeś może?

ps. ciekaw jestem co się wykluje z Eclipse TMF. Z jednej strony Xtext, który pozwala na najszybsze tworzenie modelu z edytorem. Z drugiej TCS, który pozwala na wszystko, ale tworzenie przekształceń M2M widać odstrasza potencjalnych użytkowników, a sam proces jest dłuższy.

Adrian pisze...

1. No... Krzysztofie nie był bym tak surowy. "Wstęp do DSL" Nie jest co prawda tak wyczerpujący jak słynny tutorial "die Mikrowelle" z oficjalnej strony oAW, ale na wstęp wystarczy według mnie.
2. Modele UML nie są takie straszne od kiedy bazują na EMF :) Poza tym generować z UML można całkiem skomplikowane systemy reaktywne.

Unknown pisze...

Po lekturze wpisu oraz komentarzy muszę przyznać, że kompletnie nie czuję tematu - "Xpand, oAW, Xtext, czterech współpracujących modeli (kontekst, reguła, wyrażenie, dane), metamodelu EMF" i to tylko z komentarzy (!) Tyle akronimów/pojęć, a ja wciąż drapię się po głowie i pytam samego siebie, o co w tym wszystkim chodzi?! Chyba JEE całowicie spustoszyło moją głowę. Czy tematyka DSLi musi być tak ciężka, czy to jest całkowicie inna liga konstuowania oprogramowania niż programowanie obiektowe?! Można to w ogóle porównywać w tych kategoriach? Auć, właśnie doświadczyłem "buffer overflow" - kończę...Jacek
Notatnik Projektanta Java EE

Grzegorz Białek pisze...

Nie jest tak źle. Budowa narzędzi to co prawda zupełnie inna bajka niż JEE ale ilość bibliotek jest podobna. Na szczęście nie trzeba znać ich wszystkich :)

DSL'e to tylko fragment tej dziedziny jednak moim zdaniem najciekawszy. Jeżeli byłbyś zainteresowany tematem polecam stronę:

http://www.eclipse.org/modeling/

Ewentualnie wersję bardziej interaktywną czyli udział w spotkaniu EclipseCamp. W listopadzie kolejna edycja, jeżeli wszystko się uda to spróbuję zorganizować wersję wrocławską (z pewnością nie zabraknie na niej tego typu tematów)

Grzegorz Białek pisze...

To lista miast w jakich odbędą się spotkania. Na razie to tylko kilka pozycji ale za tydzień będzie zdecydowanie więcej :)

http://wiki.eclipse.org/Eclipse_DemoCamps_November_2008