MS Dynamics CRM
Eine Weile habe ich mit Microsoft Dynamics CRM gearbeitet. Und damit ein Produkt kennengelernt, dessen Ansatz ich interessant finde, mich aber auch nachdenklich stimmt.
Mit Dynamics CRM kann man sich eine datenzentrierte Webanwendung “zusammen klicken” und erhält eine ansprechende GUI, einen mächtigen Formular-Editor und Daten sind auch per API abfragbar und veränderbar. Das Ganze ist JavaScript-basiert und mithilfe von C#-Plugins erweiterbar. Für CRM wurden auch diverse Hilfstools entwickelt, sodass man sehr viele Aufgaben ohne Code in einer GUI erledigen kann.
Auf der anderen Seite hat CRM aber auch ein paar Tücken. (Ich kenne die 2013er Version, vielleicht hat sich das also bis jetzt gebessert. Ich kann mir nicht vorstellen, dass diese Einschränkungen komplett behoben sind.) Dinge, die einfach funktionieren müssen, waren nicht oder nur sehr umständlich möglich.
Gewisse Design-Entscheidungen mussten auch zeitig getroffen werden, welche die Erweiterbarkeit des Produkts in der Zukunft einschränkten. Auch das war ein Fakt, den ich nicht für optimal hielt.
Nichtsdestotrotz war das eine spannende Zeit. In diesem Artikel möchte ich über die Dinge schreiben, von denen ich in meiner Zeit mit CRM das Folgende gelernt habe: Auch wenn die “Schulinformatik” (hier im Sinne von Schulmedizin) etwas Bestimmtes lehrt (Redundanzvermeidung von Daten z.B.), in der Praxis kann man auch zu einer Lösung kommen, die diesen Leitspruch nicht einhält und trotzdem eine korrekte Implementierung darstellt.
Redundanzvermeidung
CRM verfolgt mit seinen Formularen fast einen MVC-Ansatz, mit der Ausnahme, dass die Formulare sehr eng an die jeweilige Entität gebunden ist. Man kann Formulare ebenso HTML-basiert und völlig unabhängig von den Entitäten erstellen, aber die an die Entitäten gebundenen Formulare sind der Standardweg, ein Formular zu erstellen. Berechnete Felder stellten ein Problem dar. Berechnet im Sinne von, das Ergebnis ist nicht direkt in einem Datenfeld der Entität gespeichert, sondern muss durch eine Art SQL-Abfrage berechnet werden.
Die GUI bietet Möglichkeiten, die Beziehungen zwischen den Entitäten auszunutzen, um quasi berechnete Felder zu erzeugen. Das ist jedoch immer nur bis zu einem gewissen Grad möglich. Die Grenzen der bereitgestellten GUI definieren die Grenzen des Möglichen in CRM.
FetchXML – für Abfragen “light”
Abfragen werden mit FetchXML erstellt. Es gibt immer auch andere Wege, aber FetchXML ist der Weg, wie man z.B. ein Grid mit einer eigenen Tabellenabfrage ausstattet. In der Praxis merkt man dann, dass dieser Weg für vielleicht 80% der notwendigen Abfragen gut funktioniert, aber die restlichen 20% bereiten einem wirklich Kummer. Man merkt, das man einfach nicht den kompletten Werkzeugkasten, dem einen die Sprache SQL bereitstellt, zur Verfügung hat.
Low-code / No-code
Sehr mächtig ist das Konzept der “Power User”, also die Möglichkeit, das System auch ohne Programmierkenntnisse zu konfigurieren und zu erweitern. Wenn man bedenkt, dass zur Erstellung typischer CRM-Anwendungen sowohl fachspezifisches Anwender:innenwissen, als auch IT-Kenntnisse notwendig sind, weiß man, dass es für den Erfolg eines IT-Projektes von Bedeutung sein kann, wenn Anwender:innen auch ohne Programmierkenntnisse an der Entwicklung einer Software beteiligt werden können.
Prozedurale Sprachen vs. Deklarative Sprachen
Wenn man Datenbank-Abfragen mittels ORM + C# schreibt, passiert das Folgende: Etwas, was normalerweise mit einer deklarativen Sprache wie SQL passiert, wird mit einer prozeduralen Sprache geschrieben. Ich bin davon überzeugt, dass der Weg über eine prozedurale Sprache vielleicht fehleranfälliger ist, man trotzdem zu einem korrekten Ergebnis kommen kann. Mir persönlich liegen prozedurale Sprachen mehr als SQL, weil sie in meiner Praxis eine größere Rolle spielten. Natürlich hab ich bis jetzt auch alle SQL-Anfragen in meinem Entwicklerleben gemeistert. :)
Nicht-normalisierte Tabellen sind handlebar
Zur Zeit beschäftige ich mich verstärkt mit der Vermittlung grundlegender Prinzipien von Datenbank-Design. Dazu gehört die Vermeidung von Redundanzen in einer Tabelle.
Das ist bestimmt auch richtig, aber mit CRM habe ich die Erfahrung gemacht, dass Redundanzen kein Problem darstellen müssen.
Das Argument für die Redundanzvermeidung durch Normalisierung ist, dass damit Inkonsistenzen in der Datenbank vorgebeugt wird. Redundante Daten können nach dem Ändern oder Löschen bestehender Daten oder nach dem Einfügen neuer Daten zu inkonsistenten, sich widersprechenden Daten führen. Das ist prinzipiell richtig. Nur bietet CRM mit den Plugins, die man ähnlich den Triggern in SQL auf das Einfügen / Ändern von Daten reagieren lassen kann, die Möglichkeit, diese Inkonsistenzen zu vermeiden.
Ein Beispiel für das Verständnis: Ändert sich in einer Tabelle von Bestellungen die Adresse des Kunden, dann werden in einem Update Plugin alle Datensätze des Kunden abgefragt und die Adresse dort ebenso geändert. Das scheint mir ein valider Ansatz, insofern man alle diese Eventualitäten betrachtet hat und die Implementierung dementsprechend stimmt. Elegant ist der Ansatz bestimmt nicht, aber er funktioniert.
This is day 26 of my #100daystooffload series, a challenge to write 100 blog posts in a year.