Ich habe in einigen Projekten gearbeitet, in denen der größte Teil der Geschäftslogik in der Datenbank implementiert wurde (hauptsächlich über gespeicherte Prozeduren). Andererseits habe ich von einigen Programmiererkollegen gehört, dass dies eine schlechte Praxis ist ("Datenbanken dienen zum Speichern von Daten. Anwendungen übernehmen den Rest").
Welcher dieser Ansätze ist im Allgemeinen besser?
Die Vorteile der Implementierung von Geschäftslogik in der DB sind:
- Zentralisierung der Geschäftslogik;
- Unabhängigkeit von Anwendungstyp, Programmiersprache, Betriebssystem usw .;
- Datenbanken sind weniger anfällig für Technologiemigration oder große Umgestaltungen (AFAIK).
- Keine Überarbeitung der Migration von Anwendungstechnologien (z. B. .NET nach Java, Perl nach Python usw.).
Die Nachteile:
- SQL ist für die Programmierung von Geschäftslogik weniger produktiv und komplexer, da es an Bibliotheken und Sprachkonstrukten mangelt, die das anwendungsorientierteste Sprachangebot bieten.
- Schwieriger (wenn überhaupt möglich) die Wiederverwendung von Code durch Bibliotheken;
- Weniger produktive IDEs.
Hinweis: Die Datenbanken, von denen ich spreche, sind relationale, beliebte Datenbanken wie SQL Server, Oracle, MySQL usw.
Vielen Dank!
Antworten:
Geschäftslogik geht nicht in die Datenbank
Wenn es sich um mehrschichtige Anwendungen handelt, scheint es ziemlich klar zu sein, dass Geschäftslogik, die Art von Intelligenz, die ein bestimmtes Unternehmen steuert, in die Geschäftslogikschicht und nicht in die Datenzugriffsschicht gehört.
Datenbanken machen ein paar Dinge wirklich gut:
Jetzt können Sie natürlich alle möglichen Dinge in einer Datenbank kodifizieren, die sich auf Ihre geschäftlichen Belange beziehen, z. B. Steuersätze, Rabatte, Vorgangscodes, Kategorien usw. Aber das Geschäft Aktion der auf diesen Daten genommen wird , ist im Allgemeinen nicht in die Datenbank codiert, für alle Arten von Gründen , die bereits von anderen erwähnt, obwohl eine Aktion wird gewählt anderswo in der Datenbank und ausgeführt.
Und natürlich kann es Dinge geben, die aus Gründen der Leistung und aus anderen Gründen in einer Datenbank ausgeführt werden:
Natürlich ist nichts in Stein gemeißelt. Gespeicherte Prozeduren eignen sich für eine Vielzahl von Aufgaben, da sie auf dem Datenbankserver gespeichert sind und bestimmte Stärken und Vorteile aufweisen.
Überall gespeicherte Prozeduren
Es ist eine gewisse Anziehungskraft, alle Ihre Datenspeicherungs-, Verwaltungs- und Abrufaufgaben in gespeicherten Prozeduren zu codieren und einfach die resultierenden Datendienste zu nutzen. Sie würden sicherlich von den maximal möglichen Leistungs- und Sicherheitsoptimierungen profitieren, die der Datenbankserver bereitstellen könnte, und das ist keine Kleinigkeit.
Aber was riskierst du?
Und natürlich, wenn Sie einen Webdienst benötigen (in den wahrscheinlich sowieso alles geht), müssen Sie diesen noch erstellen.
Was ist also typische Praxis?
Ich würde sagen, dass ein typischer, moderner Ansatz darin besteht, einen objektrelationalen Mapper (wie Entity Framework) zu verwenden, um Klassen zu erstellen, die Ihre Tabellen modellieren. Sie können dann über ein Repository mit Ihrer Datenbank sprechen, das Sammlungen von Objekten zurückgibt. Diese Situation ist jedem kompetenten Softwareentwickler vertraut. Der ORM generiert dynamisch SQL entsprechend Ihrem Datenmodell und den angeforderten Informationen, die der Datenbankserver verarbeitet, um Abfrageergebnisse zurückzugeben.
Wie gut funktioniert das? Sehr gut und viel schneller als gespeicherte Prozeduren und Ansichten zu schreiben. Dies deckt im Allgemeinen etwa 80% Ihrer Datenzugriffsanforderungen ab, hauptsächlich CRUD. Was deckt die anderen 20% ab? Sie haben es erraten: gespeicherte Prozeduren, die von allen wichtigen ORMs direkt unterstützt werden.
Können Sie einen Codegenerator schreiben, der das Gleiche tut wie ein ORM, aber mit gespeicherten Prozeduren? Sicher kannst du. ORMs sind jedoch im Allgemeinen herstellerunabhängig, von allen gut verstanden und werden besser unterstützt.
quelle
Ich bin fest davon überzeugt, Geschäftslogik so weit wie möglich aus der Datenbank herauszuhalten. Als Performance-Entwickler meines Unternehmens weiß ich jedoch zu schätzen, dass es manchmal notwendig ist, eine gute Performance zu erzielen. Aber ich denke, es ist viel seltener nötig, als die Leute behaupten.
Ich bestreite Ihre Vor- und Nachteile.
Sie behaupten, dass es Ihre Geschäftslogik zentralisiert. Im Gegenteil, ich denke, es dezentralisiert es. In einem Produkt, an dem ich gerade arbeite, verwenden wir gespeicherte Prozeduren für einen Großteil unserer Geschäftslogik. Viele unserer Leistungsprobleme rühren von wiederholt aufgerufenen Funktionen her. Zum Beispiel
Das Problem bei diesem Ansatz ist, dass die Datenbank in der Regel (in manchen Fällen ist dies falsch) dazu gezwungen wird, Ihre Funktion N-mal pro Zeile auszuführen. Manchmal ist diese Funktion teuer. Einige Datenbanken unterstützen Funktionsindizes. Sie können jedoch nicht jede mögliche Funktion gegen jede mögliche Eingabe indizieren. Oder kannst du?
Eine gebräuchliche Lösung für das obige Problem besteht darin, die Logik aus der Funktion zu extrahieren und in die Abfrage einzufügen. Jetzt haben Sie die Kapselung und die duplizierte Logik unterbrochen.
Ein weiteres Problem, das ich sehe, ist das Aufrufen gespeicherter Prozeduren in einer Schleife, da es keine Möglichkeit gibt, gespeicherte Proc-Ergebnismengen zu verknüpfen oder zu schneiden.
Wenn Sie den Code aus dem verschachtelten Prozess ziehen, dezentralisieren Sie ihn erneut. Daher müssen Sie zwischen Kapselung und Leistung wählen.
Im Allgemeinen finde ich, dass Datenbanken schlecht sind bei:
Datenbanken sind gut in:
Indem Sie teure Vorgänge wie Schleifen und String-Parsing ausführen und in Ihrer App-Ebene belassen, können Sie Ihre Anwendung horizontal skalieren, um eine bessere Leistung zu erzielen. Das Hinzufügen mehrerer App-Server hinter einem Load Balancer ist in der Regel weitaus billiger als das Einrichten der Datenbankreplikation.
Sie haben jedoch Recht, dass dies Ihre Geschäftslogik von der Programmiersprache Ihrer Anwendung entkoppelt, aber ich verstehe nicht, warum dies ein Vorteil ist. Wenn Sie eine Java-App haben, haben Sie eine Java-App. Das Konvertieren einer Reihe von Java-Code in gespeicherte Prozeduren ändert nichts an der Tatsache, dass Sie über eine Java-App verfügen.
Ich bevorzuge es, den Fokus des Datenbankcodes auf die Persistenz zu legen. Wie erstelle ich ein neues Widget? Sie müssen in 3 Tabellen einfügen und diese müssen sich in einer Transaktion befinden. Das gehört in eine gespeicherte Prozedur.
Die Definition, was mit einem Widget geschehen kann, und die Geschäftsregeln für die Suche nach Widgets gehören in Ihre Anwendung.
quelle
Ich habe in 2 verschiedenen Unternehmen gearbeitet, die unterschiedliche Sichtweisen zu diesem Thema hatten.
Mein persönlicher Vorschlag wäre, gespeicherte Prozeduren zu verwenden, wenn die Ausführungszeit wichtig ist (Leistung). Da gespeicherte Prozeduren kompiliert werden, ist es besser, wenn Sie eine komplexe Logik zum Abfragen der Daten haben, diese in der Datenbank selbst zu belassen. Außerdem werden die endgültigen Daten erst am Ende an Ihr Programm gesendet.
Ansonsten denke ich, dass die Logik eines Programms immer in der Software selbst sein sollte. Warum? Weil ein Programm testbar sein muss und ich glaube nicht, dass es eine einfache Möglichkeit gibt, gespeicherte Prozeduren in einem Komponententest zu testen. Vergiss nicht, ein nicht getestetes Programm ist ein schlechtes Programm.
Verwenden Sie die gespeicherte Prozedur daher mit Vorsicht, wenn dies erforderlich ist.
quelle
Es gibt einen Mittelweg, den Sie finden müssen. Ich habe beängstigende Projekte gesehen, bei denen die Programmierer die Datenbank nur als überteuerten Schlüssel- / Wertspeicher verwenden. Ich habe andere gesehen, bei denen die Programmierer keine Fremdschlüssel und -indizes verwenden. Am anderen Ende des Spektrums habe ich Projekte gesehen, in denen die meisten, wenn nicht alle Geschäftslogiken in Datenbankcode implementiert sind.
Wie Sie bereits bemerkt haben, ist T-SQL (oder dessen Entsprechung in anderen gängigen RDBMSs) nicht der beste Ort, um komplexe Geschäftslogik zu codieren.
Ich versuche, ein vernünftiges Datenmodell zu erstellen, die Funktionen der Datenbank zu verwenden, um meine Annahmen über dieses Modell (dh FKs und Einschränkungen) zu schützen, und sparsam mit Datenbankcode umzugehen. Der Datenbankcode ist nützlich, wenn Sie etwas benötigen (dh eine Summe), was die Datenbank sehr gut kann, und erspart Ihnen das Verschieben von zig Datensätzen über die Leitung, wenn Sie sie nicht benötigen.
quelle
Wenn es sich bei Ihrer Geschäftslogik um Mengenoperationen handelt, ist dies wahrscheinlich ein guter Platz in der Datenbank, da Datenbanksysteme wirklich gute Mengenoperationen ausführen können.
http://en.wikipedia.org/wiki/Set_operations_(SQL)
Wenn es sich bei der Geschäftslogik um eine Art Berechnung handelt, gehört sie wahrscheinlich außerhalb der Datenbank- / Speicherprozedur, da die Datenbanken nicht wirklich für das Schleifen und Berechnen ausgelegt sind.
Obwohl dies keine festen Regeln sind, ist es ein guter Ausgangspunkt.
quelle
Darauf gibt es keine richtige Antwort. Es hängt davon ab, wofür Sie die Datenbank verwenden. In einer Unternehmensanwendung benötigen Sie die Logik in der Datenbank über Fremdschlüssel, Einschränkungen, Trigger usw., da nur an dieser Stelle alle möglichen Anwendungen Code gemeinsam nutzen. Darüber hinaus bedeutet das Einfügen der erforderlichen Logik in den Code im Allgemeinen, dass die Datenbank inkonsistent ist und die Daten von schlechter Qualität sind. Das mag für einen Anwendungsentwickler trivial erscheinen, der nur darauf achtet, wie die GUI funktioniert, aber ich versichere Ihnen, dass die Leute, die versuchen, die Daten in Compliance-Berichten zu verwenden, es sehr ärgerlich und kostspielig finden, wenn sie eine Geldbuße in Milliardenhöhe erhalten, wenn sie Daten haben, die nicht funktionieren befolge die Regeln nicht richtig.
In einer Umgebung ohne behördliche Auflagen, in der Sie sich weniger um die gesamten Datensätze kümmern und nur ein oder zwei Anwendungen auf die Datenbank zugreifen, können Sie möglicherweise davonkommen, alles in der Anwendung zu belassen.
quelle
Nach ein paar Jahren ist die Frage immer noch wichtig ...
Einfache Faustregel für mich: Wenn es sich um eine logische Einschränkung oder einen allgegenwärtigen Ausdruck (einzelne Anweisung) handelt, platzieren Sie ihn in der Datenbank (ja, Fremdschlüssel und Prüfeinschränkungen sind auch Geschäftslogik!). Wenn es prozedural ist, indem es Schleifen und bedingte Verzweigungen enthält (und wirklich nicht in einen Ausdruck umgewandelt werden kann), setzen Sie es in Code.
Vermeiden Sie Mülleimer-DBs
Versuche, wirklich die gesamte Geschäftslogik in Anwendungscode zu platzieren, führen wahrscheinlich dazu, dass die (relationale) Datenbank in einen Papierkorb umgewandelt wird, in dem das relationale Design größtenteils vollständig weggelassen wird, in dem Daten einen inkonsistenten Status aufweisen können und Normalisierung fehlt (häufig hauptsächlich XML, JSON) , CSV usw. Mülleimerspalten).
Diese Art der reinen Anwendungslogik ist wahrscheinlich einer der Hauptgründe für den Aufstieg von NoSQL - natürlich mit dem Nachteil, dass sich die Anwendung um die gesamte Logik selbst kümmern muss, die seit Jahrzehnten in relationale Datenbanken integriert ist. NoSQL-Datenbanken eignen sich jedoch besser für diese Art der Datenverarbeitung. Beispielsweise behalten Datendokumente eine implizite "relationale Integrität" in sich. Für relationale Datenbanken ist es einfach Missbrauch, der immer mehr Probleme verursacht.
Ausdrücke (satzbasiert) anstelle von prozeduralem Code
Im besten Fall sollte jede Datenabfrage oder -operation als Ausdruck und nicht als Verfahrenscode codiert werden. Eine großartige Unterstützung dafür ist, wenn Programmiersprachen Ausdrücke wie LINQ in der .NET-Welt unterstützen (derzeit leider nur Abfragen, keine Manipulation). Auf der Seite der relationalen Datenbanken wurde lange Zeit gelehrt, SQL-Anweisungsausdrücke den prozeduralen Cursor-Schleifen vorzuziehen. So kann die Datenbank optimieren, den Vorgang parallel ausführen oder was auch immer nützlich sein mag.
Verwenden Sie DB-Datenintegritätsmechanismen
Wenn es um RDBMS mit Fremdschlüssel- und Überprüfungsbeschränkungen, berechneten Spalten, möglicherweise Triggern und Ansichten geht, ist dies der Ort, an dem die grundlegende Geschäftslogik in der Datenbank gespeichert wird. Eine ordnungsgemäße Normalisierung trägt zur Aufrechterhaltung der Datenintegrität bei und stellt eine eindeutige und eindeutige Instanz der Daten sicher. Auch wenn Sie es in Code und DB duplizieren müssen, sollten Sie diese grundlegenden Mechanismen der Datenintegrität nicht auslassen!
Gespeicherte Prozeduren?
Gespeicherte Prozeduren sind heutzutage selten erforderlich, da Datenbanken kompilierte Ausführungspläne für SQL führen und diese wiederverwenden, wenn dieselbe Abfrage erneut auftritt, nur mit unterschiedlichen Parametern. Daher ist das Vorkompilierungsargument für SPs nicht mehr gültig. Man kann SQL-Abfragen in der Anwendung oder im ORM speichern oder automatisch generieren, wodurch vorkompilierte Abfragepläne die meiste Zeit gefunden werden. SQL ist eine Ausdruckssprache, solange Sie nicht explizit prozedurale Elemente verwenden. Im besten Fall verwenden Sie also Codeausdrücke, die in SQL übersetzt werden können.
Obwohl sich die Anwendungsseite, einschließlich des von ORM generierten SQL, nicht mehr in der Datenbank befindet, zähle ich sie im Gegensatz zu gespeicherten Prozeduren immer noch als Datenbankcode. Da es weiterhin SQL- und Datenbankkenntnisse erfordert (mit Ausnahme der einfachsten CRUD) und bei richtiger Anwendung erheblich anders funktioniert als der Prozedurcode, der normalerweise mit Programmiersprachen wie C # oder Java erstellt wird.
quelle
Es hängt wirklich vom Geschäft, seiner Kultur und seinem Erbe ab. Abgesehen von technischen Überlegungen (diese wurden von beiden Seiten behandelt), zeigen die gegebenen Antworten, dass es darauf ankommt, woher die Leute kommen. In einigen Organisationen sind Daten König und der DBA ist eine starke Figur. Dies ist eine typische zentralisierte Umgebung, ein Rechenzentrum mit einer Reihe von Terminals. Die Präferenz in dieser Art von Umgebung ist klar. Der Desktop kann sich viele Male grundlegend ändern, bevor sich etwas im Rechenzentrum ändert, und dazwischen wird es wenig geben.
Das andere Ende des Spektrums ist die reine 3-Tier-Architektur. Oder vielleicht mehrschichtig in einem weborientierten Geschäft. Sie werden hier wahrscheinlich eine andere Geschichte hören. Der DBA ist, falls vorhanden, nur ein Kumpel, der einige administrative Aufgaben ausführt.
Ein moderner Anwendungsentwickler wird mehr Affinität zum zweiten Modell haben. Wenn Sie mit einem großen Client-Server-System aufgewachsen wären, wären Sie wahrscheinlich im anderen Lager.
Es sind oft so viele nichttechnische Umgebungsfaktoren beteiligt, dass es keine generelle Antwort auf diese Frage gibt.
quelle
Der Begriff Geschäftslogik ist interpretationsfähig. Bei der Erstellung von Systemen möchten wir die Integrität der Datenbank und ihrer Inhalte sicherstellen. In einem ersten Schritt sollten verschiedene Benutzerzugriffsberechtigungen eingerichtet werden. Betrachten wir als sehr einfaches Beispiel eine ATM-Anwendung.
Um den Kontostand zu ermitteln, sollte eine Auswahl in einer geeigneten Ansicht in Ordnung sein. Wenn Sie jedoch Geld überweisen möchten, möchten Sie, dass die Transaktion von einer gespeicherten Prozedur gekapselt wird. Es sollte der Geschäftslogik nicht gestattet sein, die Tabellen für die Gutschrift- und Belastungsbeträge direkt zu aktualisieren.
In diesem Beispiel könnte die Geschäftslogik den Kontostand überprüfen, bevor sie die Übertragung anfordert, oder einfach den gespeicherten Prozess für die Übertragung aufrufen und den Fehler melden. IMHO sollte die Geschäftslogik in diesem Beispiel vorab prüfen, ob ausreichend Guthaben verfügbar ist und ob das Zielkonto vorhanden ist, und erst dann die Überweisungsgelder aufrufen. Wenn zwischen den ersten Schritten und dem gespeicherten Prozessaufruf eine weitere Belastung erfolgt, wird nur dann ein Fehler zurückgegeben.
quelle