Umwandlung eines Klassendiagrammes in einen Graphen

Exkurs Klassendiagramm

Als Ausgangslage wird das Klassendiagramm gewählt. «Ein Klassenmodell beschreibt Klassen von Objekten, ihre Eigenschaften, Operationen und Beziehungen untereinander.» (Oestereich & Scheithauer, 2013, S. 170) Es gibt verschiedene Arten von Beziehungen zwischen Klassen. So können Abhängigkeiten in Form von Vererbung oder Implementierung dargestellt werden. Aber auch Anhängigkeiten in Form von Aufrufen und Verwendungen innerhalb eines Objektes. Oestereich und Scheithauer (Oestereich , Scheithauer, 2013, S. 200) führen die Verschiedenen Arten von Verbindungen in ihrem Buch auf und liefern für alle Arten eine Definition und Erklärung.

Exkurs Graph

Ein Graph besteht aus Punkten, im folgenden Knoten genannt, und Linien, im folgenden Katenen genannt. Die Knoten können durch eine oder mehrere Kanten miteinander verbunden sein. Dabei ist es möglich das die Kante gerichtet ist. Dies wird durch einen Pfeil an der Kante signalisiert. Dabei zeigt der Pfeil auf den Knoten auf welchen er verweist.

Einfache Darstellung eines Graphen mit 4 Knoten und 4 Kanten
Einfache Darstellung eines Graphen mit 4 Knoten und 4 Kanten

 

Sind alle Knoten eines Graphen durch mindestens eine Kante verbunden so spricht man von einem zusammenhängenden Graphen. Hat ein Knoten keine Kanten so spricht man von einem Isolierten Knoten.

Vorgehen

Forschungsobjekt

Zum durchführen der Arbeit wurde eine Semesterarbeit, in dem Fach Projektarbeit, an der FFHS verwendet. (Federer, Eberlein, Wallner, 2016) In dieser Arbeit wurde eine Anwendung geschrieben, in welcher der User eine Ausgangswährung und einen Betrag in eine Zielwährung umrechnen kann. Die Arbeit basiert auf einem Microservice Ansatz so das der Code Serverseitig auf Java basiert. Dieser Serverseitige Code wurde zum analysieren in dieser Arbeit verwendet. Der Code wurde im Rahmen des damaligen Projektes durch die zuständigen Dozenten geprüft und mit gut bewertet.

Erstellung des Klassendiagramms

Um aus dem Quellcode ein Klassendiagramm zu gewinnen wurde die Entwicklungsplattform InteliJ verwendet. Diese bietet die Möglichkeit ein Klassendiagramm aus Code generieren zu lassen. Dabei kann man für alle Packages wählen ob die Nodes angezeigt werden sollen. Wir lassen alle Klassen und ihre Beziehungen Anzeigen. Das daraus resultierende Diagramm wurde auf Vollständigkeit überprüft.

 Diagramm erstellt mit InteliJ
Diagramm erstellt mit InteliJ

 

Bilden des Graphen

Ein Klassendiagramm besteht aus Objekten und Beziehungen zwischen diesen Objekten. Um daraus einen Graphen zu bilden wurde für jedes Objekt ein Knoten und für jede Beziehung eine Kante erstellt. Da die Beziehungen in einem Klassendiagramm schon gerichtet sind wird diese Richtung auch für die Kanten im Graphen übernommen. In dem Paper (Baowen Xu, Dazhou Kang, Jianjiang Lu, 2004) wird die Komplexität von Klassendiagrammen mit Hilfe von Graph Analyse berechnet. Dabei werden ebenfalls die Beziehungen als Kanten und die Objekte als Knoten gesehen. Zusätzlich wurden den Kanten je nach Art der Beziehung einem Gewicht versehen. In dieser Arbeit wurde auf die vergabe von Gewichten verzichtet. Es soll der Zusammenhang zwischen den Objekten dargestellt und untersucht werden. Im speziellen ob Fehler im Aufbau des Graphens gemacht worden sind. Dafür ist aus der Sicht des Autors eine Gewichtung nicht der Graphen nicht notwendig. Weiter wurde untersucht ob es Möglichkeiten gibt Klassendiagramme in ein von Computer lesbares Format zu transformieren. Diverse UML Generatoren bieten auch die Möglichkeit UML zu exportieren. Für diese Arbeit konnten diese Formate nicht verwendet werden, da sie zu speziell und nicht standardisiert sind. Der Graph wurde also anhand der Daten des Klassendiagramms mit Gephi (Gephi) erstellt. Alle Objekte und Beziehungen wurden typisiert. Dies wurde mit der Überlegung getan das bei Analysen der Type eine Rolle spielen könnte. Da in einem Klassendiagramm alle Beziehungen gerichtet sind befinden wir uns auch in unserem Graphen in einen gerichteten Graphen.

Graph erstellt in Gephi
Graph erstellt in Gephi

 

Auf die Möglichkeit, den Graph als Multigraphen darzustellen, wurde bewusst verzichtet. Auch wenn ein Objekt mehr als eine Beziehung zu anderen Objekten haben kann ist für unsere Überlegung nur die Tatsache das eine Beziehung existiert von Bedeutung. Wir haben daher bewusst auf einen Multigraphen verzichtet.


Überlegungen

Zur Analyse des Graphen wurden folgende Überlegung angestellt. Klassen sollten klein sein. Ausserdem sollten Klassen nur einen einzigen Grund haben sich zu ändern. Eine Klasse sollte nur für eine Sache zuständig sein und nur genau für diese. (Martin, 2009) Wenn die Frage «Was macht diese Klasse?» mit mehr als einer Antwort beantwortet werden muss ist meine Klasse zu gross. Als zweites Kriterium soll untersucht werden ob sich Objekte gegenseitig aufrufen. Dabei gibt es Fälle wo ein gegenseitiges Aufrufen von Klassen Sinn macht. Eine innere Klasse kann natürlich die Klasse aufrufen, in welcher sie eingebettet ist und die Äussere Klasse kann genauso Abhängigkeiten von der Inneren Klasse haben. Objekte, welche sonst voneinander abhängig sind sollten, wenn sie so eng verknüpft sind, in eine Klasse zusammengeführt, oder das Design überdacht werden.Als drittes Kriterium soll untersucht werden ob die Netzwerkdichte einen Einfluss auf unsere Hypothesen hat. Die Netzwerkdichte gibt das Verhältnis zwischen vorhanden und möglichen Kanten an. Sie wird als ein Wert zwischen 0 und 1 angegeben. Als viertes Kriterium untersuchen wir die Betweenness Centrality. Wir gehen davon aus das Klassen, welche eine Hohe Betweenness Centrality haben wichtig für Applikation selbst sind. Das heisst hier werden Komponenten zusammengeführt und verschiedene Funktionen aufgerufen.

Methoden zur Graph Analyse

Der Grad eines Knotens ist definiert als die Anzahl der von dem Knoten ausgehenden Kanten. (Krischke, Röpcke, 2015, S. 18) In unserem Fall repräsentiert der Grad also die Ausgehenden Beziehungen eines Objektes. Da es sich um einen gerichteten Graphen handelt sprechen wir von Eingangsgrad und Ausgangsgrad. Wir können also davon ausgehen, dass wenn wir den Ausgangsgrad bestimmen wir die Anzahl der von dem Knoten ausgehenden Beziehungen haben. Wenn wir uns nun auf das Verantwortungsprinzip beziehen legen wir in unserer Arbeit die Grenze für maximal auftretende Beziehungen auf 5. Klassen welche mehr als 5 Beziehungen zu anderen Klassen haben sind aus Sicht des Autors zu gross. Dabei wird 5 als Annahme genommen was Um gegenseitige Abhängigkeiten zu untersuchen wird eine Kreissuche durchgeführt. Ein Kreis wird definiert als ein Weg, ausgehend von einem Knoten, definiert. Nach der Verwendung verschiedener Kanten gelangt man zurück an dem Ursprungsknoten. Dabei wird keine Kante doppelt verwendet.

(Krischke, Röpcke, 2015, S. 22).

Um diese Berechnung auszuführen exportieren wir den Graphen in Gephi im gml Format. Zum einlesen und verarbeiten der erstellten Datei verwenden wir ein Python Programm. In dem Python Programm suchen wir, ausgehend von jedem einzelnen Knoten, nach Kreisen in dem Graphen. In jeden Durchlauf suchen wir nach Verbindungen, welche wir noch nicht aufgenommen haben und suchen tiefer in den Baum. So können alle Bäume definiert werden.   Als weiteren Indikator wollen wir die Kantendichte analysieren. Die Kantendichte (Krischke, Röpcke, 2015) in einem ungerichteten Netzwerk berechnet sich wie folgt: 

M = Anzahl der Kanten im Graphen

Daraus leiten wir die Formel für den gerichteten Graphen ab.

Zusätzlich werden wir noch einige Kennzahlen berechnen und versuchen daraus Erkenntnisse zu ziehen. Die Kantendichte ist eine Zahl, welche das Verhältnis von Kanten in einem Graphen zu der maximalen Anzahl von Kanten angibt. Wir werden eine Zahl bilden in der Annahme das die maximale Anzahl Kanten = n(n-1) ist. Wobei n gleich die Anzahl der Knoten im Graph ist. Dies ist die maximale Anzahl für einen einfachen gerichteten Graphen. Die Betweenness Centrality Cb i ergibt sich aus der Anzahl der kürzesten Wege Pikj zwischen den Knoten k und j, auf denen der Knoten i liegt, im Verhältnis zur Zahl aller kürzesten Wege Pkj zwischen den Knoten k und j.

(Krischke, Röpcke, 2015).

Ergebnisse

Von allen Untersuchten Knoten gab es einen Knoten mit einem Ausgangsgrad von 6. Dabei handelt es sich um die Klasse DAOCurrency. Zur Überprüfung des Ergebnisses wurde diese Klasse genauer untersucht. Was macht diese Klasse? Wie in den Überlegungen angegeben war dies die erste Fragestellung. Bei der Klasse handelt es sich um ein Daten Zugriffs Objekt. Das bedeutet das diese Klasse für die Kommunikation zwischen Datenbank und Applikation zuständig ist. Als Antwort können wir folgende Aussagen treffen. Die Klasse DAOCurrency ist für das speichern von Kurswerten zuständig. Die Klasse ist für das holen von Kurswerten zuständig. Die Klasse ist für das holen von Historie-Daten zuständig. Die Klasse führt Berechnungen in den Historie-Daten durch. Wir haben hier also auf die Frage 4 Antworten. Das würde gegen das Verantwortlichkeitsprinzip verstossen. Man kann also sagen das in diesem Fall unsere Annahme bestätigt worden ist. Als nächstes versuchen wir einen Kreis zu bilden. Dafür wurde die Python Funktion angewendet. Diese findet genau einen Kreis. Kreise welche mit inneren Klassen gefunden werden haben wir bewusst ignoriert. Den gefundenen Kreis haben wir uns genau angeschaut. Es ist so, dass die Klasse DAOCurrency die Klasse Tool verwendet und die Klasse Tool die Klasse DAOCurrency verwendet. Wenn wir in den Quellcode schauen so sehen wir das der Aufruf in der Klasse DAOCurrency durchaus sinnvoll ist. Der Aufruf in Tools jedoch völlig fehl am Platz ist. Nach Rücksprache mit den beteiligten Personen hat sich herausgestellt das diese Funktion am Ende des Projektes noch schnell implementiert wurde. Hier handelt es sich also tatsächlich um einen Fehler, welcher bei der Implementierung begangen wurde. Als nächstes wurde die Netzwerkdichte berechnet. Diese berechnet sich wie folgt.

Wie oben angenommen sind wir davon ausgegangen das eine niedrige Dichte ein Indikator für gutes Design ist. Wenn wir weiter unsere Annahme nehmen das 4 der maximal ausgehende Grad eines Knotens ist so ergibt sich daraus

Kmax = maximal Anzahl Kanten, wenn Annahme 1 stimmen soll.

Das heisst um unserer Annahme 1 nicht zu wiedersprechen darf die Netzwerkdichte nie grösser als 0.09 sein. Eine genaue Zahl für die maximale Netzwerkdichte als Indikator müsste noch festgelegt werden. Hier führe ich die beiden höchsten Ergebnisse bei der Berechnung der Betweenness Centrylity auf. DAOCurrency mit 14 und CurrencyLoader mit 7. In der DAOCurrency Klasse befindet sich bei Analyse des Codes tatsächlich viel Logik. Es macht also Sinn sich diese Klasse in der Entwicklung genauer anzuschauen. Allerdings sei hier angemerkt das schon bei der Überprüfung des Ausgangsgrades ein Fehler im Design aufgezeigt worden ist. Um die Betweenness Centrality also genau zu untersuchen sollten zuerst diese Fehler behoben werden. Bei der Klasse auf Rang 2 sieht dies anders aus. Es handelt sich zwar um eine Klasse, welche mit Threads arbeitet sie ist jedoch sehr klein. Eine genauere Beobachtung erscheint hier überflüssig.

Screenshot aus Excel mit allen durchgeführten Berechnungen
Screenshot aus Excel mit allen durchgeführten Berechnungen

 

Wie in Abbildung 4 zu sehen wurde eine Vielzahl weiterer Berechnungen durchgeführt. Bei Analyse der Ergebnisse wurden jedoch keine markanten Besonderheiten mehr gefunden, welche einen Einfluss auf die Softwareentwicklung haben könnten. Eventuell könnte es, mit weiteren Daten, möglich sein eine Klassifizierung der Daten vorzunehmen. Dies war in dieser Arbeit wegen fehlender Daten nicht möglich. 


Ausblick

Um die Studie abzuschliessen müssten die Erkenntnisse und Versuche auch auf anderen Projekten angewendet werden. Können wir die Ergebnisse auch auf anderen Projekten reproduzieren so wäre dies ein Indiz dafür das sich unsere Annahme bestätigt. Für die Zukunft müssten die Möglichkeiten der Analyse weiter ausgebaut werden. Im nächsten Schritt wäre eine Einteilung des Graphen in Cluster möglich. Packages werden gebildet um Klassen, welche zusammengehören zu Bündeln. Wäre es möglich durch das berechnen Klassen zu finden welche sich in den falschen Packages befinden. Dafür müsste man den Graphen um Packages erweitern oder einen zweiten Graphen mit der Benutzung von Packages aufbauen. Falls sich die Thesen dann immer noch bestätigen wäre eine nächste Möglichkeit eine Automatisierung der Graph - Erstellung. Weiter müssten die Ergebnisse, welche in den zusätzlichen Analysen getroffen haben überprüft werden. Gerade im Bezug auf die Messzahlen wären Ergebnisse aus grösseren Projekten nötig. Hier konnte im Rahmen der Arbeit kein klares Ergebnis erzielt werden.

Fazit

Im Rahmen dieser Arbeit konnten aufgezeigt werden das es durchaus möglich ist mit Graph Analyse Fehler im Design aufzudecken. Ob dies auf andere Projekte angewendet werden kann konnte im Rahmen dieser Arbeit nicht geprüft werden. Es ist jedoch damit zu rechnen das dies ebenfalls zutrifft. Gerade die Bestimmung ab welchen Grad eine Klasse einem Review unterzogen werden sollte müsste in vielen weiteren Versuchen geprüft werden. Können aus dieser Analyse sinnvolle Informationen für die Softwareentwicklung gewonnen werden. Meine Antwort lautet ja. Wenn es Möglich ist schon in der Konzeptionsphase Design, - und Architekturfehler aufzudecken sollte diese genutzt werden. Gerade ein fehlerhaftes Design kann in der Softwareentwicklung zu erheblichen Problemen bezüglich der Erweiterbarkeit führen. Ausserdem erschwert ein nicht gut konzipierter Aufbau die Integration von neuen Mitarbeitern in einem Projekt. Natürlich müssen vor einer endgültigen Aussage noch weitere Projekte überprüft werden und eine Verifizierung der Ergebnisse durchgeführt werden. Das aus den Statistiken und Messzahlen so wenig Informationen gezogen werden konnten war so nicht erwartet. Hier hat sich der Autor klarere Erkenntnisse erhofft.

Kommentar einfügen: