Myśli, porady, tutoriale na temat środowiska Eclipse (i nie tylko)...

poniedziałek, 21 kwietnia 2008

Eclipse Modeling Framework (EMF), część III

Ostatnio wygenerowaliśmy kod, a w tej części tutoriala spróbujemy z tego kody skorzystać.

  1. W projekcie FamilyTree stwórzmy pakiet familytree.main (klikamy prawym przyciskiem na katalog src i wybieramy New->Package). W pliku plugin.xml wchodzimy na zakładkę Dependencies i w sekcji Required Plug-ins klikamy przycisk Add i w nowym oknie wpisujemy org.eclipse.emf.ecore.xmi (jest to dodatkowy plugin, który pozwoli nam na prosty zapis instancji naszego modelu do pliku) i zatwierdźcie wybór klikając OK.
  2. Ściągamy TEN plik z klasą ModelMain, kopiujemy go do nowego pakietu i otwieramy w edytorze. W klasie znajdziecie m.in. następujące trzy metody:
    • createModel - tworzy kilka elementów modelu
    • saveModel - zapisuje model do pliku
    • loadModel - wczytuje model z pliku oraz wypisuje na konsolę znalezione dzieci zapisanej do pliku rodziny

    Łatwo zauważyć, że kod wczytywania i zapisywania modelu może być reużywany w prawie niezmienionej postaci. Natomiast kod operujący na modelu nie różni się prawie niczym od operacji na zwykłych klasach (jedyną różnicą jest korzystanie z fabryki przy tworzeniu obiektów).
  3. Uruchommy kod, klikając prawym przyciskiem myszy na edytorze i wybierając Run As-> Java Application.
  4. Zobaczmy teraz jak działa powiadamianie o zmianach. W klasie ModelMain odkomentujmy metodę listenForChanges oraz jej wywołanie w metodzie main. W metodzie listenForChanges pokazany jest przykład prostego nasłuchiwania na zmiany w modelu. W naszym przypadku nasłuchujemy na zmiany obiektu son, zauważmy że gdy zostajemy powiadomieni o zmianie to mamy łatwy dostęp do wartości przed zmianą, jak i do wartości po zmianie. Uruchommy kod (tak jak w poprzednim punkcie), aby zobaczyć efekt.

    Na tym dzisiaj kończymy, w kolejnej części zobaczymy jak uruchomić wygenerowany przez EMF'a edytor i jak nim operować.

Eclipse Modeling Framework (EMF), część II

W poprzedniej części tutoriala udało nam się stworzyć model, teraz przyszedł czas na wygenerowanie kodu.

  1. Mając stworzony model możemy wygenerować z niego model implementacyjny. Z menu kontekstowego dla folderu model w naszym projekcie wybieramy New->Other->EMF Model. Podajemy nazwę (kończącą się na genmodel), np. My.genmodel, klikamy Next. Na kolejnej stronie wybieramy co będzie podstawą naszego modelu implementacyjnego, w naszym przypadku będzie to model Ecore, który chwilę wcześniej stworzyliśmy, wskazujemy nasz plik klikając na przycisk Browse Workspace. Klikamy Next, a później Finish. Powinien pojawić się plik My.genmodel oraz otworzyć się nowy edytor właśnie z tym plikiem.
  2. Jeśli przypatrzymy się nowemu plikowi w edytorze to zobaczymy, że nie różni się on za bardzo od pliku My.ecore, który edytowaliśmy poprzednio. Rożnica leży w atrybutach poszczególnych elementów (wystarczy spojrzeć do widoku Properties dla którejś z klas). Plik genmodel przechowuje szczegóły dotyczące kodu, który za chwilę będziemy generować.
  3. Przyszedł czas na generowanie kodu. W edytorze pliku My.genmodel klikamy na najwyższy węzeł i wybieramy Generate All. Po chwili zauważymy, że w katalogu src naszego projektu pojawił się kod oraz że zostały stworzone trze nowe projekty FamilyTree.edit, FamilyTree.editor, i FamilyTree.tests. Po co nam te dodatkowe projekty?
    • projekt editor zawiera wspominany na samym początku edytor instancji naszego modelu
    • projekt edit zawiera klasy umożliwiające sprawną edycję elementów wyświetlanych w edytorze
    • projekt tests zawiera szkielety testów dla wygenerowanego kodu
  4. Spójrzmy na chwilę do katalogu src projektu FamilyTree. Znajdziemy tam trzy pakiety:
    • familytree - zawiera interfejsy odpowiadające klasom zdefiniowanym w naszym modelu. Dodatkowo znajdziemy tam dwie klasy FamilytreeFactory oraz FamilyTreePackage. Ta pierwsza (jak sama nazwa wskazuje) pozwala nam w łatwy sposób tworzyć obiekty modelu, ta druga natomiast zawiera stałe oraz specjalne metody dostępu do niektórych elementów modelu.
    • familytree.impl - zawiera implementację klas zdefiniowanych w naszym modelu
    • familytree.util - zawiera klasy pomocnicze do operacji na naszym modelu
  5. Najważniejsze elementy w wygenerowanym kodzie w projekcie FamilyTree to interfejsy oraz implementacje naszych klas z modelu. Jeśli przypatrzymy im się bliżej to zobaczymy, że w każdym interfejsie pojawiły się metody pozwalające na dostęp do pól klas, a w klasach pojawiły się odpowiednie pola oraz implementacje metod. Warto zauważyć, że przy każdym wygenerowanym elemencie w komentarzy JavaDoc znajduje się adnotacja @generated. Jeśli do jakiejś metody wprowadzimy zmiany, których nie chcemy stracić po ponownej generacji kodu to powinniśmy adnotację tę zmienić na @generated NOT, a w przypadku metod dodawanych przez nas do kodu nie powinniśmy takiej adnotacji w ogóle dodawać
  6. Spójrzmy na metody getName oraz setName w klasie IndividualImpl:

    public String getName() {
    return name;
    }

    public void setName(String newName) {
    String oldName = name;
    name = newName;
    if (eNotificationRequired())
    eNotify(new ENotificationImpl(this, Notification.SET,
    FamilytreePackage.INDIVIDUAL__NAME, oldName, name));

    }
    Jak widzimy kod get’a po prostu udostępnia wartość odpowiedniego pola, natomiast metoda set’a oprócz ustawienia nowej wartości wysyła powiadomienie o zmianie tej wartości do wszystkich obiektów nasłuchujących na tę zmianę.

    Na tym dzisiaj kończymy. W kolejnej części zobaczymy, jak w prosty sposób korzystać z wygenerowanego kodu i z zalet, które daje nam EMF.

niedziela, 20 kwietnia 2008

Eclipse Modeling Framework (EMF), część I

Ostatnio na zajęcia przygotowywałem materiał na temat MDA. Jako przykład takiego podejścia pokazywałem studentom projekt Eclipse Modeling Framework. Materiał jest w postaci tutoriala, więc doszedłem do wniosku, że nie zaszkodzi go tutaj umieścić.


Czym jest EMF?
OMG dostarcza tylko specyfikację MDA, natomiast konkretne implementacje dostarczają już firmy komercyjne oraz różne projekty open source. Wiele koncepcji MDA odnajdziemy w projekcie EMF (Eclipse Modeling Framework).
EMF sam w sobie jest frameworkiem dla generowania narzędzi i innych aplikacji na podstawie prostych modeli klas. EMF pozwala zamienić model na wydajny, poprawny i łatwy do zmiany kod Javy.
Główne zalety EMF’a to:
  • EMF na podstawie modelu potrafi wygenerowań kod Javy nadający się od razu do wykorzystania. Dodatkowym atutem jest możliwość wpływania na sposób generowania kodu. Zmiany wprowadzone w utworzonym kodzie nie są tracone podczas wprowadzania modyfikacji do modelu i ponownej generacji kodu.
  • Model może być dostarczony w różnych postaciach, m.in. kodu Javy z odpowiednimi adnotacjami, XML’a, pliku z narzędzi do modelowania (np. Rational Rose)
  • Instancje stworzonego modelu są domyślnie zapisywane i wczytywane z plików XMI (XML Metamodel Interchange). Można również dostarczyć swój własny sposób przechowywania modelu.
  • EMF pozwala na generowania prostego edytora umożliwiającego edycję instancji modelu z poziomu interfejsu użytkownika.
  • Wygenerowany kod umożliwia nam w prosty sposób nasłuchiwanie na zmiany dokonywane w instancji modelu.
Skoro EMF ma tyle zalet to spróbujmy stworzyć coś konkretnego z jego pomocą (przedstawiony tutaj przykład opiera się na artykule Using EMF).
Aby lepiej zrozumieć jak działa EMF spróbujemy stworzyć prosty model dla aplikacji do tworzenia drzew genealogicznych.
  1. Na początek musimy stworzyć projekt EMF, w tym celu wybieramy File->New->Eclipse ModelinfgFramework->Empty EMF Project, klikamy Next, podajemy nazwę projektu (np. FamilyTree) i kończymy pracę kreatora klikając Finish.
  2. Możemy się zabrać za definicję modelu. W widoku Package Explorer menu kontekstowego dla folderu model w naszym projekcie wybieramy New->Other->Example EMF Model Creation Wizards->Ecore Model, akceptujemy domyślną nazwę (My.ecore) i klikamy Finish. Powinien otworzyć się nam drzewiasty edytor, w którym będziemy definiować nasz model.
  3. Do edycji naszego modelu (a konkretnie do edycji atrybutów poszczególnych elementów) będziemy wykorzystywać widok Properties. Jeśli widok ten jeszcze nie jest otwarty, to otwieramy go wybierając w menu Window->Show View->Other->General->Properties.
  4. Jak zauważymy w naszym modelu na wstępnie mamy zdefiniowany pakiet. Klikamy na nim, a w widoku Properties zmieniamy jego nazwę (atrybut Name) oraz pozostałe atrybuty (Ns prefix, Ns URI) na familytree.
  5. Dalsza praca z modelem jest podobna do tworzenia modelu klas UML, jedyną różnicą jest to że zamiast standardowego edytora klas mamy tutaj do dyspozycji edytor drzewiasty. Stwórzmy sobie prosty model:
  6. W modelu EMF’a operujemy m.in. na następujących elementach:
    • EPackage odpowiada pakietowi
    • EClass odpowiada klasie
    • EEnum odpowiada typowi wyliczeniowemu
    • EAttribute odpowiada atrybutowi klasy
    • EOperation odpowiada metodzie klasy
    • EReference odpowiada referencji
  7. W modelu EMF potrzebujemy zawsze element, w którym będzie naszym korzeniem przechowującym pozostałe elementy, w naszym przypadku jest to klasa FamilyTree. Tworzymy ją klikając prawym przyciskiem myszy na pakiecie familytree i wybierając New->EClass. Następnie zmieniamy atrybut Name nowej klasy na FamilyTree.
  8. Pozostałe elementy modelu definiujemy w podobny sposób, trzeba jednak wziąć pod uwagę to, że każdy element modelu musi być gdzieś przechowywany, aby to określić używamy atrybut Containment. Zatem aby stwierdzić, że obiekty typu Individual mają być przechowywane w obiekcie FamilyTree (naszym kontenerze) to ustawiamy atrybut containment na relacji Individual-FamilyTree na true.

    Jeśli ktoś chce zobaczyć jak wygląda gotowy model to wystarczy ściągnąć plik My.ecore. Możemy zastąpić nasz plik gotowym modelem i przeanalizować jak poszczególne elementy modelu UML zmapowane są na elementy typowe dla EMF’a.
  9. Na koniec pracy nasz model powinien wyglądać mniej więcej tak:

Na tym dzisiaj zakończymy. W ciągu tygodnia powinna pojawić się druga część, w której zobaczymy jak z utworzonego modelu można wygenerować w pełni działający kod.

piątek, 18 kwietnia 2008

Przyjaciel Eclipse'a

Pod koniec zeszłego roku pojawiła się możliwość wspomagania finansowego Eclipse Foundation (dotyczy to jednak tylko osób prywatnych). Płatności można dokonywać za pomocą systemu PayPal. Ostatnio założyłem sobie tam konto i postanowiłem dorzucić swoje kilka groszy do fundacji Eclipse'a, i w ten oto sposób stałem się oficjalnym przyjacielem Eclipse'a. Wy oczywiście też możecie zdobyć taki status! Jak to zrobić? Wystarczy przekazać na konto fundacji 35$ (przy obecnym kursie dolara jest to stosunkowo mała kwota), żeby cieszyć się tytułem "Friend of Eclipse" (i umieścić informujące o tym logo na swojej stronie lub blogu) i dodatkowo mieć dostęp do dedykowanego serwera, z którego dużo szybciej (w porównaniu ze standardowymi serwerami na eclipse.org) można ściągnąć Wasze ulubione środowisko. Zobaczcie tutaj, jeśli interesują Was szczegóły.

P.S. Ostatnio zapuściłem się trochę z pisaniem, ale obiecuję że niedługo powrócę z ciekawymi wpisami (m.in. o projekcie EMF)