31

Is there any purpose for declaring an init() method for a type?

I'm not asking whether we should prefer init() over a constructor or how to avoid declaring init().

I'm asking if there is any rationale behind declaring an init() method (seeing how common it is) or if it's a code smell and should be avoided.


The init() idiom is quite common, but I have yet to see any real benefit.

I'm talking about types that encourage initialization via a method:

class Demo {
    public void init() {
        //...
    }
}

When will this ever be of use in production code?


I feel it may be a code smell since it suggests the constructor does not fully initialize the object, resulting in a partially created object. The object should not exist if it's state isn't set.

This makes me believe it may be part of some kind of technique used to speed up production, in the sense of enterprise applications. It is the only logical reason I can think of having such an idiom, I'm just not sure how it would be beneficial if so.

10
  • 1
    To "...seeing how common it is...": is it common? Can you give some examples? Perhaps you're dealing with a framework that requires separating initialization and construction.
    – COME FROM
    Commented Oct 31, 2016 at 7:17
  • 1
    Is the method found on a base class or a derived class, or both? (Or: is the method found on a class that belongs to an inheritance hierarchy? Does the base class calls the init() on the derived class, or vice versa?) If so, it is an example of letting base class execute a "post-constructor" which can only be executed after the most derived class has finished construction. It is an example of multi-phase initialization.
    – rwong
    Commented Oct 31, 2016 at 8:37
  • If you don't want to initialise at the point of instantiation, it would make sense to separate the two. Commented Oct 31, 2016 at 9:21
  • you might be interested. is-a-start-run-or-execute-method-a-good-practice
    – Laiv
    Commented Oct 31, 2016 at 12:51
  • 1
    Also: softwareengineering.stackexchange.com/questions/334162/… Commented Oct 31, 2016 at 22:42

9 Answers 9

52

Yes, it's a code smell. A code smell isn't something that necessarily always needs to get removed. It's something that makes you take a second look.

Here you have an object in two fundamentally different states: pre-init and post-init. Those states have different responsibilities, different methods that are allowed to be called, and different behavior. It's effectively two different classes.

If you physically make them two separate classes you will statically remove a whole class of potential bugs, at the cost of maybe making your model not match the "real world model" quite as closely. You usually name the first one Config or Setup or something like that.

So next time, try refactoring your construct-init idioms into two-class models and see how it turns out for you.

3
  • 10
    Your suggestion to try the two-class model is good. Proposing a concrete step to address a code-smell is useful.
    – Ivan
    Commented Oct 31, 2016 at 13:16
  • 1
    This is the best answer so far. One thing bugs me though: "Those states have different responsibilities, different methods that are allowed to be called, and different behavior" - Not separating these responsibilities violates SRP. If the purpose of the software was to replicate a real world scenario in every aspect, this would make sense. But in production, devs mostly write code that encourages easy manageability, revising the model if needed to better fit a software-based enviornment (continued on next comment)
    – Dioxin
    Commented Oct 31, 2016 at 23:58
  • 2
    The real world is a different enviornment. Programs attempting to replicate it seem domain specific, as in you wouldn't/shouldn't account for it in most projects. Lots of things that are frowned upon are accepted when it comes to domain specific projects, so I'm trying to keep this as general as possible (such as how calling this in the constructor is a code smell and could result in error-prone code, and avoiding it is recommended regardless of what domain your project falls under).
    – Dioxin
    Commented Nov 1, 2016 at 0:02
17

It depends.

An init method is a code smell when it is not necessary to have the object initialization separated from the constructor. There are sometimes cases where it makes sense to separate these steps.

A quick Google search got me this example. I can easily imagine more cases where the code executed during object allocation (the constructor) might better be separated from the initialization itself. Maybe you have a leveled system, and allocation/construction takes place in level X, but initialization only in level Y, because only Y can provide the necessary parameters. Maybe the "init" is costly and must be run only for a subset of the allocated objects, and the determination of that subset can only be done in level Y. Or you want to override the (virtual) "init" method in a derived class which cannot be done with a constructor. Maybe level X provides you with allocated objects from an inheritance tree, but level Y is not aware of the concrete derivation, only about the common interface (where init maybe defined).

Of course, to my experience these cases are only a small percentage of the standard case where all initialization can be done directly in the constructor, and whenever you see a separate init method, it might be a good idea to question its necessity.

11
  • 2
    The answer in that link says it's useful for reducing the amount of work in the constructor, but it encourages partially created objects. Smaller constructors can be achived through decomposition, so to me it seems that answers creates a new problem (the potential to forget to call all the required initialization methods, leaving the object error-prone) and falls under the code smell category
    – Dioxin
    Commented Oct 31, 2016 at 6:52
  • @VinceEmigh: ok, it was the first example I could find here on the SE platfform, maybe not the best one, but there are legitimate use cases for a separate init method. However, whenever you see such a method, feel free to question its necessity.
    – Doc Brown
    Commented Oct 31, 2016 at 6:54
  • I'm questioning/challenging every use case for it, as I feel there is no situation where it would be a necessity. To me, it's poor timing of object creation, and it should be avoided since it's a candidate for errors that can be avoided through proper design. If there was a proper use of an init() method, I'm sure I'd benefit from learning about it's purpose. Excuse my ignorance, I'm just astonished by how hard of a time I'm having finding a use for it, preventing me from considering it something that should be avoided
    – Dioxin
    Commented Oct 31, 2016 at 7:03
  • 1
    @VinceEmigh: when you cannot think of such a situation, you need to work on your imagination ;-). Or read my answer again, don't reduce it just to "allocation". Or work with more frameworks from different vendors.
    – Doc Brown
    Commented Nov 1, 2016 at 9:08
  • 1
    @DocBrown Using imagination rather than proven practices leads to some funky code, such as double brace initialization: clever, but inefficient and should be avoided. I know vendors use it, but that doesn't mean the use is justified. If you feel it is, please let me know why, as that's what I've been trying to figure out. You seemed dead-set on it having SOME beneficial purpose, but it sounds like you are having a hard time giving an example that encourages good design. I know under which circumstances it could be used, but should it be used?
    – Dioxin
    Commented Nov 1, 2016 at 13:04
6

My experience breaks down into two groups:

  1. Code where init() is actually required. This can occur when a superclass or framework prevents your class's constructor from getting all its dependencies during construction.
  2. Code where init() is used but could have been avoided.

In my personal experience I have seen just a few instances of (1) but many more instances of (2). Consequently, I usually assume an init() is a code-smell, but this isn't always the case. Sometimes you just can't get around it.

I have found using the Builder Pattern can often help remove the need/desire to have a init().

2
  • 1
    If a superclass or framework doesn't allow a type to gain the dependencies it needs via constructor, how would adding an init() method solve it? The init() method would either need parameters to accept dependencies, or you'd have to instantiate the dependencies within the init() method, which you could also do with a constructor. Could you give an example?
    – Dioxin
    Commented Nov 1, 2016 at 0:21
  • 1
    @VinceEmigh : init() can sometimes be used to load a config file from an external source, open a database connection, or something of that ilk. The DoFn.initialize() method (from the apache Crunch framework) is used in this manner. It can also be used to load up non-serializable internal fields (DoFns must be serializable). The two problems here is that (1) something needs to ensure the initialize method is called and (2) the object needs to know where it is going to get (or how it is going to build) those resources.
    – Ivan
    Commented Nov 1, 2016 at 14:21
3

init() methods can make quite some sense when you have objects that need external resources (like, for example, a network connection) that are concurrently used by other objects. You might not want/need to hog the resource for the lifetime of the object. In such situations, you might not want to allocate the resource in the constructor when the resource allocation is likely to fail.

Especially in embedded programming, you want to have a deterministic memory footprint, so it is common (good?) practice to call your constructors early, maybe even static, and only initialize later when certain conditions are met.

Other than such cases I think everything should go into a constructor.

4
  • If the type requires a connection, you should use DI. If there's a problem creating the connection, you shouldn't create the object that requires it. If you shove the creation of a connection inside the class, you'll create an object, that object will instantiate it's dependencies (the connection). If instantiation of dependencies fail, you wind up with an object that you can't use, thus wasting resources.
    – Dioxin
    Commented Nov 1, 2016 at 0:30
  • Not necessarily. You end up with an object that you temporarily cannot use for all purposes. In such cases, the object could just act as a queue or proxy until the resource becomes available. Entirely condemning init methods is too restricting, IMHO.
    – tofro
    Commented Nov 1, 2016 at 8:00
  • If you want to late initialize something then you can wrap it in std::optional, or similar. There's no need to leak that requirement into the class definition, causing you to write classes with weak/no invariants. And your example where the object is late initialized with network is not a good one. In that case, you are saying the object can still be used, as though it is anticipating it has not been initialized. This is confusing the whole idea of initialization. If the object is designed to expect no network connection, then it is initialized even if it is not given that connection... Commented Mar 18, 2021 at 19:56
  • Your example does not use init() as a "constructor replacement." It uses init() like a setter. If you were using init() like a constructor, then it would be necessary to call it before using the class, to avoid a crash. Really, your function is more like "attachNetworkConnection" Commented Mar 18, 2021 at 19:58
1

A typical scenario when an Init method comes in handy is when you have a configuration file that you want to change and to have the change taken into account without restarting the application. This, of course, does not mean that an Init method must be called separately from a constructor. You could call an Init method from a constructor, and then call it later when/if the configuration parameters change.

To sum up: as for most dilemmas out there, whether this is a code smell or not, depends on the situation and the circumstances.

4
  • If the configuration updates, and this requires the object to reset/change it's state based on the configuration, don't you think it would be better to have the object act as an observer towards Config?
    – Dioxin
    Commented Nov 1, 2016 at 0:25
  • @Vince Emigh Not necesarilly. Observer would work if I know the exact moment when the configuration changes. However, if the configuration data is kept in a file that can be changed outside of an application, then there is no really ellegant approach. For instance, if I have a program that parses some files and transforms the data into some internal model, and a separate config file contains default values for the missing data, if I change the default values, I will read them again when I next run the parsing. Having an Init method in my application would be quite handy in that case. Commented Nov 1, 2016 at 7:21
  • If the config file is externally modified at runtime, there is no way to reload those variables without some kind of notification informing your application that it needs to call init (update/reload would probably be more descriptive for this kind of behavior) to actually register those changes. In that case, that notification would cause the config's values to change in your application internally, which I believe could be observed by having your config be observable, notifying observers when the config is told to change one of it's values. Or am I misubderstanding your example?
    – Dioxin
    Commented Nov 2, 2016 at 13:32
  • An application takes some external files (exported from some GIS, or some other system), parses those files and transforms them into some internal model that the systems that the app is a part of uses. During that process, some data gaps can be found and those data gaps can be filled by defaulting the values. Those default values can be stored in config file that can be read at the start of the transformation process, which is invoked whenever there are new files to transform. That is where an Init method might come in handy. Commented Nov 2, 2016 at 14:50
1

Depends on how you use them.

I use that pattern in garbage collected languages like Java/C# when I don't want to keep reallocating an object on the heap (like when I'm making a video game and need to keep performance high, garbage collectors kill performance). I use the constructor to make other heap allocations it needs, and init to create the basic useful state right before every time I want to reuse it. This is related to the concept of object pools.

It is also useful if you have several constructors that share a common subset of initialization instructions, but in that case init will be private. That way I can minimize each constructor as much as possible, so each one only contains its unique instructions and a single call to init to do the rest.

In general though, it is a code smell.

5
  • Wouldn't a reset() method be more descriptive for your first statement? As for the second (many constructors), having many constructors is a code smell. It assumes the object has multiple purposes/responsibilities, suggesting a SRP violation. An object should have one responsibility, and the constructor should define the required dependencies for that one responsibility. If you have multiple constructors due to optional values, they should telescope (which is also a code smell, should use a builder instead).
    – Dioxin
    Commented Nov 1, 2016 at 0:11
  • @VinceEmigh you can use init or reset, it is just a name after all. Init makes more sense in the context I tend to use it since it makes little sense to reset an object that was never set for the first time I use it. As for the constructor issue, I try to avoid having lots of constructors, but occasionally it is helpful. Look at any language's string constructor list, tons of options. For me usually it is maybe 3 constructors max, but the common subset of instructions as initialization makes sense when they share any code but differ in any way.
    – Cody
    Commented Nov 1, 2016 at 15:53
  • Names are extremely important. They describe the behavior being performed without forcing the client to read the contract. Bad naming can lead to false assumptions. As for multiple constructors in String, this could be solved by decoupling the creation of strings. In the end, a String is a String, and it's constructor should only accept what is needed for it to perform as needed. Most of those constructors are exposed for conversion purposes, which is misuse of constructors. Constructors should not perform logic, or they risk failed initialization, leaving you with a useless object.
    – Dioxin
    Commented Nov 1, 2016 at 21:44
  • The JDK is filled with horrible designs, I could list about 10 off the top of my head. Software design has evolved since the core aspects of many languages were publicly exposed, and they linger due to the possibility of breaking code if it were to be redesigned for modern times.
    – Dioxin
    Commented Nov 1, 2016 at 21:46
  • @Dioxin I think this name distinction "reset" vs "initialize" is just a name distinction that does not correlate to anything real inside the code. Constructor, "init" and "reset" all do the exact same thing from a code standpoint. Initialization is initialization, no matter what you call it. And initialization is done in the constructor... Commented Mar 18, 2021 at 20:02
0

Generally I prefer a constructor which receives all the arguments required for a functional instance. That makes clear all the dependencies of that object.

On the other hand, I use a simple configuration framework which requires a parameter-less public constructor, and interfaces for injecting dependencies and configuration values. After that is done, the configuration framework calls the init method of the object: now you received all the things I have for you, do the last steps to get ready for work. But note: it is the configuration framework which automatically calls the init method, such you won't forget to call it.

0

There is no code smell if the init()-method is semantically embedded in the state-lifecycle of the object.

If you need to call init() to put the object into a consistent state it is a code smell.

There are several technical reasons that such a structure exists:

  1. framework hook
  2. resetting the object to initial state (avoid redundancy)
  3. possibility to override during tests
3
  • 1
    But why would a software engineer embed it in the life cycle? Is there any purpose that is justifiable (considering it encourages partially constructed objects) and couldn't be shot down by a more efficient alternative? I feel embedding it in the life-cycle would be a code smell, and that it should be replaced with better timing of object creation (Why allocate memory for an object if you don't plan to use it at that time? Why create an object that is partially constructed when you can just wait til you actually need the object before creating it?)
    – Dioxin
    Commented Nov 1, 2016 at 0:14
  • The point is that the object has to be usable BEFORE you call the init method. Maybe in another way than after it was called. See state pattern. In the sense of partial object construction it is a code smell.
    – oopexpert
    Commented Nov 1, 2016 at 5:21
  • When people discuss init() method, they are almost always talking about partial object construction Commented Mar 18, 2021 at 20:04
-4

The name init may sometimes be opaque. Let's take a car and an engine. To start the car (only power up, to listen to the radio) you want to verify that all systems are ready to go.

So you construct an engine, a door, a wheel etc. your screen shows engine = off.

No need to start monitoring the engine etc. as those are all expensive. Then when you turn the key to ignite you call engine-> start. It starts running all expensive processes.

Now you see engine = on. And the process for ignition starts.

The car won't power up without the engine being available.

You can replace engine with your complex calculation. Like an Excel cell. Not all cells need to be active with all event handlers all the time. When you focus on a cell you can start it. Increasing performance that way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.