Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is business logic in constructors a good idea?

Tags:

oop

I'm currently rebuilding a specialised ticket system at work (mainly used to support people with faults in remote sensing hardware...). Anyway, I was wondering whether doing lots of workflow type activity in an object's constructor is a good idea.

For example, there is currently this:

$ticket = new SupportTicket(
    $customer,
    $title,
    $start_ticket_now,
    $mail_customer
);

as soon as the object is created, it'll put a row into a database, go and mail the customer a confirmation e-mail, possibly send a text message to the nearest technician, etc..

Should a constructor be firing off all that work, or something more like the following?

$ticket = new SupportTicket($customer, $title);
$customer->confirmTicketMailed($ticket);
$helpdesk->alertNewTicket($ticket);

If it helps, the objects are all based on the ActiveRecord style.

I guess it may be a matter of opinion, but what do you think is the best thing to do?


1 Answers

If the constructor does all that work then the constructor knows about many other domain objects. This creates a dependency problem. Should the ticket really know about the Customer and the HelpDesk? When new features are added, isn't it likely that new domain objects will be added to the workflow, and doesn't that mean that our poor ticket will have to know about an ever increasing population of domain objects?

The problem with spiderwebs of dependency like this is that a source code change to any one of the domain object will have an impact upon our poor ticket. The ticket will have so much knowledge of the system that no matter what happens, the ticket will be involved. You will find nasty if statements gathering inside that constructor, checking the configuration database, and the session state, and so many other things. The ticket will grow to become a god class.

Another reason I dislike constructors that do things is that it makes the objects around them very hard to test. I like to write lots of mock objects. When I write a test against the customer I want to pass it a mocked out ticket. If the constructor of ticket controls the workflow, and the dance between customer and other domain objects, then it is unlikely that I will be able to mock it out to test the customer.

I suggest you read The SOLID Principles, a paper I wrote several years back about managing dependencies in object oriented designs.

like image 67
Uncle Bob Avatar answered Sep 13 '25 02:09

Uncle Bob