Behold the engineering team at SuperStartupCorp: their steady delivery of features, humble reception of feedback and crafting of well-architected software systems earn them praise up and down the company. The team greatly enjoys working together, and consistently leaves the office feeling accomplished, empowered, and happy.
How is this team able to consistently deliver features for the business, while maintaining morale in a changing sea of fluctuating product requirements, leadership changes, and unplanned site emergencies? It wasn’t always this way.
Read on to learn the first three steps to this team’s journey towards engineering happiness. And don’t forget to read on to Part 2 and Part 3 of this series.
1. They automate the easy things
SuperStartupCorp engineers liked to argue. In fact, their developers would often fight for hours on end over syntax, line lengths, casing styles, and indentation widths. Finally, enough was enough. The team decided to agree on a code style and stick with it, and enforce style automatically via a syntax checking service.
Additionally, the team took advantage of Pull Request-based CI tools to get feedback as early as possible. In their world, when a developer opened a Pull Request to get a feature ready for review, the following services would run:
- CircleCI would run the unit and feature tests
- Code Climate would analyze the build for a style grade
- Hound would scan the build for syntax and style violations
- Heroku would deploy a review application in a sandbox environment
- Github would send a Slack message to the team, notifying folks that there was a need for a reviewer on a pull request.
As a result of style and syntax automation, the team found themselves able to discuss real issues in their code reviews that reflected issues of design, architecture, and control flow rather than argue over insignificant syntactical details. Sandbox deployment allowed designers and product owners to try out new features and make comments quicker about new features in a live application. Immediate Slack notifications helped developers start code reviews as soon as they were available. In the end, the team found themselves delivering features faster because the feedback loop tightened.
2. They codify development practices
In the beginning, the teams within SuperStartupCorp used a patchwork of different working styles across teams. This worked out fine for the first few teams, but as they grew and multiplied and new engineers onboarded into the fold, coordination between them became difficult. Developers became frustrated with inconsistencies between each team: Does this team use TDD (Test-Driven Development)? Where are configuration variables stored? Who is responsible for deploying this code? What is the team’s definition of “done” as it applies to a task?
In fact, many developers became bitter with other developers. Some thought that other developers had a poor sense of code style. Others felt that test coverage was lacking when compared to other teams. Some groups struggled to please their product owners, who felt pressured to push the team to compromise quality for feature development. New developers felt lost and overwhelmed when they onboarded, seeing a myriad of ways of working and not knowing what they should do.
Finally, the engineering group came together and put together an electronic document stating a consistent working style around their group. None of these were negotiable:
- Git was used for source control
- Unit tests were mandatory (within reason, over which they argued at length over what constituted “reasonable”).
- Continuous integration principles were followed, and automated merge tools, staging environments, and feature flags were used.
- Code reviews (via Pull Requests) were mandatory. At least one other team member must approve the PR before merging.
- All applications were to now follow a new microservice architecture developed within the group – certain network request conventions and latency thresholds had to be obeyed.
- A code style guide must be followed (see #1)
There were also looser guidelines for practices that were valued, but not dogmatically enforced:
- Acceptance tests were encouraged, but not required
- Test-Driven Development was preferred, but not required
- Continuous deployment was valued, but not required
- Pair programming was supported, but not required.
Some developers were miffed – they didn’t like the way that they were forced to follow a set of rules or take on practices foreign to them. Product managers and C-suite executives felt a little annoyed that the teams wouldn’t sacrifice any of their practices when they were asked to push toward a deadline.
However, a funny thing happened. Arguments and disagreements from within the group died down. The engineering team became proud of the work that they did, knowing that they were held to high standards of excellence. Product owners noted a decrease in defect rates owing to quality software being written. Developers who initially fought the new rules learned to grow with the constraints, learning that the new process was helpful to their work. Developers were relieved of the burden of attempting to keep the peace between sparring camps. With the “how we work” document, a stake in the ground was set: technical excellence was at the core of SuperStartupCorp’s DNA.
3. They continually sharpen their tools
As an organization
SuperStartupCorp engineers were growing ever more frustrated with their jobs. Because they were beginning to deploy a fancy microservice architecture, they quickly realized that they had no way of running the full stack, or even parts of it, on their local machines. Not being able to test their code locally, they would have to wait until the build server deployed their code to a staging environment after their code merged and moved upstream before they could verify correctness.
Additionally, their build server was unable to deploy their code more than once a day, because jobs took too long to run.
Seeing this, SuperStartupCorp built out a special team of devops engineers who were tasked with the project of solving developer pain. For example, they began to develop a system of packaging up apps as Docker containers to allow developers to run clusters of apps on their local machines.
The team then optimized their build server to scale with cloud provisioning services like ECS and Google Cloud Engine. Moving to Docker also allowed the the developers to abstract away application dependencies on the host OS, allowing easier onboarding for new developers to get a system running.
Jen was hungry to learn. She wanted to level up in her programming skills and learn about new architecture patterns. She also wanted to learn new tools. One day, inspired by hearing Thoughtbot’s Ben Orenstein discussing his philosophy of “sharpening your tools” she decided to implement a new morning routine.
Every morning, when Jen came into work at SuperStartupCorp, she would spend her first 20 minutes building useful tools for her development environment. Over the past few months, she had learned a couple of great Vim shortcuts that helped her move across the screen in a more intuitive manner. She invested time in keeping her dotfiles in source control. She was currently writing a keyboard shortcut that would help her run a code linter on command from within her buffer. Some mornings, she would watch an episode of RubyTapas or read a bit of Sandi Metz’ 99 Bottles of OOP book to keep her programming skills sharp. Each of these tools or learned skills provided her a small productivity improvement that, compounded over the next few years, would pay off in tremendous productivity gains. Her learnings were quickly passed on to her peers, who asked her to do a quick brown-bag lunch talk about her tools — Jen gladly agreed.
That’s it, for now…
This is the first part of a 3-part series outlining practices for healthy engineering teams. If you want to read more, see Part 2 here, or head over to Part 3.
What practices have you found helpful for your team? Let us know in the comments!