I don’t trust me

Where I’m Coming From

HAL 9000 - I can't allow you to do that, Dave.I’ve learned that, in general, I can’t trust humans’ judgement, knowledge, or experience when working on software  projects, among other things. I’m not saying that humans are bad, I’m just saying that humans are creatures and subject to mistakes and failure. Quite so, as a matter of fact.

The past couple years I have worked in predominately old-style software development modes. I have seen success in spite of everything — in spite of the non-developers on the team, in spite of the politics, in spite of the command/control management, in spite of waterfall-esque project structure. Despite all these things, we were usually able to get something out and help the customer somewhat, but not nearly as effectively as we could have with a highly motivated team, focused on a goal, working towards total success with minimal interference in the creative process known as ‘software development’.

This frustrated me, and it has made clear, in my mind, the value of the processes I preach/endorse and attempt to practice in this environment (occasionally strides are made, but they’re hard to sustain).

Managing Human Weaknesses

Ultimately, what I’ve come to realize is that software development is really all about the people. With good people and processes that enable them to work effectively, you will have success to one degree or another (usually a good degree). So the goal is really to make sure that everyone on the team (including non-developers) are properly motivated and share the goal of the project. If not, they shouldn’t be on the team, or the project manager (or similar role) needs to work with that person and persuade them to cooperate (find out why they’re not cooperating and work with them to resolve the issues).  Once you have a good team with everyone interested in accomplishing the goal, the next task is to try to implement processes to appeal to their higher nature and set them up for success rather than crush them with threat of looming failure.

There are many processes out there, and I have found the following to be very effective in my own practice, and through observing other teams who have been practicing them.  The only failures I have seen is when the team is not properly motivated, has conflicting goals, or there are personality issues that are not properly managed by the manager.

These processes (detailed below), can be summed up with this statement: 

Setting Yourself up for Success

I don’t trust the customer

I don’t trust the customer or the target consumer for the software we’re building. I don’t trust them to know thoroughly what their problem is. I don’t trust them to be able to communicate effectively to me what picture of a solution they have in their mind. I don’t trust them to be able to know, beforehand, everything that they would need to have their problem solved to complete satisfaction. They will change their mind, remember things they missed mid-way through the project, remember that what they asked for earlier on was wrong and needs corrected, etc.

So we put in processes to help achieve better, more structured communication — but not too much, and the kind of structure that facilitates dialogue and interaction versus lengthy 500 page Word documents.  We talk with the customer more often (every few weeks) and show them what we’ve got so far to help them coalesce in their mind what it is we’re all trying to accomplish and what steps we need to take to finally accomplish it.  Finally, we (the team) hold ourselves accountable by keeping tabs on what we understood from the customer, what we promised them, and how long we said it would take us to accomplish it.  We help achieve better accuracy by promising smaller things and promising them more often since more promises over longer periods of time virtually guarantees failure.

I don’t trust the team, in general

I don’t trust the team, in general (including myself). So we have daily stand-up meetings to keep each other apprised of our situations and to keep tabs on any problems that may be brewing. It’s also a chance to allow the manager to get a feel for what roadblocks are hampering development (including non-technical ones like personnel issues).

I don’t trust the team (including myself) to deliver on what we promise, so we break promises into more manageable chunks and estimate them the best we can. After the chunks are done, we review our promises and estimates and grade ourselves on how well we did. We use this information to get better at promising and estimating in the future, and also to help us plan how close we are to being ‘finished’ based on our accuracy.

I don’t trust the developers

I don’t trust the developers (including myself). I don’t trust the developers (including myself) to:

  • make sure they don’t lose their work
  • not overwrite each other’s work.
  • not make changes that break the build and cause a work stoppage among the developers.
  • be able to manage the complexity of building new software while maintaining an existing, production branch of the software.

So I use source control/revision control/version control (whatever you want to call it).  I, personally, have found Subversion to be most effective at addressing all of these problems, but there are other similar products that are also effective. I have found the Microsoft Visual SourceSafe product to be inadequate at addressing all of the above concerns. I would recommend not using Microsoft VSS for a team development project like I have been describing.

I don’t trust the developers, including myself, to write code:

  • that, first and foremost, accomplishes the acceptance criteria
  • that is well tested and has good code coverage (where ‘good’ is subjective and relative)
  • that works as expected with all the other code in the system
  • that is acceptable to the coding standards/policies we have set as a team
  • that doesn’t break the build and cause work stoppage among all the other developers
  • that works on a system that is not a developer workstation (i.e. ‘It works on my box!’)

So I use an automated build process with continuous integration. The build process compiles the code on non-developer workstation/server that doesn’t have all the developer tools on it (only the bare minimum necessary to compile).  The build process then executes the tests (unit, integration, acceptance, etc) to ensure the fitness and working condition of the software, as well as it’s cohesiveness as an entire unit.  The build process then runs code coverage, complexity, and policy analysis to determine whether it is of the quality standards we have set for ourselves as a team.  If any of these steps are not met to our high standards of satisfaction, the build will fail and our Continuous Integration software will alert us to this fact.  Personally, I have used NAnt and MSBuild as the build tool, CruiseControl.NET as the continuous integration software, FXCop as the policy analysis tool, NCover as the code coverage analysis tool.  I have heard good things about Rake and FinalBuilder as build tools and JetBrains’ TeamCity as a Continuous Integration server.

I don’t trust me or any other developer, individually

I don’t trust my ability to estimate, so I track my estimation accuracy as the project progresses.  I don’t trust my ability to understand the requirements placed before me. So I encourage the customer not to write big long requirements specification, but rather to discuss the requirements with me using conversation starters like User Stories. I get a greater understanding of the problem and the desired solution (including the technical component of that solution) and participate in defining the specification for that requirement WITH the customer.  We then develop the actual specification and codify it in documentation, the code, and any other necessary artifacts (i.e. auditor documentation for later review).

I don’t trust my ability to actually accomplish the requirement, even if I understand it completely.  But I know that I am not likely to ever understand any requirement completely — or even that the customer himself understands the requirement completely — so I make sure to design my code such that it can be easily tested, and easily refactored later. I make sure that I don’t code too much of my assumptions in one place because it’ll be harder to unravel later.  I also write lots of tests that assert my assumptions and understanding of the problem.  I write integration tests to ensure that the code I write works well within the entire system (and not just the specific unit in which I’m working). I write acceptance tests at a higher level that serve as a customer-driven sanity check of my code which isn’t concerned with how the code is implemented as much as the end result of it’s function (i.e. when I say ‘debit from account’, it really debits from the account).

I don’t trust our tests

I don’t trust my testing discipline enough to ensure that I will achieve acceptable coverage of the code unit and cover all the edge cases and any other important scenario worth testing. I don’t trust my discipline to avoid writing a bunch of code that isn’t directly necessary to accomplishing the requirement. I don’t trust myself that I won’t go code happy and write a bunch of unnecessary code just for the pure joy of writing ‘cool code’.

So I write my tests first. I write the tests first while I’m fresh and not burnt out on writing code. I write the tests to get some of the non-interesting, non-cool stuff out of the way first.  I do this to ensure that when I get to the ‘fun’ coding, I can feel comfortable knowing that I’ve boxed my creativity and directed it into the areas I want it to go and will provide the most value for the client.  Now I don’t have the dark specter of having to come back and test my code after-the-fact which is not very enjoyable.  I also know that my code is inherently more testable because it was written to be testable in the first place and necessarily must be so. Even when trying to write code with tests in mind, I have found that I can never quite do it 100% and, when writing the tests afterwards, I end up having to refactor the main code a little to get it to work right with the tests. So writing test makes my life a lot easier. It also helps me ensure that I’ve met all the requirements and achieved quality up front instead of afterwards.

Even after all that, I still don’t trust my tests

Doing the tests first, up-front helps a lot, but it still requires some discipline and creativity to come up with test scenarios. The temptation is to take it easy and not test every case you can think of. Or maybe one day you’re tired, after a big lunch, and you just don’t feel like it. The project will suffer.

So, I pair with another developer. We keep each other honest. We work in a friendly, but adversarial/competitive mode where we write tests for the other developer and ask them to implement the code to pass the test. This keeps things interesting and adds some incentive to write good tests as well as good code.

Finally, I don’t trust the testers or the code release itself

I don’t trust the testers to test everything they should properly. I don’t trust that they won’t also fall into human nature and not test everything every time.  So I work with them to automate things to the maximum extent possible and give them the tools they need to set themselves up for success like we have on the development side.  Monkey testing (banging on the keyboard or mouse) is tedious and soul-sucking. Few people in this world enjoy it.  So, we try to minimize monkey testing and, instead, give the testers tools to automate things and add in their own test cases into the automated suite.  Then, they only have to monkey test as a last resort for some very specific, complicated case. These are usually somewhat interesting to set up and discover (but not always), so it helps to keep the testers focused and interested.

Once the testers are done and the software is ready for release, I still don’t trust that it’s ready or that any human involved at this point won’t introduce a problem at the last minute. So I make sure that releases are automated and I test this release process with the testers and other team members so we can trust the automated release packaging system.  For this, I usually use NAnt or MSBuild to automate the final packaging of the build, the documentation, licenses, or any other ‘final build’ type tasks that need to be done. I try to avoid doing anything after the testers, but, at least in my cases, I have never been able to avoid having to do SOMETHING to gather up the final package for pressing onto a CD or pushing out to a download server and sending out notifications to customers.

About Chad Myers

Chad Myers is the Director of Development for Dovetail Software, in Austin, TX, where he leads a premiere software team building complex enterprise software products. Chad is a .NET software developer specializing in enterprise software designs and architectures. He has over 12 years of software development experience and a proven track record of Agile, test-driven project leadership using both Microsoft and open source tools. He is a community leader who speaks at the Austin .NET User's Group, the ADNUG Code Camp, and participates in various development communities and open source projects.
This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • This is awesome Chad. In a very thoughtless slow spoken voice…”but we trust you Chad” :-)

    This is great stuff but food for thought this is a great case for instituting change in a culture but if you ever want to tell a customer or senior management this. Change the wording around to “I don’t expect”. I don’t trust caries to negative a connotation to it.

    Food for thought. Great post.

  • Great post Chad. I especially liked the concept of pairing on writing tests & making them pass. I haven’t come across that one before. Is that idea relatively common in projects that involve TDD and pairing?

    I would be interested to read a follow up post on your thoughts regarding the barriers of entry for the processes you described. For example, I believe that is always worth the effort to do continuous integration. Test driven development on the other hand seems to be much more difficult to achieve – it requires a certain level of discipline and experience.

  • @Joe trust vs. expect. I see your point, it’s probably a good idea, but I think that trust actually catches my intention better. I need something that has the same connotation, without some of the negative connotations. ‘Expect’ doesn’t capture it right, in my mind at least. How ’bout ‘Rely’? As in, “I can’t rely on me/you/anyone”?

  • @Paul That type of pairing is called ‘ping-pong pairing’. There are other forms of pairing, but it can be difficult because you must resist the urge to be a keyboard hog. With ping-pong, you can see about how long it’ll be until your next turn comes up so you don’t start mentally checking out.

    As for TDD, some people are opposed to it, but I haven’t ever figure out why and they never seem to have good arguments (‘It takes too long!’ — as opposed to testing AFTER development? Or… surely they’re not suggesting you do NO testing, riiiiiggghhhttt???).

    It doesn’t necessarily require full buy-in from everyone on the team (as long as you’re OK with ‘that guy’ committing code with no tests, or poor tests). It has been my experience, though, that anyone good at doing Test-After-Development LOVES or is very interested in the idea of TDD, but they just don’t know how to get started or are discouraged by the fact no one else is interested in helping him/her.

    I’ve found two types of people when it comes to testing those doing/interested-in TDD, and those who don’t do testing. I know there are some staunch TAD’ers out there who swear that TAD is better, but I haven’t met them personally and haven’t seen their work, so I can’t comment one way or the other.

    I have, however, seen TDD done effectively and it’s always helpful. I’ve never seen a project HARMED by TDD.

  • Chad, your article touches on many processes, not just TDD. Completely forget TDD for a second and just consider the concept of automated code based tests – I’m sure it would come as no surprise that I have worked on projects that have shipped with no such tests or a pittance (~2% code coverage). You joked “surely they’re not suggesting you do NO testing” but if you are talking about programmed tests then people are suggesting this every day, all around the world.

    I guess the essence of my point is that its great to discuss software process but ultimately its usefulness is restricted by the very nature of how hard it is to CHANGE software process. No doubt this is why there is a healthy market for Agile consultants. It has been my observation that for every 10 blog posts or articles that focus on improved software process there is but one that tackles the tricky problem of getting in there and changing the existing process.

    You could say that my original comment was an effort to move us closer to improving on that 10:1 ratio.

  • @Paul:

    What would you like for bloggers like us to write? In my experience, it’s always been very subjective, the arguments always different, the reasons/motives/whatever for sticking with BDUF and hurry-up-and-work-100/wk-later are different in each situation.

  • Chad. let me try to put it another way:
    At the beginning of the article you talked about developing using old-style waterfall-esque processes (lets call this point A). Then you started describing an entirely different set of processes that you have personally found to be effective (lets call this point B). I would say that very close to all of those processes fall into agile camp and these are concepts that I have already read a great deal about. Nonetheless I enjoyed the approach you took and am interested in reading more, specifically about how you got from point A to point B. Was it a gradual process, or was it sudden? Did you have to switch teams/projects/companies to get there?

  • Two references:



    Becoming a change agent isn’t easy. That’s when you start needing to look at persuasion books or something.

  • @Paul:
    Unfortunately, I haven’t worked at a place that did all of these things. Well, I guess there is some fortune because I was able to see clearly how that decision (to not use XYZ) resulted in a detriment to the project and limited our success, or caused maintenance problems, etc.

    The new gig I’m going to in March should have all of these things to some extent or another (hopefully a great extent) and so I hope to blog profusely about how well things work in contrast to my current gig which has almost none of these things, sadly.

    The first, most important thing is that everyone has to WANT the project to succeed. Then it’s just a matter of persuading them and proving that certain practices (which, for some reason seem to go against conventional wisdom, even though they seem so obviously efficient and right) actually pay off in dividends.

    Sadly, I have worked on a number of projects where many of the people involved on the project were more concerned with political points and vendettas than accomplishing the project.

    I have been successful in persuading incremental change in several organizations. It seems that it is easiest when they have gone on for several years using no methodology or some sort of quasi-abortive waterfall and are so desperate for something, that they are willing to try anything. I have seen these organizations be very successful at implementing the processes I’ve described above because they are willing to drop what they thought they knew and try something that works.

  • bogardj:
    I read my way through James’ diary years ago, and then somehow managed to completely forget about it. I had no idea that he had written a book, so cheers for that!

    I understand now, I think I made some incorrect assumptions. I too hope that you get the chance to blog profusely about your experiences!

  • jack

    you know, you sound like a dogmatist posing as a skeptic.

  • @Anonymous Jack:

    I take your lack of any argument to the contrary as implicit agreement with the subject matter. Otherwise, I am embarrassed for you due to your lack of any argument to the contrary.