Don't Treat Developer Productivity Like A Checklist... Ok, Here's That Checklist.

Don't Treat Developer Productivity Like A Checklist... Ok, Here's That Checklist.

There's no "best practice" that works perfectly in every situation. An organization's unique blend of teams, technology, culture, limits, and goals makes each scenario different. Simply following a checklist of best practices isn't enough. To really benefit from these practices, it's important to understand how they fit together and to think differently about their use cases to get the most value. We ask our teams to experiment with these practices instead of mandating them. This keeps micromanaging at bay and prevents the team from mindlessly continuing unproductive habits. However, we've learned this lesson the hard way more than once.

A Tale Of Caution: The Limits Of Checklists

You can't just tick off items on a checklist and expect everything to fall into place, especially when introducing new practices to a team. It's more about the team's readiness and the conditions you create for success.

We worked with a client to introduce Trunk-Based Development. The idea was to speed things up since their team was getting bogged down waiting days, sometimes over a week, for pull requests to get approved and merged. So, we thought, "Why not try Trunk-Based Development?" It seemed like a great idea to get things moving faster. We introduced Trunk-Based Development as an experiment. Right off the bat, it sped up our lead time. Stories that were lingering in pull requests started moving quicker. But not everything went as smoothly as we hoped.

First off, other teams who also worked on the project weren't comfortable just pushing their code into our repository. It felt odd to them because they didn't "own" the repository. Even when we said, "Hey, it's cool, we can review the code after it's merged," they still hesitated. It was a new way of working, and it just felt weird. Then, we hit another snag with testing. Our snapshot tests were brittle and our integration tests were insufficient. Without these tests working quickly and reliably, developers felt pressured to do more manual testing before pushing their code. It kind of raised the bar for what they felt they needed to do, which made some people really uncomfortable. The reactions within the team were mixed. Some loved the new approach and fully embraced it, but others didn't like it at all. It was clear we needed to work more on our regression tests before we could fully adopt Trunk-Based Development.

This experience taught us a valuable lesson. Implementing a practice like Trunk-Based Development isn't just about deciding to do it and then checking it off a list. You have to consider the team's readiness, the existing infrastructure (like automated testing), and how comfortable everyone is with the change. We had to take a step back and address those foundational issues first. Only then could we think about moving forward with Trunk-Based Development again.

Okay, Now Here's The Checklist...

We put together a list of themes and practices that we commonly see when working with strong software engineering teams. The following examples and themes are inspired by a client team that we led to deliver a two-factor authentication project. For this post, let's call them "Team Gold". This team was exceptional in terms of speed, quality, and efficiency.

Practice #1: Working As A Team, Not A Collection Of Individuals

The first practice we witnessed was their collective approach to working as a team. This is not something we see often. In many teams, we find developers who opt for solitary work, drowning out the world with their headphones and zoning in on their code with tunnel vision. That's not at all how Team Gold operated. They worked together on everything. This looked like them…

  • Breaking down the traditional silos between their roles (such as developers, testers, and designers) to help them have a full view of project development
  • Using pair programming as a default way to work from everyday tasks up to responding to production anomalies
  • Reducing meetings in favor of more time in collaborative sessions to tackle problems together in real-time

Team Gold's collaborative working style allowed them to create an environment of accountability and mutual support. They frequently share knowledge with each other, in turn, helps them maintain consistency in code quality. They even used blameless retrospectives to dissect what went wrong without pointing fingers, focusing instead on what could be improved. Success was achieved through collaboration, not individual effort. By working together, they eliminated the delays that often come from sequential task handoffs, as team members could provide immediate feedback and make decisions on the spot.

What Not To Do

As we mentioned before, what we mostly see within teams are groups of individuals who are hyper-focused on their own work. There is usually a lot of hand-off between product, engineering, code reviewers, and QA. There's also a lot of time spent in meetings planning future work that's sometimes many months out.

This type of specialization-focused approach has many downsides. First, there's a cultural signal stating that collaboration across specializations is only useful when emergencies occur. Collaboration should be continuous, not just a crisis response. Without continuous collaboration, teams are stifled from problem-solving and innovation efforts, which happens when people do not come together to exchange ideas. The cost of working in isolation often leads to the cumbersome task of integrating large chunks of work during crunch times, which is far less efficient than a team that regularly adjusts and refines ideas together. Continuous teamwork simplifies workflows and enhances the overall quality and speed of development.

?Practice #2: Simplifying Architecture And Code

This practice enabled Team Gold to change the software from a 4-pin code to a 6-pin code within a few hours. The system's components relied on durable abstractions instead of implementation details. This change was a simple configuration change in one part of the system. Going from idea to working in production in such a short period of time blew Team Gold's stakeholders' minds. They had never seen a change get implemented that quickly. This change and others were made possible by…

  • Storing all critical authentication rules in one central location allows other systems to verify login legitimacy seamlessly and without complex code navigation.
  • Ensuring their code was easy to modify and extend, allowing the ability to make quick updates like the pin code change without disrupting existing functionalities.
  • Using a queue system to manage login requests efficiently, ensuring that even during high traffic, the system remained stable and responsive.
  • Building with idempotency in mind so they could handle the same request multiple times without error, especially during the rapid rollout of new authentication features.
  • Using reliable integration tests and real-time telemetry to quickly verify the correctness of new changes and monitor their impact.

This isn't just good practice; it's a masterclass in agility, showing that the right foundations can turn even the most daunting updates into a day's work.

What Not To Do

This practice may seem simple enough, but oftentimes teams choose 'easy' over 'simple'. 'Easy' might mean patching together a quick fix that doesn't disrupt the current workflow or hacking a feature into place without considering its future impact on the system.

For example, a team might decide to add new authentication features by patching the existing system instead of redesigning the authentication architecture to accommodate growth and new technologies. Initially, this approach seems to save time and effort. However, it only partially integrates with the existing framework, causing a tangle of dependencies that can muddle data flows and complicate future updates. As these quick fixes pile up, the system becomes a patchwork of short-term solutions that are hard to maintain.

Teams with the mindset of "get the feature I'm working on done" instead of "How can I minimize the future cost of ownership" will just lead to increased technical debt, where the cost of future changes will become much higher. By focusing on simplicity — which often requires more thought and a thorough understanding of both the problem and the broader system — teams can create solutions that are durable. It might take more effort upfront, but it keeps your software strong and flexible, making life easier for everyone in the long run. Aim for lasting solutions, not just instant ones.

Practice #3: Cultivating And Maintaining Stakeholder Relationships

Having close relationships with stakeholders allows both sides to build trust and rapport with the other. Instead of simply receiving requirements, executing, and reporting back with updates, Team Gold would use the same collaborative approach that they used within their own team. With this, we found they were able to…

  • Work closely with stakeholders in daily interactions to ensure that feedback was swift and the project's direction was consistently aligned with their vision.
  • Solve problems, make good decisions, and lead projects because the stakeholders were confident in their ability to get the job done
  • Avoid future misunderstandings and unnecessary rework, making integration smooth by establishing clear API expectations with stakeholders early on.

This open line of communication and mutual trust not only kept the project aligned with stakeholder expectations but also made the entire development process more responsive and efficient.

What Not To Do

Contrast this with teams that engage stakeholders only during sprint reviews or when major issues arise. Such sporadic communication often leads to misaligned objectives, with developers often having to backtrack and redo work that doesn't meet stakeholder expectations. Going this route can turn what should be a collaborative journey into a frustrating series of corrections and compromises that result in shared frustration between the stakeholders and the development team. Instead of setting your team up for frustration with infrequent updates, keep the lines of communication open.

Key Takeaway

Overall, to truly benefit from best practices, you must understand your team's readiness and unique needs. Once you know that information, allow your team to experiment with the different practices and adapt to them as needed. Be more like Team Gold, but understand that getting there will take a while. Many of these best practices are interconnected. Allow your teams to experiment where they're comfortable. Push on them only after you know the required foundation for a practice is there. Treat this checklist like a north star instead of like a traditional checklist.

There are other practices that we did not mention in this article, so if you want to learn more, visit our Best Practice Repository or reach out to us directly. We enjoy having these conversations and sharing our findings.

要查看或添加评论,请登录

Pragmint的更多文章

社区洞察

其他会员也浏览了