Visual Model For F# – Metamodel

Metamodel

Metamodelem w informatyce nazywamy zbiór koncepcji w zakresie pewnej dziedziny. Jeśli model jest abstrakcją jakiegoś zjawiska, to metamodel będzie abstrakcją przedstawiającą właściwości tego modelu. W tym poście omówiono metamodel języka modelowania przedstawionego w poprzednich wątkach. Zaproponowany metamodel został przedstawiony na uproszczonym diagramie klas (rys. 1) poniżej. Rysunek przedstawia koncepcję budowy metamodelu, elementy, które wchodzą w jego skład, oraz powiązania pomiędzy tymi elementami.

Uproszczony diagram klas przedstawiający metamodel z projektu pracy magisterskiej

Rysunek 1: Uproszczony diagram klas przedstawiający metamodel

Metamodel został zbudowany przy użyciu narzędzi DSL Tools firmy Microsoft. Dzięki temu narzędziu można było stworzyć specyficzny język domenowy (ang. DSL), który został omówiony w poprzednich postach przedstawiających zaproponowane rozwiązanie.

Z przedstawionych poniżej pojęć metamodelu można tworzyć modele programów dla języka funkcyjnego F#. W efektywny sposób można tworzyć modele oraz generować szkielety programów funkcyjnych. Dla zaproponowanego i założonego poziomu abstrakcji można częściowo wygenerować kod F#, resztę implementacji trzeba uzupełniać ręcznie. Wtyczka nie pozwala na generację pełnego kodu modelowanych programów.

Nie jest to pełny metamodel pokrywający wszystkie aspekty języka funkcyjnego F#, ale podzbiór najważniejszych elementów. W przyszłości metamodel można poszerzać o nowe elementy i bardziej go uszczegóławiać.

Na poniżej przedstawionych fragmentach metamodelu (rys. 2 oraz rys. 3) widać, że w głównym elemencie RootModel znajdują się bloki kodu CodeBlock. Element RootModel może zawierać dowolną ilość elementów CodeBlock, ale każdy CodeBlock może znajdować się tylko w jednym RootModel. Następnie od elementów CodeBlock można prowadzić dowolną ilość relacji do elementów TypeElement lub Function. Jeśli chodzi o element TypeElement, to relacje są tak naprawdę zdefiniowane do sekcji z operacjami, czyli do części Operations. Element Function może przyjmować tylko jedną relację od elementu CodeBlock.

Fragment metamodelu 1

Rysuenk 2: Fragment metamodelu 1

Fragment metamodelu 1 cd.

Rysunek 3: Fragment metamodelu 1 cd.

Poniższy diagram (4) przedstawia inny fragment metamodelu. Widać na nim, że element TypeElement może się składać z dowolnej liczby elementów Attribute lub Operation, czyli tak naprawdę w sekcjach Attributes i Operations dla elementu TypeElement możemy dodawać dowolną liczbę elementów. Za to każdy element Attribute lub Operation musi być zdefiniowany tylko w jednym elemencie TypeElement. Element TypeElement może posiadać jedną relację dziedziczenia do innego elementu TypeElement. Element TypeElement może przyjmować wiele relacji generalizacji, tzn. może dochodzić do niego wiele relacji zakończonych grotem.

Fragment metamodelu 2

Rysunek 4: Fragment metamodelu 2

Na poniższym rysunku 5 przedstawiony jest kolejny fragment metamodelu. Element, na który warto zwrócić uwagę, to Compound. Jest to abstrakcyjny element w metamodelu, po którym dziedziną dwie inne klasy domenowe: RootModel oraz Module. Oznacza to, że te dwa elementy mogą zawierać dowolną ilość elementów takich, jak: TypeElement, Module oraz Function. Natomiast każdy z tych trzech elementów znajduje się w RootModel lub w Module. Między innymi z tego diagramu można wywnioskować, że moduły mogą być w sobie zagnieżdżone.

Fragment metamodelu 3

Rysunek 5: Fragment metamodelu 3

Rysunek 6 przedstawia fragment metamodelu, na którym widać, że takie klasy domenowe, jak: TypeElement, Attribute, Operation, CodeBlock oraz Function, dziedziczą po elemencie NamedElement. Ten ostatni posiada właściwość o nazwie Name, którą dziedziczą wszystkie pozostałe klasy.

Fragment metamodelu 4

Rysunek 6: Fragment metamodelu 4

Ograniczenia

Ograniczenia, które występują na powyższych diagramach metamodelu, automatycznie definiują składnię języka modelowania. Modele można tworzyć zgodnie z ograniczeniami metamodelu. Oprócz tych podstawowych wymienionych wyżej istnieją jeszcze inne, ukryte w kodzie źródłowym projektu.

Relacje dziedziczenia można tworzyć między elementami TypeElement tylko na tym samym poziomie zagnieżdżenia, jeśli chodzi o moduły, lub tylko w głównym obszarze modelowania, czyli w RootModel. Związków generalizacji nie można stworzyć między dwoma typami, które są w różnych modułach. To samo ograniczenie zachodzi, gdy związek ma być tworzony między głównym obszarem modelowania a jakimś modułem.

Kolejne ograniczenie dotyczy elementu Link to Operation. Związek ten można poprowadzić między blokiem kodu CodeBlock a sekcją Operations w elemencie TypeElement. Wiązanie końca strzałki tej relacji jest umiejscowione dokładnie w miejscu występowania operacji w sekcji Operations w elemencie TypeElement.

Nie wszystkie elementy języka F# da się zamodelować dzięki tak zdefiniowanemu metamodelowi. Wtyczkę można rozwinąć o nowe elementy w jej kolejnych wersjach.

adamex

About Adam Bielasty

.NET Software Developer

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *


8 − 4 =

Możesz użyć następujących tagów oraz atrybutów HTML-a:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>