dimanche 20 juin 2021

How to solve a messed up domain implementation in PHP

I know the title is not too self descriptive but I really don't think the main problem here is the language but rather how the code is structured, let's see:

I have a shared library, which is used among a lot of services we run in PHP, these services are built in Lumen, but the library looks like it's plain PHP, we have all the domain classes defined there, in a very basic "one ring to rule them all" kind of way, it has all the common behavior which somehow we assumed was never going to change that much.

So, time passed, engineers left and shifted out, some others shifter into the team (that's me) and in several services, those domain classes were extended.

We have something like this:

In shared

class A {
    protected $attribute

    protected $myListOfB

    public function __construct(array $attributes) {
        $this->attribute = $attributes['the-value-i-want'];
        $this->myListOfB = $this->initListOfB($attributes);
    }

    protected function initListOfB(array $attributes): array
    {
        // Initializes a list of B by calling B's constructor for each instance
    }
}

class B {
    protected $myAttr;

    public function __contruct(array $attributes) {
        $this->myAttr = $attributes['value']
    }
}

All good until here, the problem is in one of the services we have something like this:

In a service using shared

class B' extends B {
    protected $newSpecificAttribute

    public function __construct(array $attributes) {
        $this->newSpecificAttribute = $attributes['new-attribute-value'];
        parent::__construct($attributes)
    }
}

And, at some point, somewhere in the code we are doing:

// Some code here
$myAInstance = new A($attributes);
// Some code with the new A and it's list of B, but I actually need B'

Because A is initializing its list of B in the scope of the shared library, it is not taking the new attribute into account, so, all those instances are B and not B'. I need a way to delegate the initialization to the child in this case, Is there a way to do that in PHP? how would you guys refactor this? I could just extend A also and override the way it initializes the list of B, but the logic is not very straightforward and it's actually an N level relationship (B also contains a list of C, and C has a list of D and everything gets initialized internally from it's upper level, so, A inits B, B inits C and C inits D) so, extending everything seems like overkill and wrong.

Thank you in advance

Aucun commentaire:

Enregistrer un commentaire