I’ve been having a recurring conversation both in and out of the office about what makes a good software developer. This is in the context of people working effectively in commercial software development- so someone getting paid real money to build a software system as part of a larger professional team- not what makes someone able to write software in general.
There are multiple roles that come into play in a software development team which I view as separate axes.
The first axis is the individual contributor role. Being able to look at a feature request, think about it in the context of the system you’re working on, and come up with an implementation plan to make these work together. Often times this includes asking lots of questions to clarify the requirement or gather testing data. Once you start developing you need to be able to effectively communicate any questions or problems that come up along the way. Being responsible for a feature-level unit of work, where you can be relied upon to get that work done well and on schedule without outside supervision, is the sign of high capability on this axis.
The second axis is the architect role. This is taking a high level business or technical requirement and coming up with a feature set that can address it in the larger system. A high level requirement here might be “we need a way to manage users”. The architect then might break that down into the new data that needs to be captured, the new UI and workflows required to use and manage it, and the impacts this has on existing UI, workflows, or data access. This involves understanding the high level requirement and the system under work to a deep extent, so that what gets built actually addresses the former and works fully within the latter. The design that the architect creates can be different from that of the individual contributor because of the scope being considered. The individual contributor needs to find a way to implement a solution that has the least impact to other components of the system under work. The architect needs to consider whether the system as a whole needs to change to address the requirement. Having detailed knowledge of the system as a whole as well as being able to understand, communicate, and negotiate the tradeoffs of different high level approaches are the signs of high capability on this axis.
Axis three is the team lead role. This is breaking down the features into addressable tasks for a team, and monitoring and managing the team’s work implementing these tasks. This can include some straight-up management, but talking about that is another topic entirely so I’ll put it aside. What I want to focus on is being the technical owner for a product or component. The most important part of this role is being responsible to the business for making a commitment and meeting it. This means understanding the system and the team well enough to know what is a reasonable estimate for any specific feature for any specific developer, being able to track how the work progresses and know if there’s going to be a schedule problem, and work with the business to get this resolved.
The root of many team problems I’ve seen is that these three axes, each of which need a different viewpoint and skillset, are seen by many developers as normal career progression. While these axes usually map to the org chart in a dev organization, that doesn’t mean that it’s a progression for everyone. Not everyone who is a competent individual contributor can make the transition to an architect. The focus on the big picture of a product can be challenging to someone used to focusing on a single component at a time. I have seen many cases where there is a desire to exert the big picture responsibility in ways that conflict with business goals. The desire is to build something the right way, but that can quickly shift into overbuilding the system, spending extra time to rebuild features or components which were already working fine in order to fit in with the new architecture. When building a single feature it is important to have everything logically work together as part of a whole, but when working on the architecture of a complex existing system that is not always possible. Getting caught up in trying to make a whole system consistent in the same way that a feature must be can cause problems to someone trying to apply the same standards between the individual contributor and architect roles.
While both of those roles have a basic technical component, the team lead role goes in a completely different direction. This is about working with people and being able to have high level responsibility instead of the low level responsibility of the individual contributor. The skills used as a team lead are very different than those used by an individual contributor. Tracking schedules is very important. Being able to help clear obstacles without micromanaging can be a real challenge to someone who is used to being an individual contributor.
Now that I’ve defined these roles I’ll say that most of the problems I’ve seen managing development teams relate to movement between these roles. It may be that the individual contributor has trouble translating a product-level feature description into a detailed feature set- so the architecture they come up with doesn’t result in a solution that meets the original goal. It may be that paying attention to feature progress on a sub-daily level competing for attention with implementing individual features causes both to happen badly. Probably the most common problem I’ve seen is when an individual contributor takes on one of the other roles but wants to have the same low-level responsibility for all the features the team is working on that they’d have as individual contributor. This kind of micromanagement makes everyone unhappy. The other developers on the team don’t have freedom to use their own creativity, and the lead is basically doing the job of all of their team members. This situation doesn’t last for long- either the new team lead burns out, the micromanaged developers leave, or (in the best cases) the new lead realizes what they’re doing wrong and gives up direct implementation control of the other devs’ features.
From the management side there are some best practices that work well to ensure that someone making the transition between roles does so successfully. These are fundamental for any transition. Give the person making the transition an example, either in the form of a mentor who’s been through this transition themselves or a current successful holder of the role. Let them move into the new role in small steps so that they can get experience and guidance along the way. Kick off and post-mortem the first few cases of a new responsibility to make sure that both the manager and employee agree on what went right and wrong.
It’s important for developers to keep in mind that you can be an excellent individual contributor but not so good at the other roles. Particularly with the team lead role, the way you focus your attention is completely different. Many devs find this uncomfortable. You can be a very successful software developer without stepping out of the individual contributor role. It’s very important when you’re changing roles to pay very close attention (and be very honest with yourself) about your performance. It’s much better for you in the long run to recognize ways in which you’re not excelling and figure out how to improve in those areas.
Especially when working in a startup environment it may be that it’s impossible to find an ideal balance of these different roles into one person’s actual responsibilities. It’s important to have clear responsibility both within and outside of an engineering organization, and sometimes that means that one person needs to take all three roles or only one of them. In that case, it’s very important to have a clear view of your own strengths and weaknesses. It’s much better to say “I’m not ready to take on all of these” or “there are still places where I need to improve” and step back to an individual contributor role where you can excel, than to fight to take on or keep all of the responsibility and only perform adequately. This can be a hard decision but it shows that you have a clear view of how you’re performing and that you truly value the success of the team. It also shows that you can be honest even when it’s not in your favor, which is a great sign of your trustworthiness.
In the best teams that I’ve worked with there have been great individual contributors who are motivated for the team to be successful and not hung up on who plays what role or holds what title. They may have the skills to be an architect for certain parts of the system- and act as an architect when needed- but fill the daily role of individual contributor. Likewise developers who have previously worked as team leads understand what’s necessary for the team to work smoothly and take care of that themselves. A high functioning team like this is a joy to work with.