dimanche 20 septembre 2020

Instantiating multiple complex entity objects the "right way"

I'd like to instantiate multiple (i.e. of the same type) complex (i.e. many optional parameters) objects in my code. But how can I go about it and keep honoring SOLID principles?

Here is my thought process so far:

It seems beneficial to me, to separate the creation logic into a separate class, as sometimes the creation process of those complex objects in itself has dependencies. With a separate class, I'm able to provide those dependencies without them leaking into the object class itself. Furthermore this creation class becomes basically a service class, that can be passed around with the DI-container and fully exchanged for another implementation of the creation process.

Just by name and purpose two patterns come to mind: Factory and Builder.

It seems to me that my problem isn't the kind of problem a Factory solves. As I'm not trying to create different objects of a similar type, but really only one type of object multiple times.

So here comes the Builder:

Before I start, I have to clarify what I'm talking about when I mention "Builder" as I came across basically two different kinds of builders. The one kind of Builder seems to be the one by the Gang of Four and I'm not really familiar with this one. But I read about another kind in "Mastering PHP Design Patterns" by Junade Ali that roughly corresponds to the Builder (in Java) by Joshua Bloch as described by himself here and talked about over here.

A very basic implementation would look like this:

class ObjectBuilder implements ObjectBuilderInterface
{
 public function setAttributeA( $value ) : self
 {
  $this->attributeA = $value;
  return $this;
 }

 public function setAttributeB( $value ) : self
 {
  $this->attributeB = $value;
  return $this;
 }

.
.
.

 public function build() : Object
 {
  return new Object ($this->attributeA, $this->attributeB,...);
 }
}

The big advantage to me is that a builder provides setters that can be called in no particular order an still output a valid object. Furthermore the builder itself can have dependencies without them leaking into the object.

BUT as far as I understand the inner workings of a builder, by using the setters on the builder object the builder itself has a state and couldn't be reused for another object without unsetting all attributes first. One could make an unset call at the end of build() but that feels somewhat wrong to me and in my above mentioned sources aswell as everywhere I looked for a real life implementation of such a builder (I live in Symfony-land and had a look into FormBuilder for example) was anything like an unset() used.

So that got me thinking: If I couldn't find that many implementations of that Builder for a common problem in my code, am I somehow really off? Is there maybe a whole other approach I missed so far?

How is it possible to instantiate multiple complex objects by a service that can easily be passed around?

Aucun commentaire:

Enregistrer un commentaire