The craft of creating software is, of course, more than the code itself. In general, producing software includes a good amount of problem-solving and system thinking, but also requires a strong sense of quality to create software that not only executes but also performs its job well and reliably and, if required, can be consistently used by its target audience or the target system.
To produce great software, one needs a good balance of coding, programming, and software engineering skills. Throughout my career, I have met great programmers who were terrible coders: they were good at identifying and tackling the problem at hand and defining its boundaries and building blocks, but the code they produced was below par; untidy, unstructured, rich in anti-patterns and a nightmare to follow and maintain.
I’ve also met great coders who were terrible programmers. With no strong sense of architecture and structure, they would put all their attention on behavior and produce spaghetti code in as few source files as possible, lacking all structure while using the most obscure and advanced features of the language they could find, creating impressive syntax that would make you question your own skills as a coder as you would see them using artifacts you didn’t even know were allowed. For them, the focus tends to be on what the language can give more than the problem to solve. Both coders and programmers hate dependencies and actively try to produce software that is as self-contained as possible, which eases the compilation process.
In general, natural-born coders and programmers are not customer-oriented. Therefore, they are good at producing software for their own consumption or very technical users. Also, they tend to despise fads and fashions and at times be so future-proof that work might take twice the time to account for scenarios with a 0.01% probability of happening.
Lastly, software engineers come along. A software engineer tries to treat software as something that can be delivered—a product—hence caring about things like testing, automation, documentation, UX, quality assurance, and whatnot. I’ve met great software engineers who were terrible at coding and programming, but they were still instrumental for team success. Sure thing: Software engineers have a higher tendency to embrace fads and vapid methodologies and are more comfortable with third-party dependencies and vendor lock-in.
All in all, the skills associated with coding, programming, and software engineering can vary widely among individuals. This creates a spectrum of different combinations of these skills and what they might look like in practice. Let’s discuss them a bit more.
Good Coder, Bad Programmer
Excellent at writing clean, efficient code. Great understanding of syntax and language-specific features. Can be good in roles that require writing small, isolated pieces of code or maintaining existing legacy codebases. They will lecture you on the beauties of FORTRAN or Small Talk and how the world has lost its way since we moved from those languages.
This flavor struggles with broader software development tasks such as designing architectures, managing projects, and integrating components. May have difficulty understanding or implementing higher-level concepts like design patterns or software testing.
May also struggle in roles that require developing larger systems, leading teams, or ensuring the overall integrity and maintainability of a software project.
Best used when working as a developer in a large team where their primary responsibility is to implement specific features or fix bugs.
Good Software Engineer, Bad Programmer
Excellent at system design, requirements analysis, project management, and ensuring software quality. Strong understanding of software development processes and methodologies. Can lead and ensure projects meet quality standards. Good at coordinating and managing complex projects.
On the bad side, they might struggle with writing code, debugging elusive bugs, and implementing detailed algorithms. May rely heavily on others for actual coding tasks. May produce low-quality code when required to write it themselves.
Best used when working as a project manager, focusing on high-level design and coordination, while delegating coding tasks to skilled programmers.
Good Programmer, Bad Coder
Strong at designing and integrating software components, refactoring, understanding algorithms and data structures, and ensuring functional correctness. Good at problem-solving and debugging obscure bugs and glitches.
On the downside, they might write inefficient code, struggle with syntax, and may pay poor attention to detail in code implementation. May produce code that needs significant revision and optimization, potentially slowing down development and causing frustration for other team members. May produce code that is not customer-ready.
Can be effective in roles that require system design and integration, as long as they have support for the actual coding tasks. Works well in a collaborative environment where their design and problem-solving skills are leveraged, and their coding tasks are reviewed and optimized by peers.
Good Software Engineer, Good Programmer, Poor Coder
Excellent at system design, project management, and integrating components. Strong problem-solving skills and understanding of software development principles. Cares about user experience, and can effectively manage and design complex software systems, as long as they have a team to handle the detailed coding tasks.
Struggles with writing detailed code and may use naive syntax. May struggle in roles that require both high-level design and detailed coding without support.
Works well when leading a development team, focusing on design and integration, while delegating detailed tasks to team members with strong coding skills.
Bad Coder, Bad Programmer, Bad Software Engineer
Well, the jackpot of the bad stuff. They are in the software domain for reasons beyond them, with nepotism and cronyism being the most typical reasons why they are around. Struggling with everything, they slow the team down and produce things that most of the time need to be rewritten by someone else.
The Holy Grail: Good at Everything
Good at coding, programming, and software engineering. Can handle detailed coding tasks, can design systems, can think both structure and behavior and manage projects effectively.
May not be a specialist in any single area, but rather a generalist with well-rounded skills. Highly versatile and valuable in a variety of roles, capable of handling different aspects of software development. Can adapt to changing project needs.
A potential downside is that they may not have deep expertise in a specific area, which could be a disadvantage in specialized roles requiring in-depth knowledge.
Works effectively in both small and large teams, taking on different roles as needed, from detailed coding to high-level design and project management.
When planning large software projects, we don’t discuss enough that we might have a rich variety of types across our pool of resources.
For the record, I consider myself a good programmer, but a mediocre/naive coder and an average software engineer.
###