About 8 months ago I ran my work application through nDepend to see what kind of disaster we really had on our hands. The results provided a very deep insight into the current state of our application and certainly reaffirmed the thoughts on refactoring that we had been having. After a few months of steady refactoring, mixed with a switch from .NET 1.1 to 2.0, I again ran the solution through nDepend to see if it would confirm my belief that we had actually made a difference. To my relief, there was a noticeable difference in the results (luckily for me they were good differences).
It didn't take me to long to realize that in our refactoring efforts we had made numerous changes and had more rigorously adhered to some good OO principles, but we had done it all at once. I was left wondering which of those changes made the biggest difference? Being that this was my first attempt at rescuing software from the brink, I really wanted to know. I needed to know so that I could better apply my lessons learned on the next project (don't they all seem like they're on the brink when you first show up?).
Out of that curiosity I decided to build a series of demonstration solutions that took the same code base and progressively applied the changes I had tried to at work. I wanted to see what happened after every step in the process. In the end I've ended up with the following six solutions:
- Base Code -- this is the disaster that you have inherited or created
- Interface Based Programming -- take the disaster and interface everything
- Single Responsibility -- clean up the concerns that exist in the current classes
- Poor Man's Dependency Injection -- apply some DI to your code
- Roll Your Own Inversion of Control Container -- This one isn't pretty but it can be done
- Castle Windsor -- implement Windsor IoC where you had the Roll Your Own IoC
Throughout the evolution of the code as I moved through these solutions I did a couple of things. First, I ensured that I always had tests that passed. Everyone of these solutions is as fully tested as it could be. This means that you can also see the how the testing techniques changed as the coding style changed. Second, the functionality of the code never changes. In the sixth solution you have the exact same results as in the first.
What I was hoping to see when this experiment was over was that there would be a significant increase in the cohesion and a significant decrease in the coupling. I also wanted to see if I could manage similar results with a very small code base as I did with the large code base at work. Here's the tail of my code's evolution.
If you don't want to read the rest of this (I have a feeling it's going to get quite long), you can download the source here.
The Base Code
|This isn't really all that shocking of code for most of us. The lack of shock isn't because of the lack of egregious ignorance to good OO practices, but instead because we all to often see code written in this manner. What we have is a basic implementation of a customer, an address and a validation class. I suppose I could have taken this backwards on step farther and broken more OO best practices, by implementing the validation logic into the customer class itself. As you can see by the Abstractness vs. Instability image, this solution is firmly mired in the lower right corner which indicates that we have our code written completely to concretions and that it will have the worst possible resiliency to change. Essentially, when that inevitable change request or refactoring task comes in, you're going to have a very hard time making them happen.|
Other things to note:
Abstractness == 0
Relational Cohesion == 1.33
Interface Based Code
Single Responsibility Code
Poor Man's Dependency Injection Code
Roll Your Own IoC Code
Castle Windsor IoC Code
When I first started this exercise I figured that there would be a steady progression towards a final, top level set of metric values. As there usually are with preconceptions, I was proven wrong. I found the most interesting thing to be that the implementation of Coding to Interfaces provided the largest single movement in the metrics. There is no doubt in my mind that this technique will never be a point that I allow negotiations or discussions to remove from a code base.
The second most interesting point was that there was little to no benefit (according to all the metrics) when implementing Dependency Injection. I know, in my gut, that this is the right thing to do. I'd even go so far as to say that implementing something like Castle Windsor or StructureMap is the only way to do it, but it still is interesting to see what the metrics say.
The third thing that struck a chord with me was that the change on the Abstractness vs. Instability graph (from the Base Code to the Poor Man's Dependency Injection Code ) was about the same for this small piece of code as it was for the large project I analyzed at work. I figured that the complexity of a multi-project solution would have a bigger impact on the comparison of the results that it apparently did.
What's the single biggest lesson that you can take from this? I'd probably have to say that my biggest lesson was the confirmation that static analysis metrics are not going to provide you with answers at all, let alone at a granular level. Instead they should be used as tools at a high level which provide guidance for your decisions. I also don't think that you will be able to use them to compare projects.
If you have access to a tool like nDepend, and you're thinking about taking on a project-wide refactoring, I'd suggest that you use the tool. It's going to help you get started in the right direction and along the way it will provide feedback that, hopefully, confirms you are heading in the right direction.
Disclaimer: Although I was given a free license of nDepend by Patrick Smacchia, it was not in exchange for this blog post.
I'm sitting here watching the Argentine and Mexican U20 teams play in the Quarter Finals of the U20 World Cup and I'm noticing the language of the announcer more than I normally would during a sporting telecast. What I'm taking notice of is the richness of the language used to describe the game as it is being played. Where the announcers in North America struggle to state more than the obvious and statistics while the game is being played, this British gent (I'll try to catch his name as the second half starts -- Nigel (last name neglected)) is almost waxing poetic.
I've watched enough of every sport native to Canada and the US to know that hockey, baseball, basketball and football (grid iron, not the beautiful game) announcers would hardly make be able to pass a high school English equivalency exam. That's the announcers. The "colour commentators" are nothing more than a group of talking heads that bring nothing more to the broadcast than an ability to fill dead air.
So what is it that makes this announcer different? It's not that he is poetic in the meter of his speech. It's not that he is enlightening in the knowledge or information he provides. It's the style in which he does it. It's not a flamboyant style, but rather a descriptive and amazingly rich verse that he sings. Where a hockey announcer would suggest that the team needs to work harder to create chances, this guy aptly states that the offensive team must become much more problematic for the defenders if they are going to see success.
Other examples include:
- "They conceded a goal" (When was the last time you heard a football (grid iron) announcer use that many syllables in one word?)
- "Gave the ball away rather sloppily"
- "Highly fancied opponents"
- "The back heel is a little ambitious"
The thing that he is doing is allowing me to know exactly what is going on in the game even if I'm distracted by something else (like writing this).
How does this pertain to programming? When we are writing our code we need to ensure it's readability for the other developers on our current team, plus the developers that will follow us. Writing syntax like
does not do any justice to the underlying code. Why wouldn't we state something more poetic? Perhaps we should have our code speak to us and say
What we need to do is have our code read more like sentences where the the dots and the parentheses are treated like spaces. If you do this, plus write the words between to form grammatically correct sentence, you will find that new comers to your code will have an easier time picking it up.
One of the things that I struggle with both when writing fluent interfaces in my code and while writing papers (or blog posts as the case may be), is that I feel as though I'm running out of words to use to properly form a sentence without sounding repetitious and still conveying the pertinent message. Having and using slightly different terms in your code will allow you to enhance your code by making it more descriptive. Think of a situation where you have a service layer for retrieving Customers. If you use the breadth of the English language you can come up with the following possibilities
Each of those can have a slightly different meaning in your code if you use them consistently. Get() could be your terminology for a straight query from the database. Acquire() could represent something where more than a database call is performed and Gather() could speak to a situation where more than one source is required to build the result.
Building expressive verbiage into your codebase is not an easy thing to do. Most likely you will need a thesaurus. Definitely you will need to adjust to this style. The developers coming after you will thank you though.
I've spent some time working with and presenting on extension methods. In this screencast I create three different extensions. One to check if a string is null or empty, a second to release my presentation code from the shackles of System.Console.WriteLine(), and a third that shows how to create your own iterator inside of an extension method.
We've all heard the tales of projects that enter the throws of despair as they near their "conclusion". I'm sure we all shudder at the thought of this, shake our heads and say "I hope I'm never on a project like that". I know I did. Now I am.
For those of you that haven't heard the term before, Wikipedia has a fantastic definition of it here. The current state of project affairs for me includes all of the desperate attempts to revive it, including long hours (weekends haven't been ruled out) and more resources (because Brooks' Law doesn't apply in the reality-free-zone this company runs it's project in). The thing that is most disturbing is that nobody ever learns from the last death march that they went through. This isn't just limited to the management who should be learning how to prevent them, it also includes the people that are suffering through them.
I've been on a few of these before and I have seen a number of things that get affected when it becomes apparent that there is a death march. Oddly, this is the first time where I've seen one that was openly announced (it even had a special meeting complete with ice cream cake, because that will make it all better you know) with over five months before delivery date. The days following the announcement would have made for an interesting study on human reaction to adverse news.
To set the stage for you I'll describe a few things. First, the developer team, and a portion of the business analysts, is almost solely comprised of contractors. The second thing is that we've been working on this portion of our project since the start of the calendar year and we have approximately 1/6th of it finished. Thirdly, we have the next 2 1/2 months to complete the remaining 5/6ths.
After the announcement that we'd be working in a salt mine for the duration of our rather short, northern summer, the developers took it a number of different ways. A couple took it with a laugh, a head shake and a wise-assed crack like "Yesss....finally overtime to get me out of those nasty evenings of BBQ and beer!" A few asked pointed and concerned questions like "Will we be able to do remote work?" and "Will they actually turn on the air conditioning if we're working weekends?". Most just shook their low hanging heads, mumbled under their breath and walked out of the general vicinity of the announcement. It was pretty apparent to me that the mood was somewhere between an optimistic sigh of resignation and a bitterly angry tirade of disbelief.
I've decided that, due to a lack of other explanations, the different reactions are to be attributed to the different personalities, but the source of the general disappointment is easy to point determine. First, it's summer here in the great north and we only get about 4 months of summer and spring combined. If we're really lucky we'll get a bonus month to month and a half in the fall, but you can never count on that. This is something that just happens to coincide with the death march. The thing that is most frustratingly disappointing is that we've had 6+ months to realize that this was coming. Not only that, but the date was known a year ago and the management decided that it would be okay to schedule the work well past it. I'm not sure the rational behind that. If you have a deadline of October 15th that is hard and fast, why would you schedule development work well into the following January? Putting the information on the schedule in those time frames doesn't make the crunch miraculously disappear. Instead what you do is project a image of being incompetent in your planning to the whole team, then you turn around and say "Hey, I just had to cut 4 months off of your development time. I hope you guys (and gals) are able to make this work." With that, you've succeeded in kicking the entire development team in the scrotum.....twice.
While they're feeling like they're having the rug jerked out from under them, the development team is now doing the math to figure out the current velocity of the project. Quickly they come up with a very close to accurate estimation (probably more accurate then their last story estimation, but desperate times call for more accuracy) showing that the current pace has a completion date that is one year beyond the newly imposed deadline. Now the team starts fuming about the fact that they seem to be the only people capable of coming up with the formula to get the Average Number of Hours Work per Developer per Day. People leave early to research the limitations that they have written into their contracts. Those who don't leave start openly talking about the fact that they're contractors and they can, and will, limit the number of hours that they will be available. Some even openly state that it will be a cold day in hell before they consider working those kinds of hours for this company and, especially, this management. Everyone who was on the floor clutching for their tender twig and berries is now standing tall and chanting union slogans while burning effigies of the bosses.
A couple days will pass. If there's a weekend it may be less. Either way, people slowly start getting back to normal work, but they dread the looming expectation of overtime. The day will arrive when overtime starts occurring and a few will, begrudgingly, force themselves to come in early, or on weekends, and stay late. Others will have stuck to their guns and they will sip mohitos in the sun. Effectively, the announcement of a death march has reduced the list of those working extra hours to a mere handful. That, in turn, has provided the project with little or no benefit.
The next step is to start talking about hiring or transferring people onto the project. If all you have is a couple of months to get the product shipped, hiring newbies is going to be a far larger drain than gain. By the time they get interviewed, hired, show up for their first day and become productive, you will have a couple of weeks to use them. It's not nearly enough to make up for the time you invested in them rather than the code, but think on the bright side; you now have a maintenance team in place for when the rest of the developers walk off the project.
Once you get into a situation where a death march is inevitable, what is the best course for you to steer? The first thing I suggest is tighten the belt on scope control. If you already have good scope control, tighten it even more. If you have little or no scope control, you have to tighten this area so hard that it feels like you've cut off all circulation for the client. This doesn't mean that you can't still accept change requests, but they have to have a highly visible price attached to them. The best way I saw this done was where you'd ask the client "Which one of the new features, that we haven't started, would you like to remove in place of this change?" It's amazing how quickly the client will prioritize things when you force them to choose.
Do force the client to choose. You don't have the time to let them waffle on the choice. That decision needs to be made yesterday. Set a date and time for them to have an answer by. Reinforce the decision timeline by clearly stating that the change will no longer be able to fit the schedule if they don't decide by that date. If you've had lax change control up to this point you will find that the client will be like a change-on-a-dime junkie who is going through withdrawals. Let them kick and scream, but never give in. If you do, you've just introduced another risk for failure to an already risky project. Control all the risk that is within your grasp.
Eliminate obstacles. If you're having problems with a developer's PC, get a working replacement for it immediately. If a developer is having to attend to his vehicle in a surface lot throughout the day, find them a pass to the company parkade. If developers are working long hours and are unable to get home on public transit, get them taxi vouchers. Keeping a development team heads down, and fully effective, for a 12 hour day takes more than a couple boxes of pizza at 5 o'clock. The more non-work things that you can take off of their minds, the more you will get from them.
Remember, you want to have your developers focused. Keeping them focused doesn't mean that the work place will be quite with the exception of the steady drum beat of keystrokes. There will be talk and, if you're lucky, even a little laughter. Focusing the team is more about preventing distractions. Stop the meeting requests. No more 1 hour meeting to discuss the current state of every developers code changes. No more meetings to discuss the most effective way to communicate tool rollouts with the networking team. Encourage your developers to block off their entire calendars with one entry for "Coding".
Once you have your team ticking along for all ungodly hours of the day, it's time for you to do one last thing......shut up and listen. Just because you got them off on the right foot doesn't mean that there won't be bumps in the road. When you hear a rumble from their ranks, get involved and resolve the situation as quickly as possible.
Oh, and never start a death march by telling a Canadian development team that they'd "...rather be doing overtime during the summer than in November." You'd be amazed at how many will log off their computers upon hearing that, and go for a beer.
During my presentation at Edmug on some of the new language features in .NET 3.5, I had some great questions and scenarios thrown at me. As a follow up to those questions I've recorded a second screencast to show the scenarios discussed. You can download the follow up here.
A comment about the size of the last screencast got me playing around in Camtasia to see if I could create a more compact result. Hopefully this one (about 10% of the previous one's size) is easier for you to get at.