Wednesday, May 29, 2013

Fixing Perverse Incentives in Software Development

I read with interest an article about picking the right metric to incentivize desired behavior and thought I would add a little of my own personal insight. One problem with many (maybe most) software development organizations is that they inadvertently create perverse incentives, rewarding undesireable behavior and creating confusing and chaotic environments that, despite best efforts of all involved, seem to only on a hit or miss basis produce the desired result. Just as important, often the rewards are implicit and it isn't obvious that developers are actually being rewarded for the errant behavior.

Some short examples of widely used, but poor metrics I've observed as well as some simple and arguably better alternatives follow. For example:

  • Rewarding developers for "count of bugs fixed". Without accountability for who created the bug, this simply incents developers to release buggy half finished software that they will then subsequently be rewarded for "fixing". It's probably better to reward developers for "bug-free features delivered" or "lowest bug count".
  • Rewarding developers for "hours worked". Do we really want to incent someone to take 20 hours to do something they could actually accomplish in 20 minutes? It would be better to measure features delivered per unit time than simply the raw number of hours in chair.
  • Rewarding folks for being the "expert" in something. Inevitably this leads to situations where folks WANT to be the sole expert in something... hiding or obfuscating things or creating proprietary boondoggles that no outsider ever has a hope to figure out. Better to reward someone for creating something that is transparent and usable by all ... or better yet reward someone for teaching others how to do something than be the "expert".

Some examples of inadvertent rewards that crop up over and over again and reinforce the negative behavior:

  • We're going to pay you to your own mess. Yep, consultants love this one.. pay to build a mess AND fix it, you'll be gainfully employed for life! Maybe it would be better if we let you fix your bugs for free! on your own time! I wonder what would happen to the bug count in this case?
  • Look at the superhero. Wow! load balancer crashed and we had to call you on vacation because you're the only one who knows the root password/knows where the server is. What an ego boost! Perhaps instead we should celebrate the sysadmin who has NEVER had a server outage instead of the one who can't take a vacation because they're the only one who knows how to reboot the load balancer.
  • You're fired! This is a tricky one, and actually not a reward, but if there is a absolutely no reward in pointing out problems and ONLY risk, who's going to stand up and risk the axe for pointing out an honest error? It's much better to reward honest and constructive criticism of problems with appreciation for the effort and concern than creating a hide and go seek culture of "it's not my fault". I realize this is actually a risk, but I've put myself on a tight timeline so you'll have to live with it :)

While not comprehensive, hopefully we can use this list as a lens to view our software development teams and look beyond the superficial problems. In doing this, I believe, we can start getting better at constructing better metrics and rewards. This should lead to build better software, of a higher quality, delivered more reliably and quickly.

Thursday, May 16, 2013

When to refactor code

As a die hard refactorer, but also pragmatic programmer, I often have a tough time articulating to other developers when a refactor is important and when it is gratuitous. I can imagine many people look at decisions I've made about when it is and isn't appropriate and think it's simply a whim or "when I feel like it". To clarify this for both myself and any future victims/co workers involved with refactoring decisions I may make, I submit this 10 item checklist.

  1. Is the cyclomatic complexity of the function below 5?
  2. Did you completely understand what cyclomatic complexity was without following that link?
  3. Do you have an automated test or documented test case for every path through the function?
  4. Do all of the existing test cases pass?
  5. Can you explain the function and all it's edge cases to me in less than 1 minute?
  6. If not, how about 5 minutes?
  7. 10 minutes?
  8. Are there fewer than 100 lines of code in the function (including comments)?
  9. Can you find two other developers who agree this code is error free just by visual inspection?
  10. Is this function used in only one place?
  11. Does the function meet it's performance goals (Time/Memory/CPU)?

Scoring

Add up the "no" answers above:
  • 0-1 - Why would you even think about refactoring this? You probably just want to rename variables because you don't like the previous developer's naming convention
  • 2-5 - This might need a little tweaking, but I wouldn't hold up a production release for something in this range
  • 6-8 - OK, we probably need to fix this... It's likely we're going to keep revisiting this and/or we don't actually know what it's doing. Still on the fence, but it's highly suspect
  • 9+ - This is a prime candidate for refactoring. (Note, writing test cases is a form of refactoring)

While I know this is a rough guideline, I think it hits on the key factors that are important about the overall quality of source code and helps avoid overspending effort fixing things that aren't necessarily broken.

Monday, May 13, 2013

Apologetic Agile Development

Having lived through numerous attempts to build software embracing the concepts behind the agile manifesto, I feel there are three large categories folks fall into when talking about agile principles.
  1. The curmudgen - these folks have been writing code since punchcards where the state of the art, OR they have been brainwashed by large consulting organizations into thinking that a large heavyweight process is the only way to succeed. Note, a subset of these folks believe that "no process" is actually OK and are quite happy to cowboy-code their way through life.
  2. The fanboy - these folks think "everything agile all the time" and will rename status meetings to "scrums". These are folks who are used to working solo on projects that they can do in their heads... or they are simply not clued into the implications of actually having a repeatable process or delivering working software.
  3. The apologetic - these folks understand the principles and the value they provide, but also understand that these principles are the important thing and know that the current state of the art of software development is still very problematic. These folks often complain or quip that they are not doing "real agile", but accept that using some of the tool and principles coupled with more traditional principles, tools, and processes has much more value in most cases
I'm squarely in the apologetic camp (my ego transposes apologetic for pragmatic BTW), and while I feel I have a good understanding of where and how agile can deliver value, I also understand that many times agile gets sold as a magic bullet that never delivers completely on it's promises. I think this is a mistake: No process, methodology, or tool is perfect, folks who complain that "agile" causes problems in their projects or doesn't solve problems that they have are completely missing the point. No process, principle, or methodology should completely dominate your software development philosophy and enlightened developers should stop apologizing.