All of us have probably written code like this:
Foo f = new Foo();
And what could be simpler? As long as the logic in the constructor is simple (or better yet, the constructor is empty), it would seem that the simplest code is the best, so just use the constructor. Certainly the MSDN documentation is rife with code that uses public constructors. You can probably find plenty of public constructors used right here on my blog. Why invest the effort in writing (and using) a factory class that will probably never do anything useful, other than call a public constructor?
In his excellent podcast entitled “Emergent Design: The Evolutionary Nature of Software Development,” Scott Bain of Net Objectives nevertheless makes a strong case against the routine use of public constructors. The problem, notes Scott, is that the use of a public constructor ties the calling code to the implementation of Foo as a concrete class. But suppose that you later discover that there need to be many subtypes of Foo, and Foo should therefore be an abstract class instead of a concrete class–what then? You’ve got a big problem, that’s what; a lot of client code that has been making use of Foo’s public constructor suddenly becomes invalid.
Exposing a public constructor, observes Bain, allows code to violate the open/closed principle. This principle states that software should be open for extension, but closed for modification. Restating this in more mundane terms, developers should design their code in such a way that extending it (for example, making a class more useful by defining it as abstract and subclassing it as appropriate) does not provoke side effects elsewhere–and that’s the “closed for modification” part in a nutshell.
Bain points out that there is a simple, low-cost practice that avoids the public constructor’s violation of the open/closed principle. Just give a class constructor protected scope, and define a static Create method that uses the constructor–that’s it. Here’s class Foo’s new skeletal definition in C#:
public class Foo
{
protected Foo() {}
public static Foo Create() { return new Foo(); }
}
How hard was that? At the cost of a single line of code, you get benefits well beyond the already mentioned ability to transform the class into an abstract base class:
- If object construction becomes more complex, you can use a factory class inside the Create method.
- You can implement the Dependency Injection pattern, which facilitates unit testing with mock objects.
- You can use Microsoft’s Policy Injection Application Block to implement cross-cutting concerns such as logging, authorization, and validation.
Unfortunately, you may occasionally encounter a corner case where you must define a public constructor. The .NET Framework’s XmlSerializer cannot be used on a class with no public default constructor, since XmlSerializer must instantiate the class in order to discover the public properties that must be serialized. If you plan to serialize a class using XmlSerializer, then, you must make the constructor public–but you should mark it with the ObsoleteAttribute to warn fellow developers not to use it:
public class Foo
{
[Obsolete("Do not use--provided only for use by XmlSerializer. Client code should call Foo.Create().")]
public Foo() {}
public static Foo Create() { return new Foo(); }
}
If due to habit a fellow programmer calls the public constructor (against your intentions), the C# compiler will emit a helpful warning message. Of course, there are programmers who ignore warnings, but that is the subject of a different post.