Dependency Injection when an object needs to be created fresh

There is a small problem that I sometimes encounter when in a class I use an object (dependency) that needs to be instantiated fresh - that is within the calling class and not earlier like in a container. Let’s take a first example, which is quite obvious and simple - there is ActionsChecker class which is responsible for checking if certain actions can be performed on an order:

class ActionsChecker {
    public function canBeSent($order_id):bool {
        // ...
    }
    
    public function canBeCancelled($order_id):bool {
        // ...
    }
}

And the class which submits an order (like from a form) uses ActionsChecker like this:

class OrderSubmission {
    private $actionsChecker;
    
    public function __construct(ActionsChecker $actionsChecker) {
        $this->actionsChecker = $actionsChecker;
    }
    
    public function sendOrder($order_id) {
        if (!$this->actionsChecker->canBeSent($order_id)) {
            throw new Exception("Can't send order");
        }
        
        // send order...
    }

    public function cancelOrder($order_id) {
        if (!$this->actionsChecker->canBeCancelled($order_id)) {
            throw new Exception("Can't cancel order");
        }
        
        // cancel order...
    }
}

This is nice and ActionsChecker is instantiated somewhere else in a container and the OrderSubmission class doesn’t have to deal with it.

Now suppose I decide to change ActionsChecker because I come to a conclusion that there is no need to accept $order_id in every method and instead I will require it in the constructor (it may simplify the class or I may have other reasons for this):

class ActionsChecker {
    private $order_id;
    
    public function __construct($order_id) {
        $this->order_id = $order_id;
    }

    public function canBeSent():bool {
        // ...
    }
    
    public function canBeCancelled():bool {
        // ...
    }
}

Now I don’t need to pass $order_id to every method but instead I need to have the object created already for this specific order. A container can’t do it beforehand because $order_id is not known before OrderSubmission is used. A working version using new keyword would look like this:

class OrderSubmission {
    public function sendOrder($order_id) {
        $actionsChecker = new ActionsChecker($order_id);
        
        if (!$actionsChecker->canBeSent($order_id)) {
            throw new Exception("Can't send order");
        }
        
        // send order...
    }

    public function cancelOrder($order_id) {
        $actionsChecker = new ActionsChecker($order_id);
        
        if (!$actionsChecker->canBeCancelled($order_id)) {
            throw new Exception("Can't cancel order");
        }
        
        // cancel order...
    }
}

Instantiating objects in the class doesn’t look good to me, what other option do I have? The only thing I can think of is pass a factory object to OrderSubmission and then I would do something like this:

$actionsChecker = $this->actionsCheckerFactory->create($order_id);

which is somewhat fine but feels like a lot of boilerplate and I must admit I am often reluctant to make my dependencies require arguments in constructor (like $order_id) just because I’d have to deal with factories (create them, instantiate them and then pass them to class constructors), even when requiring such arguments would make the class (dependency) cleaner.

What are your thoughts about it and what is the most elegant solution? Should I go with a factory and accept the additional code?

If you want to go down this route, then yes, a factory would be what you’d need. I would urge you to explicitly pass it an $orderid from where ever you call it. It may be tempting to create a factory that gets the order id from the current request somehow, but when you go down that route everything will be coupled to everything so hard there isn’t any room for change / testing / etc.

Given this specific case the most elegant solution to me would be to move the functionality of the OrderChecker into the order itself, since that way the class can guarantee its own consistency.

If it’s possible to call send on an order while this is not possible, but someone called it anyway because they weren’t aware of the OrderChecker you’re in a world of hurt. Better to avoid that.

Also, generally speaking I prefer the implementation of the OrderChecker where each method accepts an $orderid over an OrderChecker that gets an $orderid in the constructor. The reason is that when it is a parameter the class itself can be fully stateless, and thus be easier to test, expand, reason about, etc.

Never solve with state that which can be solved without state. (up to a point, of course)

1 Like

It sounds like what you would want is a factory. You would pass the order ID to a factory method and the factory would build a order action checker checker and return it.

1 Like

Yes, of course, I didn’t even thought of getting $orderId from any other place!

Maybe you are right but I simplified the code for demonstration so as not to be too verbose here. In reality I will have a lot more methods like canBeCancelled() - maybe about 10 - and each would require the same $orderId argument. Also, I will need the checker to be used in several different contexts, that’s why I want to keep it as a separate class - the form submission is only one of them.

Well, that’s why I’m using the OrderChecker in the send method so as not to allow this. Those who call send don’t need to be aware of the OrderChecker because the send method will be using it internally.

This is a good observation and I agree with this, I’m just wondering whether I’ve already reached the point :smiley: . In this case I’m thinking also about forward flexibility - currently each method of the OrderChecker needs $orderId but in the future it might also need a $userId or a User object (so that for the results user permissions will be taken into account as well) or maybe some other arguments that might be relevant. In a stateless class I’d need to refactor all usages of all those methods by adding additional arguments everywhere whereas in a stateful class I only add the arguments to the factory method calls and there’s much fewer of them.

Yes, after a few attempts at solving the problem I used the factory and it looks like a good solution. I just have doubts whenever I need to use additional layers, abstractions, etc. so as not to over-complicate code needlessly. I try to avoid injecting factories to classes but in this case this seems like the best solution.

Know what object always knows the $orderid? That’s right, the order :wink:

But you could also use the Order object in several different contexts, no?

So you’ve spread the knowledge about orders over 3 classes? You know the Single Responsibility Principle? I apply that the other way around too, I like to call it the Singly Responsible Principle. Meaning that classes should have full control over themselves, and you should never have classes that access the internals of a class to make decisions on it. Also see tell don’t ask.

From what I can see in this post you have not :slight_smile:

Code for your use-case, not for your re-use-case (that might never come)

But what if you ever need to handle multiple orders at the same time, would you create multiple OrderCheckers? How would you make sure you don’t mix them up? It’ll be a lot off balls you’d need to juggle.

I’ve got a feeling that your hesitation with throwing all this logic in the Order class will make the Order too big, I personally don’t see that as a problem. If something has a lot of logic around it it’s fine to show that. At least when you want to know anything about order handling you can go to that one class and find anything you want to know all at once, without having to jump between several layers of code to see what’s going on.

I’ve been working this way for a few years, and my code has become a lot more simple because of it. Indirection seems like a nice idea to hide complexity, but when used too much it actually adds complexity.

Just wondering, have you ever heard about DDD and/or hexagonal?

I don’t share the same opinion that this logic should be in your order object. I think the order object should be dumb as possible.

I first couldn’t understand what you mean but finally it occurred to me we are talking about completely different things because our coding styles are much different and what is obvious to you is alien to me, at least in the conversation :). So the fact is that in my system there is no Order class!

I used to create such large objects for various things in applications a few years ago when I was still using an ORM and there was an Order, an Invoice, etc. and I tucked most stuff related to those things into the objects. Over time those objects grew very large and became hard to navigate and maintain. I know I made a lot of other mistakes back then so I suppose your Order class might be more elegant than what I used to create but still I’ve decided to go the other route - have small classes each dealing with a single thing and accessing others via DI.

So in this case I have the OrderSubmission class that deals with submitting the order form. It is a bit different from my sample code here because my intention was not to discuss this class but rather instantiation of its dependency. This class processes form data and delegates further actions to other classes based on UI data from the form. In effect there is the OrderSubmission class that deals with this one task and there is no Order class, therefore there is no Order object I could use in several different contexts as you suggested.

I don’t know what you mean by ‘knowledge about orders’ but each class that does something with orders has a piece of knowledge about the orders - just enough to do what it’s supposed to do. I don’t know if you can say the OrderSubmission has knowledge about orders - it has knowledge of data submitted from the form and it knows what other objects to use and to pass those data to.

I don’t know what you mean because form what I can tell and didn’t show any class that doesn’t have full control over itself or accesses internals of other classes…

Time will tell, but I’ll do it anyway just for the sake of experience and seeing how it will turn out long-term.

Actually, in this case the requirement I mentioned is very possible in the future.

I could quote you on the “Code for your use-case, not for your re-use-case (that might never come)” :smiley: Yes, using the OrderChecker on multiple orders is very unlikely in this project and might never be needed. And yes, in case I need it I will create multiple checkers, no problem :slight_smile:

Then you must have found a good way of organizing large classes in a way that they stay clean and maintainable. Personally, I find it much easier to have small classes and small methods - there are always exceptions, of course, but that’s the general idea.

I don’t like the idea of having a class with such a generic name like Order. Even the name doesn’t tell me what the class is responsible for - it does something with orders but what? Everything or just a selection of stuff? Maybe it is just a dumb object holding order data and nothing else? My classes are organized around single tasks: OrderFormSubmission deals with order form submission only and by the name I already know what the class does. ActionsChecker, which in the real project is named PossibleOrderActionsChecker, is responsible for checking if certain actions can be performed on an order. And so on.

I’ve read about DDD but not hexagonal. But they both seems to be good design concept from what I can tell.

Ah, I understand the confusion now. I was under the impression that you had an Order model class that represents an order, and that would get persisted using some sort of repository. I understand you don’t, and you have different classes that all fire queries to some orders table somewhere?

Care to elaborate?

Yes, something like this.

Ah, in that case we’re using completely different paradigms.

I use DDD heavily, so if I were to create a system like you’re describing there would be an Order class that represents an order and has all methods on it that allow actions on that Order. The Order itself is then fully responsible of keeping itself in a sane and consistent state. Also, these methods would reflect the names the business uses. So there might be a named constructor called place so when you create a new order you don’t have new Order(...) but Order::place(). And when and order is executed for example that would be $order->execute(). No anemic stuff like setState() or whatever, only actions that the business actually performs on orders, that lead to a consistent state change within the order.

Persisting models in DDD is kind of an afterthought, it’s not modelled into the domain. The main advantage being that you can put all your domain knowledge in plain old PHP objects, decoupled from absolutely everything, and write unit tests for them that run blazingly fast.

Once the domain is complete you wire it up to repositories that persist / load objects and you’re done. Obviously there is quite a lot to it, but the point is the model itself doesn’t need to concern itself with how it will be stored.

It’s a very powerful paradigm and I can wholeheartedly recommend it :slight_smile:

The interactor design pattern works well for separating business logic from the domain object for active record model architectures. For ORM architectures I tend to agree that the logic should be in the repository.

Wow, interactor feels really non DDD like. DDD is all about objects that enforce behaviours within objects, whereas interactor feel like behavior that is defined outside of the object.

Also, defining multiple listeners like in the article sounds fine, but it’s not any different than calling multiple functions sequentially, and the whole point of event driven is that subscribers know about the emitter, not the other way around. The emitter should really be an object that’s like “Yo, for anyone interested, a new user just signed up.” and then there could be an event listener that’s like “I’m interested, I’ll send them an e-mail”, while others won’t bother. It’s exactly this decoupling of action and reaction that makes event driven extremely powerful. Interactor is doing this the wrong way around so I fail to see why I should use it.

The pattern works well for ActiveRecord slimming down models, and creating small, isolated classes for business logic beyond simple select, create, and updates.

Sorry, but no, it’s got nothing to do with ActiveRecord whatsoever.

In my experience models become increasingly difficult to unit test as they become more complex. Decoupling behavior into smaller, isolated pieces of code results in smaller units easier to test individually.

I’ve never noticed that with DDD. If anything, testing the models is very easy and fast, because you don’t need to test against an actual database.

I suppose it would get hard if you’re coding against some sort of framework that gets in the way of testing?

I’m a bit late to this thread, but the red flag to the underlying problem here is broken encapsulation. The data (the order ID) is not encapsulated but is separate from the functions working on it rather than bundled together.

Firstly, are orders and ActionsCheckers really different things?

If the logic for cancelling/sending an order is the same for all orders then you can simplify it by making it a single Order class:

<?php

class Order {
    private $id;

    public function __construct($id) {
        $this->id = $id;
    }

    public function send() {
        if ($this->canBeSent()) {
            //send order
            return true;
        }
    }

    private function canBeSent() {

    }

    private function canBeCancelled() {

    }

    public function cancel() {
        if ($this->canBeCancelled()) {
            //Cancel order
            return true;
        }
    }
}

class OrderSubmission {
    private $order;
    
    public function __construct(Order $order) {
        $this->order = $order;
    }
    
    public function sendOrder() {
        if (!$this->order->send()) {
            throw new Exception("Can't send order");
        }

    }

    public function cancelOrder() {
        if (!$this->order->cancel()) {
            throw new Exception("Can't cancel order");
        }
        
    }
}

This way you’ve separated out the logic that handles the submission from the logic that sends the order and encapsulated the canBe* checks. The OrderSubmission class is no longer concerned with the state of the order (Can it be cancelled or not?) but instead just tries to send/cancel the order and leaves the “Can it be cancelled” check to the order class (where it probably belongs.)

However, given your question I suspect that some orders have different logic that determines whether they can be cancelled and sent. In which case you can extract the private methods into their own class and apply the visitor pattern:

<?php

class Order {
    private $id;
    private $actions;

    public function __construct($id, Actions $actions) {
        $this->id = $id;
        $this->actions = $actions;
    }

    public function send() {
        if ($this->actions->canBeSent($this)) {

        }
    }

    public function cancel() {
        if ($this->actions->canBeCancelled($this)) {

        }
    }
}

Now you can substitue the Actions class to apply different actions to different orders and you still have the benefit of encapsulation (only the order class is concerned with the state of the order) and the implementation of the “can this order be sent or not?” check is hidden from the OrderSubmission class. It tells the order to send, if it can’t (for reasons only relevant/known to the Order class) it can throw the exception/display an error/etc.

2 Likes

Thanks, Tom, this is an interesting approach and I’m considering whether I could create an Order class like this - in your scenario it makes sense, however there’s one small but important implementation lacking in it: the implementation of “can this order be send…”, etc. must be public whereas you’ve made it private or hidden within the Action class. As I wrote earlier, I need to be able to do the canBe...() checks from different contexts and sending or cancelling an order is only one of them. For example, I need to know if an order can be cancelled just for display purposes.

I suppose with your visitor pattern it should be possible to do this:

$order = new Order(123);
$actions = new Actions();
$canBeCancelled = $actions->canBeCancelled($order);

Edit: This might not work because in order to initialize Order I need Actions and I can’t use Actions without Order - a chicken and egg problem…

So I have the Actions class that I can use separately just to do the checks. However, this looks very similar to my ActionsChecker class that I posted in my first post, except that I can use ActionsChecker on its own by only supplying $order_id while the Actions class needs an Order object in order to function - and what’s more I’d have to create additional public methods to the Order class so that the Actions class will be able to get necessary information from the Order so that it can run its checks properly - at least there should be a getOrderId() method so that the Actions class will be able to use it. So far the Order class only has public methods which are irrelevant for the checks (like send())…

This is an interesting approach but at the moment I cannot grasp what advantages it would have over my initial ActionsChecker class.

Note that in @TomB’s class the Actions is initialized within, and thus part of the Order class, so all knowledge about the order is encapsulated within the Order class (even if it hands off of part of the responsibilities to another class, which is fine).

So the classes and the responsibilities are indeed the same as in your case, but the way they are composed is certainly not.

I’m not sure I follow. Can’t you do this?

$actions = new Actions();
$order = new Order(123, $actions);
$canBeCancelled = $actions->canBeCancelled($order);

If you’re using a DIC set up actions as a singleton instance. But yes, if you need to call it externally elsewhere you may be better off just passing the various instances around rather than encapsulate Actions in Order.

Presumably your ActionChecker class contains some logic that fetches the relevant information about an order for the given $order_id. This seems rather out of place because you have the logic for fetching properties related to an an order based on its id in the ActionChecker class, and you probably need this same logic elsewhere (Find data about an order using its id).

Depending on what you are doing you might even be better off composing the objects the other way around:

<?php
class Order {
    private $id;

    public function __construct($id) {
        $this->id = $id;
    }

    public function send() {
        // send
    }

    public function cancel() {
        // cancel
    }
}



class Actions {
	private $order;

	public function __construct($order) {
		$this->order = $order;
	}

	public function canBeSent() {

	}

	public function canBeCancelled() {

	}
}

But this is likely to make things overly complex. The underlying issue is that canBeSent is a property of an order so almost certainly belongs in the Order class. If you try to put it elsewhere it will mean passing around the order object and the object that contains the canBeSent method. Again, it’s an encapsulation issue. If your canBeSent method requires data from an order object then it belongs in the Order class.

You don’t need to pass the full object around with the visitor pattern, you could also do this:

<?php

class Order {
    private $id;
    private $actions;

    public function __construct($id, Actions $actions) {
        $this->id = $id;
        $this->actions = $actions;
    }

    public function send() {
        if ($this->actions->canBeSent($this->foo, $this->bar)) {

        }
    }

    public function cancel() {
        if ($this->actions->canBeCancelled($this->foo, $this->bar)) {

        }
    }
}

The danger of this approach is that it assumes every kind of Actions object needs the same data (e.g. it’s always the same properties which are used to calculate if the order can be sent or cancelled, which may not be the case.

As I said before, if the rules for “can this order be sent” are the same for every order it’s really easy, just put them in the Order class:


class Order {
    private $id;

    public function __construct($id) {
        $this->id = $id;
    }


    public function canBeSent() {

    }

    public function canBeCancelled() {

    }

}

Where it gets more complicated is if you have different rules that apply to different orders.

The code you posted above causes a potential issue:

$actions = new Actions();
$order = new Order(123, $actions);
$canBeCancelled = $actions->canBeCancelled($order);

Imagine you have PremiumOrderActions and StandardOrderActions which apply different rules for canBeSent depending on the type of order. The code above breaks because you need to know whether to instantiate a PremiumOrderActions or StandardOrderActions. There’s also nothing to prevent you accidentally applying the wrong rules to the wrong order. It really depends on whether all orders have the same rules for canBeCancelled or they are different based on the order type.

If there are different rules for different orders, you can do something like this (sorry I don’t know if there is a name for this pattern but it’s one I use a lot):

interface Actions {
	public function canBeSent($order);
	public function canBeCancelled($order);
}

class PremiumOrderActions implements Actions {
	public function canBeSent($order) {
		//...
	}
	public function canBeCancelled($order) {
		//...
	}
}

class StandardOrderActions implements Actions {
	public function canBeSent($order) {
		//...
	}
	public function canBeCancelled($order) {
		//...
	}
}


class OrderActionsList implements Actions {
	private $actions = [];

	public function add($type, Actions $actions) {
		$this->actions[$type] = $actions;
 	} 

 	public function canBeSent($order) {
                //call the relevant `canBeSent` method based on the order's type
 		return $this->actions[$order->getType()]->canBeSent($order);
 	}

	public function canBeCancelled($order) {
		return $this->actions[$order->getType()]->canBeCancelled($order);
	}
}


class Order {
	const PREMIUM = 1;
	const STANDARD = 2;

	public function getType() {
		//logic to return self::PREMIUM or self::STANDARD
	}
}


$orderActions = new OrderActionsList();
$orderActions->add(Order::PREMIUM, new PremiumOrderActions());
$orderActions->add(Order::STANDARD, new StandardOrderActions());


//Will now apply the correct `canBeSent` method to `$order` based on its type
$orderActions->canBeSent($order);

But without seeing more of the code, e.g. what send(), and canBeSent() are doing it’s difficult to say.