Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize() vs Constructor() method, proper usage on object creation

We all know the difference between a Constructor and a User-Defined Initialize() method fundamentally.

My question is focused on best design practice for object creation. We can put all Initialize() code into Constructor() and vice versa (move all warm-up code to Initialize method and call this method from Constructor).

Currently, designing a new class, I create any new instances inside constructor() and move any other warm-up code into Initialize() method.

What's the best trade-off point in your opinion?

like image 576
Xaqron Avatar asked Dec 11 '10 00:12

Xaqron


People also ask

What is the need for initialization of object using constructor?

A class object with a constructor must be explicitly initialized or have a default constructor. Except for aggregate initialization, explicit initialization using a constructor is the only way to initialize non-static constant and reference class members.

Is a constructor and initializer the same?

Object Initializers were something added to C# 3, in order to simplify construction of objects when you're using an object. Constructors run, given 0 or more parameters, and are used to create and initialize an object before the calling method gets the handle to the created object.

Which constructor is used to declare and initialize an object from another object?

A copy constructor is a member function that initializes an object using another object of the same class.

Does constructor create object?

Simply speaking, a constructor does not create an object. It just initializes the state of the object. It's the new operator which creates the object.


2 Answers

I think there are multiple aspects that should be taken into consideration:

  • A constructor should initialize an object in a way that it's in a usable state.

  • A constructor should only initialize an object, not perform heavy work.

  • A constructor should not directly or indirectly call virtual members or external code.

So in most cases an Initialize method shouldn't be required.

In cases where initialization involves more than putting the object into a usable state (e.g., when heavy work needs to be performed or virtual members or external need to be called), then an Initialize method is a good idea.

like image 83
dtb Avatar answered Sep 22 '22 19:09

dtb


I've found myself thinking about this a fair bit recently (hence finding this question) and whilst I dont have an answer I thought I'd share my thoughts.

  • Constructors 'ideally' should only set the object state, i.e: a few:

this.member = member;

In my opinion this plays nicely with IoC, inheritance, testing and just smells nice.

However heavy lifting is sometimes required so what I've been trying to do is:

  • Pass in the heavy lifting.

That means abstracting that initialisation code to another class and passing that in. This is usually possibly if the heavy lifting is not really your objects responsibility, so doing this actually refactors to nicer code.

If this is not possible and you do need to initialise state for your class before usage then add an initialse method. This does add temporal dependency into your code but this is not necessarily a bad thing especially when using IoC containers:

Say CarEngine requires a DrivingAssistComputer, and the DrivingAssistComputer needs to do heavy initialisation, i.e. Load all parameters, weather condition checks, etc. Another thing to note is that CarEngine does not directly interact with the DrivingAssistComputer, it just needs it to be present, doing its own thing on the side. In fact the engine may not work properly without the DrivingAssistComputer doing its thing in the background (changing some state somewhere). If we are using IoC then we have:

// Without initialise (i.e. initialisation done in computer constructor)
public CarEngine(FuelInjectors injectors, DrivingAssistComputer computer) {
  this.injectors = injectors;
  // No need to reference computer as we dont really interact with it.
}

...

So what we have here is a constructor argument marking computer as a dependancy but not actually using it. So this is ugly, but lets add an Initialise method:

public CarEngine(FuelInjectors injectors, DrivingAssistComputer computer) {
  this.injectors = injectors;
  // This ofcourse could also be moved to CarEngine.Initialse
  computer.Initialise(); 
}

...

Still not a cohesive class but at least we know that we depend on computer even though we are not directly interacting with it outside of the constructor.

Another option ofcourse is to have a CarEngineFactory that does:

 CarEngine CreateEngine(FuelInjectors injectors) {
  new DrivingAssistComputer().Initialise(); 
  return new CarEngine(injectors);
}

...

However, I find factories and IoC just confuse the matrix so I would go for the second option.

Would love to hear some thoughts on this.

Edit 1: Another option I missed above is having the Initialise method but moving this invocation to the IoC initialisation module. So creation and initialisation are still somewhat encapsulated.

like image 28
gatapia Avatar answered Sep 24 '22 19:09

gatapia