I started an interesting thread when I weighed in on the use of IoC and the Dependency Injection pattern a few days back. Seems I wasn’t sufficiently supportive of the concept of lightweight containers to please some of my readers.
Should we, the blog community, encourage IT developers to adopt new coding practices?
Hmmmm. Well, if in doing so, we are doing their organizations a favor, I’d say yes. Increasing their understanding of the tools and the limitations of the environment certainly qualifies. Encouraging the adoption of standards is generally ‘good’ as long as you don’t add costs. Encouraging the use of a lightweight container may, or may not qualify.
You see, the maintainability of an application depends not on the application, or where the requirements come from, but rather the organization that must maintain it. Who are the people, and what do they do? How close or friendly is the relationship between development and support? How are fixes funded?
Understanding the organization, the processes, and the people who will benefit from any new coding technique is the first step to understanding if there is a benefit to using it.
So, while my prior post focused on the tradeoffs of IoC in business software, this one focuses on the tradeoffs in development tools and process that impact an organization.
In general, I’d classify tools and techniques into two buckets: evolutionary and revolutionary. I’d say, in general, the use of complex OO design patterns was revolutionary. It requires training to understand how to leverage the use of a bridge pattern when maintaining systems. Other things, like moving up a version in Visual Studio tools, is more evolutionary. IoC is complex and to use it well requires training. I’d consider it revolutionary. Quite trainable, but still revolutionary.
Organizations should strive to find a solid balance between practical efforts to develop good systems, and the availability of talent that can maintain them. If your support team is not the same group of folks that writes the software in the first place, and if they have a higher turnover rate, requiring you to replenish staff from the general programming community, then it is in your best interests to optimize the ‘ramp-up’ period for a new support developer. One way to do this is to limit the number of revolutionary shifts between “average developer from the street” and “functional developer in an organization.” Depending on your choices, that may, or may not, include the use of complex pattern-based systems like an IoC container.
Why do you think RoR is so popular? Because it hides so much of the complexity, yet surfaces a great deal of power. Same thing goes for LINQ (in a different way, of course). When complexity is low, the change is more evolutionary, even if the shift in capabilities is dramatic.
Contrast the above situation with a different one. If your support team is a rotating set of folks who both develop new systems and support existing ones, and your body of code in support is not very large, then it makes perfect sense to experiment with many revolutionary changes in coding techniques. After all, you can train once, and leverage the training across a body of code.
The point is that the successful use of any revolutionary technology depends on the organization’s ability to swallow it. If your organization is structured to foster the introduction of new techniques and ideas, then by all means, adopt the appropriate ones, including lightweight containers if that appeals to you. You can train folks on design patterns in general, and DIP in specific, and you can refactor existing systems to use these patterns. Hopefully, you will have designed your system interfaces correctly so that you can get the benefit of the easy configurability promised by the IoC coding technique.
Many of the quality attributes are dependent on people. Maintainability and supportability among them. So if you honestly evaluate the use of a technique or tool in a particular system, you will need to consider the organization that will own the result. If they are not ready, it doesn’t matter how good the technology is… it will not be useful.
Software reflects the structure of the organization that builds it.
That axiom is as true today as it was when it was coined.
9 thoughts on “Inversion of control, part two”
PingBack from http://www.biosensorab.org/2008/02/20/inversion-of-control-part-two/
"IoC is complex and to use it well requires training. "
Can you provide some supporting evidence (anecdotes are fine) for this statement? Is this tool-complexity ("I can’t figure out how to configure this thing!", concept-complexity ("I can’t figure out what this thing does!") or imparted application-complexity ("My app is a mess now that I’m using this thing!")?
I’d certainly agree that writing new-apps-from-scratch with pervasive DI is revolutionary, but application complexity should be reduced, and it should be reduced a lot. In my experience, the difficulty to maintain an app is correlated more closely to the application’s complexity rather than the tools used.
Love your URL. I’m a DDR fan.
We are actually already on the same page. "Writing new apps from scratch with pervasive DI is revolutionary." What makes it revolutionary?
The structure of the code changes, for the better. Your classes are cleaner and better defined, because there are constraints on the way you wire things together. What happens is that you change the way you think about code, and the way you approach development.
Support developers write code. If IoC is to have the impact it was designed to have, then Support developers need to write code in the same modern way. They have to think about the app using the same new approach.
Support developers are developers too. In many teams, there are no support developers… just developers, and they do both. That’s the second case I mentioned above. Best case for adopting new ways of doing things. However, in a lot of very large organizations, and plenty of smaller ones, there are people who do nothing but support.
These folks will spend 80% of their time fixing code that was written 5-20 years ago. There were no lightweight containers five years ago. So the code they deal with (40 weeks out of the year) is not based on IoC. They are lucky if patterns show up!
Imagine you are one of these folks. You get a nice shiny new application written with IoC. You have one day to fix something. You have never seen a lightweight container before. You may, or may not, have access to a diagram that tells you how the classes relate. You have no time to read spec documents. Just fix it.
So you look through the code and try to find the places where class A method X is called. Guess what. It’s not called. Not in the code, anyway. And you know it has to be called, because that is the class where the bug is. But you want to make sure that your change won’t damage anything.
Quick, write a new class, put in direct calls. Ignore the config file. Compile and go. Fix is in.
And thus begins the inevitable decay.
For someone in this predicament, IoC raises complexity because it is outside what they are used to dealing with. They have to learn to think the same way as the new-code-developer. They have to discover those lessons. Learn debugging techniques. Understand what it means to drive connections through configuration.
It’s a people problem.
People problems can be solved. If you create a consistent standard across the IT group, or a sizable portion of the IT group: ALL CODE SHALL BE WRITTEN IN THIS WAY, and train everyone, then you can afford to dedicate some support folks to handling ONLY NEW CODE. Put IoC and new design practices in this bucket and support it.
Then you can afford to train people to maintain the code. Because then they can "see" and "understand" the new way of thinking that comes with IoC. Their efforts to support won’t introduce corruption in the design.
Revolution requires indoctrination, my friend.
I wonder if there are any other industries that do this–ignore innovation and future cost savings due to the short-term overhead of training.
I do like what Ed Deming once said..
"It is not necessary to change. Survival is not mandatory"
All the time. Most industries take innovation carefully.
Toyota had a huge internal fight when they decided to create a hybrid Prius, because of the huge costs of change that had to happen throughout the company and dealership network. That’s the primary reason that they released the Prius in japan years before releasing in the US, and why their first two years, they produced the Prius at half-capacity and limited the dealerships that could sell it.
I should know… I bought one.
Why do you think the american car companies have such a hard time releasing new technologies?
So, to answer your question: yes, yes, yes, yes, yes.
Ours is one of the ONLY professions that puts innovation above other attributes. We are the weird ones.
I get asked a lot what tools I use, and have planned to write a post. As my buddy Harry got there first
In your previous post you query Udi for "numbers that show that software written using an IoC container is measurably easier for a team to maintain?" I doubt he can provide them but he may surprise me. Conversely you do not share any numbers or empirical evidence to support the contrary so this dissolves into a "my experience shows" discussion. Which is fine, it just means we can both be right : )
Your example that we should not introduce revolutionary changes because 5-20 years from now the poor schlep who has to fix a bug fill find IoC “outside what they are used to dealing with.” This argument comes up often and generally involves Mort who we dismiss as an imbecile that cannot write code unless there is a visual designer to help him. Dependency Injection is an extremely simple concept. And a good IoC container abstracts the complicated parts of configuration and management to provide low friction to allow you to fully take advantage of DI. If a support dev finds a bug in the container, then yes she needs to have knowledge of IoC. Otherwise there is nothing preventing her from “Quick, write a new class, put in direct calls. Ignore the config file. Compile and go. Fix is in.”
I use IoC very effectively and its usage in my applications is nearly transparent. If you are burdened with configuration, management, or training issues then you may be using the wrong container. Nothing is right for everything and IoC is no exception. But I have yet to see a valid argument against Dependency Injection.
You are absolutely correct, it is a people problem. Don’t add to the problem by not investing in your people or designing and coding to the dumbest common denominator.
The fact that more than 75% of the problem I care about cannot be solved with coding practice, then I have the weight of benefit on my side. In other words, there is no reason to believe, empirically or not, that IoC will actually make code easier to maintain.
That said, I like DI. It just isn’t a silver bullet.
As Grigori Melnik noted on my blog previously as well as his own , there was a brand new drop of the