When taking a first swim into Object Oriented principles, there seems to be an implicit rule that your constructor signatures should be based upon what is required for a valid object to be created.
The purist in me resonates with this, but the wet-behind-the-ears TDD guy discovers that he hates that purist guy. I want to be able to TEST without having to create a ton of mock objects to simply get my object created.
Take these two classes:
public class ClassA
{
public ClassA(){}
}
public class ClassB
{
private ClassA classA;
public ClassB(ClassA classA){ this.classA = classA;}
public ClassA
{
get{return classA;} // no setter since this is required
}
}
Now this is harmless and I could mock ClassA somehow and be just fine. But if ClassA has constructor dependencies and then those dependencies have constructor dependencies we'll want to find a way to mock INSANITY.
There are a couple of thing to do with this:
- Accept that Object Oriented principles are the most important driver in the decision making process ... so grin and write all your mocks.
- Place a setter for properties which are NOT optional
So let's choose to add a setter on ClassA property in ClassB class. Now we've opened ourself up to integrity issues right? I can smell the strong aroma of NullReferenceExceptions from my keyboard.
But this is where DDD principles come in to harmonize with TDD pragmatism with the Factory and Aggregate patterns. Rather than 'new'-ing just anywhere in your application, DDD specifies that object creation and its variants (dependents) are encapsulated in a Factory. With this rule in place we can now loosen the constructor constraint we had on ClassB and provide a default (no-arg) constructor with a setter for the required properties.
My presenters or whereever else I need to fetch my aggregate object are REQUIRED to go to my factory for an object and this way I can push my dependency requirements THERE rather than on the object itself.
Now, really I want to force dependencies as much as possible into my constructor so I won't altogether avoid having parameters in my constructors. But the factory pattern allows us to both control how objects are created and enforcing dependencies, while freeing up testing scenarios by reducing the amount of mocking/stubbing required.