Frage

ich in OO glauben, aber nicht an den Punkt, wo unangemessene Entwürfe / Implementierungen sollten nur verwendet werden, um zu sein „OO-konform“.

So, wie mit dem Serlvet / EJB / Datacontainer geschichteten Architektur beschäftigen:

  • Servlets erhalten Anfragen und rufen eine "Business-Schicht" (zum Beispiel Sitzung EJBs)
  • Die Business-Schicht lokalisiert DataContainers aus der Datenbank und manipuliert sie die Geschäftslogik zu implementieren
  • DataContainers enthalten keinen echten Code, nur get / set in der Datenbank entspricht.

Dieser Ansatz Beschwerde einlegen; die DataContainers sind klar in dem, was sie tun, und es ist sehr einfach zu wissen, wo Daten kommen.

Abgesehen von nicht OO ist, führt dies zu unklar Business Layer-Klassen, die schwer zu Namen und schwer zu organisieren.

Auch wenn wir waren versuchen, mehr „OO“ zu sein (zum Beispiel einige dieser Methoden in den DataConatiners setzen), arbeiten einige dieser Operationen auf mehr als einen Satz von Daten.

Wie halten Sie Ihre Business Layer aus verwechselbar prozeduralen bekommen, aber ohne Ihre DataContainers mit Business-Logik verschmutzen?

Beispiel

class UserServlet {
  handleRequest() {
    String id = request.get("id");
    String name = request.get("name");
    if (UserBizLayer.updateUserName(id,name))
      response.setStatus(OK);
    else
      response.setStatus(BAD_REQUEST);
  }
}

class UseBizLayer {
    updateUserName(String id, String name) {
        long key = toLong(id);
        user = userDAO.find(key);
        if user == null
            return false;
        if (!validateUserName(name))
            return false;
        user.setName(name);
        userDAO.update(user);
        return true;
    }

    validateUserName(String name) {
        // do some validations and return
    }
}

class User {
    long key;
    String name;
    String email;

    // imagine getters/setters here
}
  • Wir wollen nicht validateUserName auf den Benutzer, da sie auf einen Namen arbeitet nur; Ich denke, es in einer anderen Klasse gehen könnte, aber dann haben wir eine andere Verfahren „UTI“ Typklasse
  • Wir wollen nicht, Persistenzmethoden auf dem Benutzer, da es Wert ist bei der Entkopplung Datenstrukturen aus ihrer Persistenz-Strategie
  • Wir wollen nicht, Business-Logik in unserem Servlets, da wir diese Logik anderswo
  • wiederverwenden müssen zu viel, um die User-Klasse
  • Wir wollen nicht unsere Geschäftslogik in unseren Benutzern, wie dies in Art und Weise zeichnet, Wiederverwendung von der Business-Logik schwierig und Verbinden des Benutzers mit seiner Persistenz-Strategie zu machen

Ich weiß, das Beispiel ist nicht so schlimm, aber vorstellen, 10 DataContainers und 20 BizLayer Objekte mit mehreren Methoden je. Stellen Sie sich vor, dass einige dieser Operationen nicht „zentriert“ auf einem bestimmten Datencontainer.

Wie halten wir dies ein verfahrens Chaos aus zu sein?

War es hilfreich?

Lösung

So werde ich meine Gedanken dazu in ein paar Stichpunkte Adresse:

  1. Es scheint in einem Java EE-System an einem gewissen Punkt, den Sie mit den Rohrleitungen von Java EE zu tun haben, sind die sanitären Anlagen nicht immer von OO-Konzepten profitieren, aber es kann sicherlich mit einem wenig Kreativität und Arbeit. Zum Beispiel könnten Sie die Vorteile von Dingen wie Abstrakte nehmen könnten, etc commonize wie viel von dieser Infrastruktur wie möglich zu helfen.
  2. Eine Menge von dem, was Sie in Ihre Suche in Eric Evans ausgezeichnetes Buch namens Domain Driven Design diskutiert wird. Ich empfehle Ihnen sehr es betrachten, wie er das Problem auszudrücken, das Wissen über die Domäne und den Umgang mit der technischen Infrastruktur zu unterstützen tut Adresse.
  3. Nach dem Lesen und GROKD einige DDD, würde ich meine technische Infrastruktur in Repositorys aufnehmen. Die Verwahrungsstellen würden alle geschrieben werden, um eine Strategie für die Persistenz zu verwenden, die auf der Sitzung EJBs basieren. Sie würden eine Standardimplementierung schreiben für die weiß, wie man die Sitzung EJBs zu sprechen. Um diese Arbeit zu machen, müßten Sie ein wenig Konvention hinzuzufügen und diese Konvention / Vertrag in Ihren Schnittstellen angeben. Die Verwahrungs tun alle der CRUD und sollte nur mehr tun, als dass, wenn es unbedingt erforderlich ist. Wenn Sie sagte: „Mein DAOS meine Repositories sind“, dann würde ich zustimmen.
  4. Also mit diesem fortzusetzen. Sie brauchen etwas, das Gerät von der Arbeit zu verkapseln, die in UseBizLayer exprimiert wird. Auf dieser Ebene denke ich, die Natur davon ist, dass Sie stecken das Schreiben von Code, die alle geht Transaktionsskript sein. Sie sind eine Trennung von Verantwortung und Staat zu schaffen. Dies ist in der Regel, wie ich habe es innerhalb von Java EE-Systemen als Standard Art von Architektur getan gesehen. Aber es ist nicht objektorientiert. Ich würde versuchen, das Modell zu erkunden und sehen, wenn ich könnte zumindest versuchen, einige der Verhaltensweisen commonize, die in die BizClasses geschrieben werden.
  5. Ein weiterer Ansatz, den ich vorher benutzt habe, ist die BizLayer Klassen loszuwerden und dann Proxy die Anrufe von der Domain auf die tatsächliche Repositorys / DAOs die Operation zu tun. Allerdings könnte dies einige Investitionen in den Aufbau der Infrastruktur erfordern. Aber Sie tun können, eine Menge mit einem Rahmen wie Spring und mit einigem AOP-Konzept, diese Arbeit gut zu machen und die Menge an individueller Infrastruktur abgeholzt, die benötigt wird.

Andere Tipps

da Sie Klassen und Objekte sind Implementierung, Ihre Lösung wird OO sein, unabhängig davon, wie Sie die Dinge Schicht - es kann einfach nicht sehr gut strukturiert sein, je nach Ihrer Situation / Bedürfnisse! ; -)

als auf Ihre spezielle Frage, wäre es in einigen Fällen sinnvoll für validateUserName auf die Benutzerklasse gehören, da würde jeder Nutzer gerne einen gültigen Namen hat. Oder Sie können eine Validierung Utility-Klasse haben unter der Annahme, dass andere Dinge Namen haben, die die gleichen Validierungsregeln verwenden. Das gleiche gilt für E-Mail. Sie könnten diese in NameValidator und EmailValidator Klassen aufgeteilt, die eine feine Lösung wäre, wenn sie eine Menge verwendet werden. Sie könnten auch eine validateUserName Funktion auf dem Benutzerobjekt zur Verfügung stellen nach wie vor, dass nur die Utility-Klasse-Methode aufgerufen. All dies sind gültige Lösungen.

Eine der großen Freuden über OOD / OOP ist, dass, wenn das Design stimmt, Sie wissen , dass es richtig ist, weil eine Menge Dinge nur aus dem Modell fallen, die Sie tun können, Sie konnte vorher nicht tun.

In diesem Fall würde ich NameValidator und EmailValidator Klassen machen, weil es wahrscheinlich ist, dass andere Einheiten Namen und E-Mail-Adressen in Zukunft haben werden, aber ich würde validateName und validateEmailAddress Funktionen auf der User-Klasse zur Verfügung stellen, weil das für eine komfortable Schnittstelle macht für die biz-Objekte zu verwenden.

der Rest der ‚wir-nicht-wollen‘ Kugeln richtig sind; sie sind nicht nur für die richtige Schichtung notwendig, aber sie sind auch für ein sauberes OO-Design notwendig.

Schichtung und OO gehen Hand in Hand auf der Grundlage einer Trennung von Bedenken zwischen den Schichten. Ich denke, dass Sie die richtige Idee haben, aber einige Utility-Klassen für die gemeinsame Validierungen müssen wie dargestellt

Denken Sie darüber nach, wie würden diese Aufgaben durchgeführt werden, wenn kein Computer ist, und das Modell des Systems auf diese Weise.

Ein einfaches Beispiel ... füllt Kunde ein Formular aus einem Widget zu beantragen, reicht es an einen Mitarbeiter, die Mitarbeiter der Identität des Clients überprüft, das Formular verarbeitet, erhält einen Widget, gibt das Widget und eine Aufzeichnung der Transaktion auf dem Client und hält eine Aufzeichnung der Transaktion irgendwo für das Unternehmen.

der Client speichern ihre Daten? Nein, die Mitarbeiter tun. Welche Rolle die Mitarbeiter zu nehmen, wenn er die Client-Daten zu speichern? Kundendaten Keeper.

Ist die Form überprüfen, ob sie korrekt ausgefüllt? Nein, die Mitarbeiter tun. Welche Rolle die Mitarbeiter zu nehmen, wenn er das tun? Form-Prozessor.

Wer gibt dem Kunden das Widget? Der Mitarbeiter handeln als Widget Distributor

Und so weiter ...

Um schieben diese in eine Java-EE-Implementierung ...

Die Servlets im Namen des Kunden handeln, das Formular ausfüllen (Daten aus der HTTP-Anforderung und machen das entsprechende Java-Objekt ziehen) und es an die entsprechenden Mitarbeiter (EJB) vorbei, der dann mit der Form tut, was benötigt getan werden. Während der Verarbeitung der Anforderung, müssen die EJB es passieren entlang zu einem anderen EJB, die in verschiedenen Aufgaben spezialisiert, ein Teil davon umfassen würde den Zugriff auf / Putting Informationen vom / zum Speicher (Ihre Datenschicht). Das einzige, was nicht direkt mit der Analogie Karte sollte die Besonderheiten auf, sein sollte, wie Sie Ihre Objekte miteinander kommunizieren, und wie Sie Ihre Datenschicht in Verbindung steht mit dem Speicher.

Ich habe die gleichen Gedanken selbst hatte.

In der traditionellen MVC ist die wichtigste Sache ist die Trennung der Blick vom Modell und Controller-Teile. Es scheint eine gute Idee zu sein, den Controller und das Modell einfach zu trennen, weil Sie mit aufgeblähten Modellobjekten können am Ende:


public class UserModel extends DatabaseModel implements XMLable, CRUDdy, Serializable, Fooable, Barloney, Baznatchy, Wibbling, Validating {
  // member fields
  // getters and setters
  // 100 interface methods
}

Während Sie separate Controller haben können (oder das ganze Muster) für viele der Schnittstellen oben, und ja, es ist eher verfahrenstechnischer Natur, aber ich denke, das ist, wie die Dinge in diesen Tagen arbeiten. Alternativ können Sie erkennen, dass einige der Schnittstellen das gleiche tun (cruddy - Datenbank Speicherung und den Abruf, Serializable - das gleiche in ein binäres Format, XMLable, derselben zu XML), so dass Sie ein einzelnes System zu handhaben schaffen sollte, mit jedes Potential Backend ist eine separate Implementierung, dass das System behandelt. Gott, ist das wirklich schlecht geschrieben.

Vielleicht ist es so etwas wie „Co-Klassen“, die Sie separate Quelldateien für Controller-Implementierung haben lassen, die so tun, als ob sie ein Mitglied der Modellklasse sind auf sie wirken.

Wie für Geschäftsregeln, sie arbeiten oft auf mehrere Modelle zur gleichen Zeit, und so sollten sie getrennt werden.

Ich denke, das ist eine Frage, über „Trennung von Bedenken“. Sie scheinen ein langer Weg auf die rechte Spur mit geschichteter Architektur zu sein, aber vielleicht brauchen Sie mehr von den gleichen tun - das heißt schaffen Architekturschichten innerhalb Ihrer Java EE Schichten

Ein Datacontainer sieht viel wie die Datenübertragung Objects (DTO) Muster.

Ein modernes OO-Design hat viele kleine Klassen, von denen jedem im Zusammenhang mit einer kleinen Anzahl von „Freunden“, z.B. via Zusammensetzung. Dies könnte viel mehr Klassen und Java Kessel-Platte produzieren, als Sie wirklich bequem sind mit, aber es sollte zu einem Design führen, die besser geschichtete und leichter zu Unit-Test und erhalten.

(+ 1 für die Frage, +1 für die Antwort auf die Frage, wenn Sie wissen, dass Sie die Schichtung rechts)

Primitiv, das „Wir wollen nicht wollen“ Abschnitt muss gehen. Entweder Sie wollen es richtig sein, oder Sie wollen es bleiben, wie es ist. Es gibt keinen Punkt in nicht die Schaffung einer Klasse, wenn man einen braucht. „Wir haben genug“ ist eine schlechte Ausrede.

Ja, es ist schlecht aussetzen all internen Klassen, aber nach meiner Erfahrung zu schaffen, eine Klasse pro Konzept (dh einen Benutzer, eine ID, ein Datenbank-Konzept ...) hilft immer.

Darüber hinaus ist kein Fassadenmuster etwas die Existenz von Lasten BizRules Klassen, hinter einer gut organisierte und sauberen Schnittstelle versteckt zu lösen?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top