Visual Minik - plugin do Eclipse’a, wizualizujący zależności występujące w kodzie Jan Horabik 09. 01. 2006.

Slides:



Advertisements
Podobne prezentacje
Wstęp do strumieni danych
Advertisements

C++ wykład 2 ( ) Klasy i obiekty.
Klasy abstrakcyjne i interfejsy
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Wzorce.
Generics w .NET 2.0 Łukasz Rzeszot.
Obiektowe metody projektowania systemów Design Patterns STRATEGY.
Implementacja ekstensji klasy
Programowanie Obiektowe w Javie (c.d.)
Nguyen Hung Son Uniwersytet Warszawski
Programowanie obiektowe w Javie
Serwery Aplikacji ASP .NET Web Objects Arkadiusz Popa.
RMI I RMI-IIOP Wprowadzenie Co to jest RMI?
Model – View - Controler
W ZORCE P ROJEKTOWE … czyli ktoś już rozwiązał Twoje problemy!
Obiektowe metody projektowania systemów
Obiektowe metody projektowania systemów Command Pattern.
C++ wykład 2 ( ) Klasy i obiekty.
Czytanie, pisanie i rysowanie (czyli klasa I szkoły podstawowej)

ALGORYTMY I STRUKTURY DANYCH
Wstęp do kontenerów IoC
Test Doubles Adam Gabryś , v1.1,
Klasy w C++. Deklaracja klasy class NazwaTwojejKlasy { //w tym miejscu piszemy definicje typów, //zmienne i funkcje jakie mają należeć do klasy. }; //tutaj.
Pakiety w Javie Łukasz Smyczyński (132834). Czym są pakiety? Klasy w Javie są grupowane w pewne zbiory zwane pakietami. Pakiety są więc pewnym podzbiorem.
Java 3 MPDI Programowanie obiektowe W7. import java.io.*; public class X { // kontrukcja throws – określenie jakie wyjątki może dana metoda // sygnalizować
Podstawy programowania II
Generatory dokumentacji kodu źródłowego
W większości języków programowania biblioteki wejścia/wyjścia ukrywają szczegóły obsługi poszczególnych mediów pod abstrakcją strumienia (ang. stream).
Programowanie obiektowe III rok EiT
Programowanie obiektowe – zastosowanie języka Java SE
JAVA c.d.. Instrukcji wyboru SWITCH używamy, jeśli chcemy w zależności od wartości pewnego wyrażenia wykonać jeden z kilku fragmentów kodu. Jest to w.
Java – coś na temat Klas Piotr Rosik
Dziedziczenie Maciek Mięczakowski
Seminarium problemowe
INTERFEJSY I KLASY WEWNĘTRZNE
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Programowanie obiektowe Wykład 6 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14 Dariusz Wardowski.
Przekazywanie parametrów do funkcji oraz zmienne globalne i lokalne
Programowanie obiektowe 2013/2014
OCPJP Inner classes.
Kurs języka C++ – wykład 9 ( )
Treści multimedialne - kodowanie, przetwarzanie, prezentacja Odtwarzanie treści multimedialnych Andrzej Majkowski informatyka +
K URS JĘZYKA C++ – WYKŁAD 6 ( ) Polimorfizm.
Prom Pisanie pluginów Maciej Sobkowiak & Tomek Ciesielczyk.
Obiektowe metody projektowania systemów Abstract Factory design pattern (aka. Kit)
Paweł Starzyk Obiektowe metody projektowania systemów
Wzorce Projektowe w JAVA
Programowanie Zaawansowane
Kolekcje (3) Zbiory. Porównywanie i porządkowanie elementów kolekcji. (c) Krzysztof Barteczko 2014.
do programowania obiektowego w języku Groovy
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
InMoST, Java – przykładowa aplikacja Bartosz.Michalik
Podstawowe konstrukcje języka Java Bartosz Walter InMoST Wielkopolska sieć współpracy w zakresie innowacyjnych metod wytwarzania oprogramowania Termin.
Programowanie Obiektowe – Wykład 6
Typy wyliczeniowe, kolekcje
Wątki, programowanie współbieżne
Klasy, pola, obiekty, metody. Modyfikatory dostępu, hermetyzacja
(według:
(c) Krzysztof Barteczko 2014
Programowanie Obiektowe – Wykład 2
Klasy wewnętrzne. Praktyka użycia interfejsów i klas wewnętrznych
Dynamics 365 CE i język TypeScript
Programowanie obiektowe – zastosowanie języka Java SE
PGO Interfejsy Michail Mokkas.
Założenia projektowe Javy
PGO - Projektowanie i implementacja pierwszych klas
PGO Dziedziczenie Michail Mokkas.
Zapis prezentacji:

Visual Minik - plugin do Eclipse’a, wizualizujący zależności występujące w kodzie Jan Horabik

Plan prezentacji Wstęp Visual Minik w działaniu Struktura implementacji Visual Minika Struktura mojej części kodu Możliwości JDT, wykorzystane do wyciągnięcia zależności występujących w kodzie

Wstęp Motywacja – w czasie pisania projektu często chcemy szybko zorientować się w zależnościach występujących w kodzie programu (podniesienie jakości tworzonego kodu) Visual Minik – plugin do Eclipse’a, który umożliwia wizualizację tych zależności w postaci grafu (wierzchołki – to np. pakiety, a krawędzie – zależności między nimi). Napisany w wakacje w zespole 4 – osobowym w ramach stażu.

Definicje Encja – projekt, pakiet, typ (klasa lub interfejs) lub metoda Zależność - między encjami tego samego rodzaju Metoda A zależy od metody B, jeśli w kodzie metody A jest wywoływana metoda B Typ A zależy od typu B, jeśli - któraś z metod typu A zależy od którejś metody typu B - A rozszerza lub implementuje B - jedna z metod typu A jako parametr lub typ zwracany przyjmuje obiekt typu B Pakiet A zależy od pakietu B, jeśli któryś z typów pakietu A zależy od któregoś z typów pakietu B Projekt A zależy od projektu B, jeśli któryś z pakietów A zależy od któregoś z pakietów B (jary)

Definicje Graf zależności – graf, którego wierzchołkami są encje; jeśli encja A zależy od encji B, to w grafie występuje krawędź z A do B Zmiana definicji zależności pociąga za sobą niewielkie zmiany w kodzie plugina

Co umożliwia Visual Minik generowanie grafu zależności podział wierzchołków na trzy rodzaje: main, use, return zapis grafu pomiędzy wywołaniami programu (nie trzeba wyliczać informacji za każdym razem) przechodzenie pomiędzy widokami (np. klasy w ramach pakietu) zwijanie i rozwijanie elementów grafu filtrowanie encji automatyczne (intuicyjne) rozmieszczenie wierzchołków grafu i możliwość ich przesuwania skakanie do kodu generowanie statystyk

Implementacja Cele: - łatwa zmiana języka, na którym pracujemy (np. C++ zamiast Javy) i definicji zależności (logika musi w jednakowy sposób traktować np. pakiety i klasy) - ograniczenie do minimum kodu korzystającego z zewnętrznych bibliotek i możliwość jego podmiany w razie konieczności (interfejsy)

Struktura Visual Minika

Entity public class Entity { final private String name; final private ImmObject unit; final private ImmObject data; final private EntityOption comprisedIn; final private EntityOption belongsTo; final private String key;... }

DepGetter public interface DepGetter { public Entities getMainEntities(); public Entities getBelongSubEntities(Entity entity);// należenie public Entities getIncludeSubEntities(Entity entity);// zawieranie public Entities getDependentEntities(Entity entity); // encje, które ode mnie zależą public Entities getEntitiesIDependOn(Entity entity); // encje od których ja zależę }

Implementacja DepGetter’a Dwa podejścia: 1) Wyliczamy zależności na żądanie Zalety: - mały koszt pamięciowy (proporcjonalny do rozmiaru grafu) – w pamięci trzymamy tylko ten graf, który w danej chwili jest nam potrzebny, - zmiany w kodzie uwzględniane za darmo Wady: - bardzo duży koszt czasowy (w pesymistycznym przypadku za każdym razem analizujemy cały projekt) - wielokrotnie liczymy to samo

Implementacja DepGetter’a 2) Wszystkie zależności wyliczamy na początku i trzymamy w pamięci. Zalety: - liniowy (względem rozmiaru projektu) koszt czasowy początkowego wyliczenia wszystkich informacji – dla GenRapa ok. 10min, ale wykonywane tylko raz! (serializacja) - stały koszt czasowy każdej z operacji DepGetter’a (wszystko mamy już policzone) Wady: - bardzo duży koszt pamięciowy, (aby go zredukować wprowadziłem możliwość nie uwzględniania metod) - trudne uwzględnianie zmian w kodzie (nie udało mi się tego zrealizować) - skomplikowany kod ;-)

Jak to zrobić (org.eclipse.jdt.core) ?

Jak to zrobić? //implementacja getMainEntities():... IWorkspace workspace = ResourcesPlugin.getWorkspace(); IJavaModel javaModel = JavaCore.create(workspace.getRoot()); IJavaProject[] projects = javaModel.getJavaProjects(); String projectName = projects[0].getElementName();... //implementacja getBelongSubEntities():... IPackageFragment packageFragment =... ; ICompilationUnit[] compilationUnits = packageFragment.getCompilationUnits(); IType[] types = compilationUnits[0].getTypes(); String typeName = types[0].getElementName();...

Java Search Engine Aby zaimplementować getDependentEntities() możemy skorzystać z Java Search Engine. Umożliwia on wyszukiwanie wywołań konkretnych metod, deklaracji metod, implementacji interfejsów itp. Aby z niego skorzystać, należy: - stworzyć wzorzec poszukiwań (SearchPattern) - stworzyć zakres poszukiwań (IJavaSearchScope) - stworzyć obiekt, który będzie otrzymywał wyniki poszukiwań( rozszerzyć SearchRequestor) - stworzyć SearchEngine i wywołać metodę search z powyższymi parametrami

SearchPattern IMethod method =...; SearchPattern pattern1 = SearchPattern.createPattern(method, IJavaSearchConstants.REFERENCES); SearchPattern pattern2 = SearchPattern.createPattern("Obj*", IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_CASE_SENSITIVE);

IJavaSearchScope IPackageFragment pkg =...; IJavaSearchScope scope1 = SearchEngine.createJavaSearchScope(new IJavaElement[] {pkg}); IJavaSearchScope scope2 = SearchEngine.createWorkspaceScope();

SearchRequestor class MySearchRequestor extends SearchRequestor { public void acceptSearchMatch(SearchMatch match) throws CoreException { IJavaElement element = (IJavaElement) match.getElement();... }

SearchEngine SearchPattern pattern =...; IJavaSearchScope scope =...; SearchRequestor requestor = new MySearchRequestor(); SearchEngine searchEngine = new SearchEngine(); searchEngine.search(pattern, new SearchParticipant[] {SearchEngine.getDefaultSearchParticipant()}, scope, requestor, null); - umożliwia zaimplementowanie getDependentEntities(), ale nie getEntitiesIDependOn()

Parser JDT Aby zaimplementować getEntitiesIDependOn(), musimy sparsować pliki.java AST – Abstract Syntax Tree ASTNode – abstrakcyjna klasa bazowa wszystkich wierzchołków AST, jej podklasy to m.in.: - MethodInvocation - ClassInstanceCreation - ImportDeclaration -...

ASTVisitor Odwiedzający AST ASTVisitor ma zdefiniowane metody - public boolean visit (T node) oraz - public void endVisit (T node) dla każdego typu wierzchołka. Należy stworzyć swoją podklasę klasy ASTVisitor i przedefiniować te metody, które nas interesują.

Parsowanie plików ICompilationUnit compilationUnit =... ASTParser parser = ASTParser.newParser(AST.JLS2); parser.setSource(compilationUnit); // UWAGA! Jako parametr można podać ClassFile, ale będzie to działać tylko wtedy, gdy jest z nim związany ICompilationUnit ASTNode astNode = parser.createAST(null); ASTVisitor visitor = new MyVisitor(); astNode.accept(visitor);... class MyVisitor extends ASTVisitor{ public boolean visit (MethodInvocation methodInvocation{... }; public boolean visit (TypeDeclaration typeDeclaration){... };

Rejestrowanie zmian JDT umożliwia zdobycie informacji o tym, jakie zmiany zachodzą w projekcie, w czasie działania plugina. Należy zaimplementować IResourceChangeListener i zarejestrować obiekt nowo utworzonej klasy w Workspace. Będzie on powiadamiany o zmianach poprzez obiekt klasy IResourceChangeEvent

Rejestrowanie zmian IResourceChangeListener listener = new MyResourceChangeReporter(); ResourcesPlugin.getWorkspace().addResourceChangeListener( listener, IResourceChangeEvent.POST_CHANGE); public class MyResourceChangeReporter implements IResourceChangeListener{ public void resourceChanged(IResourceChangeEvent event) { IResource res = event.getResource(); System.out.println("Resources have changed."); event.getDelta().accept(new DeltaPrinter()); }

Rejestrowanie zmian class DeltaPrinter implements IResourceDeltaVisitor { public boolean visit(IResourceDelta delta) { IResource res = delta.getResource(); switch (delta.getKind()) { case IResourceDelta.ADDED: System.out.print("Resource "); System.out.print(res.getFullPath()); System.out.println(" was added."); break; case IResourceDelta.REMOVED: System.out.print("Resource "); System.out.print(res.getFullPath()); System.out.println(" was removed."); break; case IResourceDelta.CHANGED: System.out.print("Resource "); System.out.print(res.getFullPath()); System.out.println(" has changed."); break; } return true; // visit the children }