IMO what makes a great programmer is leverage and leadership. It doesn't really matter if you're a rockstar "10x" etc., what matters is how your work empowers others. Nobody is programming in a vacuum.
In order to become great at that, you have to make enough mistakes that affect other people until you understand what helps and what hinders them. You have to realize that your code isn't just implementation but is human-oriented communication, and tools are part of the puzzle.
The more your work hinders others, and the more you are forced to deal with the consequences of it, the more you will learn what helps and facilitates others.
You can also learn some of this by using and suffering from other people's bad work, as long as you don't allow it to make you complacent.
Finally, you need to have humility. Nobody who thinks they're great is going to be truly great. You need to recognize how you suck and how to suck less. "Take the log out of your own eye so that you can see clearly to take the speck of dust out of your brother's eye."
> IMO what makes a great programmer is leverage and leadership. It doesn't really matter if you're a rockstar "10x" etc., what matters is how your work empowers others. Nobody is programming in a vacuum.
Nah. There are those types of folks, but there are other folks who are clearly above the rest in terms of technical ability. See John Carmack, Sanfilippo (of Redis fame), 100s of others. Or heck even folks who deeply understand the entire stack like Casey Muratori.
To act like there aren't folks who are "rockstars" or simply better software engineers, and at some point it boils down to soft skills, impact and leverage is corporate bullshit. There ARE people who are simply more technically gifted.
The OP didn’t ask about how to become a staff engineer, they asked how to become a great programmer. Those are not the same thing.
This. If the personalities you mentioned didn't have the soft skills GP was talking about, you wouldn't even know of their existence.
Sheer technical ability alone is not enough to be a great programmer. If you don't know how to properly communicate with others you are useless to your employer.
They are rockstarts because they have technical skills AND soft skills.
Sure, John Carmack was a technical beast when it came to computer graphics.
But one can't work for Facebook/Meta from 2013 to 2019 (and as a consultant until 2022) without soft skills.
John Carmack can have all the soft skills in the world. If he wasn't technically credible, it does not matter. This topic is about how to get that level of technical proficiency, how to become a great programmer.
Jumping in and telling folks to be a great communicator or tech lead instead is not the way to become a great programmer. That's the way to become a great staff engineer. They're not the same things.
The point is that Carmack's work was extremely influential. That wouldn't have been true if he wasn't technically great, but technically great work can fail to have any influence whatsoever. Which is greater?
You keep repeating the same idea: they're a great programmer because they're influential. You seem to be missing the point everyone else is trying to make: being a great programmer has nothing to do with being influential. Lisp is a great programming language, yet very few people use it. C++ and Javascript? Practically viruses, but every browser relies on them.
Yes, it's true that many great programmers are also highly influential. But Linus was a git (his word, not mine). He isn't influential because of soft skills, it's because he was already a great programmer.
Because we’ve seen the technical artifacts? For example, they released their work open source and we saw the quality. What’s your point here? Redis, when released, was a single person effort, for example.
Maybe it depends on how you quantify greatness. I think that if you're really good at writing a fast matrix kernel, that's lovely, but if you're really good at making a matrix kernel which is very useful to lots of people, or even just to your team or company, _that's_ great.
I still don't consider myself 'great', although I know I'm better than most. What got me to where I am is a combination of "time in seat", "variety of work", "continually challenging myself" and "being curious".
As others have said, as you gain more experience, your greatest impact will shift from your individual contribution to your ability to grow and guide teams of people.
To be able to do that effectively, you've probably had a variety of experience. You've seen things done well, and also been involved in enough mistakes to understand where the dragons lie. You've been responsible for greenfield delivery, modeling multiple business domains, have worked on codebases that resemble modular monoliths as well as microservices and can confidently explain the potential benefits and pitfalls of each. You've read a lot, kept up with changes in the field. You read other people's code, especially well written open source stuff. You probably contribute to some open source stuff too. You actively solicit feedback on your own code and don't take criticism personally. You've seen testing done well, and testing done badly. You've studied different programming paradigms and languages and become experienced enough in each to be able to make good decisions about where to use them (and where not to). You've worked with multiple different frameworks over 10s of years and can see the differences, but also the commonalities between them. You learn how to decouple your core code as much as possible from things that are subject to change on a whim. Your curiosity over your career means you have picked up adjacent knowledge; business domain knowledge being particularly valuable, but also things like an understanding of the full stack - networking, security, databases, infrastructure - you're as comfortable digging through a wireshark capture or tracing through system code as you are facilitating business/tech workshops discovering bounded contexts.
Eventually you become the goto person, the one who everyone wants to bounce ideas off. The no-nonsense person who confidently knows how to get stuff done. And then you start growing and empowering others and realise that's where the true 10x multiplier comes from.
Two things I have seen most of the really good programmers I have known. One, they read a lot of code, they mostly spend time digging into open source codebases and quite a lot of time contributes to them as well, which goes to the second point. Two, getting your code reviewed by a lot more programmers, with more experience than you, you get a much better perspective on a lot of things.
Good point. I have one question: How do I get other people to CR (Code Review) my personal projects? I'm actually willing to pay a bit for that but always find it weird to ask around. Most of the time my personal projects are small, but not trivially small so that I can put it on Stackoverflow. Something like 1,000 loc.
Sounds like a cool opportunity for a matchmaking site - swapping reviews of personal code with the goal of learning and practicing both the coding and the review. There are practice interview sites that work kind of that same way.
I'm far from a great programmer, but working I'm towards it every day. Something I've just realized more and more is that the raw programming ability is really the baseline. It really feels like good design and architecture is where the heart of programming comes from. Maintaining code I wrote two years ago has shown me how bad certain decisions where and how great other were and then I have that knowledge going forward.
As I've worked with more senior engineers who have done this over and over again, I've noticed that the raw programming part isn't any different. I still know all the same things. But they have the most valuable ideas from experience. Their foresight to lean towards a specific implementation because they've seen where this plan falls short in the past ends up being a massive time and money saver.
Dealing with tricky problems has provided the largest growth for me. I worked at a scrappy startup where I wrote a ton of CRUD endpoints and got to do something interesting here and there. You don't learn anything new when you write the same code over and over with some basic stuff in place. I've found that I've learned the most from problems that are intimidating at first.
It's honestly comforting to know I can write similar code to more experienced engineers but I'm lacking their foresight and experience.
By getting good at testing. I worked on a project with a 100% coverage requirement for a few years, and it forced me to learn how to test things that I normally wouldn't bother with. It also forced me to deal with the consequences of maintaining my tests.
I've discovered that the usual buckets used to categorize tests (unit, integration, etc) can mislead people into writing tests that make refactors painful/impossible. If you test each "unit" in isolation, then you limit your ability to change how the units interact (even if the user-facing behavior isn't changing at all.) You end up needing to change/rewrite the tests for each "unit".
Instead of units, I think about supported interfaces and tricky dependencies. Ideally, I'd test using the user-facing interface. That way, the test only changes if the user-facing (supported) behavior changes. Then I swap out any tricky dependencies (mainly slow/nondeterministic operations) for fakes/stubs/mocks. In the end, the tests look like "integration" tests, but they fit into your CI pipeline in the same place unit tests would.
This testing strategy makes me much faster and more effective. I can start writing tests before I've worked out how I'll organize the components. And if I change my mind halfway through, I don't need to rewrite any tests. If done right, those tests can survive years of refactoring with little maintenance.
There's more to good testing and being a great programmer than this, of course. But this is the lesson that has had the biggest impact on my "greatness" at programming.
What is your opinion of code coverage requirements now? I have been in a "phase" of seeing them as "code quality theatre". Considering that a function which takes a single 8-bit integer as an argument already has 256 unique inputs, and may bug only on 1-2 values, 100% statement coverage can be very misleading. A typical function has billions or trillions of unique inputs and 100% statement coverage could be very nearly 0% state space coverage. I'm 5y into my career (but 15y into programming) and aware that my opinions will change and develop as I progress. This one has been stable for a while though.
Coverage is necessary but not sufficient, your tests also need to be good and test the right things. What's your proposed alternative - that we don't even try because our tests aren't guaranteed to be perfect?
Well, almost. I use a lot of assertions to check the obvious (value out of range, null pointer, etc.) and test the happy path(s) to prove the code at least works in the cases I can anticipate. I add unit tests for complex algorithms, and to prove a reported bug is what I think it is and that it has been fixed. Otherwise, I think using unit tests to find bugs is mostly busywork.
For even a fairly trivial piece of code, the search space for bugs can be vast or even infinite. Writing unit tests to find bugs within that space is like throwing darts at an infinitely large wall and trying to hit an unknown number of invisible targets. You can only write tests for the potential bugs you anticipate - if you could anticipate a bug, you wouldn't write it, right? You end up with dozens or hundreds of tests that probably never failed, except when you have to change something. Such was my experience when I tried to maintain high code coverage. When I switched to writing assertions and acceptance tests, my rate of bug reports did not change, and I was more agile.
I think a great way to improve your codebase is to write unit tests, integration tests and by using languages with more types than say, JavaScript or PHP.
If the language has a lot of conventions for types, you can add satisfiability resolvers (SAT resolvers) and what kind of assumed safety/security comes with that.
Also, do capture the flag events online (e.g. picoCTF is a great start) which teaches you a lot about naive assumptions and programming mistakes and the reasons _why_ you should never use C++ for anything critical, and why memory ownership always fails when humans do not agree on conventions.
Start something from zero to profit getting to know all the steps to do so. You might not become the most technical programmer but you'll be one that knows how to deliver real value.
Sorry to be blunt, but how does knowing how to sell software make you good at writing it? What’s the end goal of the act of writing code supposed to be?
So my point is that someone being a real "full stack" developer that is capable of creating an app from conception to market, generating value to customers that are willing to pay for it. Someone that can understand all the lifecycle of a software in place of being a great "backend developer", "frontend developer", etc.
Study the field of engineering at large, and bring those practices back to programming. That’s how one evolves from being a programmer/code-jockey to true Software Engineer
Learning to think in terms of design - and to be able to mentally map the design onto lines of code. Learning to be able to think on both levels, more or less simultaneously.
In order to become great at that, you have to make enough mistakes that affect other people until you understand what helps and what hinders them. You have to realize that your code isn't just implementation but is human-oriented communication, and tools are part of the puzzle.
The more your work hinders others, and the more you are forced to deal with the consequences of it, the more you will learn what helps and facilitates others.
You can also learn some of this by using and suffering from other people's bad work, as long as you don't allow it to make you complacent.
Finally, you need to have humility. Nobody who thinks they're great is going to be truly great. You need to recognize how you suck and how to suck less. "Take the log out of your own eye so that you can see clearly to take the speck of dust out of your brother's eye."