We reject: kings, presidents and voting.
We believe in: rough consensus and running code. — RFC 7282
Imagine this: your team's been working hard, late nights, and pizza-fueled coding sessions, to build a killer feature. And suddenly, chaos descends like a surprise party you didn't plan for? Yep, been there.
That's when your manager, client, or the mysterious "product owner" swoops in, scratching their heads, and saying, "Isn't it obvious that...?" But the sad truth is — it's not obvious.
This kind of scenario can turn your project into a never-ending TV show (I’m looking at you The Walking Dead) – delays, rework, and a whole lot of wasted resources. Not the binge-watching experience you signed up for, right? That's when you realize it's time to create a Definition of Done (DoD).
What's the Deal with Definition of Done?
In the software world, the Definition of Done (DoD) is your secret weapon. It's an agreement that spells out when a piece of work is truly, undoubtedly, unquestionably done. No more mysteries or vague notions.
Credits - Scott Adams (Dilbert.com)
Think of it as a checklist – a fancy to-do list where each item needs to be ticked off before you can high-five and call it a day. It's your guarantee that what you've built aligns with the project's goals and quality standards.
And here's the thing: every team might have its own version of DoD. It's like pizza toppings – some like it simple, others pile on the works. Your team gathers around a digital campfire, discusses, and sets the rules. These rules go up on your project's fridge (or a virtual space), reminding everyone what "Done" really means.
But here's the golden rule: you've gotta agree on your DoD before diving into the project. Think of it as setting the rules of the game before you start playing – it just makes life easier.
Why Do You Need a DoD Anyway?
So, why is this DoD such a big deal? Well, imagine working on a jigsaw puzzle. You can't just slam random pieces together and hope it forms a Mona Lisa. You need the picture on the box to guide you. That's your DoD – it's the picture on the box.
The primary reason for having a DoD is to ensure that work meet a certain level of quality. Sometimes, when a team works on something, they might not fully grasp what's needed or how good it should be. That's where the DoD comes in – it's like a cheat sheet that helps the team understand what it really means to finish a task.
The DoD does some pretty cool things for teams:
- Shared Understanding: It ensures that everyone knows when something is truly "done." For example, if you're working on a user story, it lays out what's needed to consider it complete.
- Same Standards: It ensures that everyone in the team follows the same rules and expectations, whether it's about coding or testing.
- Spotting Confusion: The DoD helps clear up any misunderstandings or gaps in what needs to be done. If something's unclear, it serves as a tool for asking questions and getting answers.
- Better Communication: It makes communicating with people outside the team easier. You can show them the DoD to explain what's happening and why it's taking time.
- Reducing Problems: It helps avoid technical messes and reduces the number of bugs or problems.
So, the Definition of Done isn't just paperwork – it's a super useful guide that makes teamwork smoother and ensures things are done right.
What should a DoD include?
Now, here's where the magic happens. What should your DoD look like?
Sometimes, you encounter DoDs that are either too simplistic, like saying "code needs review, merge, and deploy", or overly complex — a long, confusing document. A good DoD should be simple and clear, covering only the essentials of what a task needs to be considered finished. It should evolve with the team's needs and be regularly reviewed and updated.
Here are some important aspects that a good DoD should cover:
1. The Code Works as Expected
If you asked for pepperoni, you better get pepperoni, not pineapple.
The code should do precisely what it's supposed to do. In other words, it should fulfill the acceptance criteria defined for the task.
The team needs to ensure that the code undergoes thorough testing and proves it meets these criteria. This includes automated testing to verify that the code performs as expected, although there's no need to list every single test in the document – those are more for the developers' benefit.
2. The Code Will Work as Expected in the Future
Your code should age like fine wine, not turn sour like milk left in the sun.
It's not just about today; we need to make sure the code will continue to work as expected in the future. This means monitoring the code for any changes that might affect its behavior. It's not only about testing the code; it's also about being prepared for changes in the input data, formats, or value distributions. To truly ensure that the code functions as expected, we need to be able to monitor its behavior in production and receive alerts when anything unusual happens.
3. Code Quality Matters
You don't want a house of cards; you want a rock-solid fortress.
Quality isn't just a buzzword — it's essential. Nobody likes spaghetti code. Keep it clean, organized, maintainable and scalable. The code should adhere to specific quality standards, we don't want to accumulate technical debt or let bugs creep in unnoticed. Furthermore, when we make changes that could impact performance or costs, we should be open about it.
4. Keeping Costs in Check
Don't break the bank.
Speaking of costs, the financial aspect matters too. If our changes cause a sudden spike in cloud costs, can we still say the code is performing as expected? It's reasonable to assume that the engineering team should have a handle on how their changes affect infrastructure and storage costs.
5. The code is peer-reviewed
Two heads are better than one, right?
No one works in isolation. Peer review plays a vital role in ensuring code quality. Having another team member review code changes helps identify potential bugs, defects, or misunderstandings in requirements or specifications. It's a collaborative effort to maintain code quality.
6. Stakeholder Communication and Clear Documentation
Keep your pals in the loop.
When other teams use our code or the data it creates, they have expectations too. If your changes impact others, give them a heads-up.
And don't forget the user manual – even the coolest gadgets come with a guide. Comprehensive documentation explains how everything works, not just to your team but also to the folks outside. This transparency helps everyone understand what's going on, from developers to managers to end-users.
7. Integration and Testing as a Must
Your code can't be a lone wolf. It needs to play nice with others.
Lastly, code can't operate in isolation. It needs to fit seamlessly with other components. The code should be integrated and all tests should pass before considering it complete. This step is crucial for ensuring everything works together harmoniously.
Example Definition of Done for an Engineering Team
A task is considered "done" when:
- Acceptance Criteria: The code fully satisfies the acceptance criteria outlined in the user story and undergoes comprehensive testing to validate its expected functionality.
- Automated Tests: All automated tests, verifying the acceptance criteria, pass successfully and are stored alongside the code. Performance and stability testing yield satisfactory results, and there are no regressions.
- Compliance Testing: The code is compliant with legal and regulatory requirements. All dependencies and licenses used comply with applicable regulations, such as GDPR, HIPAA, or PCI DSS.
- Testing and Performance: New unit tests are created, all tests are stored in version control, and they must undergo peer review and pass. Performance and stability tests are conducted with positive outcomes.
- Code Style and Peer Review: The code adheres to established style conventions, passes linter pipelines, and is peer-reviewed by at least one team member with no outstanding discussions. A peer review by another engineer is completed.
- Naming Conventions: Object, system, and job names follow established naming conventions.
- Future-Proofing with Monitoring and Alerts: The code is expected to perform as intended in the future, even if requirements change. To ensure this, vital metrics are monitored, and defined alerts promptly notify of any unexpected behavioral changes.
- Ticket Management: Tickets are appropriately updated to reflect their status, with accompanying comments explaining the status choice.
- Documentation: Documentation is created and regularly updated to ensure a clear understanding of expected code behavior.
- Branch Management: The code is merged into the master branch, and feature branches are deleted.
- Deployment: Code is deployed and operational in production environments, not solely on developers' machines. A rollback plan is prepared for high-impact changes. Environment-specific references are verified and updated.
- Stakeholder Awareness: Stakeholders are informed of the code's functionality and potential impacts. Communication is broad and proactive, ensuring affected teams are well-informed.
By adhering to this comprehensive Definition of Done, the engineering team ensures that their code is not only functional and reliable but also adaptable, maintainable, and in alignment with the expectations of teams relying on their code and data.
A Definition of Done is an essential tool for any software development team. It sets clear expectations, reduces ambiguity, and ensures that everyone involved in the project is on the same page.
A good DoD is straightforward and practical, laying out clear requirements that need to be met before a task can be checked off. It empowers teams to “Get shit done”.