Wir haben unsere DETANGLE Analyse Suite zur Bewertung der Qualität und weiterer Risiken bzgl. Wartbarkeit und Erweiterbarkeit auf die Corona-Warn-App für iOS und Android angewendet. Bis Version 1.11 haben wir ermittelt, wie sich Features und Bugs im Code wiederfinden, haben die Architektur-Qualität gemessen, die Technischen Schulden geschätzt und die Risiken der Wissensverteilung analysiert.
Vorab möchten wir in aller Deutlichkeit unsere Anerkennung aussprechen, welche Leistung mit der Erstellung der Corona-Warn-App erbracht wurde. Das Gesamtsystem wurde unter hoher Medienaufmerksamkeit, engem Zeitrahmen, politischem Druck und sehr hohen Datenschutzanforderungen entwickelt. Wir möchten mit diesem Blog nun auf Qualitätsaspekte und Risiken hinweisen, die nach einem anfänglichen Entwicklungsstadium aus unserer Sicht Beachtung finden sollten.
Obwohl die aktuellen Code-Qualitätsmetriken aus SonarQube, dem verwendeten Tool zur Code-Analyse bei der Entwicklung der Corona-Warn-App, immer wieder bis Version 1.11 ein sehr gutes Rating für beide Apps aufzeigen, gibt es dennoch auffallende Findings, welche diesem guten Bild in Teilen widersprechen. In diesem Post gehen wir auf die Ergebnisse zur iOS-Version der App ein.
Mehr zur Corona-Warn-App im zweiten Teil des Blogs: (Collective) Code Ownership neugedacht – Über Risiken der Wissensverteilung am Beispiel der Corona-Warn-App
Mehr zu Technischen Schulden gibt’s hier: Technische Schulden erklärt am Beispiel eines beinahe gescheiterten Videospiels
Bei der Betrachtung der Aufwandsverteilung für Features, Bugs und sonstige Arbeiten fällt auf, dass in Q4/2020 und in Jan/2021 der aufgebrachte Entwicklungsaufwand für Features in 3 von 4 Monaten (inkl. Januar 2021) unter den Wert von 60% des Gesamtaufwandes gefallen ist. Umgekehrt ist der Wartungsaufwand in Form von Bug-Fixing in 2 von 4 Monaten (inkl. Januar 2021) auf 20% des Gesamtaufwandes gestiegen.
Abb. 1: Monate Juli 2020 – Jan 2021 Links: Anteil Bug-Fixing-Aufwand am Gesamtaufwand; Rechts: Anteil Feature-Entwicklungsaufwand am Gesamtaufwand
Das sind noch keine äußerst besorgniserregenden Aufwandsverteilungen, aber sie könnten Frühindikatoren für eine Verstärkung des Trends eines sinkenden Feature-Durchsatzes darstellen.
Erläuterung der Messung des Entwicklungsaufwandes siehe [2].
Anhand der DETANGLE Architektur-Qualitätsmetriken ist aber am Ausmaß der vorgefundenen Feature-Kopplung und Feature-Kohäsion im Code erkennbar, unter welchem Zeitdruck die ersten Versionen der Apps entwickelt werden mussten. In den Releases über die Sommermonate im dritten Quartal des Jahres 2020 war zwar ein Abnehmen der Technischen Schulden, wie wir sie messen, erkennbar. Aber ab Version 1.7 und bis Version 1.11 wurde unserer Meinung nach im vierten Quartal des Jahres 2020 wieder ein Signal-Wert des gemessenen Feature-Debt-Index erreicht.
Abb. 2: Quartal 2, 2020 – Quartal 4,2020 Links: Feature-Debt-Index (FDI) über die 3 Quartale des Jahres 2020
Erläuterungen zur Feature-Kopplung, Feature-Kohäsion und des Feature-Debt-Index finden sich unter [1] und [3].
Es besteht z.B. ein steigender Handlungsbedarf bezogen auf die Architektur-Qualität der Code-Module, wo folgende Features umgesetzt wurden:
Abb. 3: Kopplung der Risk Calculation Features (1472, 1457, 1518, 1541, 1550) zu anderen Features (nicht-nummerierte Kreisbögen) aus 4. Quartal, 2020.
Abb. 3 zeigt auf einem Kreis alle GitHub Issues/PRs aus dem 4. Quartal des Jahres 2020 als einzelne Kreisbögen. Eine Verbindung zwischen zwei Bögen stellt die Kopplung zwischen zwei Features dar. Die nummerierten Kreisbögen auf der rechten Seite repräsentieren die Features zur genaueren Risikoberechnung aus V1.9. Die Verbindungen legen eindeutig nahe, dass diese Features nicht nur untereinander, sondern zu vielen anderen umgesetzten Features aus dem 4. Quartal verwoben sind. Je umfangreicher die Kopplung unter nicht-verwandten Features, desto schwieriger wird es, neue Features ohne unbeabsichtigte Seiteneffekte zur Codebasis hinzuzufügen.
Aus unserer Sicht ist damit zu rechnen, dass weitere Arten der Risikoberechnungen wie potentiell bei Besuchen von Restaurants, die einen QR-Code zum Einscannen bereitstellen, in die App Eingang finden werden. Was aber wiederum durch die nachlassende Erweiterbarkeit dieser Features aus V1.9 oder Ergänzbarkeit dieses Codes um neue Features ohne ein Refactoring zu stark ansteigendem Wartungsaufwand in Form von Bugs führen dürfte.
Die oben genannten Feature-Cluster konnten wir den jeweiligen Code-Bereichen mit einem erhöhten Feature-Debt-Index in Abb. 4 zuordnen.
Abb 4. Quellcode-Verzeichnisse. Feature-Debt-Index auf der x-Achse; Committer-Friction-Index auf der y-Achse (hier nicht relevant)
Dabei handelt es sich im Wesentlichen um folgende Quellcode-Verzeichnisse:
src/xcode/ENA/ENA/Source/Services/Exposure Submission
src/xcode/ENA/ENA/Source/Scenes/Exposure Submission
src/xcode/ENA/ENA/Source/Scenes/Exposure Submission/View
src/xcode/ENA/ENA/Source/Services/Exposure Transaction
src/xcode/ENA/ENA/Source/Models/Exposure
src/xcode/ENA/ENA/Source/Services/Risk/Provider
src/xcode/ENA/ENA/Source/Services/Risk/Calculation
In Abbildung 4 werden die Werte des Feature-Debt-Index für Verzeichnisse auf der x-Achse dargestellt (die y-Werte repräsentieren den Committer-Friction-Index (CFI), der erst im zweiten Blog zur Sprache kommen wird). Die Lines of Code der Verzeichnisse kommen durch die Größe der Blasen zum Ausdruck. Die oben genannten Exposure Submission Verzeichnisse fallen unter die größten roten Verzeichnisse, während wiederum die Risk Verzeichnisse die größten beiden gelben Blasen darstellen. Diese genannten Verzeichnisse machen ca. 20% der Codebasis aus und sind in Q4/2020 um 50% bis 150% jeweils angewachsen.
Die Quellcode-Dokumentation des gesamten Code-Basis ist in den letzten drei Monaten bis Ende Jan 2021 auf einen niedrigen Wert von 9% (an Kommentaren in Quelldateien im Vergleich zu deren nicht-leeren Zeilen Quellcode) gefallen. Insbesondere manche der oben als kritisch erachteten Quellcode-Verzeichnisse zeigen kritische Werte von 9% auf. Es liegt also eine Kombination von architekturellen Schwächen und mangelnder Verständlichkeit des Codes aufgrund geringer Code-Dokumentation in diesen Verzeichnissen vor.
Konsequenzen in den o.g. Verzeichnissen werden bereits ersichtlich in:
1. Einem nötigen, aber machbaren Abbau der Technische Schulden:
Der aktuelle Wartungsaufwand ist bereits um einiges höher als die Technischen Schulden, worunter wir den geschätzten Aufwand zur Verbesserung der Architektur-Qualität verstehen. Es lohnt sich daher, hier mit einem Refactoring anzusetzen, zumal der Verbesserungsaufwand gemessen an dem pro Monat umgerechneten Gesamtaufwand des letzten Quartals Q4/2020 ca. einer Mannwoche entsprechen würde.
2. Einem aktuell hohen Feature-Effort-Effectiveness-Index:
Der Aufwand zur Entwicklung neuer Features geht bereits mit einem erhöhten Refactoring-Aufwand zu deren Umsetzung einher.
Einige der entsprechenden test-Verzeichnisse zu den obigen Quellcode-Verzeichnissen weisen auch kritische Feature-Debt-Index Werte auf. D.h. sie sind bezüglich der umgesetzten Features genauso verwoben wie der zu testende Code, so dass das Hinzufügen von Tests für neue Features auch mit Mehraufwand im Sinne von Umarbeiten verbunden sein dürfte.
Aufgrund des alleinigen Zugangs zu den GitHub-Projekten und ohne Zugriff auf die Tickets des nicht-öffentlichen SAP JIRA Issue Trackers können wir valide Ergebnisse nur für die iOS App anführen.
Die Gründe dafür werden unten genauer beleuchtet. Erschwerend kommt hinzu, dass die Erfassung von Bugs, Features und deren Referenzierung bei der Entwicklung selbst innerhalb der iOS- und Android-App im Laufe des Projektes über die Monate sehr unterschiedlich gehandhabt wurde.
Um unsere Findings zur Corona-Warn-App-Entwicklung optimal für beide Apps nutzbar zu machen, müssten wir allerdings über die öffentlichen GitHub-Projekte hinaus ein Lesezugang zu den Tickets des nicht-öffentlichen SAP JIRA EXPOSUREAPP Projektes erhalten.
Wir möchten als letztes “Take-Away” einen Vorschlag machen. Es gibt 25 Millionen Nutzer der Apps. Das ist eine nicht zu unterschätzende Möglichkeit anonymisiert Rückmeldungen einzuholen; sei es zur Meldung von Fehlern oder für freiwillige Umfragen im Rahmen der App-Nutzung mit Feedback zu potentiell neuen (oder laufenden) Features. Selbst die Meinung zu Feature-Optionen könnte man damit erfragen, um darauf aufbauend Entscheidungen für die Weiterentwicklung zu treffen.
Aufgrund des Umfangs der Analysedaten war es uns in diesem Teil nicht möglich auf folgende Fragen eingehen:
Der zweite Teil der Blogserie wird Antworten darauf suchen und auf die Risiken in der Wissensverteilung bei der Entwicklung der Corona iOS App eingehen.
In der Software Entwicklung ist es gang und gäbe, Softwarequalität mittels Metriken der Code-Qualität zu messen. SonarQube hat sich unter Entwicklern fast schon als “Industriestandard” etabliert, um beispielsweise potentielle Bugs oder Code Smells, also schlechte Codestellen, im Code ausfindig zu machen. Das Tool bietet auch eine Schätzung der Technischen Schulden gemessen am Aufwand zur Beseitigung der besagten Codestellen an.
SonarQube wurde daher auch bei der Entwicklung der beiden Corona-Warn-Apps durchgehend bei der gesamten Entwicklung eingesetzt. Die Metriken von SonarQube zur Code-Qualität deuten für die beiden Corona-Warn-Apps durchgehend sehr gute Ratings an.
Ganz konkret möchte man wissen, inwieweit die Architektur der beiden Apps die Entwicklung neuer Features oder die Erweiterung der bestehenden Funktionalität ermöglicht. Aktuelle Ansätze bewerten eine gute Architekturqualität oftmals entlang gewisser Muster zu strukturellen Abhängigkeitsgraphen wie Aufruf-Hierarchien und -Zyklen zwischen Code-Modulen. Der Aussagewert dieser Bewertungen ist nur bedingt relevant, wenn es um die Fragestellung geht, wie weit die aktuelle Architektur die Entwicklung neuer Features begünstigt [4].
Wir haben daher mittels der DETANGLE Analyse Suite die Entwicklung der Apps anhand der Historie der GitHub Code-Repositories und der GitHub Issues und Pull Requests bezüglich der Architektur-Qualität analysiert und daraus priorisierte Handlungsempfehlungen abgeleitet, um die Wartungskosten in Form von Bug-Fixing aufgrund Technischer Schulden in Schach zu halten und die Feature-Erweiterbarkeit der iOS-App in bestimmten (aus unserer Sicht) künftig relevanten Code-Bereichen wiederherzustellen.
Die Erfassung von Bugs, Features und deren Referenzierung bei der Entwicklung des Codes wurde im Laufe des Projektes mittels GitHub Issues, GitHub Pull Requests (PRs) und JIRA Tickets des SAP-internen JIRA EXPOSUREAPP Projektes über verschiedene Zeitperioden unterschiedlich gehandhabt. Dabei wurde, unseres Erachtens, nach dem Umstieg als öffentliches Github Projekt das technische Koordinationsmittel der Pull Requests unter den Entwicklern im falschen Sinne zur Erfassung von Features und Bugs verwendet. Pull Requests sind hingegen ein Mittel zur Organisation gemeinsamer Codier-Arbeiten im Repository und sollten nicht fürs Requirements-Engineering verwendet werden. [5]
Die folgende Tabelle fasst die Facetten des unterschiedlichen Vorgehens bei der Entwicklung der iOS App über die Monate bis Jan 2021 zusammen.
Unser Vorgehen zum Bestimmen von Features und Bugs (und der auf sie zurückgehenden Änderungen im Code) bestand nun darin, aus Labels und Keywords von Github PRs und Issues deren Typ wie “feature”, “enhancement” und “bug” abzuleiten. Die Details dazu finden sich wiederum im Appendix.
Die Bestimmung der Github PR/Issue Typen hat sich bei der Corona Android App nochmals schwieriger gestaltet, da wesentlich weniger PRs mit Labels und identifizierbaren Keywords vorhanden sind, was vor allem auf die Monate des Jahres 2020 bis September zutrifft. Das ist auch am prozentualen Anteil des durch DETANGLE erfassten Entwicklungsaufwandes für features, enhancements und bugs zu erkennen. Für die iOS App konnten über 70% des durch DETANGLE gemessenen Entwicklungsaufwandes den besagten Typen zugeordnet werden, während es bei der Android Entwicklung knapp 50% des Entwicklungsaufwandes ausmachen. Daher können wir nur valide Aussagen für die Corona iOS App Entwicklung beanspruchen.
Unabhängig von den Umständen der Analyse ist zu hoffen, dass sich das im 4. Quartal abzeichnende Vorgehen für die weitere Versionsentwicklung etabliert. Dabei weisen die Vorgehensweisen bei der iOS und der Android App noch immer gewisse Unterschiede aus, auf die wir hier nicht eingehen. Für beide Vorgehensweisen gilt aber, dass die Verwendung des nicht-öffentlichen SAP JIRA Ticketingsystems die weitere Entwicklung der App in gewissem Grade doch intransparent erscheinen lässt.
Erfreulicherweise lassen sich Schlüsse zur Architektur-Qualität bereits durch die reine Betrachtung der Features einer Version ziehen, ohne als Leser über Kenntnisse des Codes verfügen zu müssen. Durche eine geeignete Visualisierung der Feature-Kopplung lässt sich feststellen, inwieweit verwandte Features die gleichen Code-Stellen betreffen oder ob sie bereits über die Codebasis streuen und über eine hohe Schnittmenge zu den Code-Stellen anderer “fremder” Features im Code verwoben sind.
Damit eröffnet sich der Raum für Diskussionen zwischen den Produkt- bzw. Projektverantwortlichen und den Technikern, den Architekten bzw. den Entwicklern über die Qualität der Architektur in Verbindung mit der künftigen Relevanz von Features. Falls für bestimmte Features (z.B. die Risikoberechnung) mit Erweiterungen oder Variationen zu rechnen ist, deren Feature-Kopplung über die Code-Basis hinweg ohne Durchsicht des Codes ersichtlich hoch ist, kann man schnell und fundiert die Entscheidung zur Ergreifung von priorisierten Refactoring-Maßnahmen des Codes hinter diesen Features gemeinsam mit allen Stakeholdern treffen.
Im Folgenden gehen wir exemplarisch den verwandten Features für die jeweiligen Versionen V1.7 bis V1.11 nach. Dabei fangen wir aus “didaktischen” Gründen mit V1.10 an, kommen auf V1.11 zurück und gehen dann zu V1.9 bis V1.7 über.
Das bestimmende Feature-Set der Version 1.10 [8] war das Kontakttagebuch, worin der Benutzer seine Kontakte zu Personen und den Treffpunkt festhalten und über zwei Wochen zurückverfolgen kann.
GitHub PRs, die wir als Features (oder Teilarbeiten davon) der Version zuordnen konnten (Stichwort: “diary”, “legal” und “journal”):
Das folgende Diagramm wirft einen Blick auf diese Features. Jeder Bogen entlang des Kreises stellt ein Feature (=GitHub Issue/PR) dar. Die Breite eines Bogens bildet den erbrachten Feature-Aufwand ab.
Abb. 5: Rein lokale Feature-Kopplung in V1.10
Es lassen sich visuell bereits folgende Schlüsse ziehen:
Das bestimmende Feature-Set der Version 1.11 [7] bestand in der Bereitstellung verschiedener vom Robert-Koch-Institut veröffentlichter bundesweiter Statistiken und deren Trends wie z.B. der Anzahl der Infizierten oder des R-Wertes.
GitHub PRs, die wir als Features (oder Teilarbeiten davon) der Version zuordnen konnten:
Im Vergleich zu Version 1.10 handelt es sich bei diesem Feature-Set nicht um ein rein lokale Feature-Kopplung untereinander. Es ist eine gewisse, aber nicht übermäßige, Kopplung zu anderen nicht-verwandten Features erkennbar.
Fahren wir nun mit Version 1.9 fort, für die sich ein völlig neues Bild ergibt.
Version 1.9 [9] war bestimmt von der Berechnung einer genaueren Risikobewertung im Falle mehrerer “low-risk” Begegnungen. Des Weiteren wurde der Ablauf bei der Handhabung eines Testergebnisses verbessert. Die Github Issues/PRs zum ersten Feature-Set sind unter dem Stichwort “risk calculation”, die zum zweiten unter dem Stichwort “submission” und “result” aufgelistet.
Stichwort “risk calculation”:
Stichwort “submission” und “result”:
Abbildung 7 erfasst nun das Iris-Diagramm zum ersten Feature-Set der genaueren Risikobewertung:
Abb. 7: Breitgestreute Feature-Kopplung der Risikoberechnung in V1.9
Es ergibt sich ein scharfer Kontrast zum Bild zur Version 1.10 und 1.11. Rein visuell lässt sich bereits folgender Schluss ziehen: alle Features (nummerierte Bögen) des Feature-Sets sind breit mit vielen anderen nicht-verwandten Features (nicht-nummerierte Bögen) global über die Codebasis gekoppelt, obwohl ihr Gesamt-Aufwand im mittleren Bereich anzusiedeln wäre.
Abb. 8: Stark-gestreute Feature-Kopplung bzgl. Corona-Testablauf in V1.9
Ein ähnliches, noch verschärftes, Bild der lokalen UND globalen Feature-Kopplung (bei einem hohen Gesamtaufwand) ergibt sich beim zweiten Feature-Set des verbesserten Ablaufs zur Handhabung durch den User im Falle eines Corona-Testergebnisses.
Als letztes schauen wir uns noch an, welches Bild sich in Version 1.7 ergibt.
In Version 1.7 [10] (Version 1.8 konnten wir übrigens nicht identifizieren) sind das Feature-Set der mehrmaligen Risikoüberprüfung pro Tag und die dahinterliegenden Github Issues/PRs, die unter den Stichworten “package”, “download” und “cycle” zu finden sind, interessant.
Stichwort “package“ und “download”:
Abbildung 9 zeigt eine mittel-ausgeprägte Feature-Kopplung des Feature-Sets der mehrmaligen Risikoüberprüfung zu anderen nicht-verwandten Features.
Nimmt man jedoch das Feature-Set zur genaueren Risikobewertung aus Version 1.9 hinzu, so verschmelzen Abbildung 7 und Abbildung 9 zu einem Bild in Abbildung 10. Daraus lässt sich folgern, dass diese beiden Feature-Sets aus den beiden unterschiedlichen Versionen, die beide den Code-Bereich der Risikoberechnung betreffen, sehr stark untereinander gekoppelt sind.
Folgende Zusammenhänge noch einmal zur Erinnerung:
Der nächste Schritt besteht nun darin, diese Quellcode-Verzeichnisse und Quellcode-Dateien genauer zu untersuchen, um daraus Handlungsempfehlungen abzuleiten.
Die untere Tabelle 1 führt die Quellcode-Verzeichnisse mit kritischen Feature-Debt-Index (FDI) Werten auf. Sie nimmt Bezug auf Abbildung 4 und stellt die gleiche Information in Form quantifizierter Werte dar. Zur leichteren Vergleichbarkeit haben wir Abb. 4 hier nochmals vor der Tabelle aufgeführt.
Abb. 11 (wie Abb. 4): Quellcode-Verzeichnisse. Feature-Debt-Index auf der x-Achse; Committer-Friction-Index auf der y-Achse (hier nicht relevant)
Folder | FDI | +/- |
src/xcode/ENA/ENA/Source/Workers/Store | 19.31 | 637% |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission/ __tests__ |
13.91 | 833% |
src/xcode/ENA/ENA/Source/Services/Exposure Transaction | 13.66 | 570% |
src/xcode/ENA/ENA/Source/Scenes/ContactDiary/AddAndEditEntry | 12.75 | 0% |
src/xcode/ENA/ENA/Source/Services/Exposure Submission | 12.00 | 1000% |
src/xcode/ENA/ENA/Source/Scenes/ContactDiary/Day | 11.07 | 0% |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission | 10.56 | 195% |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission/ View |
10.34 | 583% |
src/xcode/ENA/ENA/Source/Scenes/ContactDiary/EditEntries | 9.76 | 0% |
src/xcode/ENA/ENA/Source/Services/__tests__/Mocks | 9.00 | 584% |
src/xcode/ENA/ENA/Source/Developer Menu/Features | 7.71 | 0% |
src/xcode/ENA/ENA/Source/Services/Exposure Transaction/__tests__ | 7.22 | 173% |
src/xcode/ENA/ENA/Source/Services/Risk/Provider | 6.80 | 189% |
src/xcode/ENA/ENA/Source/Services/DownloadedPackagesStore/ __tests__ |
6.64 | 0% |
src/xcode/ENA/ENA/Source/Services/Risk/Calculation | 6.50 | 735% |
src/xcode/ENA/ENA/Source/Models/Exposure | 5.88 | 0% |
src/xcode/ENA/ENA/Source/Scenes/Onboarding | 5.55 | 1374% |
src/xcode/ENA/ENA/Source/Scenes/ENSetting/EUSettings | 5.11 | 7965% |
src/xcode/ENA/ENA/Source/Scenes/ContactDiary/Info | 4.44 | 0% |
Tabelle 1: Feature-Debt-Index im 4. Quartal 2020
Gelb markierte Werte stellen einen Signal-Level dar, während rote Zahlen erkennbar machen, dass ein kritischer Wert erreicht wurde. Die in den Take-Aways bereits erwähnten Quellcode-Verzeichnisse sind in der Tabelle hervorgehoben. Das sind genau diejenigen Verzeichnisse, welche für die breite Feature-Kopplung der Feature-Sets zur Ansteckungs-Risikobewertung/-Kalkulation und der verbesserten Handhabung von Testergebnissen aus den Versionen 1.7 und 1.9 verantwortlich sind. Zudem ist erkennbar, dass einige der dazugehörigen Test-Verzeichnisse auch einen Signal- oder kritischen Level erreicht haben.
Außerdem fällt auf, dass auch einige ContactDiary Verzeichnisse mindestens Signal-Level erreicht haben. Im oberen Abschnitt zum Feature-Set Kontaktbuch der Version 1.10 wurde dargelegt, dass es sich dabei um eine lokale Kopplung dieser Features untereinander handelt. Das spiegelt sich hier wieder in den dazugehörigen Verzeichnissen. Diese lokale Kopplung kann bei der Berechnung des Feature-Debt-Index herausgerechnet werden. Wir haben es hier aber aus Gründen der Vollständigkeit und der Konsistenz der Aussagen unterlassen.
Was sind nun die Auswirkungen und Symptome dieser hohen Feature-Debt Werte? Eine leicht erkennbare Auswirkung kann man im Umfang des Wartungsaufwands in diesen Quellcode-Verzeichnissen ausmachen. Tabelle 2 listet den Bug-fixing Aufwand aus dem 4. Quartal des Jahres 2020 auf (sortiert nach Ausmaß in der Einheit cLOC, also changed Lines of Code, wie unter [2] beschrieben). Wiederum sind einige der erwähnten Exposure Submission Verzeichnisse und Risk Verzeichnisse am meisten vom Wartungsaufwand betroffen.
Folder | Defect Effort |
+/- % |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission/View | 3.96 K | 4.03 K |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission/ __tests__ |
2.13 K | 21.16 K |
src/xcode/ENA/ENA/Source/Services/Risk/Provider | 1.97 K | 528.00 |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission | 777.00 | 5.88 K |
src/xcode/ENA/ENA/Source/Scenes/Onboarding | 657.00 | 2.89 K |
src/xcode/ENA/ENA/Source/Services/__tests__ | 589.00 | 460.00 |
src/xcode/ENA/ENA/Source/Services/Risk/KeyPackageDownload | 240.00 | 0 |
src/xcode/ENA/ENA/Source/Scenes/OptionGroup/ DatePickerOption |
232.00 | 0 |
src/xcode/ENA/ENA/Source/Services/Risk/__tests__ | 219.00 | 812.00 |
src/xcode/ENA/ENA/Source/Services/Exposure Transaction/__tests__ | 189.00 | 626.00 |
src/xcode/ENA/ENA/Source/Services/Exposure Transaction | 176.00 | 58.00 |
src/xcode/ENA/ENA/Source/Client/HTTP Client | 171.00 | 800.00 |
src/xcode/ENA/ENA/Source/Scenes/ContactDiary/EditEntries | 161.00 | 0 |
src/xcode/ENA/ENA/Source/Developer Menu/Features | 155.00 | 0 |
src/xcode/ENA/ENA/Source/Models/Exposure | 155.00 | 63.00 |
src/xcode/ENA/ENA/Source/Scenes/DynamicTableViewController | 152.00 | 3.70 K |
src/xcode/ENA/ENA/Source/Models/Exposure/__tests__ | 147.00 | 568.00 |
src/xcode/ENA/ENA/Source/Developer Menu/Features/DMDeviceTimeCheck | 123.00 | 0 |
src/xcode/ENA/ENA/Source/Client/HTTP Client/__tests__ | 118.00 | 0 |
src/xcode/ENA/ENA/Source/Services/Risk/Calculation | 118.00 | 55.00 |
Tabelle 2: Defect-Effort im 4. Quartal 2020
Das Auftragen des Feature-Debt-Index auf der x-Achse und des Defect-Efforts als Bubble Size hilft in Abb. 12 das Ganze auch besser zu visualisieren. Man sieht, dass ein Zusammenhang zwischen Feature-Debt-Index und Defect-Effort besteht: je größer der Feature-Debt, desto größer der Bug-Fixing-Aufwand (als Bubble Size).
Idealerweise möchte man messen können, ob das Hinzufügen neuer Features schwerer fällt. Dafür einfach die Anzahl an Features pro Zeiteinheit (z.B. Quartal) zu messen, ergibt irreführende Werte, da der Aufwand pro Feature sehr variiert. Unserer Erfahrung nach gilt für Entwicklungsaufwände pro Feature eher die Pareto-Regel, dass ungefähr 80% des Aufwands für ca. 20% der Features aufgebraucht wird. Unter [4] und [11] haben wir einen Ansatz erläutert, wie man den Refactoring-Aufwand bei der Implementierung neuer Feature anteilig berechnen kann. Dabei spielt das Verhältnis von Aufwand zu dem Anteil des neu erstellten Codes für das Feature eine Rolle. Je mehr sich das Verhältnis vom Wert 1 in Richtung 2 oder höher bewegt, desto höher sind die Refactoringanteile. Das gilt für einzelne Features aber auch für Quellcode-Verzeichnisse und -Dateien.
Tabelle 3 führt diese Zahlen für Quellcode-Verzeichnisse auf. Wir nennen das besagte Verhältnis von Aufwand zu neu erstelltem Code für Features den Feature-Effort-Effectiveness-Index (FEE). Dabei wird erneut ersichtlich, dass hinsichtlich dieser Kennzahl die gleichen Quellcode-Verzeichnisse wie bzgl. Defect-Effort einen FEE Wert größer als 1.5 aufweisen.
Folder | FEE | New Code |
src/xcode/ENA/ENA/Source/Scenes/ContactDiary/Store | 1.27 | 4.89 K |
src/xcode/ENA/ENA/Source/Services/Risk/Provider | 1.68 | 3.50 K |
src/xcode/ENA/ENA/Source/Services/Risk/Calculation | 1.25 | 3.39 K |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission/ View |
1.51 | 3.31 K |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission/ __tests__ |
1.78 | 2.07 K |
src/xcode/ENA/ENA/Source/Scenes/ContactDiary/Day | 1.10 | 2.01 K |
src/xcode/ENA/ENA/Source/Scenes/Home/Cells | 1.17 | 1.87 K |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission | 1.79 | 1.68 K |
src/xcode/ENA/ENA/Source/Scenes/ContactDiary/AddAndEditEntry | 1.14 | 1.22 K |
src/xcode/ENA/ENA/Source/Scenes/ContactDiary/EditEntries | 1.07 | 1.09 K |
Tabelle 3: Feature-Effort-Effectiveness im 4. Quartal 2020
Auch in dem Kontext ist eine Visualisierung mit dem Auftragen des Feature-Debt-Index auf der x-Achse und des Feature-Effort-Effectiveness als Farbe der Bubbles in Abb. 12 hilfreich. Eine rote Farbe bedeutet, dass die Feature-Effort-Effectiveness des jeweiligen Verzeichnisses den kritischen Wert von 2.0 überschritten hat, während eine orange Färbung Signal-Level Werte zwischen 1.5 und 2.0 abbildet.
Die identifizierten problematischen Quellcode-Verzeichnisse haben die höchsten Wartungsaufwände UND weisen Symptome einer bereits eintretenden schlechten Erweiterbarkeit um neue Features auf. Die Gründe sind strukturelle Schwächen der Architektur in diesen Bereichen des Codes wie wir sie mit dem Feature-Debt-Index messen.
Zum einen kann man schlechte Code-Qualität ausschließen. Wie bereits erwähnt, wird in der Entwicklung das SonarQube Tool dafür eingesetzt und für eine gute Code-Qualität Sorge getragen. Eine weitere Betrachtung aus einem neuen Blickwinkel in Tabelle 4 bringt zusätzliche Klarheit.
Folder | Defect Impact |
+/- |
src/xcode/ENA/ENA/Source/Services/Risk/Provider | 5.06 | 894% |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission | 2.58 | 0% |
src/xcode/ENA/ENA/Source/Services/Risk/KeyPackageDownload | 1.64 | 0% |
src/xcode/ENA/ENA/Source/Scenes/ExposureDetection | 1.12 | 267% |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission/View | 0.97 | 573% |
src/xcode/ENA/ENA/Source/Services/Exposure Transaction/__tests__ | 0.95 | 0% |
src/xcode/ENA/ENA/Source/Services/Exposure Transaction | 0.88 | 596% |
src/xcode/ENA/ENA/Source/Client/HTTP Client | 0.80 | 25% |
src/xcode/ENA/ENA/Source/Services/Exposure Submission | 0.75 | 0% |
Tabelle 4: Defect-Impact im 4. Quartal 2020
Mit dem Defect-Impact erfassen wir das Ausmaß an sogenannten “Cognitive Bugs”, die sich als Konsequenz eines schlechten Feature-Debt-Index ergeben. Das Besondere daran ist, dass sich zum einen das Beheben dieser Bugs über mehrere Quellcode-Dateien hinweg erstreckt. Zum anderen kommt es in Code-Bereichen mit hohen FDI oftmals zu Folgebugs, die daher hoch zu den vorherigen Bugs gekoppelt sind. Ein Versuch zur Behebung eines solchen Bugs ist meistens nicht ausreichend, da man aufgrund der Verwobenheit der Features im Code das Verständnis über die zusammenhängenden Code-Stellen verliert, und oftmals nicht alle betroffenen Code-Stellen wie erforderlich auf einmal bereinigt. Mehr Details sind wiederum unter [12] zu finden.
Es wird aber sichtbar, dass bisher bloß der Defect-Impact für das Risk/Provider Verzeichnis die gelbe Signal-Stufe erreicht hat. Also lässt sich daraus durchaus schließen, dass es neben den FDI Werten auch andere Faktoren für den hohen Defect-Effort bei den Exposure Submission Verzeichnissen gibt. Wie bereits besprochen kann es nicht an der Code-Qualität liegen. Daher haben wir den Stand der Source Code Dokumentation und deren Trends in den Exposure Submission Verzeichnissen und Risk Verzeichnissen analysiert. Dabei erachten wir ein Verhältnis von Kommentaren zu Programmcode ohne Leerzeilen (unserer Bezeichnung nach die Source-Code-Documentation (SCD) Ratio) unter 10% als einen kritischen Level und innerhalb von 10% bis 20% als Signal-Level.
Folders | SCD | No. of Defects | Defect Effort |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission/ View |
0.09 | 30 | 4.27 K |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission | 0.10 | 42 | 7.61 K |
src/xcode/ENA/ENA/Source/Scenes/ExposureSubmission __tests__ |
0.11 | 22 | 2.45 K |
src/xcode/ENA/ENA/Source/Views/ExposureSubmission | 0.14 | 3 | 64.00 |
src/xcode/ENA/ENA/Source/Services/Exposure Submission | 0.16 | 7 | 98.00 |
src/xcode/ENA/ENA/Source/Services Exposure Submission/__test__ |
0.16 | 0 | 0 |
Tabelle 5: SCD Ratio und Defect-Effort für Exposure Submission im 4. Quartal 2020 und Jan 2021
Bei der Beobachtung der Trends wird zudem sichtbar, dass die SCD-Ratio Werte in den Quellcode-Dateien der Exposure Submission Verzeichnisse in den letzten Monaten bis Januar 2021 kräftig gefallen sind.
In den Risk Verzeichnissen gibt es ähnliche, wenn auch weniger ausgeprägte Trends und Abfälle vom Dez 2020 auf Jan 2021. Die SCD-Ratio im relevanten Risk/Provider Verzeichnis liegt (im Gegensatz zum Risk/Calculation Verzeichnis) noch immer bei 17%, also recht nahe bei den unkritischen 20%.
Folder | SCD | No. of Defects | Defect Effort |
src/xcode/ENA/ENA/Source/Services/Risk | 0.11 | 30.00 | 2.76 K |
src/xcode/ENA/ENA/Source/Services/Risk/Provider | 0.17 | 24.00 | 2.18 K |
src/xcode/ENA/ENA/Source/Services/Risk/ KeyPackageDownload |
0.03 | 5.00 | 240.00 |
src/xcode/ENA/ENA/Source/Services/Risk/__tests__ | 0.02 | 3.00 | 219.00 |
src/xcode/ENA/ENA/Source/Services/Risk/Calculation | 0.08 | 3.00 | 118.00 |
Tabelle 6: SCD-Ratio und Defect-Effort für Risk im 4. Quartal 2020 und Jan 2021
Mittels DETANGLE schätzen wir auch den Verbesserungsaufwand, um diese kritischen Code-Bereiche zu refactorn. Wir sehen diesen Aufwand als das Ausmaß der Technischen Schulden an, die man in Zukunft zurückzahlen muss. Die Details der Berechnung sind hier weniger interessant. Es sei erwähnt, dass die Schätzung dieses Aufwandes gemessen an dem pro Monat umgerechneten Gesamtaufwand des letzten Quartals Q4/2020 laut DETANGLE einem machbaren Aufwand von ca. einer Mannwoche entsprechen würde. Wir lassen uns gerne daran messen, ob diese Aussage der Durchführung auch entsprechen würde. Wir empfehlen Refactoring-Arbeiten unbedingt als einen eigene nIssue-Typen aufzunehmen und Refactoring-Commits mit diesen Tickets zu assoziieren.
Zum Schluss möchten wir noch auf eine weitere Visualisierung aufmerksam machen, welche die Auswirkung der Feature-Kopplung sehr plastisch zum Ausdruck bringt. Unter einem Feature-Netzwerk-Diagramm verstehen wir ein Netzwerk an Knoten und Kanten, welches Issues mit Quellcode-Dateien in Verbindung bringt.
Zum einen stellen die runden Knoten in Abb. 17 feature, enhancement und bug Issues/PRs in GitHub dar. Zum anderen sind die rechteckigen Knoten Quellcode-Dateien. Es besteht eine Kante zwischen einem feature, enhancement oder bug und einer Datei genau dann, wenn zur Umsetzung des Issues/PRs die Quellcode-Datei verändert wurde.
Nun stellen Abb. 17 und Abb. 18 zwei unterschiedliche Perspektiven bzgl. der Feature-Kopplung dar. Abb. 17 enthält die Quellcode-Dateien mit hohen Feature-Kopplungswerten ab einem gewissen (recht niedrigen) Schwellenwert, während Abb. 18 Quellcode-Dateien aufführt, die sehr geringe oder gar keine Feature-Kopplung aufweisen.
Die roten Kreise stellen bug Issue/PRs dar. Quellcode-Dateien aus den Risk und Submission Verzeichnissen sind schwarz umrandet. Man kann mit bloßem Auge schnell feststellen, dass diese Dateien mit hoher Feature-Kopplung sehr oft verstärkt von Bugs (mit Rot gekennzeichnet) betroffen sind.
Abb. 18: Feature-Netzwerk mit Quellcode-Dateien von niedriger Feature-Kopplung, Zeitraum Juli 2020 bis Januar 2021
Abbildung 18 bietet ein Kontrastbild an. Quellcode-Dateien mit keiner oder niederschwelliger Feature-Kopplung sind im Großen und Ganzen nur sehr vereinzelt von Bugs geschweige denn vielen Bugs betroffen.
Diese beiden Bilder führen die Konsequenzen einer hohen Feature-Kopplung plastisch vor Augen. Falls ein Refactoring zur Beseitigung der architekturellen Schwächen der Feature-Kopplung ausbleibt, stellen diese Quellcode-Dateien eine Art Attraktoren für Wartungsaufwände dar und sind potentiell für deren unkontrolliertes Wachstum verantwortlich.
[1] JCON 2020 Talk “Feature and Time-Based Software Analysis”,
How it works: https://youtu.be/aD4OQScGILo?t=510
2 Minuten: 8:30 – 10:32
[2] JCON 2020, “Feature and Time-Based Software Analysis”,
Measuring Development Effort: https://youtu.be/aD4OQScGILo?t=790
5 Minuten: 13:10 – 18:27
[3] JCON 2020, “Feature and Time-Based Software Analysis”,
Calculating Feature Debt: https://youtu.be/aD4OQScGILo?t=1073
10.5 Minuten: 17:53 – 28:30
[4] Blog Cape of Good Code, “Architektur-Hotspots trotz guter Abhängigkeitsstruktur”
https://capeofgoodcode.com/de/wissen/architektur-hotspots-trotz-guter-abhaengigkeitsstruktur/
[5] Github Pull Requests:
https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests
[6] Releasebeschreibung 1.12 Corona Warn App:
https://www.coronawarn.app/de/blog/2021-02-04-cwa-1-12-announcement/
[7] Releasebeschreibung 1.11 Corona Warn App:
https://www.coronawarn.app/de/blog/2021-01-28-corona-warn-app-version-1-11/
[8] Releasebeschreibung 1.10 Corona Warn App:
https://www.coronawarn.app/de/blog/2020-12-28-corona-warn-app-version-1-10/
[9] Releasebeschreibung 1.9 Corona Warn App:
https://www.coronawarn.app/de/blog/2020-12-16-corona-warn-app-version-1-9/
[10] Releasebeschreibung 1.7 Corona Warn App:
https://www.coronawarn.app/de/blog/2020-11-25-corona-warn-app-version-1-7/
[11] JCON 2020, “Feature and Time-Based Software Analysis”,
Refactoring-Anteile bei Feature-Implementierung messen:
https://youtu.be/aD4OQScGILo?t=871
3 Minuten: 14:34 – 17:50
[12] JCON 2020, “Feature and Time-Based Software Analysis”,
Cognitive Bugs: https://youtu.be/aD4OQScGILo?t=1658
2 Minuten: 27:38 – 28:22
Unser Vorgehen zum Bestimmen von Features und Bugs (und der auf sie zurückgehenden Änderungen im Code) bestand nun darin, aus Labels und Keywords von Github PRs und Issues deren Typ abzuleiten. Dabei haben wir versucht, nicht nur die Typen “feature”, “enhancement” und “bug”, sondern auch die Typen wie “chore” (Hausarbeit), “refactor” und “technical” nach folgenden Regeln für Github PRs und Issues abzuleiten, wobei wir uns hier im Blog auf “feature”, “bug” und “enhancement” beschränkt haben. Die Handhabung der Referenzierungen in Commits können wir hier auch nur anschneiden. Folgende Regeln haben wir vereinfacht angewendet:
Um einen besseren Eindruck zu gewinnen, seien einigeZahlen genannt für den Zeitraum ab Beginn, also dem 30.05.2020, bis zum 28.01.2021:
Eigenschaft Github PR | Anzahl |
Github PRs ohne Label | 681 |
Github PRs mit Label “bug” | 279 |
Github PRs mit Label “feature” | 99 |
Github PRs mit Label “enhancement” | 86 |
Github PRs mit Keyword “bug” im PR Titel | 114 |
Github PRs mit Keyword “fix” aber nicht “typo” im PR Titel | 156 |
Github PRs mit Keyword “feature” im PR Titel | 181 |
Zum Beispiel konnten wir aufgrund der Keywords im Titel von den 681 PRs ohne Label für 451 PRs (114 + 156 + 181) einen Typ bestimmen.