Bring Back Specialization
I’ve looked at a lot of software developer job postings recently, and one thing has become very clear to me: modern developers are supposed to be jacks-of-all-trades. For example, it has become quite common to abolish the separation between frontend and backend developers, so instead of just needing to know one of these things, it’s now often expected that we know both. To make things worse, both frontend and backend development have been getting increasingly complicated over the last fifteen years. In the frontend, we’ve seen the emergence of more and more complicated frameworks and metaframeworks combined with elaborate build processes and involved deployment techniques. In the backend, things are more grounded but also far from ideal. In addition to some backend programming language, backend developers are also expected to work with all kinds of databases, message queues, caching services, API protocols, and authentication methods. This is such an issue that I’ve already seen satirical tweets on the subject.
To make things worse, thanks to the DevOps movement, operation work was partially offloaded to software engineers. While the idea of a closer cooperation between developers and operators sounds good on paper, in practice it has many problems, as Cory O’Daniel has outlined in his famous “DevOps is Bullshit” article. For the context of this post, the important thing about DevOps is that it increases the amount of things developers need to know even further. They need to figure out how to deploy to production and how to monitor the current state. This doesn’t sound terribly difficult at first, until we remember that the days of deploying with a simple bash script are long gone. Software systems are much more distributed today, so there is often an elaborated order in which different parts of the system need to be deployed after a change. But wait, isn’t that what tools like Kubernetes are supposed to help us with? Yes, but that also means that we now need to understand Kubernetes and its implications on our application design. That’s no easy task, as even Google has admitted.
Things get even more challenging when we consider the cloud. Cloud providers like AWS offer a dazzling amount of different services. As of 2020, AWS offers more than 200 products and services, and I’m sure the number is even higher by now. We usually need to combine several of these services to get the desired outcome. Understanding what services are best for our use case, how we should combine them, how any future changes might affect us, and, most important of all, how much money this is going to cost us is quite a challenge. And while we figure that out, we also need to design our deployment pipelines to automate everything and describe the infrastructure in code.
And there is one more thing: testing. Manual testing was largely replaced with automated testing. While this is a good thing for routine tests, it’s not great for specialized testing. Being good at testing software and being good at developing it are two very different skill sets. A great software tester might find exotic bugs that we’d never catch with automated tests. Sadly, these roles have largely disappeared. Granted, highly directed testing via test cases was always a waste of time, money, and energy, but just getting rid of testers entirely is a step too far.
All in all, a developer’s job has become a lot broader over the last fifteen years, and I think this is a problem. There is a limit to the amount of knowledge we can realistically acquire. By increasing the number of things we need to know something about, we limit our capacity for deep and specialized knowledge. This problem is made worse by the incredible capabilities of modern software. A tool like Kubernetes or a message broker like Kafka are very powerful tools that require a lot of time to understand in their entirety. As time is limited, most developers just learn the parts that they need in their daily work. Rather than actually specializing in something, we acquire tiny, specialized pieces of a dozen different things. We end up as jacks-of-all-trades, but also as masters of none.
While this generalist approach can take us very far, it clearly has limits. In some situations, we will require deeper knowledge, knowledge that we most likely won’t have at hand, as we never bothered to learn it. Specialization has value, which is clearly visible in other jobs. For example, when we need heart surgery, we want to go to a specialist instead of just any surgeon. So, why don’t we apply the same logic to software development and let a backend engineer get really good at building backends? The only explanation I have for this trend is that generalist software developers are very convenient for management. With lots of generalists, managers can just exchange developers at will without having to worry about whether they have the right skill set. While I can see the appeal, I highly doubt that this strategy produces great results in the long run.
The bottom line is, if we want excellence, we need specialization. I think we should bring it back into software development. Let people play to their strengths rather than burdening them with a lot of other additional tasks where they will be mediocre at best.
Conclusion
Software developers need to be generalists today, as this is what the market demands. However, this produces subpar results, as specialization is needed for excellence. We should revisit the way we distribute tasks in software development and let people play to their strengths.
If you liked this blog post, please share it with somebody. You can also follow me on Twitter/X.