While everyone can learn and practice programming, it’s hard to find a good software engineer, even harder to find a great one. My definition of a great software engineer is someone who can solve real world problems with software expertise, not someone who can only write code, or someone who can only talk about architecture on paper, or someone who complicates real world problems.
Yes, we can all learn programming related concepts, languages, tools, and etc. But how to use them effectively on a business problem is really a test stone for anyone. It’s important to study textbooks, learn from others; even more so to practice in real world with real business context. The latter is the major differentiator for a graduate to become a so-so engineer or a rock star.
Lost VMs or Containers? Too Many Consoles? Too Slow GUI? Time to learn how to "Google" and manage your VMware and clouds in a fast and secure HTML5 App.
In my opinion, there are 3 stages for one to grow in software competence:
- Starter. At this stage, he just graduated from school with all the basic knowledge for a software engineer. He can write a good amount of code but is limited in project scope and real world techniques/hacks. Because he is still new, he does not have much domain knowledge therefore have a little trouble to model a business problem to computer domain. He also needs to learn team development process along the way.
- Experienced. After several projects over the year, he has learned enough domain knowledge, therefore is comfortable in abstracting business problems to computer problems. He has also learned design patterns, development process, and best practices in using whatever languages/APIs/Frameworks. He talks like an architect with many buzzwords like interfaces, patterns, dependency injections, platform, etc. When writing code, he can apply advanced techniques and manage large code base. While he can use various techniques, there is a tendency to overuse or underuse technologies.
- Expert. With more real world projects, continuous learning, and reflective thinking on the past projects, he now has deep domain knowledge in that sense that not only does he know what the requirements are but also why there are such requirements. He can effectively mode real world problem in a straight-forward and simplified way. While writing code, he prefers plain and natural code with no or little tricks and uncommon techniques unless absolutely necessary. He values simplicity above everything else: simple design, simple code, minimum patterns. He understands software development is about people not process.
One may confuse the simplicity here with first stage. But the key difference is that an expert chooses to be simple while a starter happens to be simple due to limited expertise. As a result, the readability is far apart.
Most programmers start with the first stage can gradually move onto the second stage over the years. Experiences and continuous learning matter than anything else for the transition. Most of programmers can achieve the transformation, but stop at the second stage for a long time before moving onto the 3rd stage if that happens at all.
The key factor to move beyond stage two is no long experiences, but the reflective thinking: how to get the most out of the past experience and others’ experience. The ability to abstract and generalize is essential – how to differentiate the major and minor factors in a problem and model them accordingly. These two capabilities do require a lot of practices and thinking, but not really proportional to the years of experiences. Some of us will get to stage three but most won’t. Among the experts, some may arrive much sooner than others.
It’s worth noting that this growth pattern is not unique to programming. You can find similar ones in other disciplines as well.
Here we talk about technical competence, not titles in corporate where you might find quite a big mismatch between technical skills and titles in the ladder. That is surely beyond the scope of this article.