Ich habe inzwischen 35 Jahre Softwareentwicklung auf dem Buckel - viele davon für Geld...
Ich habe nun seit fast 35 Jahren mit Datenbanken zu tun. Ich kann mich noch an meine Vorlesung im Studium zu dem Thema erinnern: Strukturiertes Ablegen großer Datenmenge mit Hilfsmitteln zum einfachen, gezielten Zugriff auf enthaltene Informationen. Und dann vergleiche ich das mit dem, was ich in meiner praktischen Arbeit bei Kunden und Arbeitgebern sehe und gesehen habe. Wenn dann meine Grundstimmung ebenfalls noch passt, dann kommt ein Artikel wie der vorliegende heraus.
Im ersten Teil geht es um die erfrischenden lokalen Besonderheiten relationaler Datenmodelle. Ich hatte vergessen, zu erwähnen, dass es hier um relationale Datenbanken geht - spezialisierte Formen wie Zeitreihendatenbanken oder Geodatenbanken betrachte ich hier nicht, weil ich damit noch nicht so lange Berührung und daher wenig Erfahrung mit Produktivinstanzen in meiner Laufbahn gesammelt habe - ich bin mir aber sicher, dass es entsprechende Wucherungen auch da gibt. Die sogenannten Cloud- oder Dokumenten- oder noSQL-Datenbanken lasse ich hier mal ganz raus, weil sie mit traditionellen Datenbanken nichts zu tun haben.
Nun also zu Datenmodellen: Eigentlich lernt man etwas über Normalformen, egal wo und wie man mit Datenbanken und ihren zugrunde liegenden Modellen in Berührung kommt. Ich habe den Verdacht, dass selbst in Büchern, die "in 2 Wochen" oder "in 10 Tagen" im Titel haben dieses Wort zumindestens einmal benutzt und in vielen davon sogar erklärt wird.
Das ist ein Konzept, das in meiner Erfahrung erstaunlich selten tatsächlich eingesetzt wird. Warum das so ist? Keine Ahnung - man könnte versuchen, das darauf zu schieben, dass sich heute kein Entwickler mehr mit dem Mdoell auseinandersetzt, sondern einfach den erstbesten OR-Mapper dazu verwendet, ein Schema automatisch erzeugen zu lassen. Das ist vielleicht einer der Gründe dafür, aber ich denke, es ist eher Faulheit und Ignoranz, die hier den Löwenanteil bringen. Was meine ich damit?
Nun - stellen wir uns ein Schema oder Modell vor, das eine Tabelle mit Stammdaten von Personen enthält. Nun muss im Zuge der Entwicklung der Anwendung ein neuer Sachverhalt für diese Person aufgenommen werden. Dieser Sachverhalt hat eine 1:1 Beziehung zur Person - man könnte das mit einer neuen Tabelle und einer Fremdschlüsselbeziehung mit UNIQUE-Constraint modellieren. Einfacher ist es aber, neue Spalten zur Personentabelle hinzuzufügen. Kurz darauf passiert dasselbe mit einem zweiten Sachverhalt - auch hier wieder eine 1:1 Beziehung mit der Person, jedoch linear unabhängig vom ersten. Was geschieht? Weil wir eingetretenen Pfaden folgen werden auch hier wieder neue Spalten zur Personentabelle hinzugefügt, statt eine eigene Tabelle zu modellieren.
Nicht nur, dass das im Laufe der Zeit zu einer gigantisch breiten Tabelle führt, was nicht gut für die Performance der Datenbank sein kann - die Tabelle ist auch extrem spärlich befüllt:
|Person |Person |Sachverhalt A|Sachverhalt A|Sachverhalt A|Sachverhalt B|Sachverhalt B|Sachverhalt B|
|Spalte 1|Spalte 2|Spalte 1 |Spalte 2 |Spalte 3 |Spalte 1 |Spalte 2 |Spalte 3 |
|--------|--------|-------------|-------------|-------------|-------------|-------------|-------------|
|Daten |Daten |Daten |Daten | | | | |
|Daten |Daten | | | |Daten | |Daten |
Nun könnte man sagen, dass ein "vernünftiges" Datenbankmanagementsystem so etwas intern schon erkennen und entsprechend effizient speichern wird. Wenn man sich darauf verlassen möchte - bitte, allerdings leistet diese Art der "Datenmodellierung" dem nächsten Antipattern Vorschub, auf das ich jetzt zu reden kommen möchte.
Neue Spalten - bisher habe ich diskutiert, was passiert, wenn neue Entitäten falsch zum Modell hinzugefügt werden. Ich habe so etwas tatsächlich in der Praxis erlebt - bis zum Excess, der darin bestand, dass eine EMail versendet wurde, in dem die 100. Spalte in der zentralen Tabelle der Datenbank gefeiert wurde. Meine Reaktion war: Ich würde mich schämen und das nicht auch noch feiern!
Soll nun aber eine einzelne neue Spalte zu einer Tabelle hinzugefügt werden - speziell zu einer, die schon sehr viele Spalten aufweist - kommt mit schöner Regelmäßígkeit die Diskussion "Brauchen wir eigentlich eine neue? Können wir nicht einfach eine nachnutzen, die bereits da ist? Mein ebenso regelmäßiger Einwurf, dass die Spalte, die da nachgenutzut werden soll ja nicht ohne Grund existiert wurde dann ebenso regelmäßig gekontert mit - aber da hat ja schon seit 5 Jahren niemand mehr reingeschrieben!
Also ich erkenne in dieser Argumentation ein Problem - scheinbar aber eben nur ich. Diese Spalte enthält Daten, sie wurde für einen bestimmten Sachverhalt angelegt und gehört dazu - auch wenn man sich nicht die Mühe gemacht hat, daraus ein eigenes Entity zu schaffen. Was, wenn dieser Sachverhalt doch irgendwann wieder benötigt wird - zur Migration beispielsweise - und ein Stück Code eine Abfrage durchführt, in deren Ergebnis alle Datensätze auftauchen - auch die, in denen der Wert in diesen Spalten gar keinen Bezug zu dem alten Sachverhalt haben? Ganz einfach - wir erzeugen eine weitere Spalte in der Tabelle, die uns sagt, zu welchem Sachverhalt die jeweilige Zeile gehört. An deiser Stelle hatte ich dann regelmäßig das Gefühl, nichts mehr zur Diskussion beitragen zu können - damit hat man ja jetzt das Kunststück vollbracht, Entities innerhalb eines Entities zu implementieren.
Aber es gab auch noch weitere - ebenso "geniale" Ideen zur Erweiterung von Tabellen: Wir haben das nagende Gefühl, dass viele Spalten in einer Tabelle schlecht sind - daher haben wir ein schlechtes Gewissen und versuchen, es dadurch zu geruhigen, dass wir eine Binärspalte (einen Blob) benutzen - damit müssen wir die Tabelle nie wieder anfassen - alle Erweiterungen schreiben wir einfach in den Blob rein und interpretieren ihn, wenn wir ihn auslesen! Ah - nun haben wir also nicht Entitäten in Entitäten implementiert, sondern eine noSQL-Datenbank in einer relationalen Datenbank implementiert - mit allen Nachteilen und keinem ihrer Vorteile - Glückwunsch! Das wird auch nicht dadurch besser, dass man statt einer Binärspalte eine JSON- oder XML-Spalte benutzt.
Besonders grandios wird es - und ich habe tatsächlich auch das in meiner Laufbahn in Produktivsystemen erlebt - wenn diese one-catches-all-Spalten Referenzen auf Datensätze in der Datenbank enthalten. Referentielle Integrität kann da natürlich nicht mehr sichergestellt werden - ON DELETE und ON UPDATE funktionieren nicht mehr. Damit kann man davon ausgehen, dass mit dem Speichern eines Datensatzes in der Datenbank der Prozess des Verrottens beginnt...
Die unsaubere Erstellung von Datenmodellen ist aber nicht nur auf Datenbanken beschränkt: XML ist ein weiterer dankbarer Kandidat für so etwas: In meiner Laufbahn habe ich hin und wieder gesehen, dass XML ohne jedew Schema benutzt wurde, was das Parsen extrem erschwerte. Wurden Schemata benutzt, war das auch nicht immer besser: Sehr oft kam in den XML-Schemate nämlich xs:any vor. An sich wäre das nicht schlimm - immer wieder stellte sich aber heraus, dass das Protokoll auf ein bestimmtes Element innerhalb dieses xs:any aufbaute, dessen Korrektheit eben nicht bereits vom Parser gecheckt werden konnte!
Interesant is auch immer wieder, dass es nicht nur im Inhalt oder der Struktur zu data rot kommt - auch die Dokumentation ist leider sehr oft davon betroffen. Wenn auf solche Fragen wie "Wie viele Zeichen sind in dieser Spalte erlaubt?" nicht nur die Antwort kommt "Das wissen wir nicht" sondern auch noch "Wir wissen nicht, wie man das herausfinden könnte", dann ist da definitiv etwas faul.
Auch die Auseinanderentwicklung von Modell und Code ist problematisch und hat etwas mit Dokumentation und Impact Analyse zu tun: Ein Beispiel: Für einen bestimmten Use Case habe ich eine Implementierung vorgenommen, die Kompromisse gemacht hat, da die Spalte des Datenmodells eine gewisse Länge hatte. Nachdem ein Weisungsbefugter sagte "Mach die Spalte einfach breiter" war meine Antwort: "Kannst Du mirgarantieren, dass nirgendwo in der Codebasis die aktuelle Länge fest einprogrammiert ist und irgendwo etwas auf seltsame Art und Weise kaputt geht, wenn wir das ändern?" - Die Breite des Feldes ist ungeändert immer noch im Produktivbetrieb...
All diese Dinge sind technical debt - alle sorgen dafür, dass data rot nicht oder viel zu spät erkannt wird. Manche Leute - und ich neige in diese Richtung - sind ja der Meinung, dass es so etwas wie Security Vulnerabilities und Software Bugs nicht gibt - alle Software Bugs sind Security Vulnerabilities. Und wenn schon im Datenmodell auf die beschriebene - oder andere - Weisen geschlampt wird, kann es um die Cybersecurity des Produktes nicht gut bestellt sein!
Styles für GeoJSON in EBMap4D
22.08.2021
Ich habe bereits darüber berichtet, dass EBMap4D jetzt über die Möglichkeit verfügt, beliebige GeoJSON-Layer darzustellen. Nun ist die Anwendung um die Möglichkeit erweitert worden, in diesen GeoJSON-Daten enthaltene Stilinformationen für die Darstellung zu nutzen.
WeiterlesenAI und ML Android Basteln C und C++ Chaos Datenbanken Docker dWb+ ESP Wifi Garten Geo Go GUI Hardware Java Jupyter JupyterBinder Komponenten Links Linux Markdown Markup Music Numerik OpenSource PKI-X.509-CA Präsentationen Python QBrowser Rants Raspi Revisited Security Software-Test sQLshell TeleGrafana Verschiedenes Video Virtualisierung Windows Upcoming...
Ich schrieb vor einiger Zeit über die Visualisierung und Analyse von Abhängigkeiten in Linux-Distributionen, die auf Debian aufbauen. Damals habe ich noch behauptet, dass andere Distributionen, die zum Beispiel auf yum als Paketmanagement-Lösung setzen nur schwer in dieser Art und Weise analysierbar sind. Ich habe weiter recherchiert und nun auch dafür eine Lösung gefunden.
WeiterlesenHier meine Highlights der DefCon 34 in Las Vegas
WeiterlesenIch habe neulich darüber geschrieben, dass ich mit in meinem Homelab von Gitlab verabschieden möchte und nach Alternativen gesucht habe. Bei meiner Suche stieß ich auf verteilte Issue Tracker, die die vertraute Integration von PlantUML nicht bieten. Daher suchte ich nach einem Weg, auch dieses Feature in solchen Lösungen zu integrieren.
WeiterlesenManche nennen es Blog, manche Web-Seite - ich schreibe hier hin und wieder über meine Erlebnisse, Rückschläge und Erleuchtungen bei meinen Hobbies.
Wer daran teilhaben und eventuell sogar davon profitieren möchte, muss damit leben, daß ich hin und wieder kleine Ausflüge in Bereiche mache, die nichts mit IT, Administration oder Softwareentwicklung zu tun haben.
Ich wünsche allen Lesern viel Spaß und hin und wieder einen kleinen AHA!-Effekt...
PS: Meine öffentlichen Codeberg-Repositories findet man hier.