Private constractors and static instance creators

Since .NET3 there is a significant change in how Microsoft,”partners” and open source projected have delivered their assemblies. Until .NET2 there was a lot of usage of constructors with parameters but the introduction of WPF,WCF,WF and LINQ prety much forced the definition of types with parametless constructors.

.NET even introduced Property setting just after the construction to help move to a parametless constructors world. Who doesn’t remember all these problems with the specific constructor for deserialization. Funny errors appeared when for any reason any object was serialized and deserialized inside an engine like Workflow Persistent service.

Personally I never felt comfortable with constructors with parameters. I have always been writing framework code with heavy use of delegates and dynamic code generation. Parameters in the constructions never helped assemblies with this kind of types. But there is always the case of requiring constructors with parameters. There is no official best practises approach for this matter but here is what I think about this.

I make the following distinctions on the whys and why nots for constructors overloading.

The don’t to it cases:

  1. A class instance is too volatile to leave its functionality to not properly and guided initialization. This can be solved in two ways. Either use a bunch of Guard methods inside every call or use static instance creators. The good thing about this approach is that the static creators are actually functions that can differ in signature and name. The name is very important because usually this kind of classes have serious variations based on the input parameters. In this case overloading the functions doesn’t help and proper naming guides the code and the developer better. Also different function names help a lot in a stack trace because you can clearly see the function name that crashed when the constructors by design all have the same name. Stack trace isn’t good at revealing for which of the overloaded functions or constructors were used, so you need always to be very careful when deciding to overload.
  2. The class can be really initialized with totally different ways. This means that the constructors will execute different code and probably won’t end up at a common code.This kind of cases usually reflect the wish of the developer to provide a helper to properly initialize his class for various different scenarios that he can think of. But in the spirit of code decoupling I strongly believe that these “helpers” should not be constructors but static functions probably with different names. This case resembles the first one and one can argue that is looking into a mirror from a different angle. The reason I differentiate this case, is because it is similar to most of the IO and XML type initializers that come with .NET. All of them target the same functionality but for different channels, like files, streams in memory streams and so forth. Most of the classes provide static instance creators overloaded or with different names depending on the situation. The reality is that in order for a class like this to get to the same state ready to be used different things need to happen with a variety of errors. For example a file can not exist. But end result is having an instance that you know is ready and stable to use.
The go for it cases:
  1.  The classic service initialization paradigm from MVC controlers and services examples. Here a class really needs to execute the same logic on some private members but it allows a different initial values for these fields. Common characteristic for such cases is that all constructors end up on the same code through the use of the this keyword. This means that more or less the class is constructed the same way because it ends up doing so with the same piece of code. The overloading of constructors here gives a flexibility but it never adds functional change. And always keeps the default constructor available.
  2. The most important one for me is if the class has a persistable state. If you feel that for any reason the class acts as a container for data then a default constructor is at least required. If the class could for any reason be required to be persisted in the future then default constructor becomes even more important. Even a service-like class should have a default constructor because even if it isn’t holding data it is holding a reference to something the provides functionality.These service-like classes can be easily initialized from engines like WCF and unit testing.

As a rule of thumb I would suggest that constructors with parameters should never be used as a means of converting a variety of external arguments to an internal set. The conversion should always exist outside the scope of the constructor for better error handling and code decoupling.

Additionally I believe that type instance initialization should be as fast as possible and any heavy operation (that has the potential to go wrong) should be delivered though some sort of function. Don’t forget that constructors cannot be unit tested.

To summarize, I would only use additional constructor to the default one for two major reasons.

  • Mock the provided that would normally be created. See MVC controller and service examples.
  • Provide some slight variations of the default constructor. This variation never changes the creation process and it is mandatory for all constructors to use the same piece of code. Unit testing shouldn’t differ and these variations should be applicable also by property setting, thus allowing same unit testing patterns. But setting properties on the same command as with the constructor really makes this option is becoming obsolete.
Advertisements

2 comments

  1. Hi Alex,

    I see you feel really passionate about the subject:) But let me start with saying that it would be much easier to read this if you would give some examples. You are talking about the code, after all, why not giving people some code?

    On the matter, I believe one of the good reasons to have a constructor with parameters is to make an immutable class. For example:

    public class Currency
    {
    public Currency(string code)
    {
    // TODO: Validate params

    Code = code;
    }

    public string Code
    {
    get;
    private set;
    }

    public static Currency EUR
    {
    get
    {
    return new Currency(“EUR”);
    }
    }

    public static Currency USD
    {
    get
    {
    return new Currency(“USD”);
    }
    }
    }

    public class AmountInCurrency
    {
    public AmountInCurrency(decimal amount, Currency currency)
    {
    // TODO: Validate params

    Amount = amount;
    Currency = currency;
    }

    public decimal Amount
    {
    get;
    private set;
    }

    public Currency Currency
    {
    get;
    private set;
    }

    public AmountInCurrency ConvertTo(Currency newCurrency)
    {
    decimal rate = 1; // TODO: get actual rate
    return new AmountInCurrency(Amount * rate, newCurrency);
    }

    public AmountInCurrency GetTax(decimal taxRate)
    {
    return new AmountInCurrency(Amount * taxRate, Currency);
    }
    }

    Having immutable classes you can write pretty nice code chaining calls, like that:

    var amount = new AmountInCurrency(15.00m, Currency.EUR);
    var vat = amount.ConvertTo(Currency.USD).GetTax(30.00m);

    On the other hand, I would not do it when creating a DTO, like that:

    [Serializable]
    public class Event : PersistentEntity
    {
    public DateTime CreationDate { get; set; }
    public string Title { get; set; }
    public string EventText { get; set; }
    public DateTime EventDate { get; set; }
    public DateTime EventTime { get; set; }
    public Guid CategoryId { get; set; }
    }

    Because I agree, I would prefer to have this code generated, and be able to create instances of such classes in the generic engine.

    Thanks for the interesting topic!

    • Artem thank you and I agree about the code. Problem is that last time I checked I couldn’t optimize the layout of the page and code gets overflowed.

      About immutable objects I aggree because they are simple and don’t do much. Another example from .NET is the encoding. Most of the access to these instances is provided through static constructors. The reason they still have the constructor with parameters public is because only the most common cases are ready provided but the mechanism must be open for every other or unforseen case.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s