Stilfrage SRP Container

Habe folgendes

public class Container {
  private List<Box> boxes = new ArrayList<>();

  public void addBox(Box box) {
    boxes.add(box);
  }
}

public class Box {
  private final int id;
  private final String name;

  public Box(int id; String name) {
    this.id = id;
    this.name = name;
  }
  //getter
}

void otherCode {
  Box box = new Box(1,"a name");
  container.add(box);
}

und ich bin am Überlegen ob ich das in sowas wie

public class Container {
  private List<Box> boxes = new ArrayList<>();

  public Box createBox(int id, String name) {
    Box box = new Box(id, name);
    boxes.add(box);
    return box;
  }
}

public class Box {
  private final int id;
  private final String name;

  public Box(int id; String name) {
    this.id = id;
    this.name = name;
  }
  //getter
}

void otherCode {
  Box box = container.createBox(1,"a name");
}

Letzteres sieht zwar auf den ersten Blick bei der Verwendung hantlicher aus, widerspricht aber in der createBox-Methode dem SRP.

Was meint ihr?

Ich würde auch die erste Variante bevorzugen. Bei der zweiten wird einfach nicht klar, dass createBox etwas zum Container hinzufügt.

Danke für die Antwort. Prinzipiell bin ich auch der selben Meinung.

Das Problem, dass ich allerdings habe ist, dass ich im Nachgang über die Liste im Container gehe und die Boxen nochmals “validiere” (bei manchen Boxen ein zusätzliches Flag setzen muss). Wenn ich allerdings vergesse, die Box dem Container hinzuzufügen und diese damit der “Validierung” entgeht, dann fliegt mir später die Anwendung um die Ohren.

Da muss ich wohl noch etwas Gehirnschmalz investieren und meine Datenstrukturen überprüfen.

manchmal hat man noch doppelte Verlinkung, hier etwa wenn die Box ein Attribut ‘Container parent’ hätte, welches gesetzt werden muss,
da bietet sich createBox() umso mehr an, den eigenen Container als Parent übergeben und das add(), alles in einem sicheren Abwasch

ich persönlich bevorzuge die Sicherheit solcher Konstrukte, sofern möglich,
spart im Falle von 10 Boxen hintereinander auch jede Menge Zeilen, eben fehleranfällige Zeilen

in Swing wird ja zumindest das Parent-Setzen auch in der add()-Methode gemacht, allerdings fast nichts derart create-Artiges,
mag dann ein gewisser Unterschied sein, eben eine Frage beim add(), nicht beim create


ein Kriterium ist natürlich auch wie kompliziert diese Erstellung ist (hier wenig) und von wie vielen Code-Stellen gebraucht,

Zwischenvariante ist eine create-Methode ohne gleich add()
-> container.add(container.create(...));
wobei das create nicht unbedingt im container sein muss

hier vorliegend gibt es eine komplette Wiederholung der Konstruktor-Parameter als Methoden-Parameter,
das ist unschön, auch für sich wieder fehleranfällig, muss etwa bei Änderungen korrekt mitgezogen werden,
steht auf der Gegenargument-Seite

Die zweite Lösung ist schon deshalb schlecht, weil Container und Box sehr stark gekoppelt werden. Falls es später mal unterschiedliche Boxen geben sollte (je nach Kontext vllt auch mal Kühlboxen oder sowas), dann hast du bei der zweiten Option keine Chance mehr das umzusetzen. Auch die Konstruktorparameter koppelst du mehr als nötig.

Ich würde auf jeden Fall Lösung 1 nehmen.

Die Box sollte nur über den Container zugreifbar sein, sobald sie darin ist. Ansonsten gibt es mit großer Wahrscheinlichkeit Chaos. Wenn du diesen Grundsatz beherzigt, dann taucht eine Box, die du erstellst, aber nicht hinzufügst, einfach nicht mehr auf.

Von der Syntax her würde ich das in etwa so angehen:

container.add(standardBox);```

Als “handliche Variante” könntest du auch überlegen dem add(Box b) einen Rückgabewert zu verpassen:

  container.add(box);
  return box;
}```

Dann kannst du erzeugen und Hinzufügen auch recht übersichtlich gestalten:
```Box b = container.add(new Box(1, "a box"));```

Und dank Generics auch für alle Subtypen verwendbar.