In my previous “An Attempt at a Pragmatic Framework for Defining a ‘Senior Engineer’”, in the “A Process to Estimate Work” section I said:
“It is beyond the scope of this post to describe everything that goes into making a good estimate, but suffice to say a senior engineer views estimates as a difficult challenge to be surmounted, and as a result will normally ask for dedicated time simply to come up with the estimates.”
A commenter asked that I write an article on estimation, and this is my feeble attempt to do so.
First a few warnings:
- I would not consider this advice practical. Some if not all of what I am saying would cause riots in the street if it were even brought up in most development organizations. For that reason – at a minimum – I would not forward this article to your management team. I don’t even recommend you read it.
- Most of these points only apply to larger enterprise projects. Small developer-centric teams will have a good sense of their ability to produce work, and a formal procedure for estimation would do more harm to the schedule than good.
- Even if you follow every piece of this advice perfectly, a single scope change can drastically alter your original estimate. Most projects have countless scope changes after development begins.
- I would recommend using Agile/Lean methodologies to produce velocity/capacity based estimates, but those are usually not good enough for a Sales, Product, Marketing, or Executive teams; as those teams deal in contractual deadlines. This approach is when one or all of them demand an estimate and refuse to accept anything that is not a single calendar date.
- You need exceptional communication skills to convince others to do any or all of these. If you are conflict averse then I strongly recommend you don’t read this article, as even thinking this way will frustrate you and anyone you bring it up with.
- Some of my most respected colleagues violently disagree with me on many of these, so know there are different perspectives on this topic. However, since this is my blog and not theirs, you’re stuck with my opinion. As with all things, I encourage you to seek out different perspectives so that you can have a more holistic understanding of whatever topic is being discussed.
- You will not be able to unread this. If you agree with the things I am about to say, but you know your organization would bristle at the thought of adopting some or all of these, I will only have made you miserable. Don’t do that to yourself – you deserve to not be miserable at work.
You have been warned.
The following is the process that I use when I am are given the impossible task of coming up with a single hard date in which a project will be finished. You are not me, so your mileage may vary:
- Never Be Bullied into an Estimate
- Get Approval for Time to Estimate
- Be Able to Recite the Requirements from Memory
- Be Intimately Familiar with the Entire Codebase
- Diagram the Work to Be Done in Exhaustive Detail
- Painstakingly Break Down Every Development Task
- Know the Quality of Existing Tests and Their Test Coverage
- Estimate Required Refactorings Separately
- Know What Each Member of Your Team Is Realistically Capable Of
- Know Which Tasks Will Go to Each Team Member
- Establish Backup Engineers
- Know Everyone’s Vacation Schedule
- Put “Uninterruptible Coding Days” on the Schedule
- Gauge Burnout Potential and Consequence
- Know the Acceptance Tester’s Capacity
- Present Your Estimate Like You Are Bidding for Work
Never Be Bullied into an Estimate
The most critical yet the most difficult of all the things on this list. If you refuse to do something your employer tells you to do, that’s called “insubordination” and they have a right to fire you. There is nothing stopping a manager from cornering you publicly and demanding you pull an estimate out of your ass, so they will. If you refuse, be prepared to update your resume and look for a new job.
Your only hope is to convince whoever is demanding the estimate that it is in no one’s best interest for you to produce a guesstimate based on nothing, when you could produce an estimate based on a thorough analysis. Best of luck with that. I’ve lost more of those arguments than I have won.
Get Approval for Time to Estimate
If you managed to avoid being bullied into an estimate, you now need to estimate the time needed to produce an estimate. Let that sink in for a moment. It’s tempting to time-box the time spent estimating, but the reality of the situation often makes an extended period of estimation necessary. My position is “it’s done when it’s done” which is an extremely unpopular position to take.
My personal methodology is that a software development project has 3 phases:
I am conflating the term “production”, which I don’t mean in the way the industry typically means it (the environment in which we deploy the final build to), but instead I mean this exactly as Hollywood movies do. During Pre-Production, the development team shouldn’t be allocated/hired, so there should be minimal cost burn as the estimation time drags on. I could say a lot more about this, but if you study how movies are produced you’ll get the gist.
Be Able to Recite the Requirements from Memory
That’s right: from memory. Think about this like being a stage actor who must memorize their lines before a performance – that’s how well you need to know the requirements. There is no substitute for this, as while you are coding you will not know what you don’t know, and therefore you won’t know when you should refer to the documentation to clarify something you don’t understand. My attitude is, since you have to analyze the requirements anyway, you might as well commit them to memory. As a bonus, you’ll earn the respect of non-technical staff members when you know the requirements better than they do.
Be Intimately Familiar with the Entire Codebase
Yes. The entire codebase – not just the parts you worked on and/or are familiar with. There are two reasons why you must do this:
- If you have no unit tests (or equivalent), you won’t know what you might break.
- Unless you know what’s already written, you won’t know what you can reuse.
Considering enterprise code bases can be hundreds of thousands of lines of code, this may seem like a daunting task – and it is. I recommend coffee, a comfortable chair, and some way to make notes to prevent yak shaving (I use my IDE’s bookmarking feature).
Diagram the Work to Be Done in Exhaustive Detail
You may think when I say “Diagram” I am saying “Add diagrams to the requirements”, but that’s not what I am saying. If you truly understand the work to be done, you can draw it on a whiteboard and/or in a drawing program (I use Visio). Do this until it’s second nature, as it will act as a form of analysis, diagnosis, and communication with the rest of your team. If you have resisted until now, learn UML.
Painstakingly Break Down Every Development Task
Yes – “Painstakingly”. This sucks. It’s boring, thankless, and takes a long time to do properly. Unfortunately, it’s essential. You need to have each development task estimated in order to come up with your final estimate, and it is far easier to estimate a small development task than a big one. I really, desperately hate doing this and have to force myself to every single time. The mantra I say to myself is, “If you think you can code it, then surely writing a sentence of what you want to code should be easy.” Doesn’t help much – still sucks.
Know the Quality of Existing Tests and Their Test Coverage
I use “tests” here to primarily mean automated tests, but specifically unit tests (or equivalent). If your codebase is massive, but you have no unit tests, you are very screwed. If you gave up and found another job I wouldn’t blame you. There are techniques to deal with this, but they mostly fall under the category of prerequisite refactorings which have to be separately estimated. Word to the wise: always write unit tests, because one day the code base will be much bigger than it is today, and you may need to enhance it. Without unit tests, you will be flying blind, and your estimates will necessarily be worse than they would have been with unit tests.
Estimate Required Refactorings Separately
Just about every project that enhances a legacy codebase will be easier to estimate if some aspect of the codebase is refactored beforehand. Maybe the new project will need to make extensive use of a 3rd party service, but the current adapter to that service is shitty. If you make a fit-for-use API, it will reduce the time spent on all development tasks that need to use that 3rd party service. Since refactorings are their own mini-projects, they have to be estimated separately. If those refactorings require other refactorings, they you have to continue down the rabbit hole until you have found all the required refactorings. You then need to figure out which refactorings can be done in parallel (if you have more than one developer) vs. which ones are dependent on each other in order to understand the true schedule impact.
Know What Each Member of Your Team Is Realistically Capable Of
Subjective peer assessment: The stuff that lawsuits are made of.
The productivity of different developers can vary widely based on a wide variety of factors, but you have to know who is capable of doing what type of work. I don’t believe in the luck-of-the-draw Kanban/Taskboard style task assignment for myriad reasons, despite their near ubiquitous use for that purpose.
We’re a team, and we all have our strengths and weaknesses. My philosophy is that each team member should be put in a position where their strengths are put to best use, and their weaknesses don’t hold back the project. This philosophy flies in the face of many standard corporate management practices, and as a result can cause many internal political problems. You had better know what you are doing before you attempt this, and be prepared the accept the consequences of any resulting backlash.
Know Which Tasks Will Go to Each Team Member
Some people are better than others at certain task types. If you’ve got a developer gifted with regular expressions, give them the regex-heavy tasks. Same for any other type of expertise-to-task pairing. Once you’re done, take a step back and see if you have any choke points, and if so, what you can do about them. Since you know your development tasks, and you know the capabilities of your developers, matching them up should be easy.
Establish Backup Engineers
A Backup Engineer has two purposes:
- If the primary developer is not available, they can step in.
- If the primary developer is running behind, they can step in to help them catch up.
One of the benefits of a pair programming (particularly promiscuous pair programming) is that you don’t need a back up engineer. If you don’t pair program, however, you need some type of redundancy so that someone can’t get sick, go on vacation, or quit, and wreck the project schedule in the process. The fear of this is one of the many reasons that people don’t like to assign specific types of tasks to specific developers, as they think it’s avoiding the hit-by-a-bus scenario. In my experience, you’d rather a hit-by-the-bus scenario (provided you have a backup engineer) than incur the massive ramp-up costs of a cold developer wading into someone else’s partially complete work.
The key to a backup engineer is that they are a warm-backup: they are already familiar with the work enough to take over if they needed to. This can be done just through regular peer design and code reviews. Not as good as pair programming, but as least it doesn’t cut your theoretical maximum productivity by 50%, which is an extremely unpopular project managerial concept.
Know Everyone’s Vacation Schedule
If people are on vacation, they won’t be working. If a member of a team has a hard dependency on someone on vacation, they also will not be able to work. You need to know every single day people will be on vacation to even make a first-pass attempt at a realistic schedule. Don’t fall into the trap of “it will all wash out in the end.” This is one of those knowable piece of information that you can know if you ask, unlike sick days.
Put “Uninterruptible Coding Days” on the Schedule
To maximize a developer’s production of code, you must maximize the time they spend coding. Code is not written in activities other that writing code. Writing code requires focus. Being interrupted prevents focus. Provided you have done everything I have suggested up until this point, you should know exactly what you have to code. Shut up, put on head phones, and code dammit. The time for discussion is behind us.
As this is a completely foreign concept to management, you will have to formally schedule in days where developers are left alone to code. That means no meetings, no desk crashing, and no expectations of email or chat replies. There are a multitude of excuses why this is said to be “not possible”, too numerous to go into here. My position is as follows: Only developer tasks worked on during Uninterruptible Coding Days have a chance of coming close to their original estimates.
Gauge Burnout Potential and Consequence
All projects come with stress, but not all stress is bad. For example: when you play a game in your leisure time, that’s a good form of stress; being yelled at by your manager because you’re a few hours late on a 3-day estimate is a bad form of stress. Depending on your situation, you can gauge how likely your team is to burnout at any given point in the project. If you see a particularly stressful part of the project where burnout is likely, that’s a good time to schedule a team activity away from work, like attending a conference. Most managers would laugh at this idea, but that’s only because they have never tried to code while burnt-out: productivity drops to zero, or less-than-zero if the code breaks and causes churn for other members of the team.
Know the Acceptance Tester’s Capacity
If you don’t have the authority to declare work is ready for production, then you need to know the availability of the people who do. For example, if a QA team is testing another project at the same time that your project is ready for testing, then you are going to have to stand in line and wait your turn. If you have to wait for several weeks, then there are several weeks added to the schedule. The only way I know to avoid this situation is to have a fully dedicated QA team which means they are idle for periods of the project, or to invest in a full automated test suite which most organizations don’t have the willingness to commit to.
Know the Deployment Windows and Required Lead-Times
If deployments happen only on certain days of the week, and/or have to be scheduled weeks in advance, you need to plan accordingly. If the deployment team needs 3 weeks of warning before a deployment, and that’s only after you have been certified by QA, then that time needs to be factored into a schedule. The only way I know to avoid this situation is to fully automate your deployments, which thankfully is becoming the de facto way organizations do deployments.
Present Your Estimate Like You Are Bidding for Work
At this point, provided you are not throwing-up or in tears, I do have some good news: If you present your estimates as if you are a contractor bidding for work, you can present all of the due diligence done so far to produce an estimate, as well as itemize estimation work yet to be done. Doing this puts the onus on management to either let you continue with the estimation effort or knowingly accept a partially-formed estimate. No matter what they decide, you’re in a better position that you would have been otherwise.
I’m done. I would advise you to re-read my warnings at the beginning of this article.