Über das Leben in einer Welt sich ändernder Anforderungen und die Vorteile kleiner Funktionen

Seit mehr als einem Jahr erstellen wir in MyStore Funktionen, mit denen unsere Benutzer etikettierte Waren kaufen und verkaufen können. Die Nachrichten über die Kennzeichnung sind bei Habré so oft verrutscht, so kurz: Seit 2019 sind Waren unbedingt gekennzeichnet. Nicht auf einmal, aber jetzt müssen Sie Zigaretten, Schuhe, Parfums und Autoreifen kennzeichnen. Gleichzeitig arbeiten wir in einer Situation der Unsicherheit, in der sich die API von Regierungssystemen ständig ändert.


Daher haben wir nur zwei Möglichkeiten, uns in Regierungsbehörden zu integrieren: Warten Sie, bis sich alles beruhigt hat, und verpassen Sie die Marktführerschaft, oder entwickeln Sie ein System in einer Welt sich ändernder Anforderungen.


Wir haben uns für die zweite entschieden - nur im Sinne flexibler Methoden. Ich denke, Agile kann wirklich helfen, angewandte Probleme zu lösen. Und das Leben in einer Welt mit sich ständig ändernden Anforderungen ist das Feld, in dem Sie sich umdrehen können.



Mein Name ist Maxim Sukharenko, ich bin Teamleiter der MySklad-Serviceplattform. Und heute werde ich Ihnen erzählen, wie wir mit sich ändernden Anforderungen arbeiten.


Von Classic zu Scrum


Die erste Frist für die Entwicklung des Systems durch die Regulierungsbehörden war für April 2019 geplant, aber Sie verstehen alles. Infolgedessen wurden die Fristen auf Oktober verschoben. Und wo es neue Fristen gibt, gibt es neue Anforderungen und neue Formate. Wir konnten es kaum erwarten, dass die API repariert wurde - dann hätten wir keine Zeit, die Integration zu implementieren. Deshalb beschlossen sie, "mit der Parteilinie zu zögern".


Wir haben über den klassischen Ansatz nachgedacht, mit dem wir einen Adapter für ein externes System herstellen können. Ergänzen Sie es mit einem Stecker mit einem Schalter und rufen Sie von Zeit zu Zeit die Funktionalität des Steckers und des Adapters auf den aktuellen Stand des externen Systems auf.



Die Logik schlägt vor, dass Sie die Anforderungen zu einem bestimmten Zeitpunkt korrigieren müssen, um ein System mit einer sich ständig ändernden Schnittstelle zu entwickeln. Aber nur auf was? Bis wir einen Teil der Funktionalität entwickeln?


Sie müssen zugeben, dass es unangenehm ist, unvollendete Funktionen zu belassen, für die Tests nicht bestanden wurden, und sie auch bei einem neuen zu brechen. Sie können die Anforderungen für den Feature-Entwicklungszeitraum festlegen. Aber was tun mit großen Funktionen, die mehrere Monate in der Entwicklung leben können? Es ist einfach unmöglich, Anforderungen für einen so langen Zeitraum festzulegen.


Also wandten wir uns an Scrum. Er sagt uns, dass wir bis zum Ende des Sprints ein funktionierendes Produkt mit neuen Funktionen bereitstellen müssen. Aber wie kämpft dies mit Fixing-Anforderungen und großen Funktionen? Zu diesem Thema gibt es einen guten Witz:


"Doktor, wenn ich es so mache, tut es mir weh."
"Und du machst es einfach nicht so."


Wer nicht versteht, macht keine großen Features . Sie können die Anforderungen für ein oder zwei Wochen festlegen, um mit dem Sprint übereinzustimmen, und die Implementierung der Funktion gemäß den Anforderungen für den Zweck des Sprints festlegen. Und die Funktionalität muss in solche Teile geschlagen werden, damit sie in ein oder zwei Sprints passen. Denken Sie zu knifflig? Und dann! Sie wissen einfach nicht, wie Sie Tickets schneiden sollen. Sah, Shura, sah, sie sind golden.


Natürlich ist dies nicht so einfach, wir müssen gezielt darauf zugehen - um die Entwicklung von "Wir werden es sechs Monate lang tun, dann werden wir eine neue Version für den Test herausbringen" zu verlassen.


Das Geheimnis ist, am Ende jedes Sprints eine stabile Version zu haben . Natürlich könnte dies den Anschein haben, dass dies die Entwicklungszeit aufgrund des Anstiegs der Gemeinkosten für die Stabilisierung der Niederlassung verlängern wird und dass die Entwicklung nicht optimal sein wird. Aber hier ist die Situation fast die gleiche wie bei den Tests. Lassen Sie uns weiter unten darüber sprechen.


Missionen bekämpfen


Und jetzt zu realen Situationen. Unsere Aufgabe war es, die Verschlüsselung zwischen unserem System und der API so zu konfigurieren, dass der Benutzer alle Anforderungen mit einem Schlüssel signiert. Ich denke, viele von Ihnen sind auf CryptoPro gestoßen, also mussten wir.


Wenn Sie den Standardansatz verwenden, wird eine isolierte Aufgabe gebildet - das Einrichten der Kryptografie für den Dienst. Wir werden es an eine Person hängen und für einen Monat den Status entfernen und uns darüber ärgern, warum es in keiner Weise enden wird. Und der Entwickler wird sich allmählich in eine wilde Kreatur aus der anderen Welt verwandeln, mit Schaum im Mund und wilden Augen.


Wir haben es in kleine Aufgaben geschnitten und im ganzen Team verteilt. Ich vergleiche Kryptographie mit Alkohol: In Gesellschaft und in einer moderaten Dosis ist es viel besser als viel und allein.
Da wir einen Cloud-Dienst entwickeln, war es für uns einfacher, das CryptoPro EDS Browser-Plug-In zu verwenden (dies ist keine Werbung, dies ist Hoffnungslosigkeit). CryptoPro CSP kann damit Schlüssel und Verschlüsselungsmethoden auf eine Webseite erweitern.


Zuerst wählt der Benutzer aus, welchen Schlüssel er für die Arbeit mit dem Dienst verwenden möchte, und dann erfolgt die Authentifizierung, um ein Token zu erhalten. Und erst dann werden mit Hilfe von Verschlüsselung und Token API-Aufrufe getätigt. Es scheint, dass alles einfach ist (nein).


Zunächst haben wir MVP isoliert von unserem Service durchgeführt, um die Interaktion des Plugins mit der API zu konfigurieren. Wissen Sie, wie viel Dokumentation über das cryptoPro-Browser-Plugin vom Hersteller vorhanden ist? Überhaupt nicht! Nur Reverse Engineering Beispiele, nur Hardcore. Schlaflose Nächte und Versuche festzustellen, welchen Einfluss diese oder andere Parameter haben.


Und erst dann konnten wir versuchen, es in unser Ökosystem einzubauen. Eine Person bringt das Erscheinungsbild der Prototypkomponente in eine menschliche Form, die zweite verbindet sie mit der Geschäftslogik, die dritte schreibt Anweisungen für die Nachwelt, um sie zu konfigurieren. Jede Aufgabe hat ein bestimmtes Ziel und ist relativ isoliert von den anderen. Und die Leute haben etwas zu besprechen und mit wem sie den Schmerz teilen können.


Die Situation ist also ziemlich stabil geworden. In kleinen Iterationen fügen wir neue Funktionen hinzu. Von Zeit zu Zeit aktualisieren wir die externe Schnittstelle und verbreiten die Änderungen tief in unserem System. Aber es stellt sich die Frage: Bis zum letzten in einem separaten Zweig leben oder versuchen, ständig kleine Features im Master zu behalten?


Funktionalität testen


Ich schlage vor, herauszufinden, was mit Tests zu tun ist und was zu tun ist, wenn wir einem Live-Projekt Integration hinzufügen.


Beginnen wir mit dem Testen. Zunächst werden wir bestimmen, wie wir die getestete Funktionalität nennen können. Ich schlage vor, die Funktion zu benennen, die die Abnahmetests bestanden hat, einschließlich der Regressionstests. Wir sind uns nur einig, dass wir nicht auf den Life-Hack "Keine Tests - das heißt, alles wird getestet" zurückgreifen werden. Wir müssen unseren Code im Produkt beibehalten. Je mehr Testabdeckung vorhanden ist, desto besser. Je höher der Prozentsatz der Automatisierung solcher Tests ist, desto billiger ist jede Iteration des Testens der Funktionalität und desto häufiger kann sie durchgeführt werden.


Wir haben eine Reihe von Akzeptanz- und Regressionstests, von denen einige automatisiert sind, andere von Hand gehalten werden.


Wenn wir uns formell nähern, sollten wir nach jeder Codeänderung Tests durchführen. Zum Beispiel haben sie Ihre Funktion in sechs Tickets aufgeteilt und während des Testprozesses zehn Fehler gefunden. Und lassen Sie jeden Test vier Stunden dauern: Automatisch zählt nicht, manuell dauert nur vier Stunden. Es stellt sich heraus, dass wir mit der grundlegenden und formalen Arbeitsweise 64 Stunden verbringen werden.
Versuchen wir nun, nicht nach jeder Codeänderung, sondern nach einer zu testen. Die Logik legt nahe, dass wir nur 32 Stunden verbringen. Und wenn Sie Tests erst durchführen, nachdem Sie die Funktionalität entwickelt und alle Fehler behoben haben. Dies setzt jedoch voraus, dass alle Mängel voneinander isoliert sind, was im Leben nicht der Fall ist.


Im Leben stellt sich heraus, dass nach der Entwicklung der Funktionalität Tests durchgeführt werden und die erste Welle von Fehlern durchgeführt wird. Dann werden die Fehler behoben, die Funktionalität ist unterbrochen, sie werden durch den Fehler getestet. Sie führen einen zweiten globalen Test durch und eine neue Welle von Fehlern tritt auf. Diese Fehler wurden ausgeblendet und traten auf, als sie die erste Welle korrigierten und die Funktionalität änderten. Und so mehrmals.


Normalerweise erhalten Sie drei bis fünf vollständige Testläufe - abhängig von der Komplexität der Funktionalität und der Direktheit der Hände. Der Prozess kann jedoch noch weiter beschleunigt werden - wenn Sie auf kleine Features setzen.


Wenn Sie beispielsweise eine Funktion mit einem Test nach vier Stunden in zwei Funktionen mit einem Test nach dreieinhalb Stunden aufteilen, erhalten Sie fünf statt vier Stunden. Es scheint keinen Gewinn zu geben. Dies äußert sich jedoch in einer Verringerung der Komplexität der freigegebenen Funktionalität und einer Verringerung der Wahrscheinlichkeit von Ketten verwandter Fehler. Infolgedessen werden Iterationen vollständiger Tests weniger.



Zum Projekt hinzufügen


Jetzt analysieren wir die Situation, wenn Sie ein Feature in einem Projekt erstellen, an dem Entwickler noch arbeiten. Angenommen, wir verwenden das relativ standardmäßige Branch Per Feature-Konzept (Branch Per Ticket) des Quellcodes.


Offensichtlich ist die Höhe der Kosten, um die Relevanz des Brunchs aufrechtzuerhalten, proportional zu seiner Lebensdauer. Je weniger Code-Kreuzungen in aktuellen Tickets vorhanden sind, desto weniger Probleme treten bei der Fusion auf. Dies hängt indirekt von der Lebensdauer ab: Je mehr Zeit vergangen ist, desto höher ist die Wahrscheinlichkeit, dass verwandte Tickets angezeigt werden. Je weniger Brunch lebt, desto weniger Aufwand investieren wir in seine Relevanz.


Es bleibt zu verstehen, wie teilweise funktionale Funktionen auf dem Produkt bereitgestellt werden. Die Antwort ist ganz einfach: Sie sollte für den Benutzer nicht zugänglich sein. Wenn Sie fragen möchten, warum Sie dies tun sollten, können Sie einige Absätze oben zurückgeben.


Es scheint nicht sehr gut zu sein, den toten Code im Assistenten zu behalten. Das stimmt, aber er ist nicht tot. Sie können eine geheime Seite mit Stiften erstellen, die solche Funktionen enthalten. Oder eine spezielle Abfolge von Aktionen, die Sie wie Ostereier in Spielen zu dieser Funktionalität führen. Außerdem können Sie es sofort testen.


Natürlich gibt es auch andere Möglichkeiten, mit der Variabilität der Anforderungen umzugehen. Und dieser Ansatz hat seine Grenzen und Nutzungsbedingungen. Wie Sie wissen, gibt es noch keine Silberkugel.

Source: https://habr.com/ru/post/de460883/


All Articles