As I live my life as a programmer, I often wonder where I stand. To be honest, I still can’t clearly define my own level. It’s not like a standardized test where you get a definite score. But I believe I can talk about what makes a good programmer or even an S-level one. Likewise, I think I can describe what a C-level programmer is.
A good programmer writes good code. While the definition of “good code” can vary slightly, there are universally accepted traits. The first is readability. Though it may sound vague, good code is easy to read. Even a highly complex algorithm can be written in a way that’s easy to understand, while a simple feature might be expressed in confusing code. Good code is easy to follow and comprehend, regardless of how complex the process behind it might be.
Code readability isn’t just about writing style; it’s also heavily influenced by patterns. Every company—large or small—has some form of a code style guide. If it doesn’t, it likely isn’t mature enough to discuss code quality seriously. Writing maintainable code within a unified style is a key trait of a good programmer. On the other hand, someone who disregards style guides or whose code patterns change constantly can be hard to work with.
The second important trait is growth. The world of programming evolves slowly yet rapidly. While some companies focus on legacy technologies, many adopt new and trending ones. A programmer who can’t keep up with these trends is unlikely to be considered outstanding. Failure to adapt to new frameworks increases the chances of one’s skills—and eventually oneself—being replaced.
Growth is a trait many companies seek, but it’s tricky to measure. A portfolio of projects might serve as an objective indicator, but for those already working, growth isn’t always visible. Most developers spend their time reinforcing what they already know rather than exploring new areas. That’s why growing as a programmer is easier said than done—and hard to measure quantitatively.
From what I’ve observed, the difference in growth over time is closely tied to one’s practical understanding of technology. Developers who have grown rapidly, especially in big companies, are rarely out of touch with current technologies. These people—who often fall into the S-level category—are usually engaged with the latest tech in some way: writing, participating in open source, or testing new tools in their companies.
Growth also directly relates to a programmer’s curiosity. Some developers treat programming as a hobby; others don’t. Those who treat it as a hobby naturally explore new technologies and take on side projects, gaining experience over time. These small differences eventually determine whether one understands modern tech trends or not.
For example, someone who’s new to web development or only familiar with older frameworks might not see the value of GraphQL. They might struggle to explain the difference between Django and Express or weigh the pros and cons of Google Cloud vs AWS. Perhaps this is already veering into S-level territory. That said, I didn’t intend to clearly separate good programmers from S-level ones—after all, S-level programmers possess all the qualities of a good programmer and more.
So then, what is a C-level programmer? If we think in terms of grades, they are average or below. To sum it up in one sentence: they don’t truly understand their weaknesses. They might think their code is readable when it’s not. But why does this happen? Because writing good code isn’t just about your own perspective. You need to read others’ code, too. There are better algorithms and design patterns out there than you might realize. Without self-awareness, it’s hard to objectively assess your code quality—and as a result, they often produce poor code.
This may not be a big issue in small projects. But once a project grows in complexity—accumulating legacy code, constant changes, and shifting architectures—that’s when the difference shows. Clear code is easy to maintain and instantly recognizable as well-written. Conversely, some code is so messy that even the original author can’t understand it. If someone can’t read their own code, can they really be called a good programmer?
Another trait that separates average from great is documentation. Code is the translation of thought into a language a computer can understand. While code contains intention, that intention doesn’t always translate clearly to others—or even to your future self. That’s why documenting your code is essential. This can take the form of inline comments or separate documentation. Personally, I use spreadsheets to jot down important parameters and purposes. It takes extra time but greatly aids collaboration and maintenance.
Equally important as documentation is logging. A good system isn’t one without errors, but one that tracks and responds to them effectively. The worst systems are those where errors occur but you have no clue where or why. Logging helps build system reliability and enables quick issue resolution. Logs related to user behavior or traffic can also feed into marketing insights, UI/UX improvements, and overall product quality.
If you care about these things and understand how to format and use this data properly, you can make huge contributions to product stability and improvement. This is the difference between just being a developer and being someone who elevates the product. Writing the code for logs or metrics might be simple—but effectively using them requires a systems-thinking mindset.
When I taught programming at university and observed computer science majors, I was often surprised by how passive their approach was. To me, programming wasn’t an academic subject—I saw it as a tool for realizing my passions and interests. But some students treated it like a subject they didn’t want to study. One piece of evidence was the number of side projects they had.
Every excellent programmer I’ve met has a wealth of project experience. Whether personal or collaborative, they spent their free time building or contributing to projects that advanced their careers and skills. On the other hand, average or passive programmers lacked these experiences. Their portfolios consisted only of school assignments, and their best app might have been something they did for homework.
Can someone who doesn’t apply their skills ever become the best? Can they lead the industry? Most likely not. They will always be followers. Leaders are always in the minority. Not everyone can be exceptional. Whether we like it or not, most people are average or close to average. That’s why, if you’re not already great, it’s better to consider yourself C-level or below—it helps fuel growth.
I consider myself a C-level programmer. Not because I fail to meet all the traits above—many of them, I practice. But I can’t confidently say I’m better than others. The gap between me and truly top-tier programmers feels too wide. Even if I might technically fall into the A or B category, I’d rather think of myself as C-level and continue to improve.
Lastly, I want to leave you with this thought: it’s hard to distinguish between a good and a C-level programmer from the outside. But truly exceptional programmers stand out instantly. Even if they downplay their abilities, others will call them S-level. You don’t need to obsess over rankings. But for me, I refuse to live as just another average guy in this field. I want to grow what I’m good at and live as an S-level programmer.