Startseite / Artikel / Sieben Fragen, die vor dem Schreiben der ersten Zeile eines Artikels geklärt werden sollten

Sieben Fragen, die vor dem Schreiben der ersten Zeile eines Artikels geklärt werden sollten

Eine Checkliste vor der Implementierung, die das tatsächliche Benutzerproblem, Garantien für die Vollendung, Zuständigkeiten für Regeln, veraltete Daten, Wiederholungsversuche und Konkurrenz, Beobachtbarkeit sowie Sicherheit bei der Einführung abdeckt.

2797 Wörter

Der schnellste Weg, sich bei einer neuen Aufgabe produktiv zu fühlen, besteht darin, einen Editor zu öffnen und direkt mit der Entwicklung zu beginnen: Den Endpunkt hinzufügen, die Spalte sowie das Komponenten. Das Problem ist, dass die erste Implementierung stillschweigend alle Fragen beantwortet, die niemand gestellt hat, und diese Antworten zu Schemata, API-Verträgen sowie Tests werden, die schwer wieder rückgängig zu machen sind. Dieser Leitfaden erläutert sieben Fragen, die erfahrene Entwickler vor dem Programmieren klären, was schiefgeht, wenn sie übersprungen werden, und wie man die Arbeit im richtigen Maß halten kann, damit sie die Lieferzeit beschleunigt statt verlangsamt.

Warum die erste Implementierung so viel Gewicht hat

Wenn eine Anfrage eintrifft, macht das Arbeiten mit Code eine abstrakte Aufgabe greifbarer und kleiner. Doch die offenen Fragen sind nicht verschwunden. Jemand muss weiterhin entscheiden, wer für eine Geschäftsregel verantwortlich ist, was „erledigt“ bei einer mehrstufigen Operation bedeutet und was mit vor der Änderung erstellten Datensätzen geschieht. Wenn niemand entscheidet, trifft die Entscheidung zufällig der Code.

Diese zufällige Entscheidung beschränkt sich selten auf einen einzigen Bereich. Die Struktur der ersten Version wird oft zur Tabelle, zum Antwortformat, zum gemeinsam genutzten Hilfsprogramm, das jeder importiert, sowie zum Zustandsmodell, von dem die Benutzeroberfläche abhängt. Sobald anderer Code darauf verweist und die Produktionsdaten dieser Struktur folgen, bedeutet ein Richtungswechsel Migrationsarbeiten, Kompatibilitätsmaßnahmen und koordinierte Veröffentlichungen. Im Vergleich dazu ist es günstig, bereits zu Beginn eine Stunde in die richtigen Fragen zu investieren.

Von außen betrachtet kann das wie Zögern wirken: Bestehende Workflows durchlesen, herausfinden, was der Benutzer eigentlich erreichen will, prüfen, wie sich alte Daten verhalten, über teilweise fehlgeschlagene Versuche sprechen. In Wirklichkeit handelt es sich dabei um das gleiche Problemlösen, das der Code ohnehin durchführen müsste – nur wird es in Anbetracht der geringen Kosten für eine Änderung der Meinung durchgeführt.

1. Trennen Sie die gewünschte Funktion vom zugrunde liegenden Problem

Oft kommen Anfragen in Form von Lösungen: Ein Button hinzufügen, ein Filter einbauen, eine Exportfunktion schaffen, einen neuen Status definieren. Die Anfrage mag völlig vernünftig sein, beschreibt aber lediglich das, was jemand sich vorstellt, gebaut zu bekommen – nicht die dahinterliegende Frustration oder das geschäftliche Ziel.

Die Berücksichtigung dieser zugrundeliegenden Bedürfnisse verändert das, was man entwickelt. Eine Anfrage nach einer CSV-Exportierung kann tatsächlich von Managern stammen, die wöchentliche Zahlen zwischen den Abteilungen nicht vergleichen können. Ein Export hilft zwar, er schafft aber auch wiederkehrende manuelle Tabellenarbeitsaufwände, die durch einen gespeicherten Bericht oder eine automatisierte Zusammenfassung vollständig beseitigt werden könnten. Eine Anfrage nach einem weiteren Statuswert kann darauf hindeuten, dass ein einzelnes Feld bereits überlastet ist und gleichzeitig für Zahlungen, Genehmigungen und Lieferungen genutzt wird. Durch Hinzufügen dieses Wertes wird das Ticket abgeschlossen, was das Datenmodell noch schwieriger zu verstehen macht.

Das bedeutet keineswegs, jede kleine Anfrage genauestens zu prüfen oder eine einfache Änderung in ein umfangreiches Produktworkshop-Projekt zu verwandeln. Ziel ist es, genug über die Situation des Benutzers zu erfahren, um beurteilen zu können, ob der vorgeschlagene Wandel tatsächlich das Ergebnis verbessert. Ein paar gezielte Fragen reichen in der Regel aus:

  • Wer kann seine Arbeit heute nicht erledigen?
  • Was machen sie derzeit noch manuell?
  • Welche Entscheidung wird durch diese neuen Informationen unterstützt?
  • Was wird möglich, sobald die Funktion vorhanden ist?
  • Wenn man diesen Schritt überspringt, optimieren die Entwickler automatisch den ursprünglichen Antrag. Die Schaltfläche ist ansprechend, das Komponente wiederverwendbar, die API übersichtlich – doch die Funktion enttäuscht weiterhin, weil sie das Anliegen nur präziser als das eigentliche Problem löst. Es geht nicht darum, mit dem Programmieren zu warten, sondern sicherzustellen, dass der Code die richtige Lösung ist.

    2. Definieren Sie, was Erfolg für die gesamte Operation bedeutet

    Viele Anforderungen nennen eine Aktion, ohne anzugeben, wann sie abgeschlossen ist. Ein Antrag einreichen, einen Datensatz freigeben, ein Projekt duplizieren oder Daten synchronisieren – all das klingt einfach, bis mehrere Schritte involviert sind und einer davon fehlschlägt.

    Nehmen Sie einen Freigabeprozess, der die Änderung speichert, eine Zeile im Prüfprotokoll einträgt, ein Ereignis auslöst und den Anfragenden benachrichtigt. Wenn der Schreibvorgang erfolgreich ist, aber die Benachrichtigung fehlschlägt – gilt die Freigabe dann als erfolgreich? Wenn der Benutzer es erneut versucht, könnte das Dokument zweimal freigegeben werden? Wenn der Eintrag ins Prüfprotokoll nicht geschrieben werden kann, sollte die Statusänderung rückgängig gemacht werden? Wenn das Ereignis verzögert wird – ist die Freigabe abgeschlossen oder noch ausstehend? Das sind keine trivialen Implementierungsfragen. Sie definieren, was das Produkt seinen Nutzern verspricht.

    Die nützliche Übung besteht darin, die Abschlussgrenze vor dem Erstellen des Workflows zu bestimmen:

    • Effekte, die entweder gemeinsam erfolgreich oder gescheitert sein müssen – denn ein teilweiser Ergebnis würde einen ungültigen Zustand darstellen – gehören in eine Transaktion.
  • Effekte, die wertvoll, aber sekundär sind – wie beispielsweise eine Begrüßungs-E-Mail – sollten nicht darüber entscheiden, ob die Hauptaktion erfolgreich war. Sie gehören in der Regel zu einer Hintergrundaufgabe mit Wiederholungsversuchen sowie einem expliziten „pending“-Status.
  • Das gleiche Problem tritt bei kleinen Funktionen auf. Wenn jemand einen Export startet – gilt dies dann als erfolgreich, sobald die Datei vorhanden ist und der Vorgang angenommen wurde, oder erscheint später ein Link? Wenn die Benutzeroberfläche „Gespeichert“ anzeigt – hat der Server die Dauerhaftigkeit bestätigt oder änderte sich nur der lokale Zustand?

    Lassen Sie dies vage, dann erfindet jede Schicht ihre eigene Definition. Die Benutzeroberfläche zeigt Erfolg an, obwohl der Backend-Teil noch arbeitet; ein Worker versucht erneut etwas, von dem der Benutzer bereits annimmt, es sei fehlgeschlagen; und die Überwachung meldet eine erfolgreiche Anfrage, obwohl ein wesentlicher Nebeneffekt verschwunden ist. Zunächst klare Garantien festzulegen, erleichtert in der Regel die Implementierung, denn jeder Schritt hat dann eine klare Aufgabe. Dadurch wird auch das Antwortkonzept geprägt: Eine API, die „accepted“ zurückgibt, unterscheidet sich von einer, die „done“ zurückgibt, und Clients müssen wissen, welche Art von Antwort sie erhalten.

    3. Entscheiden Sie, welche Schicht für jede Entscheidung verantwortlich ist

    Eine Funktion kann zwar korrekte Ergebnisse liefern, dennoch unsicher sein, wenn die Entscheidung in der falschen Schicht getroffen wird. Häufige Beispiele:

    • Die Frontend-Schicht versteckt einen Button vor Benutzern ohne Genehmigung, doch die API akzeptiert den Aufruf, wenn er direkt gestartet wird.
  • Ein Controller überprüft einen Zustandswechsel, doch ein geplanter Job ruft den zugrunde liegenden Service auf und umgeht diese Überprüfung.
  • Ein Service lehnt Duplikate ab, doch ein Wartungsskript schreibt direkt in die Tabelle.
  • In jedem Fall existiert die Regel, doch nicht jeder Ablauf muss durch sie geleitet werden.

    Die Lösung besteht darin, die Schicht zu finden, die über ausreichende Befugnisse verfügt, um die Regel zu verwalten. Die Benutzeroberfläche kann zur besseren Bedienbarkeit Berechtigungen widerspiegeln, stellt aber niemals die Sicherheitsgrenze dar. Ein Controller eignet sich gut zur Überprüfung der Struktur einer HTTP-Anfrage, während Geschäftsregeln in der Regel tiefer liegen müssen, damit Hintergrundjobs und interne Aufrufer ein identisches Verhalten zeigen. Eine Eindeutigkeitsprüfung auf Anwendungsseite liefert freundliche Fehlermeldungen, doch nur eine Datenbankbeschränkung schützt tatsächlich die Invarianz, wenn gleichzeitige Schreibvorgänge stattfinden.

    Das Eigentum gilt sowohl für den Zustand als auch für die Regeln. Filter, die geteilt werden müssen und nach einem Neuladen erhalten bleiben, eignen sich ideal für die URL. Temporäre Eingaben gehören zur Formularstruktur. Berechtigungen sowie der persistierte Status stammen vom Server, und der Client sollte nicht aufgrund lokaler Schätzungen seine eigene Version erstellen.

    Wenn die Autorität unklar ist, entstehen Koordinationsschwierigkeiten: doppelte Überprüfungen in mehreren Ebenen, Kopien desselben Wertes, die synchron gehalten werden müssen, sowie Änderungen, die zu umfangreichen Such- und Ersetzvorgängen führen. Ein Policy-Update betrifft dann die Benutzeroberfläche, den Controller, den Dienst, einen Worker sowie eine oder zwei Abfragen – ohne Garantie dafür, dass jede Kopie weiterhin denselben Sinn hat. Geben Sie jeder wichtigen Entscheidung einen klaren Verantwortlichen. Andere Ebenen können das Ergebnis anzeigen, im Cache speichern, durchsetzen oder weiterleiten, sollten es aber nicht neu definieren. Dadurch sinken sowohl das Sicherheitsrisiko als auch die Wartungskosten, denn jeder weiß, wo sich die Quelle der Wahrheit befindet.

    4. Berücksichtigen Sie die bereits vorhandenen Daten

    Für das gewünschte Modell wird neuer Code geschrieben. Produktionsdaten enthalten jedoch auch Spuren aller früheren Modelle.

    Es ist einfach, ein Feld für nach der Veröffentlichung erstellte Datensätze verpflichtend zu machen, doch Tausende älterer Zeilen haben es möglicherweise nicht. Ein neu gestaltetes Statusmodell kann zukünftige Arbeitsabläufe gut beschreiben, während historische Zeilen in Statusen stecken bleiben, die der neue Code nicht mehr erkennt. Eine neu verpflichtende Beziehung kann auf eine Entität verweisen, die zum Zeitpunkt der Erstellung älterer Zeilen einfach noch nicht existierte.

    Vor dem Hinzufügen von Validierungen oder der Änderung des Schemas fragen Sie sich:

    • Können bestehende Datensätze zuverlässig migriert werden?
    • Ist ein temporärer „unbekannter“ Zustand notwendig?
    • Überschreibt diese Änderung die Geschichte oder ändert nur das zukünftige Verhalten?

    Ehrlichkeit ist das wichtige Wort. Jeden Leerlauf mit einem praktischen Standardwert zu füllen kann eine NOT NULL-Beschränkung erfüllen, während falsche Daten eingeführt werden. Wenn die zuständige Abteilung eines alten Datensatzes niemals erfasst wurde, führt das Eintragen der aktuellen Abteilung dazu, dass Abfragen einfacher werden, historische Berichte jedoch weniger glaubwürdig sind. Manchmal bietet das ehrliche Schema Platz für Werte wie „unbekannt“ oder „veraltet“, da Unwissenheit ein echter Bestandteil der Vergangenheit dieses Datensatzes ist.

    Auch alte Strukturen existieren außerhalb der Datenbank. Ältere Clients könnten weiterhin frühere Payload-Formate senden, geplante Aufgaben könnten von Statuswerten abhängen, die der neue Ablauf entfernen möchte, und Berichte könnten Spalten nach Regeln interpretieren, die schon vor langer Zeit geändert wurden.

    Ihre Unterstützung für veraltete Verhaltensweisen muss nicht ewig andauern, doch die Entscheidung zur Migration sollte klar sein. Einige Daten können sicher umgewandelt werden, andere erfordern eine manuelle Überprüfung, einige alte Kunden verdienen ein Kompatibilitätsfenster und wieder andere können absichtlich abgeschaltet werden. Wenn man die Frage ignoriert, verschwindet sie nicht – stattdessen taucht sie als verstreute Workarounds, Spalten mit fehlenden Werten, die niemand versteht, fehlgeschlagene Migrationsversuche sowie Supportprobleme nach dem Deployment wieder auf. Eine frühzeitige Entscheidung ermöglicht dem Team einen koheren Übergang anstelle vieler lokaler Vermutungen.

    5. Gehen Sie davon aus, dass Arbeit wiederholt werden muss und Konflikte entstehen

    Featurebeschreibungen gehen in der Regel von einem Benutzer, einer Klickaktion und einer reibungslosen Abfolge aus: Die Anfrage kommt einmal an, in der Zwischenzeit berührt nichts anderes das Datensatz, und die Antwort erreicht den Client. In der Produktion gibt es jedoch keine dieser Garantien.

    • Ein Benutzer klickt erneut, weil die Seite scheinbar blockiert ist.
  • Die mobile Verbindung bricht ab, nachdem der Server mit der Verarbeitung fertig ist, aber bevor die Antwort ankommt.
  • Die Warteschlange liefert dieselbe Nachricht zweimal aus.
  • Zwei Administratoren genehmigen denselben ausstehenden Vorgang mit wenigen Sekunden Abstand.
  • Eine geplante Aufgabe aktualisiert ein Datensatz, den der Benutzer noch in einer älteren Version anblickt.
  • Die vorab zu stellende Frage ist, ob die Aktion mehrfach ausgeführt werden kann, ohne Gefahr zu bergen, und ob sie gleichzeitig ablaufen darf. Wenn eine Wiederholung schadlos ist, können zusätzliche Mechanismen unnötig sein. Wenn eine Wiederholung eine zweite Zahlung, Einladung, Datei oder Lagerreservierung erstellt, benötigt das System eine Möglichkeit, zu erkennen, dass mehrere Versuche einer logischen Aktion entsprechen.

    Das Werkzeugset umfasst Idempotenzschlüssel, eindeutige Beschränkungen, bedingte Aktualisierungen, Versionsspalten für optimistisches Sperren, Transaktionen sowie eine Tabelle mit den bearbeiteten Nachrichten-IDs. Welche Methode geeignet ist, hängt davon ab, wo das Risiko liegt. Was niemals funktioniert, ist der Ansatz „Wir haben zuerst nachgesehen“, als könnte zwischen der Überprüfung und der Schreiboperation kein anderer Prozess eingreifen.

    Konkurrenzfehler sind besonders gefährlich, weil jede Zeile bei der Überprüfung korrekt erscheint. Der Fehler liegt im Übergang zwischen Lesen und Schreiben: Zwei Anfragen lesen denselben, gültigen Snapshot, beide bestehen ihre Überprüfungen und speichern jeweils ein Ergebnis, das eigentlich nur einmal auftreten sollte. Es ist weitaus besser, wenn die Datenbank eine der beiden konkurrierenden Operationen mit sichtbarem Konflikt ablehnt, anstatt zwei widersprüchliche Wahrheiten zu speichern, die später von Hand aufgelöst werden müssen.

    6. Planen Sie, wie sich die Funktion in der Produktion erklären wird

    Auf Ihrem Rechner verfügen Sie über Breakpoints, die Möglichkeit, eine Aktion zu wiederholen, sowie einen frischen Zustand des Designs. In der Produktion erhält das Team möglicherweise lediglich eine Support-Nachricht, die mitteilt, dass etwas nicht funktioniert hat.

    Stellen Sie sich daher die Untersuchung vor, bevor Sie den Code schreiben. Wenn eine Operation fehlschlägt – wie kann man dann feststellen, an welcher Stelle es zu einem Fehler kam? Kann eine einzelne Anfrage über verschiedene Dienste hinweg nachverfolgt werden? Zeigen die Protokolle an, ob die Aktion einmal oder dreimal ausgeführt wurde? Können Sie zwischen „nie gestartet“, „im Gange“, „teilweise abgeschlossen“ und „fehlgeschlagen“ unterscheiden?

    Dies ist kein Aufruf, alles zu protokollieren. Unstrukturierter Datenvolumen erschwert die Untersuchungen, anstatt sie zu erleichtern. Nützliche Überwachungsfunktionen sammeln genau genug Informationen, um den Ablauf einer einzelnen wichtigen Operation rekonstruieren zu können:

    • Eine Anfrage- oder Korrelations-ID
    • Die Ressourcen-ID und der Name der Operation
    • Dauer
  • Die stattgefundene Zustandswechsel
  • Die Versuchszahl
  • Eine stabile Fehlerkategorie
  • Auch die Bedeutung des Fehlers sollte beibehalten werden. Eine fehlgeschlagene Abfrage sollte nicht stillschweigend zu einer leeren Liste werden. Ein Timeout des Anbieters sollte nicht die Tatsache übergehen, dass die entfernte Seite die Arbeit möglicherweise bereits abgeschlossen hat. Ein allgemeiner Fehlerfangblock sollte nicht alle Ursachen in einer einzigen generischen Meldung zusammenfassen, bevor diese die Protokollierungsstelle erreicht.

    Denken Sie gleichzeitig an die Wiederherstellung. Ist es sicher, eine fehlgeschlagene Aufgabe erneut auszuführen? Kann der Support den aktuellen Zustand einer Operation ohne manuelles Abfragen mehrerer Tabellen einsehen? Kann der Benutzer sicher erneut versuchen, und kann ihm jemand eine genaue Übersicht über das Ergebnis geben?

    Opake Funktionen werden teuer, sobald etwas schiefgeht, und das Nachrüsten von Protokollierungsfunktionen kommt oft zu spät, weil der relevante Kontext nur während des Laufs der Operation vorhanden war. Wenn man die Nachweise bereits von Anfang an einplant, werden sie zu einem Bestandteil der Funktion statt zu einem Notfallpatch nach einem Vorfall.

    7. Entscheiden Sie, wie Sie nachweisen wollen, dass die Änderung sicher ist

    Wenn Tests nach dem Code geschrieben werden, spiegeln sie in der Regel seine aktuelle Struktur wider. Es gibt einen Hilfsfunktion, weshalb ein Test überprüft, ob sie aufgerufen wurde; es gibt eine Rückfalllösung, weshalb ein Test sicherstellt, dass diese angewendet wird; es wird ein Repository emuliert, weshalb ein Test bestätigt, dass die Emulation das Erwartete zurückgab. Solche Tests bestehen zwar, beweisen aber nicht viel.

    Die Entscheidung über die Überprüfungsmethode zuerst offenbart oft Schwächen im Design. Wenn eine Operation idempotent sein muss, sollte der Test sie mehrmals ausführen. Wenn gleichzeitige Freigaben eines Datensatzes unmöglich sein müssen, benötigt der Test tatsächlich konkurrierende Aktualisierungen. Wenn „nicht gefunden“ und „fehlgeschlagen“ unterschiedliche Ergebnisse sind, muss der Vertrag beides sichtbar machen. Wenn die Regel durch eine Datenbankbeschränkung durchgesetzt wird, kann kein simulierter Unit-Test zeigen, dass sie eingehalten wird.

    Das bedeutet jedoch nicht, dass jede Funktion eine umfangreiche End-to-End-Testsuite benötigt. Wählen Sie das Testniveau entsprechend der Schicht, die tatsächlich die Garantie durchsetzt:

    • Eine reine Transformation kann direkt unitgetestet werden.
    • Ein API-Vertrag erfordert in der Regel einen Integrationstest.
    • Eine im Datenbank gesicherte Invariante muss gegen eine echte Datenbank getestet werden.
  • Eine riskante Migration kann die Überwachung, einen schrittweisen Rollout oder ein Feature-Flag mit einem geplanten Entfernungstermin erfordern.
  • Auch die Umkehrbarkeit gehört in dieselbe Diskussion. Falls sich die Änderung falsch verhält, kann sie ausgeschaltet oder rückgängig gemacht werden, ohne die in der Zwischenzeit geschriebenen Daten zu verlieren? Wird die vorherige Anwendungsversion nach der Schema-Änderung weiterhin laufen, oder erfordert die Migration eine Erweiterungs- und Verkleinerungsschleife? Können Sie zuerst einer kleinen Gruppe die neue Version bereitstellen, bevor alle davon abhängen?

    Falls ein Design schwer zu testen oder schwer rückgängig zu machen ist, ist das oft ein Zeichen dafür, dass eine Operation zu viele Aufgaben übernimmt oder dass der Änderungsprozess einen kleineren Zwischenschritt benötigt. Ein absoluter Beweis ist nicht das Ziel, da Software stets Unsicherheiten beinhaltet. Man möchte vielmehr, dass die kritischen Garantien in Tests und Metriken sichtbar werden und dass gefährliche Entscheidungen rückgängig gemacht werden können, damit ein Fehler zu einer Lektion statt zu dauerhaften Schäden wird.

    Die Vorbereitungsarbeiten im angemessenen Maße halten

    Diese Fragen sind kein Argument dafür, dass Planung immer besser ist als Handeln. Übermäßige Analyse kann einfache Arbeiten verzögern und eine Architektur für Risiken schaffen, die sich niemals realisieren werden. Ein vernünftiger Filter besteht darin, sich nur auf Entscheidungen zu konzentrieren, die teuer wären, falls der Code falsch entscheiden würde: alles, was mit persistenten Daten, Geldern, Berechtigungen, externen Nebeneffekten oder öffentlichen Verträgen zu tun hat. Eine Kopieränderung oder eine interne Refaktorierung hinter einer stabilen Schnittstelle benötigt selten die vollständige Liste.

    In einer vereinfachten Form passt die Checkliste in die Beschreibung eines Tickets:

    • Das eigentliche Problem in einem Satz und wer es hat
    • Was „erledigt“ bedeutet und welche Effekte sekundär sind
    • Der alleinige Verantwortliche für jede Geschäftsregel
    • Der Plan für vorhandene Daten und alte Kunden
    • Behavior bei erneuten Versuchen und unter gleichzeitigem Zugriff
    • Was protokolliert wird und wie Fehler behoben werden
  • Wie die Garantie getestet wird und wie eine Änderung rückgängig gemacht werden kann
  • Zusammenfassung

    Sobald diese Fragen beantwortet sind, wird der Code in der Regel deutlich übersichtlicher. Das Zustandsmodell weist weniger unmögliche Kombinationen auf, jede Regel hat ihren festen Platz, die Datenbank stellt die Invarianten sicher, die Antworten geben an, ob die Arbeit abgeschlossen ist oder lediglich akzeptiert wurde, und die Tests konzentrieren sich auf die Garantie statt auf die aktuelle Anordnung der Funktionen.

    Deshalb können sorgfältige Ingenieure zu Beginn einer Aufgabe langsam erscheinen und dennoch früher fertig werden: Sie weigern sich, zulassen zu wollen, dass Produktunsicherheiten, veraltete Daten, Konkurrenzen sowie operative Blindstellen stillschweigend in dauerhafte technische Entscheidungen umgewandelt werden. Der richtige Zeitpunkt, sich mit diesen Problemen auseinanderzusetzen, ist vor dem ersten praktischen Implementierungszeitpunkt, an dem Aufrufe, Tests und Produktdaten zur Verfügung stehen. Die Funktion selbst zu schreiben ist selten der schwierige Teil – vielmehr liegt die Herausforderung darin, festzulegen, was sie bedeuten darf.

    Verwandte Artikel

  • Backend-Systemdesign durch Engpässe: Vom URL-Kürzer bis zum E-Commerce — Ein auf Anforderungen ausgerichteter Ansatz zur Gestaltung von Node.js-Backends: Wann Load Balancer, Redis, Replikate, Warteschlangen und Geschwindigkeitsbeschränkungen hinzugefügt werden sollten und was jede dieser Lösungen kostet.