Abbau von Abhängigkeitszyklen in der Softwareentwicklung
Ein Blick darauf, wie Entwickler mit Abhängigkeitszyklen im Code umgehen.
― 6 min Lesedauer
Inhaltsverzeichnis
In der Softwareentwicklung ist es echt wichtig, Code zu schreiben, der gut funktioniert und leicht zu warten ist. Ein grosses Problem, mit dem Entwickler kämpfen, sind sogenannte Abhängigkeitszyklen. Das passiert, wenn zwei oder mehr Teile der Software sich gegenseitig abhängig machen, was es schwer macht, den Code zu ändern oder zu testen. Wenn diese Zyklen zu oft auftauchen, kann das die Software unordentlich und fehleranfällig machen.
Es gibt zwar Tools, die helfen, diese Zyklen zu finden, aber wir wissen immer noch nicht viel darüber, wie Entwickler sie im echten Leben beheben. Dieser Artikel schaut sich an, wie Entwickler diese Abhängigkeitszyklen angehen, mit Fokus auf die Muster, die sie verwenden, und die häufigen Fehler, die sie machen. Durch das Verständnis dieser Muster können wir Entwicklern helfen, besser mit diesen Situationen umzugehen.
Die Herausforderung der Abhängigkeitszyklen
Abhängigkeitszyklen sind ein häufiges Problem in Software. Sie entstehen, wenn zwei oder mehr Objekte oder Klassen sich gegenseitig aufrufen, was eine Schleife bildet. Das kann den Code schwer verständlich und änderbar machen, weil Entwickler sich oft nicht sicher sind, welcher Teil was macht. Ausserdem kann es die Wiederverwendbarkeit oder Testbarkeit des Codes einschränken. Wenn diese Zyklen in einem Programm wachsen, können sie ein verworrenes Netz bilden, das schwer zu bearbeiten ist und eher ausfällt.
Was wir gemacht haben
Um zu verstehen, wie Entwickler diese Probleme lösen, haben wir uns 38 Open-Source-Softwareprojekte genauer angeschaut. Unser Ziel war es zu sehen, wie Entwickler erfolgreich diese Zyklen zwischen zwei Klassen entwirren und welche Muster sie dabei verwenden. Wir haben viele Änderungen in den Projekten analysiert, um gemeinsame Strategien und Fehler zu identifizieren.
Ergebnisse
Aus unserer Forschung haben wir fünf häufige Muster gefunden, die Entwickler nutzen, um Abhängigkeitszyklen zwischen zwei Klassen zu beheben:
Nicht genutzten Code entfernen: Dabei löschen Entwickler alten oder unnötigen Code, der zum Zyklus beiträgt. Das war das häufigste Muster, das wir gefunden haben.
Code zwischen Klassen verschieben: Manchmal können Entwickler Code von einer Klasse in eine andere verschieben, um den Zyklus zu durchbrechen. Das kann entweder das Verschieben von Code von einer zyklischen Klasse zur anderen sein oder das Verschieben in eine neue dritte Klasse.
Aufrufketten kürzen: In manchen Fällen finden Entwickler einen Weg, andere Klassen direkt aufzurufen, statt durch den Zyklus zu gehen. Das vereinfacht die Interaktion zwischen den Klassen.
Eingebaute Funktionen nutzen: Entwickler können auch Funktionen in Programmiersprachen oder Frameworks nutzen, anstatt die Interaktionen manuell zu codieren, was helfen kann, die Abhängigkeit zu reduzieren.
Komplexes Refactoring: In manchen Fällen sind detailliertere Änderungen notwendig, die ein grösseres architektonisches Refactoring erfordern, was bedeutende Umschreibungen oder Umorganisation des Codes einschliesst.
Wir haben auch bemerkt, dass diese Muster oft mit der Art und Weise zusammenhängen, wie die abhängigen Klassen entworfen sind und wie sie mit anderen Klassen interagieren.
Häufige Fehler
Während sie versuchen, diese Zyklen zu beheben, machen Entwickler manchmal Fehler. Wir haben drei Hauptarten von Fehlern identifiziert, die häufig auftreten:
Zyklen verschieben zu einer Elternklasse: Manchmal verschieben Entwickler die Abhängigkeit nicht, sondern verlagern sie auf eine Elternklasse, was neue Zyklen entstehen lassen kann.
Zyklen verschieben zu Kindklassen: Ähnlich wie beim vorherigen Problem können Zyklen versehentlich auf abhängige Kindklassen verschoben werden, was zu einem neuen Zyklus führt, anstatt den vorherigen zu lösen.
Zyklen verschieben zu einer dritten Klasse: In einigen Situationen kann es wie eine Lösung erscheinen, Code in eine neue Klasse zu verschieben. Wenn das jedoch falsch gemacht wird, kann das einfach einen weiteren Zyklus erzeugen.
Diese Fehler zu erkennen, kann Entwicklern helfen, sie zu vermeiden, wenn sie mit Abhängigkeitszyklen umgehen.
Der Ansatz zur Musterfindung
Um zu untersuchen, wie Entwickler mit diesen Zyklen umgehen, haben wir zuerst Daten aus verschiedenen Projekten gesammelt. Das beinhaltete, den Quellcode und die Abhängigkeitsgraphen zu betrachten – im Grunde genommen Karten, die zeigen, wie verschiedene Teile der Software miteinander verbunden sind.
Wir folgten einem strengen Prozess, um festzustellen, ob ein Entwickler einen Zyklus erfolgreich behoben hat. Wir schauten uns die Änderungen im Code an und identifizierten spezifische Aktionen, die entweder zum Erfolg oder Misserfolg bei der Behebung des Zyklus führten.
Ergebnisse der Studie
Nach der Analyse der Daten entdeckten wir einige wichtige Ergebnisse über die Muster und Strategien, die Entwickler verwenden:
Wiederkehr der Muster: Wir bemerkten, dass eine grosse Mehrheit der Änderungen konsistent den fünf Mustern folgte, die wir identifiziert haben. Das zeigt, dass es effektive Strategien gibt, die viele Entwickler nutzen, um Abhängigkeitszyklen zu lösen.
Design-Kontext zählt: Die gewählten Muster hängen oft nicht nur vom Zyklus selbst ab, sondern auch davon, wie die Klassen mit umgebenden Klassen interagieren. Der Kontext, in dem Klassen verwendet werden, kann die Wahrscheinlichkeit beeinflussen, dass bestimmte Muster gewählt werden.
Erfolgs- und Misserfolgsraten: Wir fanden heraus, dass, während die meisten Entwickler Zyklen erfolgreich entwirren können, ein kleiner Prozentsatz es nicht schafft, dies korrekt zu tun. Das deutet darauf hin, dass trotz der Verwendung derselben Muster die Ergebnisse je nach Kontext und speziellen Implementierungen variieren können.
Praktische Implikationen
Diese Erkenntnisse können helfen, die Praktiken in der Softwareentwicklung zu verbessern. Die gängigen Muster können als Leitfaden für Entwickler geteilt werden, die mit ähnlichen Herausforderungen konfrontiert sind. Ausserdem kann das Bewusstsein für die Fehler zu besseren Entscheidungen führen, wenn Entwickler Code refaktorisieren.
Für Studenten und neue Entwickler können diese Einblicke als Lernmaterial dienen, um über die Komplexitäten von Abhängigkeitszyklen und den effektiven Umgang damit zu lernen.
Fazit und zukünftige Arbeiten
Zusammenfassend haben wir die Muster und häufigen Fallstricke aufgedeckt, die mit der Verwaltung von Abhängigkeitszyklen zwischen zwei Klassen in Softwareprojekten verbunden sind. Das Verständnis dieser Aspekte kann Entwicklern helfen, ihre Herangehensweise an die Wartung ihrer Codebasen zu verfeinern.
Unsere nächsten Schritte beinhalten, weitere Projekte zu untersuchen und zu schauen, wie sich diese Muster in verschiedenen Programmiersprachen und Frameworks bewähren. Durch die Erweiterung unserer Forschung wollen wir umfassendere Richtlinien entwickeln, die Entwicklern helfen, Abhängigkeitszyklen effektiv und effizient zu lösen.
Diese Arbeit hebt die Bedeutung der fortlaufenden Erforschung in der Softwaretechnik hervor, um die Codepraktiken zu verbessern und qualitativ hochwertige Softwaresysteme aufrechtzuerhalten.
Titel: An Empirical Study of Untangling Patterns of Two-Class Dependency Cycles
Zusammenfassung: Dependency cycles pose a significant challenge to software quality and maintainability. However, there is limited understanding of how practitioners resolve dependency cycles in real-world scenarios. This paper presents an empirical study investigating the recurring patterns employed by software developers to resolve dependency cycles between two classes in practice. We analyzed the data from 38 open-source projects across different domains and manually inspected hundreds of cycle untangling cases. Our findings reveal that developers tend to employ five recurring patterns to address dependency cycles. The chosen patterns are not only determined by dependency relations between cyclic classes, but also highly related to their design context, i.e., how cyclic classes depend on or are depended by their neighbor classes. Through this empirical study, we also discovered three common counterintuitive solutions developers usually adopted during cycles' handling. These recurring patterns and common counterintuitive solutions observed in dependency cycles' practice can serve as a taxonomy to improve developers' awareness and also be used as learning materials for students in software engineering and inexperienced developers. Our results also suggest that, in addition to considering the internal structure of dependency cycles, automatic tools need to consider the design context of cycles to provide better support for refactoring dependency cycles.
Autoren: Qiong Feng, Shuwen Liu, Huan Ji, Xiaotian Ma, Peng Liang
Letzte Aktualisierung: 2023-12-17 00:00:00
Sprache: English
Quell-URL: https://arxiv.org/abs/2306.10599
Quell-PDF: https://arxiv.org/pdf/2306.10599
Lizenz: https://creativecommons.org/licenses/by/4.0/
Änderungen: Diese Zusammenfassung wurde mit Unterstützung von AI erstellt und kann Ungenauigkeiten enthalten. Genaue Informationen entnehmen Sie bitte den hier verlinkten Originaldokumenten.
Vielen Dank an arxiv für die Nutzung seiner Open-Access-Interoperabilität.
Referenz Links
- https://github.com/apache/wicket/commit/f96f99e
- https://github.com/apache/wicket/commit/763dcc3
- https://github.com/apache/commons-math/commit/3a7d733
- https://issues.apache.org/jira/browse/MATH-689
- https://www.designite-tools.com
- https://structure101.org
- https://www.sonarqube.org
- https://github.com/multilang-depends/depends
- https://archdia.com
- https://github.com/apache/wicket/commit/dec227e
- https://github.com/apache/ant/commit/ca5799f
- https://github.com/apache/hbase/commit/dd70cc3
- https://github.com/apache/ant/commit/284e790
- https://github.com/apache/wicket/commit/829caa5
- https://github.com/apache/ambari/commit/73819ca