Is it an acceptable practice to initialize physical/external resources from a constructor when the resource is needed for the object to do it’s work?
For instance, let’s say I wanted to create an object that proxies a durable message queue and that the message queue is a physical database table.
Would that make sense to create an idempotent constructor which physically create the table if it doesn’t exist yet?
E.g.
IMessageQueue queue = new SQLTableMessageQueue('table_name', dataSource);
Perhaps a static factory method would be more appropriate? In that case, the table creation would occur in the factory method and the constructor would be free of such behavior.
IMessageQueue queue = SQLTableMessageQueue.create('table_name', dataSource);
I’m not too sure what would be an appropriate approach? Another idea I had was to use the Repository Pattern.
5
Usually constructors are not used to initialize external resources, there are few reasons,
- Testability – It would be very hard to create unit tests
- To be in compliance with SRP
You could always pass the message queue to the constructor where you use it.
class QueueProcessor
{
private IMessageQueue _queue;
public QueueProcessor(IMessageQueue queue)
{
_queue = queue;
}
}
Yes, you can use a factory to create the queue
class QueueFactory
{
public IMessageQueue CreateMessageQueue
{
return new SQLTableMessageQueue('table_name', dataSource);
}
}
With this approach you can easily mock the message queue for testing, and also it does comply with the SRP compared to constructing the queue within the constructor.
6
Google’s C++ Style Guide asks you to refrain from doing work in constructors. Their arguments may or may not be applicable to your language. Testing on the Toilet’s six-year-old advice #3 on how to write testable code by not doing work in the constructor still holds though.
If you search for it online you’ll find tons, /*Programmers*/ is one place to start.