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.

Dioxin
  • 943
  • 1
  • 9
  • 19
  • 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 Oct 31 '16 at 07:17
  • 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 Oct 31 '16 at 08:37
  • If you don't want to initialise at the point of instantiation, it would make sense to separate the two. – JᴀʏMᴇᴇ Oct 31 '16 at 09:21
  • you might be interested. [is-a-start-run-or-execute-method-a-good-practice](http://softwareengineering.stackexchange.com/questions/205821/is-a-start-run-or-execute-method-a-good-practice/205826#205826) – Laiv Oct 31 '16 at 12:51
  • 1
    Also: http://softwareengineering.stackexchange.com/questions/334162/start-method-vs-setting-up-everything-in-constructor – whatsisname Oct 31 '16 at 22:42
  • Btw, in languages that support reflection (i.e. synthesizing calls to methods by name, provided as a string at runtime), it is possible to synthesize factory methods that wrap (i.e. hide, or conceptually encapsulate the details) multi-phase initialization. But the actual classes will still have to define these post-constructor methods. – rwong Oct 31 '16 at 23:51
  • @rwong Multi-phase initialization has similar consequences to not using DI: what if the 2nd phase of initialization fails? If the object can still function, it's not required for the responsibility of whatever behavior the object could still perform. This suggests the object has multiple responsibilities. If the object can't function, you wasted time on the first initialization, and now you have a useless object. I feel multi-phase initialization can only be justified through domain specific requirements. Please shine some light if you disagree, I'm still eager to understand. – Dioxin Nov 01 '16 at 00:42
  • @rwong That (and other statements) brings many more questions to mind, most specifically: is there a justifiable reason to have a partially constructed object? That seems to be the core of my question, the `init()` method is really just an example of such, one that I've seen far too often to not ask about. – Dioxin Nov 01 '16 at 00:43
  • @COMEFROM It's very common, going as far as appearing in the JDK (`java.applet.Applet`). I'm aware that applets are outdated, and that JApplet may have some outdated design concepts. That's why I'm questioning the use of it. If you'd like me to grab more examples I'd be glad to, but it's pretty obvious that, for how hard it is to justify, this idiom is used often. Seeing how multiple questions have been asked in regards to it, I don't believe it's an obscure concept. – Dioxin Nov 01 '16 at 01:24
  • @VinceEmigh Multi-stage initialization is very common in GUI widget initialization. This is because GUI tend to use OOP inheritance as a means of widget behavior customization. Such involves lots of behavior overriding (**very often** done in a way that violates OOP rules). As a result, not only they have an `init()`, but possibly `postInit()`, `postPostInit()`, and so on (half-jokingly). If a strict OOP theorist were to analyze GUI framework source code, s/he might conclude that these bastardized widgets don't form an inheritance hierarchy at all. – rwong Nov 01 '16 at 03:15

9 Answers9

50

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.

Karl Bielefeldt
  • 146,727
  • 38
  • 279
  • 479
  • 8
    Your suggestion to try the two-class model is good. Proposing a concrete step to address a code-smell is useful. – Ivan Oct 31 '16 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 Oct 31 '16 at 23:58
  • 1
    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 Nov 01 '16 at 00:02
16

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.

Doc Brown
  • 199,015
  • 33
  • 367
  • 565
  • 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 Oct 31 '16 at 06: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 Oct 31 '16 at 06: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 Oct 31 '16 at 07:03
  • @VinceEmigh: see my edit – Doc Brown Oct 31 '16 at 07:38
  • I feel memory should not be allocated for ian object until you need the object, unless allocation is timely (which in that case, there may be a deeper problem). I can't think of a situation where I'd ever want to encourage separation of allocation and initialization, as that leaves the object partially constructed, yet still available for use. – Dioxin Nov 01 '16 at 00:08
  • 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 Nov 01 '16 at 09:08
  • http://docs.oracle.com/javaee/6/api/javax/servlet/Servlet.html . Servlet init method has been there for while. – Laiv Nov 01 '16 at 09:31
  • 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 Nov 01 '16 at 13:04
  • I don't want to find an excuse to use it is what I'm trying to say. I want to know if there's whether there's any benefit behind using it, or if it can always be replaced with a stronger, safer design. I can think of many places it can be/is applied, I just having a hard time finding a situation where partial initialization would be preferred from an engineering perspective. – Dioxin Nov 01 '16 at 13:27
  • The example above is not a excuse. It's an example of Specification. Specification have nothing to do with how your components are created, it only say how are they going to be initialized "properly" into the whole context (ServletContext). Both phases might happens at different time. As you see It's not only about "smell implementation" it could be required by design. Bad design? Maybe. Anyaways can you say what's a good design? You can try but It's going to be just a personal opinion. Nothing more , nothing less. The hard time comes with looking for benefits instead of understanding needs. – Laiv Nov 01 '16 at 21:31
  • @Laiv The "excuse" response was towards "*When you can't think of a solution, use your imagination*", which to me sounds like "*Find a way*". I know I can force it, but my goal is to find a justifiable use: a "*it's the best way to solve this problem*" reason. That doesn't include following a badly designed specification (whats the reason for it existing in the specification?). Good design is hardly opinion based. Context sensitive maybe, but it's easy to tell between good and bad design: Good design serves a purpose (solves/prevents problems) with reasoning that's widely accepted – Dioxin Nov 02 '16 at 21:18
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().

Ivan
  • 565
  • 4
  • 9
  • 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 Nov 01 '16 at 00: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 Nov 01 '16 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.

tofro
  • 891
  • 6
  • 10
  • 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 Nov 01 '16 at 00: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 Nov 01 '16 at 08: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... – user2445507 Mar 18 '21 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" – user2445507 Mar 18 '21 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.

Vladimir Stokic
  • 2,943
  • 14
  • 25
  • 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](https://en.m.wikipedia.org/wiki/Observer_pattern) towards `Config`? – Dioxin Nov 01 '16 at 00: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. – Vladimir Stokic Nov 01 '16 at 07: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 Nov 02 '16 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. – Vladimir Stokic Nov 02 '16 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.

Cody
  • 121
  • 4
  • 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 Nov 01 '16 at 00: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 Nov 01 '16 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 Nov 01 '16 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 Nov 01 '16 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... – user2445507 Mar 18 '21 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.

Bernhard Hiller
  • 1,953
  • 1
  • 12
  • 17
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
oopexpert
  • 769
  • 4
  • 7
  • 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 Nov 01 '16 at 00: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 Nov 01 '16 at 05:21
  • When people discuss init() method, they are almost always talking about partial object construction – user2445507 Mar 18 '21 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.

Luc Franken
  • 2,664
  • 15
  • 9