Von fachlichen und technischen Daten
In einer Geschäftsanwendung werden vor allem fachliche Daten bearbeitet. Daneben gibt es aber eine ganze Reihe von technischen Daten (wie einer ID oder einem Erstelldatum). Diese beiden Arten von Daten können problemlos nebeneinander abgelegt werden. Sobald man allerdings beginnt die Grenzen zu verwischen fangen die Probleme an.
Bis sich die Auswirkungen dieser Vermischung bemerkbar machen kann man sich meist nicht mehr an die dazugehörigen Entscheidungen erinnern. So beginnt ein mühsames Suchen nach den Ursachen von teils äusserst seltsamen Fehlern.
Ich will gar nicht zusammenrechnen wie viele Stunden ich so verloren habe. Dabei waren es zu Beginn jeweils ganz kleine Entscheidungen die am Ende zu solchen Problemen führten. Wie klein die sein können soll das nachfolgende fiktive Beispiel rund um Auftragsformulare zeigen.
Wenn aus technischen Daten fachliche werden...
Meist beginnt alles mit einer kleinen zusätzlichen Anforderung. Neu soll beispielsweise das Eingangsdatum eines Formulars geführt werden. Man kann nun ein zusätzliches Feld "Eingang" anlegen oder den Wert ins Feld "Erstellt" hineinschreiben. Das ist ja für die Anwendung das gleiche, da alle Formulare beim Eintreffen erfasst werden.
Allerdings wird das Feld "Erstellt" durch die Anwendung hinweg immer als technisches Feld betrachtet das man weder auf der Oberfläche anzeigt noch irgendwie sonst verwendet. Damit ist es nun vorbei. Für das Objekt "Formular" wird das Feld "Erstellt" nicht nur angezeigt sondern auch noch gleich umbenannt – allerdings nur auf der Oberfläche. Und in den Reports. Und im Export. Und bei allen anderen zukünftigen Verwendungen dieses Objekts.
... und dies zu Problemen führt
Die Sonderregelung für "Formular" ist zu diesem Zeitpunkt schon aufwändig aber noch kein Problem. Dazu braucht es meist noch eine kleine Veränderung der Geschäftsabläufe, wie einer externen Erfassung der Formulare.
Um diese externe Erfassung zu ermöglichen kommt dann oft eine Excel-Liste als Transfermethode zum Einsatz. So müssen die externen Sachbearbeiter nichts Neues lernen und im Zielsystem wird eine kleine Importfunktion hinzugefügt. Soweit ist dies ebenfalls noch kein Problem. Doch was soll nun ins Feld "Erstellt" geschrieben werden? Das Datum an dem die Daten importiert wurden oder das Eingangsdatum?
Aus fachlicher Sicht muss das Eingangsdatum gesetzt werden, da sich zwischen dem Eingang und dem Import Preise verändert oder Fristen abgelaufen sein könnten. Aus technischer Sicht wird das Formular mit dem Import erstellt.
Das Problem ergibt sich sobald beide Sichten "ihr" Datum benötigen. Das technische Erstelldatum könnte beispielsweise für einen Report zur internen Kostenverrechnung dienen. Wird dieser Report nach Eingang aber vor dem Import der Formulare ausgeführt stimmen die Werte nach dem Import nicht mehr mit dem Datenbestand in der Applikation überein. Die importierten Formulare fehlen im Report, werden daher nicht verrechnet und Ende Jahr gilt es zu klären woher die Differenz kommt.
Ursachen
Bei den Fällen die mir bekannt sind war die Ursache oft eine verfrühte Optimierung oder der krampfhafte Versuch Diskplatz zu sparen. Weder der zusätzliche Speicherplatz noch der Aufwand ein Feld mehr anzulegen hätte man bemerkt. Im Gegensatz zu all dem Aufwand zum Aufspüren der fehlerhaften Auswertungen.
Bitte beachten: DRY (Don’t repeat yourself) gilt nur wenn es sich wirklich um die gleichen Dinge handelt. Andernfalls ist dies keine Repetition sondern erfüllt einen anderen (unabhängigen) Zweck.
Wie verhindern?
Im obigen Beispiel hätte man spätestens als die Importfunktion erstellt wurde die Datenfelder trennen müssen. Allerdings denkt in so einem Moment niemand an solche Zusatzaufgaben. Und nur um Daten genauer abzulegen will niemand all die Oberflächen und Reports anpassen.
Daher bin ich mittlerweile der Meinung dass bei den ersten Anzeichen einer fachlichen Verwendung der technischen Daten die Alarmglocken läuten müssen. Fängt man an bei einzelnen Objekten technische Felder einzublenden ist dies ein deutliches Zeichen das hier ein fachliches Feld fehlt. Der Aufwand dies jetzt gleich sauber zu lösen ist geringer als wenn man wartet bis dieses Feld überall verwendet wird. Und fehlt doch gerade die Zeit kann man immer einen entsprechenden Task eröffnen und im nächsten Sprint (mit zusätzlichen Informationen) beheben.
Dies gilt übrigens im gleichen Masse für fachliche Felder die technisch genutzt werden, auch wenn dieser Fall wohl weniger oft vorkommt.
Fazit
Das Single Responsibility Principle (SRP) gilt nicht nur für Klassen und Methoden, sondern auch für Daten. Bevor man für eine kleine Einsparung bei der Datenmenge anfängt Felder mehrmals zu verwenden sollte man sich über die möglichen Konsequenzen bewusst werden und darauf verzichten. Angesichts der aufwändigen Fehlersuche bezweifle ich das durch ein "eingespartes" Feld wirklich Kosten gespart werden können.