A couple years ago, if you read some of the "best practices" stuff coming out of Redmond, you'd have thought that software factories were going to transform software development. Thankfully, this turns out not to have been the case. I never met a software factory I didn't detest almost immediately, and I'm glad the idea hasn't really caught on any more than it did.
Software factories generally consist of some tools to assist software development, but a central theme of these tools is that they generate code for you. I've always felt that automation in software development is a very good thing, but it's vitally important that you understand what you're left with when you're done. If automation results in code that you never have to touch or see, then you're probably more productive as a result, but if you're generating code that you're going to have to maintain, there's a very good chance that you're taking one step forward and two steps back.
Most developers are familiar with "Don't Repeat Yourself" (DRY). The objective of DRY, of course, is not just reduction in code (and thus, effort) when developing new software, but a centralization of logic that pays dividends as you maintain software. Code generation often accomplishes a deceptively attractive initial productivity for new development, but the generated code is typically littered with repetitive code. This code is "free" when generated, but it's an anchor around your neck every time you have to maintain the code, or even when you step through it while debugging. It clutters your project, reduces readability, and inhibits your capacity to maintain, revise, and refactor your software. There's a reason why repetitive code is usually right at the top of Code Smells lists.
Given my strong preference for software craftsmanship, it shouldn't be surprising that I consider software factories that barf out projects and classes that you're supposed to maintain an absolute blight upon the landscape of software development, but there are any number of other automation tools available to us. Here are some thoughts on a few of these:
- Designers. These remain the best example of code generation done right, in my opinion. Designers, when properly executed, produce wholly-standalone code files that we can largely ignore. Classes are declared as "partial" so that if you need to modify them, you can do so without touching the generated code. Some designers will add [DebuggerStepThrough] attributes so you don't see this code when debugging. All of these things help the generated code disappear unless we're specifically looking for something, and that's a very good thing.
- Snippets. I remain mixed on these little gems. When used correctly, they can be a big help, but in practice, they're almost always a sign that you should be doing things differently. Whether or not you're using a snippet to generate code, you don't want to end up with code that violates DRY, and this means that the opportunities to use snippets effectively are few and far between.
- T4. The best usage I've seen of this generation tool (built into Visual Studio, by the way), is Rob Conery's SubSonic data access project. T4 creates code from templates written in an ASP-like syntax, and is great for iterating over a database or other object structure to crank out code in for...each loops. Like designers, this code is intended to be read-only (you shouldn't modify the generated code), and it can be marked with [DebuggerStepThrough].
- Reflection. Yes, it's a little bit of a stretch to call reflection an automation tool, but creative use of reflection can help you achieve some Ruby on Rails-like productivity by adding behavior dynamically. Reflection is commonly maligned as a performance-killer, but Rocky Lhotka has been doing great things with reflection in CSLA for years with minimal impact on performance.
- Copy-paste coding. If you're not even using a tool to help you with your unnecessary code duplication, you're definitely doing it wrong. 'Nuff said, I think.
In addition to these "automation" tools, there are language features and frameworks available to us today that can serve the same productivity objectives without resulting in tons of repeated code:
- Attributes. Typically used with reflection to act on classes at run-time, attributes can make your code much more expressive by declaring behavior rather than implementing it over and over.
- MVC. Since MVC is a framework, it doesn't really do anything at all to enforce DRY (or any other coding practice), but it encourages a declarative style of Model development that's very consistent with the ideas I've been discussing here, and most MVC examples use a very expressive, compact Model syntax.
- Model-driven development. Microsoft's data modeling bits (known at various times as "Oslo") consist of tools, modeling syntax, and extensions that create a very dynamic metadata-driven application environment. We're still looking at the early stages of these tools, but the broad objective is to make object behavior completely declarative and dynamic. There's a danger that we could trade unmaintainable code for unmaintainable configuration data, but I think that as this technology matures, it's going to move us in the right direction.
In addition to the options available to us today, we'll continue to see innovations in the future. When you're reviewing and evaluating these options, though, remember to always add lightness, because less code is better.
Related articles by Zemanta
- Model Driven Development: Code Generation or Model Interpretation? (theenterprisearchitect.eu)
- Why Coding is not enough (basilv.com)
- Using a Software Factory Approach for Customized Modeling (devx.com)