I’m putting together a new quickstart for StructureMap tonight. In looking over my notes, I found a draft from earlier this year where I was trying to argue the value proposition of an IoC container. I’m scrapping most of that post, but I wanted to share some thoughts on dependencies and structure in software designs. My advice is to get yourself to bullet number 4 below in order to make your design, unit testing, and coding efforts more efficient – regardless of whether or not you use an IoC container.
I think the evolution of a developer’s mindset towards structuring applications goes something like this:
- Just gotta make this work. There isn’t any separation of concerns. Code responsibilities tend to fall wherever the developer happened to be in the code when he or she realized they needed something (what I refer to as stream of consciousness coding). For myself in the late nineties, this trait manifested itself as popping open an ADO connection and grabbing an ADO recordset anytime, and anywhere, that I needed some data in the middle of a long ASP page. I’ve worked in a couple different development environments and read code in twice that many since, but in my experience nothing leads to a big ball of mud faster than the combination of ASP Classic and developer carelessness. The code worked, and that’s definitely something, but large amorphous code modules tend to be difficult to troubleshoot, maintain, and modify. Plus, they can easily lead to duplication because code isn’t structured for reuse.
- The next stage is learning to put things in their place. The developer has progressed enough to internalize the value of separating concerns into cohesive modules. The developer is thoughtfully asking the question to himself or herself "where should this code go?"
- Wait, I’ve separated my concerns, but everytime I change one module changes ripple into other modules. Each concern seems to know too much about the details and functions of other concerns. Now we start to worry about being able to change how the system behaves by making isolated changes that impact the fewest number of modules as possible. To make this happen we need to make sure the different modules are loosely coupled from each other. At this point we begin to make much more use of interfaces and abstractions to reduce the coupling between modules. We also strive to build modules that do not incorporate any knowledge of the other modules that the first module depends on.
- The developer is fully cognizant of dependency relationships in his or her codebase. At this point we’re ready to consider using Dependency Injection and Inversion of Control to both further encourage loose coupling and exploit the seams in our application.
- The developer finally learns some completely new way of building software and feels like they’ve started all over again at phase #2.
I think the leap from #1 to #2 is huge chasm that many developers will fail to cross in their careers, but every following transition becomes easier.
The following is a partial repeat of an older post, but I think it applies here:
Coder to Craftsman
When people first learn how to write code they necessarily focus on just making the code work, with little or no thought for style or structure, and certainly no thought for the future. Any particular piece of code tends to land wherever the coder happened to be working when they realized that they needed that piece of code — or wherever the RAD wizards felt like dropping the code.
I think there is an inflection point where a coder mindlessly spewing out code transforms into a thoughtful software craftsman capable of creating maintainable code. That inflection point happens the day a coder first stops, lifts his/her nose out of the coding window, and says to him/herself "where should this code go?" That might also lead to questions like "how can I do this with less code?" or "how can I write this to make it easier to understand?" or even "how can I solve one problem at a time?" The rest of a developer’s career is spent pursuing better and better answers to the question "where should this code go?"