Introduction
Starting fresh can be - pardon my silly pun - refreshing. Being part of a greenfield project from the very beginning, especially when you undertake a leading role within it, can be a source of motivation, coupled with a promise that you are going to do things "the right way", at least this time. You are rarely alone, however. After all, this isn't only about you, but rather you and your team. Now, how would you manage bringing your team members onto the same page as you?
Okay - perhaps starting fresh can appear daunting at times. My experience as a CTO at a small start-up has proven to me that, just by sharing your motivation or spreading your enthusiasm amongst the members of your team, it isn't enough to make things fall into place. Instead, it's always about fostering an engineering culture coupled with the right agreements and clear expectations and vision.
By the way, this article turned out to be a lengthy essay on a topic that's already very broad, therefore if you are scrolling in a rush, I am outlining the TL;DR version (sort of like a list of action points) for your to consider below:
- Level with your team, know their strengths and weaknesses, clarify responsibilities but foster cross-domain awareness and communication at the same time.
- Help people grow. The motivation to grow will spread from those who are passionate to those who might appear less inclined at first. Enable them to band together (i.e. form a guild) and to channel their efforts into innovative and productive changes to your project or product.
- “Broadcast” your work, successes, failures and overall learnings. Let people know.
- Make sure to align on seemingly common terms. For example, when is "done" actually done? When are we ready to ship to production?
- Practice your guesstimates on the time it takes to complete tasks, no matter their complexity. You’ll get better at it eventually.
- Set the stage for working with code and align on branching strategies, pull request reviews, ..., etc.
- Don't stop improving developer experience: developer productivity is something to strive for!
- Rotate pagerduty or tasks with considerable responsibility. Everyone should feel equally competent to respond to business-critical tasks.
Enable communication across roles and beyond ownership and fixed responsibilities
Perhaps you are part of a team where people tightly fit a job description, and they are willing to grow within their predetermined roles. On the other hand, you might work with a group of "jack of all trades" or generalists that might require some guidance so that they can shift their focus and allocate their energy appropriately. Alternatively, your team could very well be an exotic mix of both aforementioned groups.
In any case, there's a baseline of responsibilities that everyone shares, no matter their assigned role. For example, if you discover a bug on an API, you wouldn't shrug it off simply because the feature you are developing on the mobile app is not affected by it. Similarly, you wouldn't just develop a backend based off of a spec sheet without pursuing a deeper understanding of the purpose and value the project or product brings to the table. Therefore, beyond clarifying the main area of focus for each member, related to their unique skillsets and desired trajectory of growth, it's important to acknowledge that, more often than not, people make mistakes and supporting one another can prevent disasters down the line. Remember that, product owners and stakeholders make mistakes too.
Furthermore, depending on your team's composition and delivery roadmap, pressure could concentrate on a subset of your team at a given time. In theory, that pressure could be alleviated by spreading tasks more evenly across the team, considering people are flexible and willing to allocate their focus on a new programming language, service or domain. Understandably, such an action plan could pose a mental overload risk for those who are switching to a different context, and this can drag many more side effects along with it: an increase in alignment meetings, more technical debt, ..., etc.
Therefore, you - as a technical leader - cannot plan in isolation and come up with something that instructs person A to switch from X to Y, person B from Z to Y, and so on, simply because it seems reasonable on paper. You must account for and count on your team's input to land on a plausible plan together. Now, most importantly, your team won't be able to know or provide genuine feedback, unless:
- They are enabled to communicate and share knowledge - avoid working in silos!
- They are encouraged to ask questions on every level. Just because a senior team member “said so”, that doesn't mean there are no alternatives or room for compromises or improvements.
- They have a high-level understanding of everyone's responsibilities and where you are all headed towards as a team
In short, maybe person A working on the frontend has a fantastic idea to drive user engagement that will take less effort than the complex plan you and your stakeholders came up with . On the other hand, person B could take up some of the workload for writing and extending the API documentation if they feel that the backend team is going through a tough week. Better yet, person B might discover a cool library for generating API docs from source code automatically.
Invest in people's desire to improve
Nowadays, tech professionals are playing cat and mouse with technology, given the pace of progress (measured in new JavaScript frameworks per day) and the rate at which (critical) vulnerabilities pop up that need to be patched. The more friction we generate with an increasing number of tools, libraries and patterns, the more we tend to forget the terrible code we wrote a while back - until git-blame names and shames us. Alright, such concentration of satire in one paragraph constitutes an anomaly for this article - allow me to pull a mental hand-break and redirect my train of thought to the core of what I am trying to explain.
Some do it for the money, others because it's their passion; we do what we do because of an ultimate goal - or so we tend to think sometimes. However, things are not always black or white. No matter if you strictly work a typical 9-5 while doing nothing that is related to your field outside of that, or - the other way around - the typical 9-5 just so happens to occur while you are exercising your passion, you want to be better. Perhaps you are after a minuscule amount of "better", just enough to overcome some slight hurdles, or a giant leap of progress that will make you stand out.
Now that we have established that some desire of betterment is there in all of us, let's talk about...the middle ages! Guilds, in particular, "[...] an association of artisans and merchants who oversee the practice of their craft/trade in a particular area." I guess it's easy to spot who the artisans are in this parallelism. Of course, the concept of "guilds" is not exclusive to middle aged artisans or merchants. Spotify has integrated it deeply into their model, where they define guilds - among other concepts - as "[...] a community of interest".
The idea behind encouraging your team members to form even smaller teams with a common interest and goal is to enable them to keep up with the progress in technology, exchange opinions on new patterns and solutions, and propose or evaluate changes to the codebase. Perhaps this sounds like extra work, which won't immediately add value to your product. However, overtime, as you and your team face new challenges, guilds can accommodate fertile ground for engaging developers in a productive way which can even help drive innovation within the corresponding vertical of your product. Ultimately, people should use their time effectively and efficiently, while maintaining the sense of fulfillment and growth that will keep them going.
Show off early, show off often
Don't get me wrong; by “showing off” I mean presenting your work to others, highlighting your successes in addition to your mistakes and learnings. This contributes to building and maintaining an insightful and effective awareness-level for everyone in the team.
I was once part of a cross-functional team responsible for an internal tool that handled the dispatching of drivers. During a company biweekly meeting, with most teams present, the customer support department presented an overview of their KPIs, successes and pain points. The information they shared got us thinking about our next steps with the tool. Admittedly, we had a product owner in place at the time, who escalated and served requests from other departments to us, however, being able to get the information first-hand from the people that can explain it best was a very effective way, which sparked our interest and we were able to assess and prioritize a feature in our internal tool that would greatly improve the customer department's workflow.
Based on my experience, although it may seem inefficient, bringing teams and departments together to talk and show off their work enables teams to understand better of the common goal, mission and vision of the company. You can dedicate a meeting every two weeks where everyone from your team shows off their progress or their learnings from their mistakes.
Clarify when "done" is actually done
"It's done, but..." - I am sure we hear or say that a lot when working with others. Developing software is a little like cooking: everyone has different perspectives (in addition to tolerances and tastes) on when something is "done". Think about all the "doneness" levels of a stake or the crust of a pizza dough. In a similar fashion, considering agile methodology's feedback loop, if we would think of our software product as a loaf of bread, imagine that, one end of that bread is in the mouths of our users and the other one is dough that we nit, while everything in between is being baked at different temperatures, all at the same time.
Therefore, given that we are working in a team setting, we should have a common understanding about the state of our product that reaches the end users. Ask yourself and your team the following:
- What is the happy path? What are the acceptance criteria for that path?
- What are the "nice-to-haves"? How can we make the happy path leaner, so that we can get our first release out early?
- What are the edge cases we want to cover in a follow-up release?
- What is the test coverage we are looking for (unit tests)?
- If it's about a frontend deliverable, and a designer is involved, has the implementation been reviewed by them?
- Is integration testing needed? Has it been implemented?
- Has the release been reviewed by a stakeholder on an integration environment?
However, the definition of "done" does not only regard features in the software product; it also concerns the vision, goal and instructions (a.k.a requirements, spec sheet, designs, ..., etc.) that will be used and understood by the designers or developers that will bring said feature into fruition. During the implementation phase, a vague scope will cause a lot of back-and-forth, which can certainly slow the team's pace dramatically and probably cause some technical debt as well. Therefore, this begs the following questions:
- Is the business goal and overall vision clear to the people involved?
- Are the acceptance criteria and requirements clear? Have they been reviewed by the team?
- Are the designs ready? Are they pixel-perfect? Are wireframes enough?
- Are the estimates on par with the delivery roadmap of everyone involved?
After setting clear expectations with your team on the definition of "done", they will use that word with confidence when talking in daily meetings or coordinating their work with others.
Talk openly about your time estimates and deadlines
Time estimation is one of the biggest challenges in our domain. Some teams resort to using T-shirt sizes or the Fibonacci sequence as a scale to express complexity of tasks instead, while completely eclipsing pure time estimates. Nonetheless, deadlines need to be there so that we can communicate progress to the outside world.
In certain cases, your team members might give their time estimate in completing a task, while they are only focusing on how long it takes them to write the corresponding code. However, certain processes should usually be accounted for:
- Communicating with other teams their feature depends on (for example, a team that's responsible for a backend API)
- Reviewing UI implementations with designers or the QA team finding bugs in the deliverable. Adequate time needs to be planned for solving such issues
Having clear communication on the estimates from each team (think of it as having "soft" deadlines), while, at the same time maintaining hard deadlines with adequate buffer time before the deliverable is passed on the hands of real customers, is a good compromise between internal and external expectations. The rule of thumb still applies here: under-promise and overdeliver.
Align on how to best contribute code
We talked already about clarifying roles and, in your daily process, you and your team will ultimately figure out and pick up tasks to work on. Given that software engineers have their own process for writing code, with distinct implementations and styles, while also different approaches in reviewing and merging code, some alignment in that regard is warranted.
I am not going to go too technical here, therefore, consider the following points:
- What is your repository strategy? Mono- or multi-repo?
- What is your branching strategy? Is it perhaps more of a trunk-based development approach?
- What is your commit message style? Should you use semantic commits?
- Should every pull request (PR) be reviewed? If so, how many "eyes" should be on that PR?
- How do you handle hotfixes?
- Should you automate patch updates for your application's dependencies?
In my opinion, such agreements constitute the cornerstone in your engineering culture. You may also discuss how to bypass certain agreements in periods of pressure, in addition to having a plan to later remedy the side-effects of doing so.
Improve developer experience
Beyond user experience (UX), you should care about developer experience (DX) too. From my experience, DX and UX form a symbiotic relationship in the long run. Ultimately, happy developers deliver great software.
Think about the following points:
- What's your process for releasing a new version? Are there any manual and error prone actions involved? At best, you should have a CI/CD pipeline set up for that.
- Are APIs and SDKs clearly documented? Or is there a lot of guesswork involved?
- Are roles and permissions for services and systems configured and attributed accordingly? Perhaps there's a communication barrier a team member must overcome each time they want to spin up a test service or instance?
Similar to reaching good understanding when contributing code together as a team, good DX is a very important part of your engineering culture: it will boost the team's productivity, sense of ownership and overall impact.
Conclusion
I hope you find this article as a source of inspiration for improving your teamwork. Admittedly, this wasn't meant to be an exhaustive list of action points, rather a collection of topics that, based on my experience, should be high on a technical leader's priority list. You may be part of a team with highly specialized roles, such are the roles of agile coach or developer experience engineer, whose daily job would be to tackle and dive deeper into some of the points we surfaced here. Nonetheless, it’s good to have an overview, even if you are not starting fresh, perhaps this article will help you consider whether some processes can be added or optimized to improve your teamwork.