Hazard warning: this post is not about Java though it might appear to be so if you go through the first few paragraphs. If anything, it is about how we call the same thing by seemingly different names.
One of the worst hellish concept that any programmer has to learn when moving over to the world of Java is the notion of dependency injection. The beast itself goes by many names such as DI (abbreviated form of dependency injection) or also known as inversion of control (IoC).
The trouble with IoC is not the concept itself but the manner in which it is explained. I was first introduced to this notion in late 2008 when all my prior experience had been in C++, perl & php. What I was faced with was xml hell in the form of Spring IoC 2.x and a lot of voodoo in the form arbitrary casting, auto wiring, and complete gibebrish as scope is prototype. A few years later, guice happened and it brought in its own set of jargon in the form of binders, modules & providers. And then we saw what every nascent industry sees: a wish to create inter-operable standards in the form of JSR-330 the struggle each vendor faces between trying to be standards compliant and innovative at the same time.
Over time, I learnt how to think on these lines and rather well but I still struggled to find meaningful ways to explain what it is; especially to someone who does not practice idiomatic Java as the only style of coding. The whole just made sense when I saw this video which talks of goal based programming amongst other things. It them became apparent to be that one of the largest development communities to use this concept just does not know it by this name. If you are wondering what it is, the answer is Makefile.
The core syntax of a makefile is as follows:
what_do_i_want: list of prerequisites What do I do with these prerequisites to get what I want
Interestingly, the make terminology for what_do_i_want happens to be target which suggests that we are indeed indulging in goal based programming. If you think of how make thinks of your C project, it compiles *.c neither because it knows how to do it not because we asked it to do so. What we usually say is build the default target which probably means build an executable which probably means it needs a few shared libraries that needs to be built which probably means a few object files are needed to build the shared library which probably means a few C source files need to be compiled.
Come to think of it, most people also do a lousy job of describing what is the single biggest problem make solves. The most cited beginner level reason of it smartly compiling only files that have changed is far from the truth. Building a consumable finished product is hard. If you don’t understand it, try and draw parallels between cooking & software. When you embark upon cooking roasted potatoes, one of the ingredients that you might need would be ground black peppers. The recipe for making roasted potatoes does not tell you any of the following:
- How to cultivate black peppers
- How to harvest black peppers
- How to separate out the good peppers from the bad ones
- How to grind black peppers
- Should you be doing any of the above or just buy ground peppers
- If you indeed decided to buy them, then where to buy them, what is the right price etc. etc.
Makefiles are exactly like recipes: you list your ingredients and then how to cook it. If one of you ingredients itself needs some preparation, then it might come with its own recipe. The place where the metaphor breaks down (like all other metaphors) is that agriculture has an enormously large lead time unlike software assembly; agriculture is like software development. Cooking on the other hand is like a build system.
The idea behind inversion of control is to say that various objects in a live process (not to be confused with program) need to be built in a culinary method as opposed to an agricultural approach. Instead of making things in anticipation that someone would use it, we prepare it only when someone asks for it. The converse of this is that if the entity that depended on something goes away, then the something should also go away if no one else depended on it. The previous line is a layman’s explanation of how automatic garbage collection systems define “liveness” & it has got me wondering if is mere coincidence that IoC as an object management paradigm became prevalent in the most popular language that has automatic memory management. In short, just say what you need and it is someone else’s headache to provide it to you. There might be a recursive element to this whole approach but that is still someone else’s problem. The “someone else” here of course is the dependency management system.
All this just makes me believe the software industry is rather immature when it comes to expressing concepts as we seem to do the same thing in different places with such unrelated names and over-emphasis on minor details that we miss out of the core concepts. If you are looking for another such example, then try and read about linux kernel developers talking in term of RCU and the RDBMS camp who talk of MVCC.