Frage

Ich habe eine Klasse: Schedule

.
public class Schedule {

private int locationNum;
private int cost;
private String costReason; 
private Date weekOfChange;
private Date dayOfChange;
private String changeReason; 

// and all those getters and setters

public Schedule(int locationNum, int cost, String costReason, Date weekOfChange, Date dayOfChange, String changeReason) throws ApplicationException {
//change is all or nothing - all attributes are present or none
if((weekOfChange!=null && dayOfChange!=null && changeReason!=null) || (weekOfChange==null  && dayOfChange == null && changeReason == null))  {
this.weekOfChange = weekOfChange;
this.dayOfChange = dayOfChange;
this.changeReason = changeReason;
}
else { throw new ApplicationException();}
//similary another if block to ensure that if cost is specified 
//then there exists the corresponding reason code for it.
}
}

Bisher habe ich meine Vorliebe Schedule Klasse. Ich bin jedoch nicht mit den Kontrollen getan, hätte ich einige andere Kontrollen tun:

  • die locationNum eine gültige Speicher-Nummer in der Datenbank.
  • ist changeReason Text eines dieser 6 verschiedenen changeReason Codes in der Datenbank.
  • etc etc ....

Normalerweise würde ich schreibe diese nicht in Schedule Klasse, Coz offensichtlich, kann ich nicht DAOs von dieser Klasse aufrufen. Also, ich würde eine Business-Schicht und eine Art von Validator-Klasse hat, ein Objekt vom Typ Zeitplan zu akzeptieren und eine Reihe von Datenbank-Validierungen in Folge durchführt und Fehler für die Anzeige / was auch immer zu sammeln.
Nun, hier sind meine Fragen:

  1. Wenn Sie Schedule als POJO zu behandeln sind und argumentieren, dass ein Objekt für die Validierung selbst nicht verantwortlich ist - ich würde die gesamten Code im Konstruktor auf die Business-Schicht der Validator-Klasse bewegen. Aber, wenn ich dies tun würde, ist nicht anämisch Planen? Ist das, was sie als Verletzung der einzigen Verantwortung Prinzip?
  2. Lets nehme ich den Code zog ich in meinem Konstruktor auf eine Business-Schicht-Klasse haben, so dass alle Arten von Validierungen jetzt in meiner Busines Schicht sind. Lassen Sie uns annehmen, dass jemand dayOfChange auf NULL in meinem Datenspeicher verändert und jetzt ich Objekte aus meiner Datenbank bin Laden. Nun, mit dieser Art eines Objekts, kann meine Anwendung brechen, wäre es nicht? Coz Ich würde geschriebenen Code haben unter der Annahme, dass die Validierungsregeln erfüllt sind. Ich denke, meine Frage ist immer verwirrend, aber der Punkt den ich versuche zu machen ist, dass ich in diesem Zusammenhang eher diese Kontrollen in Konstruktor getan haben Integrität der Daten von Schedule Klasse versteckt zu gewährleisten.
  3. Wie wird es in der Regel getan? Was ist die beste Praxis?

Schätzen Sie Ihre Beteiligung an dieser Diskussion.

War es hilfreich?

Lösung

Wenn Sie wirklich haben „all jene Getter und Setter“, dann müssen Sie Ihre Klasse besser validieren als im Konstruktor. Wenn die Invarianten der Klasse sind, so dass alle weekOfChange, dayOfChange und changeReason null sein müssen oder nicht alle dürfen nicht Ihre Setter null gehen schnell Ihre Klasse in einem ungültigen Zustand zu versetzen. Meinst du Setter haben oder meinen Sie Ihre Klasse unveränderlich sein?

Bevor sich Gedanken darüber waren Validierung sollte eine Analyse der Klasse gehen vielleicht zu tun. Schauen Sie sich all seinen gültigen Zustände und Invarianten für bestimmte Staaten. Dann werden Sie verstehen, ob Ihre Klasse wandelbar oder unveränderlich sein sollte. Wo Sie sich gegenseitig bedingen Covarianten haben (wie weekOfChange, dayOfChannge und changeReason es Sinn macht, sie in dort eine eigene Klasse zu verpacken und Zusammensetzung in der Schedule-Klasse verwenden. Dies wird die „Regeln“ über diese Dinge Felder in einem einzigen Ort setzen und den Zeitplan vereinfachen .

Das gleiche mit anderen zusammenarbeiten Feldern (wie Kosten und Kostengründen). Dann wird Schedule von Selbst Validieren Klassen zusammen. Wenn diese beiden sind unveränderlich und Schedule ist unveränderlich auch haben Sie Ihr Selbst eine viel einfachere Domain.

Also, Ihre Frage zu beantworten: es ist besser, dass eine Klasse seiner Zustände und Invarianten definiert und setzt nur das Minimum an seine Mitarbeiter, wo praktisch. Die Verantwortung für den internen Zustand des Zeitplan sollte mit Zeitplan und mit einem wenig mehr Design ruht es mit relativer Leichtigkeit tun kann.

Sie haben also

    class Schedule {
         private Change change;
         private Cost cost;
         private Location location;

        public Schedule(Location location, Cost cost, Change change) {
           this.change = change;
           this.cost = cost;
           this.location = location;
        }
}

Und colloborators wie

public class Change {
    private Date weekOfChange; //shoudln't these two fields be one, a date is a date after all??
    private Date dayOfChange; //shoudln't these two fields be one??
    private String changeReason; 

    public Change(Date weekOfChange Date dayOfChange, String changeReason) {
      this.weekOfChange = weekOfChange;
      ...etc.
    } 
}

Obwohl ich würde rät Sie dringend, Ihre Klassen Invarianten mit defensiven Kopieren von irgendwelchen wandelbar Werten zu schützen, die von Client-Code übergeben werden.

Andere Tipps

  

Wenn Sie Schedule als behandeln waren   POJO und argumentieren, dass ein Objekt nicht   selbst verantwortlich für die Validierung - I   müsste der gesamte Code bewegen   der Konstruktor für das Unternehmen   Schicht der Validator-Klasse. Aber, wenn ich   wurden, dies zu tun, Planen ist nicht   anämisch? Ist das, was sie nennen   Verletzung der einzigen Verantwortung   Prinzip?

POJO nur bedeutet, dass Sie nicht von einer bestimmten Klasse abzuleiten haben oder Verwendung ein Enhancer-Byte-Code, um die gewünschte Funktionalität wie oder Mapping zu erhalten. Es bedeutet nicht, dass die Objekte ohne Funktionalität anämisch sein sollten.

  

Nun, mit dieser Art von einem Objekt, mein   Anwendung kann brechen, wäre es nicht?   Coz würde ich Code geschrieben haben unter der Annahme,   dass Validierungsregeln erfüllt sind. ich vermute   meine Frage ist immer verwirrend, aber   der Punkt, auf den ich versuche, ist, dass   in diesem Zusammenhang möchte ich lieber   diese Kontrollen im Konstruktor getan   gewährleistet die Integrität der versteckten Daten durch   Schedule Klasse.

Wer sagt, dass Sie keine Regeln in einer separaten Klasse definiert nennen können aus dem Konstruktor Ihrer Schedule Klasse? Wenn es den Zugang zu nicht-öffentlichen Bereichen braucht, könnte man sie macht private verpacken und die Regeln Klasse im selben Paket hat -. Oder sie als Parameter an die Regel passiert

  

Wie wird es in der Regel getan? Was ist der   best practice?

Ob Sie Validierungsregeln separate Klassen bewegen auf die Notwendigkeiten der Anwendung abhängen sollte, nicht auf mißverstanden buzzwords.

Gut Gründe getrennte Regelklassen zu haben wäre:

  • Die Regeln sind so viele und so komplex, dass sie alle in die Schedule Klasse setzen würde es zu groß machen.
  • Sie wollen nicht immer alle Regeln anzuwenden.
  • Die Regeln können wiederverwendet werden auf verschiedene Klassen zu arbeiten, die nicht unbedingt in der gleichen Vererbungshierarchie sind (das heißt, sie über eine Schnittstelle arbeiten).

Es sieht aus wie es zwei unterschiedliche Verhaltensweisen für den Schedule Konstruktor. Dort sollte daher zwei Konstruktoren sein. Eventuell sogar zwei Implementierungsklassen.

locationNum und changeReason. Diese werden zur Zeit schwach typisiert. Sie sollten wahrscheinlich ihre eigene Klasse. Nach Ihrer Frage hängen die gültigen Werte auf den Kontext. Im Moment Schedule hat keinen Zusammenhang. Sie könnten Schedule unabhängig von Kontext zu halten, wobei in diesem Fall gibt es keine Datenbank Beschränkungen für locationNum und changeReason sind. In die andere Richtung, Schedule, locationNum und changeReason könnte auf kontextabhängig sein, und der Konstruktor sollte lediglich prüfen, ob sie alle im gleichen Kontext sind. Ein Paket-private Konstruktor (wie eines armen Mannes friend wirken) können die Kontrollen verzichtet werden.

Ein POJO impliziert ein (gut geschrieben) Objekt und damit das Verhalten. Die Frage scheint es zu bedeuten, „Struktur“ zu werden. Vermeiden Sie structs.

Handel Schicht scheint irreführend. Es scheint ein Geschäftsunternehmen zu sein, sollte es Geschäftsverhalten hat. Es kann jedoch nicht von Geschäftsprozessen enthält (Service).

Ihre Bewerbung wird immer davon ausgehen, bestimmte Dinge über die Datenbank, einschließlich dem (öffentlichen) Schema. Wenn Sie Einschränkungen entfernen, dann können Sie auch Ihre Anwendung brechen. Dies ist das gleiche, als wenn Sie in ähnlicher Weise Code geändert, die auf abgehangen.

Die gängige Praxis ist anämisch Objekte mit prozeduralen Code zu haben. In den meisten Fällen ist dies nicht best practice.

Warum ist locationNum ein int, wenn Sie in der Tat auf eine Instanz einer anderen Klasse beziehen, sagen Location? Wenn Sie die richtige Objektreferenzen verwenden würden Sie sie in Schedule bestätigen konnte und konfigurieren Sie die ORM (falls vorhanden) die referentielle Integrität zu erzwingen.

Ihre Fragen zu beantworten:

1) Ich glaube nicht, Ihre Klasse anämisch sein wird, wird es eher für den Moment ein DTO sein, sehe ich kein Problem damit.

2) Wenn die Validierung in der Business-Schicht ist, bedeutet das nicht, dass Sie ein ungültiges Objekt würden immer, weil die Validierung noch da sein wird, in der Regel Ihres Validierungsprozess irgendwie um eine InvalidDataException oder etwas und gewinnt beschweren ‚t können Sie die‚beschädigte‘Objekt verwenden. Wenn das Null-Datum nicht ein akzeptabler Wert ist (null konnte nicht normal in die Datenbank erhalten), dann sollte die Geschäft / dao Schicht um diesen Fehler fangen und das Objekt verhindern, indem Sie Ihre App zu gewöhnen.

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