Anwendungsdienstschicht, die Datenbankfunktionen aufruft. Schlechte Architektur?

11

Szenario:

  • Stapel: Java, Frühling, Ruhezustand.
  • Modell: Client-Server-Anwendung.
  • Muster: Model-View-Controller (MVC).

Die Service Layer-Klassen weisen drei Verhaltensweisen auf:

  1. Einige Dienste haben die Geschäftsregel innerhalb der Methoden und delegieren die Persistenz an die Anwendung. Mögen:

    EntityManager.save (Entität);

  2. Einige Dienste rufen einfach eine Datenbankfunktion auf (Übergabe von Parametern).

    CallableStatement cls = con.prepareCall ("{call databaseFunction (args)}");

  3. Einige Dienste verfügen über Methoden mit beiden Verhaltensweisen.

Meine Fragen:

  1. Gibt es ein Problem damit, dass Anwendungsdienste Datenbankfunktionen direkt aufrufen? Wird dies nicht als schlechte Praxis angesehen? Was wäre ein Architekturmodell für ein solches Projekt?
  2. Gibt es ein Problem damit, dass der Verhaltensmix im selben Dienst enthalten ist? Wie Transaktionen und Konsistenz?
  3. Macht diese Kapselung im Falle einer Wartung dem Entwickler klar, dass er auch die Funktionen in der Datenbank ändern sollte? Wie vermeide ich das?
  4. Tritt dieses Szenario in anderen Anwendungen auf der ganzen Welt auf oder war es nur ein Architekturfehler?
Linuxunil
quelle
Diese Frage ist ähnlich, aber nicht genau gleich. Softwareengineering.stackexchange.com/questions/180012/…
Jon Raynor

Antworten:

7

Gibt es ein Problem damit, dass Anwendungsdienste Datenbankfunktionen direkt aufrufen? Wird dies nicht als schlechte Praxis angesehen?

Ich denke es gibt. Sie stellen dem Anwendungsdienst Kenntnisse über die Datenbankinternale zur Verfügung. Wenn Sie die Datenbank in irgendeiner Weise ändern (Speichermodul ändern oder sogar ein Feld umbenennen oder einen Index erstellen), müssen Sie möglicherweise den Anwendungsdienst ändern, was gegen SRP verstößt .

Was wäre ein Architekturmodell für ein solches Projekt?

Siehe Kommentar unten.

Gibt es ein Problem damit, dass der Verhaltensmix im selben Dienst enthalten ist? Wie Transaktionen und Konsistenz?

Ich glaube nicht, dass es ein technisches Problem gibt, aber es gibt ein logisches. Sie mischen nur zwei Ansätze in der Anwendung, wodurch sie vage, weniger strukturiert und schwer an Änderungen anzupassen ist. Siehe auch die obigen Kommentare zum Verstoß gegen SRP.

Macht diese Kapselung im Falle einer Wartung dem Entwickler klar, dass er auch die Funktionen in der Datenbank ändern sollte?

Sicher tut es das.

Wie vermeide ich das?

Platzieren Sie Methoden und Funktionen, die direkt mit der Datenbank arbeiten, in einer separaten Abstraktionsebene (sei es eine DAO-Schicht oder ein einfaches Repository-Muster - abhängig von der Komplexität Ihrer Anwendung).

Tritt dieses Szenario in anderen Anwendungen auf der ganzen Welt auf oder war es nur ein Architekturfehler?

Ich denke in unserer Welt passiert alles;)

Vladislav Rastrusny
quelle
Wenn ich das richtig verstehe, kann es ein technisches Problem geben, dass bei Aktualisierungen von Funktionen / gespeicherten Prozessen und auch über einen ORM die Zustände einer bestimmten Transaktion sehr schwer zu beurteilen sind. Während die Anwendung im aktuellen Zustand funktioniert, kann eine kleine Änderung zu einigen wirklich großen Problemen führen. Ich habe die Erfahrung mit Hibernate gemacht, dass Sie viele nervige Probleme haben werden, wenn Sie nicht zulassen, dass alle Tabellen verwaltet werden, mit denen es funktioniert.
JimmyJames
nette und prägnante Antwort. SRP war das erste, was mir in den Sinn kam, als ich mir den Code zum ersten Mal ansah. Einige Mitarbeiter sagen, dass die Methode nicht gegen SRP verstößt, da sie nur die Datenbankfunktion aufruft. Einige dieser Funktionen wählen jedoch aus, fügen sie ein und aktualisieren sie. Verstößt es also gegen SRP oder nicht? (Vielleicht ist dies selbst eine andere Frage, die getrennt diskutiert werden muss?)
Linuxunil
1
+1 für diese Zeile denke ich in unserer Welt passiert alles;)
Linuxunil
@linuxunil SRP sollte auf allen Ebenen der Architektur respektiert werden. In meinem Fall meinte ich SRP auf der Ebene des Dienstes, nicht auf der Ebene der Methode. @ JimmyJames Yep. Die meisten ORMs funktionieren mit den gespeicherten Prozeduren nicht gut. Aber manchmal sind gespeicherte Prozesse notwendig.
Vladislav Rastrusny
3

Nach Ihren Angaben gibt es eine Service-Schicht, sodass das Architekturmuster, das als geeignet erscheint, Layered Architecture ist. Weitere Referenz

Ja, es ist normalerweise eine schlechte Praxis, direkte Datenbankaufrufe auf einer anderen als einer Datenzugriffsschicht durchzuführen. Auf diese Weise greift die Geschäftsschicht nur auf eine Abstraktion der Datenbank zu.

Was das Mischverhalten betrifft, könnte die Verwendung eines Entwurfsmusters als DAO-Muster oder Repository-Muster dazu beitragen, diese Verantwortlichkeiten zu delegieren und so den Code zu verbessern.

Einige der Vorteile der Verwendung eines Entwurfsmusters und eines ORM sind die Lesbarkeit Ihres Codes und die Kapselung der Verantwortlichkeiten. Wenn sich also Ihr Datenbankzugriff ändert, sollte sich an Ihrer Geschäftsschicht nicht viel ändern.

J. Pichardo
quelle
Ich bin mir nicht sicher, warum dies abgelehnt wurde. In dieser Antwort wird empfohlen , Code zu trennen , der sich mit verschiedenen Problemen befasst . Fühlt sich hier wie ein Prinzip der Programmierung an ... nicht sicher, was es ist ... Mann. Wenn ich nur an den Namen denken könnte. +1 Übrigens
Greg Burghardt
Ist es nicht eines der soliden Prinzipien?
J. Pichardo
3
No. Das "S" in fester ist die S ingle Verantwortung Principal (SRP). Die von Ihnen empfohlene Trennung von Bedenken ist jedoch ein gültiger Grund für die Trennung der Dienstlogik von der Datenzugriffslogik. In der anderen Antwort von Vladislav wird der Principal of Single Responsibility erwähnt. Ehrlich gesagt passen die SRP und die Trennung von Bedenken gut zusammen, wie Wein und Käse.
Greg Burghardt