Apriko für den Unternehmerpreis 2024 nominiert!
Wir haben aufregende Neuigkeiten: Apriko ist zusammen mit COO und Gründungspartner Muhamed Ramiqi für den renommierten swissalbs Unternehmerpreis 2024 nominiert!
Wir haben aufregende Neuigkeiten: Apriko ist zusammen mit COO und Gründungspartner Muhamed Ramiqi für den renommierten swissalbs Unternehmerpreis 2024 nominiert!
Hast du dich schon mal gefragt, was Payrolling oder Payroll eigentlich beinhaltet? Und kennst du Try & Hire schon? Die Antwort ist nicht ganz einfach, weil der Begriff «Payrolling» für 2 unterschiedliche Dienstleistungen genutzt wird.
Bei Apriko streben wir nach einem hohen Automatisierungsgrad der Kundenprozesse, einer schnellen Markteinführung und einer kontinuierlichen Verbesserung unserer Software. Um dies in einer anspruchsvollen Domäne und komplexen Softwarearchitektur sicherzustellen, ist eine präzise Planung und konsequente Umsetzung von Anfang an unverzichtbar.
In der heutigen Softwareentwicklung stehen Teams vor der Herausforderung, sicherzustellen, dass ihre Systeme nahtlos mit unterschiedlichen, oft komplexen Abläufen und Logiken zusammenarbeiten. Diese Systeme müssen zudem mit einer Vielzahl an Softwarelösungen kompatibel sein, die regelmässig aktualisiert werden. Allerdings besteht bei diesen Updates das Risiko, dass zuvor reibungslos funktionierende Prozesse durch Änderungen im Quellcode plötzlich nicht mehr ordnungsgemäss ablaufen.
Solche Rückschritte, bekannt als Software-Regressionen, können auftreten, wenn neue Funktionen hinzugefügt, Software-Updates eingespielt oder frühere Fehler behoben werden. Da Software und Schnittstellen sich kontinuierlich weiterentwickeln, steigt die Gefahr, dass jede Änderung unerwartete Probleme verursacht.
Mehrere Faktoren verschärfen das Problem der Software-Regressionen erheblich: Wissensverluste, schnell wechselnde Technologien und eine wachsende Codebasis erschweren es den Entwicklerinnen und Entwicklern, alle Auswirkungen einer Änderung vollständig vorherzusehen. Dies führt zu einer Zurückhaltung bei Optimierungen und beim Austausch veralteter Softwarekomponenten.
Daraus resultiert oft eine verlängerte Testdauer, die dazu führen kann, dass selbst kleinere Änderungen mehrere Monate an Testzeit erfordern. In extremen Fällen kann dies so weit gehen, dass kaum noch Änderungen oder neue Funktionen entwickelt werden, da die Aufwände für Tests und Validierung unverhältnismässig hoch sind. Dies schränkt die Innovationskraft der Softwareentwicklung erheblich ein.
Bei Apriko setzen wir auf den Ansatz des Behavior Driven Development (BDD). Das Ziel der verhaltensgetriebenen Softwareentwicklung besteht darin, die Zusammenarbeit zwischen dem Entwicklerteam und dem Business mithilfe einer gemeinsamen Sprache zu vereinfachen. Dadurch wird ein einheitliches Verständnis geschaffen und das Testing automatisiert.
Das Verhalten der Anwendung steuert methodisch den Designprozess. Die ubiquitäre Sprache übersetzt dieses Verhalten in Elemente, die eine Analyse des Codes sowie nachfolgende Akzeptanztests schon vor Fertigstellung der Software ermöglichen. Die Automatisierung des Testens verbessert die Qualitätssicherung und beschleunigt die Markteinführung.
Der BDD-Ansatz basiert auf einer domänenspezifischen Syntax, die häufig durch das Gherkin-Format veranschaulicht wird. Diese Syntax folgt dem „Given-When-Then“-Modell:
Der Vorteil von BDD liegt darin, dass die Software nicht durch umfangreiche und komplexe Spezifikationen beschrieben wird, sondern durch klare, verständliche Beispiele. Diese sind so formuliert, dass sie für alle Beteiligten nachvollziehbar sind und Missverständnisse weitgehend ausgeschlossen werden. Die Beispiele sind so strukturiert, dass sie direkt in automatisierte Akzeptanztests überführt werden können.
Im .NET-Umfeld wird BDD oft durch SpecFlow unterstützt. SpecFlow ermöglicht es, in natürlicher Sprache verfasste Softwarekriterien, die gemäss der Gherkin-Syntax in Feature-Dateien dokumentiert sind, in ausführbaren Code zu überführen. Dies vereinfacht die Durchführung automatisierter Tests und bietet eine transparente Übersicht über den Teststatus – ob Tests erfolgreich waren, fehlgeschlagen sind oder noch nicht implementiert wurden. Dadurch erhalten Entwicklerinnen und Entwickler eine präzise und aktuelle Dokumentation des Softwarezustands und der Akzeptanzkriterien, was Unsicherheiten hinsichtlich fehlerhaften Verhaltens oder veralteter Dokumentationen effektiv eliminiert.
Wir verfolgen einen API-first-Ansatz, bei dem das API im Mittelpunkt steht. Bevor wir eine User Story umsetzen oder eine Zeile Code schreiben, wird das komplette Verhalten – einschliesslich positiver Fälle, Fehlerfälle, Validierungen, Operationen und bekannter Randfälle – in Feature-Files im Gherkin-Format konzipiert und spezifiziert.
Um die gemeinsame Sprache möglichst effizient zu gestalten, haben wir spezifische Steps definiert und das Verhalten dieser Steps einheitlich implementiert. Das ermöglicht es uns, Tests basierend auf den Spezifikationen zu automatisieren, ohne eine Zeile Testcode zu schreiben.
Mit diesen standardisierten Elementen lassen sich alle denkbaren API-Verhalten definieren und überprüfen.
Aus den Operations-Schritten (When) in der Spezifikation generieren wir HTTP-Requests und verwenden die HTTP-Response zur Validierung in den Überprüfungs-Schritten (Then). Die in der Spezifikation enthaltenen Tabellen werden in das Payload für die HTTP-Requests überführt, während die Tabellen aus den Überprüfungs-Schritten entsprechend serialisiert werden, um den Response-Content zu vergleichen. Dabei konvertieren wir die Tabellen in die benötigten Formate wie JSON, XML, etc.
Wir verwenden auch standardisierte Steps, um beispielsweise unsere CSV-, PDF- oder Word-Export-Inhalte zu vergleichen oder externe APIs zu mocken bzw. zu simulieren.
Damit die Szenarien und die daraus folgenden Tests in einem Service nicht von anderen Services abhängig sind, haben wir einen Step entwickelt, mit dem wir eine Event-Message in den Event-Bus stellen können.
So sind wir in der Lage, in den Tests und in der Konzeption die Message als Schnittstelle zu anderen Services zu betrachten, ohne Details über andere Domänen oder Services kennen zu müssen. Das verringert die Komplexität, definiert eine klare Schnittstelle und stellt die Entkopplung weiter sicher.
Für jedes Szenario wird automatisch eine isolierte Umgebung samt Datenbank mit dem aktuellen Code-Stand der Software bereitgestellt. Aus der in Gherkin geschriebenen Syntax werden wie oben beschrieben HTTP-Requests generiert und im Sinne eines Blackbox-Tests gegen unsere API geprüft.
Die Tests laufen vollautomatisch bei jeder Code-Änderung nach den klassischen Unit-Tests und wir erhalten innerhalb von 15 Minuten Feedback, ob wir Regressionen verursacht haben. Dabei werden in wenigen Minuten mehrere Tausend Szenarien ausgeführt und alle Funktionen zu hundert Prozent auf ihr Verhalten getestet. Wenn keine Regressionen bestehen und ein Feature unsere weiteren Qualitätsanforderungen wie z. B. Code-Review oder explorative Testing bestanden hat, kann es auf Knopfdruck in die Produktion ausgerollt werden. In unserer Gesamtarchitektur, die auf Microservices und modellgetriebener Architektur mit selbst entwickelten Code-Generatoren basiert, macht die Spezifikation achtzig Prozent der gesamten Codebasis aus. Dies ist eine beachtliche Bilanz und unterstreicht die Wirksamkeit unserer Designansätze und deren Umsetzung.
So sind wir in der Lage, in den Tests und in der Konzeption die Message als Schnittstelle zu anderen Services zu betrachten, ohne Details über andere Domänen oder Services kennen zu müssen. Das verringert die Komplexität, definiert eine klare Schnittstelle und stellt die Entkopplung weiter sicher.
Für jedes Szenario wird automatisch eine isolierte Umgebung samt Datenbank mit dem aktuellen Code-Stand der Software bereitgestellt. Aus der in Gherkin geschriebenen Syntax werden wie oben beschrieben HTTP-Requests generiert und im Sinne eines Blackbox-Tests gegen unsere API geprüft.
Die Tests laufen vollautomatisch bei jeder Code-Änderung nach den klassischen Unit-Tests und wir erhalten innerhalb von 15 Minuten Feedback, ob wir Regressionen verursacht haben. Dabei werden in wenigen Minuten mehrere Tausend Szenarien ausgeführt und alle Funktionen zu hundert Prozent auf ihr Verhalten getestet. Wenn keine Regressionen bestehen und ein Feature unsere weiteren Qualitätsanforderungen wie z. B. Code-Review oder explorative Testing bestanden hat, kann es auf Knopfdruck in die Produktion ausgerollt werden. In unserer Gesamtarchitektur, die auf Microservices und modellgetriebener Architektur mit selbst entwickelten Code-Generatoren basiert, macht die Spezifikation achtzig Prozent der gesamten Codebasis aus. Dies ist eine beachtliche Bilanz und unterstreicht die Wirksamkeit unserer Designansätze und deren Umsetzung.
Behavior Driven Development ist ein echter Gamechanger, wenn es korrekt angewendet und konsequent umgesetzt wird. Der damit verbundene Aufwand darf jedoch nicht unterschätzt werden und sollte sorgfältig eingeplant werden, wobei auch die Unterstützung des Managements essenziell ist. Die konsequente Erstellung der Spezifikation als Anforderungs- und Designartefakt dient als Treiber für die nachgelagerte Entwicklung. Die Erstellung auf diesem Detaillierungsgrad ist eine abstrakte und anspruchsvolle Arbeit, die erfahrene Entwicklerinnen und Entwickler mit den entsprechenden Fähigkeiten erfordert. Wichtig ist, den eingeschlagenen Weg konsequent zu verfolgen; Lücken in der Spezifikation mindern die Aussagekraft der Regressionstests erheblich. Die Investition in diesem Ansatz zahlt sich jedoch schnell in Form langlebiger Produkte aus und kann einen echten Wettbewerbsvorteil bieten.