Deutsche Fachsprache, englischer Code: Wo verläuft die Grenze?
Die Begriffe an der Workshop-Wand sind deutsch, der Code ist englisch. Diesen Ăśbergang entscheidet fast nie jemand bewusst, und genau das wird teuer.
(Bild: Manuel Masiero / KI / iX)
- Golo Roden
Am Ende eines Modellierungsworkshops sieht das dafür genutzte Whiteboard oft beeindruckend aus. Zettel in mehreren Farben kleben darauf, Pfeile dazwischen verweisen auf Zusammenhänge, und auf den Pfeilen stehen die Begriffe, um die drei Tage lang gerungen wurde: „Rechnungsstellung“, „Mahnlauf“, „Teilzahlung“, „Storno“. Die Fachabteilung nickt, die Entwicklerinnen und Entwickler nicken, und alle haben zum ersten Mal seit Monaten das Gefühl, über dieselbe Sache zu sprechen.
Eine Woche später öffne ich das Repository, und die erste Klasse heißt InvoiceService. Nicht aus Trotz, nicht nach einer Diskussion, sondern weil es sich beim Tippen so angefühlt hat, wie Code eben aussieht. Zwischen Whiteboard und Repository liegt eine Entscheidung, die niemand getroffen hat, und um die es in diesem Beitrag geht.
Der Reflex hat gute GrĂĽnde
Ich halte diesen Reflex durchaus für nachvollziehbar. Immerhin: Alles, woraus Entwicklerinnen und Entwickler ihr Handwerk lernen, ist englisch: die Schlüsselwörter der Sprache, die Signaturen der Standardbibliothek, die Dokumentation der Frameworks, die Antworten auf Stack Overflow. Wer den ganzen Tag „for“, „return“ und „Repository“ liest, schreibt beim nächsten Bezeichner nicht plötzlich auf Deutsch weiter.
Dazu kommt ein Argument, das in jeder dieser Diskussionen fällt: die internationale Lesbarkeit. Wenn morgen jemand aus einem anderen Land ins Team kommt, soll der Code lesbar und verständlich bleiben. Das Argument ist nicht falsch, es ist nur in den meisten Fällen unbelegt, weil das betreffende Team seit acht Jahren aus denselben sechs Personen in derselben Stadt besteht und sämtliche Anforderungen seit jeher auf Deutsch bekommt.
Es gibt außerdem noch einen Grund, den allerdings kaum jemand ausspricht: Englisch im Code sieht nach Professionalität aus. Ein Bezeichner wie createInvoice wirkt wie Software, rechnungErstellen wirkt wie ein Provisorium aus dem Rechnungswesen. Dieses Gefühl ist unter Entwicklerinnen und Entwicklern durchaus real und verbreitet. Und zugleich ist es der schwächste aller Gründe, weil es über die Fachlichkeit rein gar nichts aussagt.
Vor allem aber gelten diese Gründe für die Technik. Dass HttpClient nicht HttpKlient heißen sollte, wird wohl niemand bestreiten, und ich persönlich möchte eine solche Umbenennung auch nicht. Der Reflex wird erst dort teuer, wo er auf Fachlichkeit trifft, und dieser Übergang ist so fließend, dass er im Alltag nicht auffällt.
Stilfrage oder Modellierungsfrage?
Sobald das Thema nach der zu verwendenden (natürlichen) Sprache aufkommt, kippt die Diskussion üblicherweise binnen weniger Minuten in einen Streit über Geschmack. Jemand schreibt rechnungErstellen auf das Whiteboard, jemand anderes verzieht das Gesicht, und ab da geht es um Denglisch, um Umlaute in Bezeichnern und um die Frage, ob das nicht furchtbar aussehe. Genau diese Diskussion ist die Ursache dafür, dass sich an der Sprachfrage nie etwas ändert. Sie verbraucht die gesamte Aufmerksamkeit für den unwichtigsten Teil des Problems.
Videos by heise
Deshalb möchte ich einen Test voranstellen, der die beiden Ebenen sauber trennt. Übersetzen Sie einen Namen und prüfen Sie danach, ob sich mit dem Vokabular noch genau dieselben Unterscheidungen ausdrücken lassen wie vorher. Ist das so, handelt es sich um eine Stilfrage. Fehlt hinterher eine Unterscheidung, ist es eine Modellierungsfrage.
rechnungErstellen und createInvoice bezeichnen exakt denselben Vorgang, und es geht keine Unterscheidung verloren. Deshalb ist das eine Stilfrage, also eine Teamkonvention, und darüber lohnt keine lange Debatte. Wenn dagegen „Verfügbarkeit“ und „Einsatzbereitschaft“ im Code beide zu availability werden, dann hat sich das Modell verändert.
Nebenbei erledigt derselbe Test die Umlautfrage, die sonst garantiert als erstes aufkommt. Ob im Code Verfügbarkeit oder Verfuegbarkeit steht, ändert keine einzige Unterscheidung. Insofern fällt auch das unter Stil und Konvention, ist also die Diskussion nicht wert.
Was beim Ăśbersetzen verschwindet
Der Verlust, um den es hier inhaltlich geht, ist deshalb so schwer zu bemerken, weil das englische Wort durchaus existiert und auf den ersten Blick vollkommen passend wirkt: „availability“ ist keine schlechte Übersetzung von „Verfügbarkeit“, sondern im Gegenteil sogar eine gute. Es ist nur leider zugleich auch eine gute Übersetzung von „Einsatzbereitschaft“, und in einer Domäne, in der ein Fahrzeug verfügbar sein kann, ohne einsatzbereit zu sein, hängen an diesem Unterschied später wichtige fachliche Entscheidungen.
Am häufigsten sehe ich das Muster bei Vorgängen, die im Deutschen fein aufgefächert sind. „Auftrag“, „Bestellung“ und „Abruf“ sind in vielen Unternehmen drei verschiedene Dinge mit drei verschiedenen Rechtsfolgen, drei verschiedenen Beteiligten und drei verschiedenen Zeitpunkten. Im Code heißen sie dann alle order, und zwar nicht, weil jemand die drei für dasselbe hielte, sondern weil das englische Wort auf alle drei anwendbar ist.
Der Moment des Verlusts ist dabei unsichtbar, und das macht ihn so heimtückisch. Er tritt zum Beispiel ein, wenn eine einzelne Person spät am Abend noch schnell eine Klasse anlegt und dafür ein Wort wählt. Es gibt keine Diskussion, kein Review hakt nach, und die Fachabteilung bekommt den Namen ohnehin nie zu sehen. Erst wenn Monate später der zweite der drei Vorgänge modelliert werden soll, stellt sich heraus, dass der beste Name bereits vergeben ist, und dann heißt der zweite eben specialOrder.
Schlimmer als der Hinweg ist der Rückweg. Solange nur übersetzt wird, weiß das Team noch, was gemeint war; das Wissen sitzt in den Köpfen derjenigen, die im Workshop dabei waren. Zwei Jahre später aber liest jemand order im Code, die Fachabteilung liest „order“ im Bericht, und beide Seiten raten, welcher der drei Vorgänge gemeint ist.
Nicht selten raten beide Seiten falsch und der Fehler gehört leider zu der Sorte, die keinen Test rot werden lässt. Er zeigt sich als Auswertung, die nicht stimmt, als Prozess, der an einer Stelle hakt, oder als Diskussion darüber, ob eine Zahl im Report die richtige ist. Ich habe an anderer Stelle darüber geschrieben, wie stark die Wortwahl bestimmt, ob ein System eine Geschichte erzählt oder einen Polizeibericht. Die Sprachwahl liegt jedoch noch eine Ebene darüber. Sie entscheidet, welche Wörter überhaupt zur Auswahl stehen.
Wenn die Fachsprache Gesetz ist
Es gibt Domänen, in denen diese Abwägung gar nicht erst stattfindet, weil die Sprache vorgegeben ist. „Umsatzsteuer“ ist nicht „VAT“. Die beiden Begriffe beschreiben ähnliche Konzepte, sie sind aber in unterschiedlichen Rechtsordnungen definiert, und sobald es um Sätze, Fristen, Ausnahmen und Meldepflichten geht, laufen sie auseinander.
Zur „Vorsteuer“ gibt es überhaupt kein Gegenstück, das ein englischer Begriff in einem Wort einfängt. Ein „Mahnbescheid“ ist kein „reminder“, eine „Kündigungsfrist“ (im arbeitsrechtlichen Sinn) keine „notice period“, und ein „Betriebsrat“ ist kein „works council“ mit denselben Befugnissen. Wer solche Begriffe übersetzt, macht sie nicht ungenauer, sondern falsch.
Hier ist die Domänensprache nicht Ausdruck einer Vorliebe, sondern Teil der Anforderung. Das Gesetz definiert den Begriff, die Fachabteilung verwendet ihn, die Prüferinnen und Prüfer fragen danach. Ein Modell, das an dieser Stelle übersetzt, weicht nicht vom Geschmack ab, sondern von der Rechtslage.
Was in solchen Domänen passiert, wenn trotzdem übersetzt wird, lässt sich gut beobachten. Im Code steht tax, im Gespräch mit der Steuerberatung steht „Umsatzsteuer“, und zwischen beidem sitzt eine Person, die den Übergang im Kopf leistet. Solange diese Person da ist, funktioniert das. Wechselt sie die Stelle oder kommt eine Prüfung ins Haus, muss jemand rekonstruieren, welcher steuerliche Begriff hinter welchem Feld steckt, und diese Rekonstruktion ist reine Archäologie.
Die Schweiz treibt das noch weiter: Dort ist Bundesrecht auf Deutsch, Französisch und Italienisch gleichermaßen verbindlich, drei Fassungen desselben Gesetzes, keine davon ist das alleingültige Original und keine davon ist einfach nur eine Übersetzung. Ein Team, das für diesen Markt entwickelt, hat nicht die Wahl zwischen drei Sprachen, sondern die Aufgabe, drei gleichwertige Vokabulare in einem Modell unterzubringen.
Wer darf den Namen korrigieren?
Damit komme ich zu der Frage, die mir in solchen Diskussionen wohl am häufigsten gestellt wird, und sie ist vollkommen berechtigt: Wo genau soll die Grenze verlaufen? Soll wirklich alles im System auf Deutsch geschrieben werden?
Die Antwort darauf lautet nein, und es gibt ein Kriterium, an dem man diese Antwort festmachen kann: Ein Name gehört dann in die Domänensprache, wenn Fachexpertinnen und Fachexperten ihn korrigieren könnten. Legen Sie ihnen RechnungAusgestellt vor, können sie widersprechen: Das heiße im Haus „Rechnungsstellung“ und das sei etwas anderes als „Rechnungsversand“. Legen Sie ihnen HttpClient vor, können sie nichts dazu beitragen, weil der Name in ihrer Domänensprache keine Bedeutung hat.
Praktisch anwenden lässt sich das Kriterium mit einem Vorlesetest. Nehmen Sie die Namen der Events und Commands eines Moduls, lesen Sie sie der Fachabteilung vor und beobachten Sie, was passiert. Kommt Widerspruch, Nachfrage oder ausdrückliche Zustimmung, dann gehören diese Namen in die Domänensprache, unabhängig davon, in welcher sie gerade geschrieben sind. Kommt ein ratloser Blick, sind Sie in der Technik gelandet, und der Name ist dort richtig aufgehoben.
Dieses Kriterium hängt nicht an Schichten, Ordnern oder Namensräumen, sondern daran, wer über den Namen urteilen kann. Deshalb funktioniert es auch in Codebasen, in denen die Schichtung längst aufgeweicht ist. Es liefert eine erstaunlich klare Aufteilung: Aggregate, Events, Commands, fachliche Zustände und fachliche Fehler tragen die Domänensprache, während Frameworks, technische Bausteine, Logs und Metriken englisch bleiben.
Gemischte Bezeichner wie RechnungRepository sind nach diesem Kriterium kein Sündenfall, sondern die sichtbar gewordene Naht zwischen beiden Welten. Der fachliche Teil des Namens sagt, worum es geht, der technische, wie es umgesetzt ist. Ich halte das nicht für einen faulen Kompromiss, sondern für ehrlicher als jede der beiden reinen Varianten. Persönlich gefällt es mir vom Stil her zugegebenermaßen nicht, aber darüber kann ich hinwegsehen, weil ich die dahinterliegende Überlegung für die wichtigere halte.
Kommentare, Commit-Messages und Dokumentation fallen dagegen unter das erste Kriterium: Sie lassen sich übersetzen, ohne dass eine Unterscheidung verloren geht. Damit sind sie Konvention, und jedes Team darf sie regeln, wie es möchte.
Die Schnittstelle als Grenzfall
Der Fall, an dem sich das Kriterium bewähren muss, ist die Schnittstelle nach außen. Hier bricht die Diskussion regelmäßig neu aus, meist mit dem Argument, eine API müsse selbstverständlich englisch sein. Ich halte die Frage in dieser Form für falsch gestellt.
Die bessere Frage lautet: Ist diese Schnittstelle Teil des Modells oder eine Veröffentlichung davon? Eine API, die ausschließlich andere Systeme derselben Domäne bedient, gehört zum Modell. Sie spricht dessen Sprache, und dort zu übersetzen heißt, genau den Verlust eine Ebene weiter außen einzubauen, den der Kern gerade vermieden hat.
Diese Unterscheidung ist deshalb so nützlich, weil sie eine Frage beantwortet, die sich sonst bei jedem einzelnen Feld neu stellt. Ein Team muss nicht für jede Route und jedes Attribut erneut abwägen, sondern einmal je Schnittstelle festlegen, auf welcher Seite der Grenze sie steht. Danach ergibt sich die Sprache von selbst, und die Diskussion verlagert sich von der Namenswahl auf die Frage, wer diese Schnittstelle eigentlich nutzt. Das ist die deutlich produktivere Frage.
Eine API mit fremden, international verteilten Konsumentinnen und Konsumenten ist etwas anderes. Sie ist eine Kontextgrenze, und an Kontextgrenzen ist Übersetzung nicht nur erlaubt, sondern die saubere Lösung. Entscheidend ist, dass sie explizit stattfindet, mit einem dokumentierten Mapping, das jemand lesen und prüfen kann.
Explizit heiĂźt vor allem: Wo zwei Fachbegriffe auf ein englisches Wort fallen wĂĽrden, mĂĽssen sie getrennt bleiben. Ein Fahrzeug, das verfĂĽgbar, aber nicht einsatzbereit ist, braucht in der ĂĽbersetzten Fassung zwei Felder statt einem:
{
"vehicleId": "8f2c1a",
"available": true,
"operational": false
}
Dazu gehört die Festlegung, dass available für die Verfügbarkeit steht und operational für die Einsatzbereitschaft, und zwar dort, wo sie später auch jemand sucht. Fehlt sie, sucht sich in zwei Jahren jede Konsumentin und jeder Konsument eine eigene Deutung, und die Unterscheidung zerfällt genau dort wieder, wo sie mühsam erhalten wurde.
Der Fehler ist also nicht die englische Schnittstelle. Der Fehler ist die stillschweigende Schnittstelle, bei der die Übersetzung im Kopf einer einzelnen Person stattgefunden hat und nirgends aufgeschrieben wurde. Sprachgrenzen sind Kontextgrenzen, und Kontextgrenzen gehören dokumentiert.
Warum Event Sourcing keine zweite Chance gibt
Bis hierhin gilt alles Gesagte unabhängig davon, wie ein System seine Daten hält. Es gibt allerdings eine Architektur, in der die Sprachfrage eine deutlich schärfere Form annimmt, und das ist Event Sourcing.
In einem klassischen System, das Zustände überschreibt, ist ein Name eine Refactoring-Entscheidung. Fällt in zwei Jahren auf, dass order drei Vorgänge vermengt, benennt jemand um, passt die Datenbankspalten an, und nach einer Stunde ist die Sache erledigt. Unangenehm, aber ohne Nachwirkung.
Events sind unveränderlich, und das ist ihr Sinn. Ein Event, das vor sieben Jahren als InvoiceIssued geschrieben wurde, heißt in sieben weiteren Jahren immer noch so, und mit ihm ist auch jede Unterscheidung konserviert, die beim Benennen verlorenging. Ob ein bestimmtes order-Event einen Auftrag, eine Bestellung oder einen Abruf meinte, lässt sich nachträglich nicht rekonstruieren, wenn die Information nie im Event stand.
Damit ist der Name eines Events keine Refactoring-Entscheidung mehr, sondern eine Festlegung mit einer Lebensdauer von Jahrzehnten. Ich kenne wenige andere Stellen in der Softwareentwicklung, an denen eine beiläufige Wortwahl so lange nachwirkt. Wer Event Sourcing einsetzt, sollte die Sprachfrage deshalb nicht beiläufig im Code beantworten, sondern bewusst vor dem ersten geschriebenen Event.
Die Entscheidung, die niemand trifft
Eine allgemeingültige Antwort auf die Sprachfrage gibt es nicht, und ich misstraue jedem, der sie anbietet. Es gibt Domänen, in denen Englisch die richtige Wahl ist, es gibt Teams, für die Deutsch die einzig sinnvolle ist, und es gibt Systeme, in denen beides nebeneinander steht, sauber getrennt an einer dokumentierten Grenze.
Ein klarer Fehler ist es dagegen, die Sprachfrage nie zu stellen. Dann entscheidet sie sich nämlich trotzdem, nur eben nebenbei: durch den ersten Commit, durch die Vorlage eines Frameworks oder durch diejenige Person, die am lautesten für ihre Gewohnheit argumentiert. Wie teuer es wird, wenn Software rein technisch gedacht wird, habe ich an anderer Stelle beschrieben; die Sprachfrage ist ein Musterfall dafür, weil sie technisch aussieht und fachlich ist.
Der Aufwand, es besser zu machen, ist überschaubar. Es braucht eine Stunde im Team, die beiden Kriterien aus diesem Beitrag und die Bereitschaft, das Ergebnis aufzuschreiben. Domain-Driven Design ist an vielen Stellen komplizierter gemacht worden, als es sein müsste. An dieser Stelle ist es tatsächlich einmal einfach.
(mro)