How to Write Great Software Engineering Tickets: Separating Architecture from Tasks
Writing great software engineering tickets is hard. It doesn’t matter if you are a non-technical author, such as a Product Manager, or a seasoned engineer, such as a Dev Lead. Making business requests make code sense is a skill that only comes with the experience of writing many stories, epics and releases.
What makes a “good” ticket is subjective, but there are things you can focus on to make ticket outcomes objective. Two of the easiest outcomes to monitor are a ticket’s actual hours and its release’s actual hours. Being successful is often tied to minimizing your budget, which means spending less time on individual tickets and overall ticket rework for releases.
How do we go about reducing initial ticket hours and getting things right the first time to avoid rework? You may be familiar with best practices for making tickets clearer by including proper documentation, naming all relevant resources (stakeholders and others) and writing business logic in a way that translates to code.
One not so obvious way to write better tickets comes from excluding, rather than including. Tickets that do too much take a lot of time as they both have a lot of content to address, but also tend to lose focus. A good way to avoid having tickets lose focus is to separate issues into smaller tickets that have a sole focus of either addressing tasks or building architecture.
How are Tasks and Architecture Different?
If all software tickets look the same, then this is the perfect article for you. A ticket for a code feature can broadly be seen as adding something new, or updating existing code. These are two generalized items that may make all tickets appear the same.
However, when we look closer we see that there are two further categories for grouping ticket objectives. Ticket objectives can fall into one of two categories: tickets that make actions possible and tickets that perform these actions. To match our terms you could say the first category includes architecture tickets and the second includes task tickets.
It’s important to be able to tell the difference because architecture must always come before tasks can be completed. An airplane must be built before you can fly, a phone must be built before someone can make a call and APIs must be built before an engineer can leverage data to build and populate an engaging UI.
When looking at work to be done, it is important to make the distinction between tasks and architecture to avoid issue blocking, out of sequence ticket assignments and loss of focus for engineers. This isn’t a question of the chicken or the egg. Architecture must precede tasks and this is important for planning sprints and release work.
Separating Work to Keep Focused
While order of operations makes sense for separating tasks and architecture, there are other benefits as well. A major benefit of separating this work comes from having clear, single responsibilities for tickets. Vaguely written tickets lead to assumptions, and assumptions introduce new features that a Product Manager could never dream of having to pull out during a QA feedback round.
Keeping tickets to a single responsibility is paramount to avoiding misunderstandings and rework. What I mean by single responsibility is that each ticket should handle a single job of either introducing supporting architecture or completing a given task.
For a hypothetical, let’s assume that we are a Product Manager wanting to move from having a single, standard payment plan to multiple payment plans based on the given user. Great, we can write a single ticket and hand it off to a Full Stack Software Engineer to complete. This seems like it would work well, but doing this breaks the rule we just covered of separating architecture from tasks.
To complete this work, we will need new views, a new controller with methods for putting together each payment plan card as well as logic to look at the users to auto assign plans based on their attributes. These are all very different items and should be treated as such.
Creating the UI is a task as it will consume data from our controller to make a view, so this should be separated into a task ticket. We need to look at a new user plan attribute on our user model to be able to generate payloads and actions to compose these payloads.
In order to do this, we will need to have an architecture ticket to create the payment options controller and its methods. Where this gets really interesting is updating the user model. We have an architecture job of adding a new field to the users table through a database migration, but then a task for setting values on all existing records through a data migration. Here, architecture must precede task, but we may put these two items in the same ticket to prevent the work from getting too separated.
As you can see, by identifying task and architecture items from a larger ticket we were able to determine a non blocking path for the work. Along with this, separating the work allows us to spread these jobs between multiple different engineers so items can be completed in relative parallel.
Conclusion
Beginner’s luck really does not apply with planning efficient releases and tickets. Staying under budget requires experience and understanding of how software is developed as well as the business needs being addressed. One key to reaching your goals is to separate work in an efficient and nonblocking manner that keeps tickets moving forward and rework to a minimum. I hope this article helped you understand the difference between task and architecture jobs and how to best plan your next sprint or release!