There is a lot of stress going on in the world as I write this post. Presently we are under quarantine due to COVID-19 and lots of folks are working remotely. There are also protests happening across the US in response to the homicide of George Floyd at the hands of a police officer. Everybody is feeling the turmoil. In this stressful time it is important to maintain sensible expectations. This is true in every aspect of life. In this post, however, I want to focus on the creation, delivery, and maintenance of software systems and the timeline expectations generated as part of project management and the software development lifecycle (SDLC).
This is not a new issue. I posted about it in January before COVID-19 and the protests started. However, as companies are cutting staff and the amount of work to be done increases for those remaining, it becomes easy to let stress dictate deadlines. Taking a step back from a situation almost always shows the decisions made under stress to be marginal at best. As such, I want to take a step back and talk about a few things that help to create sensible expectations of a team that creates good software:
- What does it take to deliver software changes?
- Reasons to rush
- How to rush
What does it take to deliver software?
Because my mind works well with lists I’m going to start this section with a list of items it takes to deliver good software in a reasonable amount of time without putting undue stress on anybody. I’ll expand on these after listing them out. They are:
- Good requirements
- Understanding of existing code
- Reasonable testing infrastructure
- An understanding of how quickly it is necessary to act
- This one gets it’s own section below
My definition of “good” requirements: Good requirements are detailed enough for a developer familiar with the business to be able to start work with minimal questions. This means that the requirements need to be more than “this field on the form needs to look like this” or “what I entered on the screen wasn’t saved.” There need to be examples of data that reproduce the problem or highlight the issue to be added. A discussion of why changes are requested reduce questions and help spread the knowledge of the business logic. Such requirements will allow developers and testers to understand the scope of an issue. This understanding will lead to better time to completion estimates which, in turn, will allow for better planning. Better planning and project management, of course, creates sensible expectations (if communicated appropriately of course).
Please note that no single paragraph, no matter how well written, will cover the extent of what good requirements look like. For the sake of this discussion I believe that my description above will do. There are, however, books written on the subject that cover this topic in greater detail. Note: I haven’t read that book specifically but, as a general rule, the books that come out of Microsoft Press are pretty good. If there is a better book on the topic please let me know.
Understanding of existing code
The developers that will be making a change need to understand the code they will be changing. If they haven’t interacted with the code already they will need to spend time reading and playing with it before they can make a change. This will extend the amount of time that it will take the developer to complete their task. It is a requisite for a developer to be able to make the change effectively. That is not to say that developers should be allowed to work only on what they are already familiar with. The plan to approach a project just needs to include extra time for a developer to learn in order for the expectations laid upon them to remain sensible.
There are ways to mitigate the penalty of a developer having to learn a new area of code. Since this isn’t the main point of the post, I will keep this short: All of the ways to mitigate the learning process boil down to implementing patterns: good design patterns, common calling conventions, and frameworks that implement APIs in ways developers will recognize.
Reasonable testing infrastructure
This is yet another gigantic topic that I am going to breeze over for the sake of making the point that this infrastructure needs to be reasonable to deliver software in a reasonable timeline. The items that, at a minimum, need to be setup are:
- A clear and simple release management process (that is, how a change flows from a developer through testing and on to production)
- Quality assurance (QA) and user acceptance testing (UAT) teams that knows how to test quickly in both a manual and automated manner
- An attitude among all the teams (Dev, QA, and UAT) that allows all of them to work together instead of being territorial about solving problems.
I’ve spent most of my career as a developer and, as such, I have not spent time gathering books and other resources for testing. Please let me know if you have resources to put here.
Acceptable reasons to rush
There are a few reasons that I can think of that are legitimate reasons to cut corners. These include:
- Production environment is broken
- Governmental regulations change deadline looming
- Achieving first to market status
With the exception of the production environment being broken I would argue that even these important reasons shouldn’t cause a crunch. The requirements planning phase of a project should plan for a minimally viable product (MVP) and a fully featured product. As a due date approaches requirements should be cut from the product as necessary to finish what can be finished with quality. These are all things that I have witnesses a great project manager handle.
How to rush when you need to
Here we can get to my definition of “rush”. Rushing, to me, includes cutting corners from the development process. This means skipping writing automated tests (either from dev or QA), reducing the manual testing process to the happy path, and, as a last resort, having employees work overtime.
After finishing a project it is critical to do a retrospective on the rush that covers:
- Why the rush was needed
- What was done to solve the problem
- What parts of the normal process were skipped
- What can be done to retroactively address the process parts that were skipped.
Completing this retrospective and giving time to solve technical debt accrued during a rush is, from my experience, the item that is most often skipped by companies. The reason for this is often that most projects are treated as emergencies that cannot be put off to handle tasks that aren’t part of the projects. This way of thinking snowballs into a code base that is a gigantic plate of spaghetti and a team that is paralyzed with fear at dealing with certain projects. Taking time to figure out what happened is important!
Don’t use these reasons all the time
Rushing should be like salt; used sparingly. While it feels great to get something solved and out the door quickly that feeling is addictive. If a team rushes all the time it will find itself cutting corners on the ways to deliver good software. The more the corners are cut the harder it will be to get them instituted again. It’s a vicious cycle.
Recently a connection read and reviewed Mentoring a Software Engineering Team and gave me a great piece of feedback: I’d failed to comment on the responsibility each team member has to complete their tasks. This article on sensible timelines is a good place to address this issue.
Just as it is my job as a tech lead / senior engineer on my team to clear a path for the other engineers to get their work done it is their job to reciprocate this effort and get their work done. This includes:
- Completing tasks in a timely manner
- Communicating clearly when there is an issue including
- Unclear requirements
- Timelines that are too aggressive
- Environmental blockers
Please note that taking personal responsibility does not mean working excessive hours. As discussed in this post sensible expectations for when work can be delivered are critical. Part of developing sensible expectations means planning for all team members to recreate and rest. Team members reporting lots of hours for tasks on a regular basis should be a red flag to spend time re-evaluating timeline expectations.
Coming to the end of this post I feel like I have written a large advertisement for Rework from the folks at Basecamp. Please go read it. Rework talks about creating a business as a whole that will avoid many of the reasons to rush and, as such, it may disagree with what I’ve said here.
That being said I’ve only ever worked at companies that often worked in a panic without sensible expectations of how quickly software can be delivered. I have often had to tell the folks I work with to go home, rest, and come back to reevaluate their expectations of how long tasks should take to get done. I will repeat the same thing here to you:
Go get out of the office, recreate, and rest. Only then will you be able to see clearly what actually needs to be done and how to best go about it.