How do you tame the many heads of the hydra?

There have been numerous posts about hiring the "right" people. One of the more ideal characteristics is a passion for the industry and for learning new techniques. But as I look at more and more code written by these zealots (and I don’t mean that to be derogatory because I count myself as one of them) and because I have been thinking about brownfield applications lately for some reason, a kind of pattern seems to emerge in projects written by them.

The way to recognize this pattern is if you can tell what the developer has been learning or reading about from scanning various parts of the codebase. Here’s a scenario:

New guy: How are we handling dependencies in the code?

Eager and enthusiastic veteran: Oh, it’s awesome, man! At first, we were just newing shite up. Then I went to JP’s course and he had this pretty cool hand-rolled IoC container so we started using that in the service layer. Eventually, we took the plunge and brought in Windsor. We don’t use it everywhere but some of the newer presenters do. But then we saw the new stuff in StructureMap so this one part of the app is using that.

NG: So you have four different ways to get new instances of a class?

EaEV: Yeah, but don’t worry your purty li’l head over it none. We’ll be standardizing on one soon.

NG: Oh yeah? Which one?

EaEV: Well, it *was* going to be StructureMap but NInject looks pretty cool…

The point being: How do you handle implementing new techniques as you’re learning them? You have a web application built by a team that still things they’re coding in classic ASP and now you want to move it to an MVP pattern.

Naturally, for new screens, you can do this pretty easily. But as the code grows, you eventually get to a mishmash of new MVP screens and old code-smackdab-in-front screens that everyone treats like your disfigured, but still oddly attractive sister/cousin who’s kept locked in the basement except during family reunions/speed-dating sessions.

What’s worse, the problem is exacerbated as new techniques come in vogue and as new people are brought on to the project.

Also, for the most part, we usually don’t want to go refactorin’ just for the intellectual exercise. Most of the time, I like to move to a pattern or implementing some new technique on an as-needed basis. Which means you don’t overhaul the entire application just because you’re working in one area. If your admin section is working, I say leave it alone, despite your psychological issues with DataSets. (But at the first sign of bugs or new features in that area, bring in your hacksaw and have at ‘er.)

In any case, it’s cute little dichtomy. You certainly don’t want to keep doing things the old and busted way but you are hesitant to fork part of the application down a new and inconsistent path.

And this isn’t limited just to large projects. I’m experiencing it even know on an application I started earlier this year. An application, I might add, where I’m the sole developer. It’s an MVC app with bits of Fluent NHibernate in it but not all the mappings have been migrated over yet.

The way to avoid this, of course, is to stop learning. But if you’re one of those eager types, then let’s explore some options. Unfortunately, all I’ve got are the thoughts in my head. And keep in mind, these are the same thoughts that evoked that little speed-dating analogy a few paragraphs up.

// TODO: Refactor this when the client stops reporting bugs and adding features

This is kind of the bare minimum you can do to at least acknowledge that some work needs to be done. It’s well-intentioned but not very practical. Most of the time, we leave these comments because we want to cover our asses in case someone goes looking through the code and spontaneously goes blind. In any case, if the client isn’t reporting bugs or adding features, that means no one is actually using the app.

The "Refactoring" Iteration

"That’s it. I’ve had enough looking at this code. You, Mr. Project Manager Person, tell the client that we have deemed the application unpalatable and that we are holding it ransom until such time that it we feel warm and fuzzy about working with it again."

Don’t need any limbs to count the number of times this has worked for me.

Leave it the way it is and strive for consistency

If you think you can get away with this, I applaud your ability to hire Type-B programmers.

Deal with it

This is probably my default approach. Hunker down and get your work done within the constraints laid out for you. Fix what you can, when you can. The application will morph. Try to control the shape and rate in which it does so. Knock of one head of the hydra at a time and hope three more don’t grow in its place. It’s probably not the most glamourous position to take but like any stance that involves lowering your standards, it’s easier to attain your goals.

None of this strikes me as being all that encouraging, which is probably why this post lingered in my //TODO list for so long. I’m not sure there are any solutions to this other than to practice deep breathing exercises whenever you look at the code. Best I ever hope for is to provide value for my pay and try to learn something as I go.

Kyle the Acknowledged

This entry was posted in Brownfield, Refactoring. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Vikas Kerni

    When you are responsible for delivery of Software System, delivery matters.
    Wait for right opportunity for refactoring and keep everything ready
    (acquire the knowledge of system and have resharper).
    Have right resources in your team.
    Don’t be afraid to take course correction.
    If there is technique,framework or advancement in platform that helps you do more with less code, adopt it . (Generics)
    If something is not working, abandon it.(Microsoft ObjectDataSorurce)
    Break consistency, if benefits are overwhelming(Generic vs Strongly Typed Collections)

  • Richard

    Funnily enough, I was having similar thoughts on the way in this morning as a breakwater against techno-utopianism. I’ve even come up with a name for it 😉 PDD: Pragmatism Driven Development.

    1) You don’t always get to play with your new [toys/tools/methodology/language/heck, even operating system]
    2) You may have to play with someone else’s [toys etc]
    3) Sometimes the toys aren’t ready yet
    4) Large scale refactoring is probably not an option

  • Iain Hunter

    Funnily enough I’ve been thinking the same thing when I look at my feed reader and see countless posts on BDD, DDD, TDD, Mocking, Mocking sucks, etc etc. The problem is of course if you give a million programmers a million blogs, you’re going to get a lot of noise and not very much of it useful.

    The trick is to identify the techniques that yeild a real benefit and attempt to add them to a project slowly, and once you’ve picked one mocking framework, for example, stick with it for the duration of the project. Don’t be tempted and don’t let any other team member to swap tools mid project cause JP said it was neat.

    In his excellent book Facts and Fallacies of Software Engineering, Robert Glass makes 2 points that are pertinent to this discussion.

    1. Hype (about tools and techniques) is the plague on the house of software.
    2. New tools and techniques cause an initial LOSS of productivity.

    So I always bare this in mind when anyone tells me of the latest and greatest idea

  • Jeremy

    One way to justify slipping some of these things into the next sprint is the concept of ‘dev stories’. They’re just like user stories, except they deal solely with technical debt.

    You still have to justify them (what will standardizing on our IoC container buy us down the road?) but stakeholders for some reason are more open to an idea when it’s presented in a format familiar to them. (Wow…these look just like user stories…they MUST be important!)

    User stories, of course, still take priority but if you find yourself with some room at the end of a sprint…especially if its not enough room to justify starting another user story…then they’re worth tackling.

  • Al Tenhundfeld

    Great post! This is a big problem for large product development teams. I have definitely seen teams where the developers dread discussing problems with the tech lead, because the lead will always want to use some new “much more elegant” tool (library/framework/whatever) to solve the problem.

    I think the simple answer is except in the most extreme extenuating circumstances, consistency is much more important than adopting the latest trends.

    However, I think, at high, level this discussion is really about “technical debt.” I know many industry leaders, e.g., Martin Fowler, believe the massive technical debt we accrue is a major problem for us as an industry, especially in its invisibility to the business stakeholders.

    If we choose consistency over using the more efficient/maintainable/extensible new tools, we are accruing technical debt in the form of worse code and increased development and maintenance time downstream.

    If we choose to adopt the new tools and forego consistency, we accrue technical debt through increased ramp-up time for new team members, the death-by-a-thousand-cuts cost of context switching between approaches, and the increased likelihood of edgecase conditions as these approaches integrate.

    I think any solution to this problem must include raising the visibility of technical debt. For example, one approach I’ve heard of (from Martin Fowler I think), is to give two estimates for a task.

    For example, you could do something like this: “Adding this new report format will take 8 jellybeans. If we had technology XYZ in place, adding the new report format would take 3 jellybeans.” I’ve tried this with some modest success. It takes discipline and perseverance , but after the 3rd or 4th time hearing about the time-saving benefits of XYZ, a manager will ask, “And how much would it take to add XYZ?” At this point, you have to sell the business value of your ideas. And if there is no business value — e.g., faster development, fewer bugs, etc. –, then it probably doesn’t make sense.

    I guess my main point is that you should almost always value consistency over using the hot new ideas. However, you should make the technical debt you’re building visible to those who prioritize your work. At some point, the value of refactoring your code will become obvious to management, and you should refactor all of the code to the new standards in one big chunk.

    (in my opinion)

  • BigJimInDC

    Agreed on the ways to address a project where this has already occurred. That said, my favorite way to promote not doing this in the first place is two-fold.

    First off, learn to “spike” ideas using side-projects that aren’t part of your “production” code-base. I’ve literally reached the point where I create projects that are prefixed with “Spike.” to ensure that it’s that obvious.

    Second, leave the initial technology choice in place unless 1) there are business requirements that are made extremely simpler by switching a technology mid-stream in a project; or 2) you know for a fact that you can perform a complete switch immediately, ensuring the project isn’t riddled with multiple ways to do things.