This is part 1 of the Disciplined Engineering series. It is for teams that want to establish a culture of engineering excellence for their organization. For teams that already have an established process, we recommend reading Part 2: Creating Code Confidence. If you’re looking to further improve upon your process, please check out Part 3: Refining Your Engineering Process.
Building an Engineering Process
A well-defined process for taking a feature from inception to production is critical for any healthy engineering organization. Teams with well-defined processes are able to write better quality code at a quicker pace and be more flexible and independent.
The first step for many organizations is understanding your current structure and documenting the fundamentals of your process. These processes should be identified and agreed upon by all of the members of your team across engineering and business that have an active role in a project. Once the processes are known, they must get documented and shared among everyone on the team. This gives your team a foundation for building and refining your engineering process and a shared understanding of how everyone contributes to releasing a feature.
Once you understand your current process, you and your team can iterate on it to make improvements and address concerns. Creating this positive feedback loop is the foundation of many engineering processes, from Agile to test-driven development and many others. Feedback loops involve completing some amount of work and then evaluating that work in order to make positive changes. These regular evaluations and minor corrections make significant improvements in the quality and sustainability of your project over the long term.
We’ve helped many teams improve their processes to bring out the best in their organization. Establishing an engineering process within your organization will make your team better able to react to changes, like onboarding a team member or shifting your organization to work from home, because everyone will have well-known, documented ways to produce work. Here are the fundamental practices that we’ve found to help improve the quality of applications and the sustainability of our engineering organization.
The first thing a team should do when building their process is to identify the steps that a feature goes through from inception to production. In Agile parlance, this is often agreeing on the definition of done.
For example, one team may define “done” as a story that has gone through all of these stages:
- The story has been added to the sprint
- Code is complete
- Unit and functional tests have been written and are passing
- Code is reviewed and merged
- Business has reviewed the feature and signed off
- Feature has been slated for release to production
This is not a comprehensive set of instructions for developing a feature. Instead, it provides a basic framework that allows the team to build roles and responsibilities. Now the team can assign people and roles to each step of the process. It will also highlight a number of questions around your process, like, “what does a code review look like?” and “when can stories be added to the sprint?” Answering these questions will inform the rest of your process.
Sprint planning is the first step in any engineering process. It is the first opportunity for the entire team to get together and discuss a planned set of features with engineering and business. By the end of planning, everyone on the team should have a good understanding of the work that will be undertaken during the sprint.
There are a number of steps that need to be taken in order to ensure everyone is able to correctly execute a planned sprint. First, features planned for the sprint should be presented to the rest of the team. Implementers (engineers, designers, QA, etc.) then ask questions to define the scope of the work before assigning a point value to the feature. When sizing stories, it is important to take into account any risk or uncertainty that may be a part of the work. For instance, adding a feature that follows a well-known pattern documented by your organization has inherently less risk (and therefore should have fewer points assigned) than a feature that requires a new or seldom-used approach. Once the work has been sized, the project manager can work with product owners and engineers to assign work to the sprint. The amount of work added to the sprint should roughly equal the number of points completed in previous sprints (i.e. your average velocity) and be agreed upon by the whole team.
After a set of features have been assigned, it should be broken down into smaller steps by engineers and others responsible for completing the work. Each step should encompass a single piece of work that is limited in scope so it can be completed in a reasonable amount of time. The specifics of how this is done and how small each step should be decided by the team. While breaking down tasks, engineers should rely on the team’s documented patterns and prior work to identify tasks that will follow a known path to completion. Any work that doesn’t follow known patterns should include a design phase where the implementer can vet an approach with another team member. This step is critical for identifying the best approach as soon as possible. Teams that skip this step often end up redesigning solutions in code reviews, which has a serious impact on quality, morale, and velocity.
Building Shared Knowledge
Throughout the course of your project, the team is constantly making decisions. For engineers, these decisions are often regarding how to approach solving a particular problem. For instance, a common decision point is often, “how does my team represent a date in the front-end, back-end, and between the two?” Optimally, these important decisions are identified during planning where documented decisions can be referred to as part of the design—undocumented decisions are known risks that must be solved and documented.
Important decisions around reusable patterns or foundation processes should be stored in a prominent and consistent location as a single source of truth. Many teams that don’t write down their common patterns rely too heavily on institutional knowledge that silos and fractures understanding to only a few key contributors (see TalkScript 53: Single Point of Failure for more on this). This forces engineers to make a choice between attending every meeting so they may constantly remain abreast of undocumented information or risk being left behind and producing slow, sub-optimal work. Failing to document shared knowledge also negatively impacts numerous other practices from establishing a consistent velocity to efficiently onboarding a new team member. This is why teams should make it a priority to create and maintain a well-organized, streamlined, central repository of knowledge so that engineers are able to efficiently find and share common patterns and architectural decisions.
Through the course of a sprint, engineers should be documenting their questions and assumptions made during development. New patterns and solutions that emerge should be vetted early with another engineer as a mini-design phase. It should then be the responsibility of both engineers to later share the agreed-upon design and document any patterns that emerge in your team’s central knowledge repository. This will ensure that knowledge is shared among the team and in turn that quality and consistency will be maintained. Teams that make knowledge sharing a priority often see marked improvements in their velocity across all contributors.
A retrospective is an opportunity to iterate and refine your engineering process. Everyone on the team should answer two questions: what worked well and what needs to be improved. The goal of the retrospective is to identify deficits in your process and make changes to guarantee the quality of your application. Therefore is it important to conduct a blameless review. Failures should be looked at as the responsibility of the entire team to refine their process to prevent them from occurring again.
This is also a good time to collect and share metrics with the rest of the team. Metrics should reflect the quality and sustainability of your engineering process. For example, taking the time at the beginning of the retrospective to review how many points were completed compared to average velocity can set the tone for the rest of the discussion. Engineering should also collect and share metrics that reinforce their efforts. For example, if adding unit tests has been an initiative for the team, then sharing branch coverage is an excellent way to highlight engineering’s important investments. Sharing metrics that reflect the quality of the application is important. Without this information, teams often have no information to identify risk until things start to fail.
Creating a good culture that cares about software quality is an admirable goal of any organization. Quality can be achieved through incremental, well-crafted processes supported by all sides of an organization. We’ve touched upon the very basics of building an engineering culture centered around iteration and self-evaluation. Any organization that starts here can build a successful and effective culture of engineering.
You can read more about this topic in Part 2: Refining Your Engineering Process or how to Part 3: Create Code Confidence in your engineering projects. Many times organizations simply don’t have time to address engineering improvements. If you need help, contact us to learn more. We’ve helped numerous organizations refine their processes!