Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is passing stateful objects to constructor a bad thing?

It is my intuitional understanding that instantiating objects by passing their constructors a stateful object is a bad practice. Take this code for example:

class MathValues
{
    private $x;

    public function __construct($x, $y)
    {
        $this->x = $x;
        $this->y = $y;
    }

    public function getX()
    {
        return $this->x;
    }

    public function getY()
    {
        return $this->y;
    }
}

class MathCalculator
{
    private $mathValues;

    public function __construct(MathValues $class)
    {
        $this->mathValues = $class;
    }

    public function calculateMultiplication()
    {
        return $this->mathValues->getX() * $this->mathValues->getY();
    }
}

$mathValues = new MathValues(2,5);

$mathCalculator = new MathCalculator($mathValues);
$someValue = $mathCalculator->calculateMultiplication();

Now, I have been a web developer for a long time and only recently I've started developing in OOP paradigm, following(as hard as I can) SOLID principles, service oriented architecture, etc. Also for some time now I've been developing using Symfony2/3 framework. Everything I see out there(including Symfony's service container) says that constructor should be used to pass other services(stateless instances) but I can not for the life of me find what principle says that you should not pass a stateful object to a constructor.

So my question is as in the header - What principle says that it's a bad thing to pass a stateful object to a constructor?

UPDATE

It seems my question has not been clear enough, so I updated my example. In this example problems and the solution is clear: every time, when I need to multiply something, I need to create 2 instances of 2 classes. Instead, I could create a single service MathCalculator and pass it 2 arguments - x and y. So what I'd need is only 1 instance for all the values i want to do math operations to and an object for every value(if even needed) that i need to do math operation with.

Not to mention that stateful programming is a bad dynamic and I believe in separating value immutable objects and services that do not have state at all.

like image 302
drakonli Avatar asked Jan 31 '26 10:01

drakonli


1 Answers

First of all, as you already recognise since you mentioned it in your update, it isn't ideal to keep instantiating new MathCalculators every time you have different MathValues for it to operate on.

The first thing you need to ask is whether values x and y actually have any domain-specific, real-life relationship to each other with regards to MathCalculator. If they can both be just random values that a user enters, then putting them both in the same class is not good - S of SOLID says you should apply the principle of single responsibility or encapsulation. One instance of MathValues should have one value and y should become another instance of MathValues, so in this case MathValues becomes redundant and you can just use a set or list of numbers.

I suspect you are using MathValues as a Data Transfer Object (DTO)

Otherwise, if x and y are somehow related and they do belong in the same class, e.g. geodata or grid references, then what you have done with MathValues is an example of the Anaemic Domain Model anti-pattern and a violation of the Law of Demeter

You should put your business logic into your entity to adhere to the S of SOLID - the responsibility for knowing how to multiply x and y belongs to MathValues, so to satisfy the duty of single responsibility and encapsulation, you should refactor that method into that class.

Admittedly this is debatable because actually your MathValues also looks like a DDD Value Object in which case you wouldn't want any logic in there, rather you would aggregate the MathValues into a aggregate class and put the method there instead. That though is a decision you would only want to make later when your domain starts getting more complicated.

like image 172
Adam Avatar answered Feb 03 '26 06:02

Adam