I received a heartfelt response from a new software developer in response to my “What Do You Need to Become an Elite Developer?” blog post. With his permission, I decided to post his letter and my response – with his name omitted.
First, I want to thank-you for the article you wrote concerning becoming an elite programmer. I have not read it through entirely as of yet because I am overly tired making it difficult to process properly, so I will do so once I have had some rest. I did feel a sense of urgency to write this e-mail to you while I had it in my mind.
I made a career change to become a developer last December, and spent six months learning Ruby. I got my first position as a developer in July of 2014, and was in the position for six months.
I needed an entry level position, but the position was a little bit over my head in terms of the work I was required to do (Building REST APIs, Consuming with AngularJS, using Kendo Grid, all of which I had never done before. And in Java, a language I had never used). I learned to do the work, but I just was not fast enough to keep pace in an Agile environment with developers that had coded through high school and college, or who already had years of experience.
That position was in Java, using Spring and Hibernate, and AngularJS. I am currently unemployed and am looking for entry level positions in .NET. Since I left my last employer, a friend of mine who was always suggesting I learn to program suggested a tutorial in .Net for me to get started.
I rather enjoy C#, .NET, and the Entity Framework. Having never used visual studio before, it is a breath of fresh air to use, providing I have the memory resources to use it :) (which I do, finally).
One thing eats at me though, as I learn the language and the framework. I do not feel I am becoming any better as a programmer. My longing as a developer is to write code with the same mastery as I speak and write the English language. Therefore, I am really wondering what the next step is to become a stronger developer. It is a question that has been eating at me for months now.
I don't want to be a google coder, or tutorial coder, etc. To me, it is a big problem if every time I need to write an essay or a letter, I always have to have some grammar book showing me the structure of a sentence or paragraph to make sure I'm getting it right. I understand this is necessary when learning a new framework and new language, but it should not be necessary 75 percent of the time.
Anyways, I've made this e-mail long enough, and I'm sure you have plenty to do.
Any advice would be much appreciated.
Here’s what I wrote back.
I know a few friends who've gone through this journey - making the decision to change careers to programming sometime after graduating college. You actually remind me a lot of the cofounder of my new, yet-to-be-announced startup. Graduated from University in 2008, made the decision in 2011 to become a programmer after several years of being a marketer. I'm in the process of training him on .NET from the ground up now.
I can tell you first and foremost that based on your description of your learning process, you're on the right track. Most "google coders" stop once they reach the bare minimum to perform menial work and coast along from there. Org charts around the world are staffed with thousands of rank-and-file programmers who make it a goal to maintain the status quo and never learn anything new. This is why VB6 and Perl are still alive and well in the industry. The fact that you want to move beyond this from the onset immediately puts you in a more economically desirable group of programmers.
So let's talk about the role that tools and frameworks have in the course of learning how to be a developer. As you've mentioned, learning Java or .NET doesn't really feel like they're making you a "better" developer than you were when you just knew Ruby. You're not wrong for thinking this - knowing how to write a "Hello World" in three languages isn't much more useful than being able to write it in one language.
What will make you a better developer is learning some general principles and practices that are platform-agnostic, and then learning how these principles are applied on each platform becomes tremendously valuable. For instance, learning how to do "design by contract" is going to be radically different experience on Ruby than it is in .NET or Java - because the type system, the OO model, and the runtimes all have starkly different implementations. It's not important to understand why they're different now - but that should be a goal as part of your learning.
What are some of these platform-agnostic principles that you should learn? Here's a list of the ones I've prioritized in my own career:
- Programming & design patterns - time-tested formulas for solving common programming problems that will appear regularly in your career. Some patterns you should learn first: factory pattern, strategy pattern, adapter pattern, iterator pattern, command pattern, observer pattern, and decorator pattern. Here's a link to the famous "Gang of Four" book on design patterns - this is the Bible of design patterns.
- Unit testing - building automated tests for code forces you to design code in a way that is inherently more testable, but also makes it easier for you to unearth breaking changes when you modify existing code. Ruby probably has the best tools for doing this, but it's something you should know how to do in every language.
- Domain-driven and enterprise design - once you have a grasp on design patterns, we can take that same "formula" approach to how we design entire applications rather than just specific components within a codebase. WHA?!?! No, seriously! This is where the concept of software "architecture" transforms from being a fuzzy concept to an actionable methodology. The book that really, really helped me understand this is Dino Esposito's Microsoft .NET - Architecting Applications for the Enterprise. He does a great job of introducing a few different design approaches for applications and has some actionable formulas for implementing them in .NET - definitely worth a read.
- Learning how to read someone else's code - you know what's a lot harder than writing code? Reading someone else's. Being able to sort through a code base and understand why someone organized classes the way they did, or what this function does, or what code depends on this, will make you seem superhuman compared to most programmers. It's the most underappreciated and important skill any programmer can have. Best way to learn this is to get involved in an open source project. Pick a small one at first, then scale into bigger ones as your interests and abilities expand.
- Code reuse - reusing code is the entire point of object-oriented programming, but unfortunately most programmers do a terrible job at making their code reusable. I made it a goal to become very, very good at doing this and as a result my output as a programmer went up tremendously. The best way to learn how to do this? Get involved with an open source project or create your own.
- Source control and deployment (DevOps) - I had an employee at MarkedUp who became an absolute genius at DevOps; one of the things he did was master the fine-grain details of how Github, Amazon Elastic Beanstalk, Windows Azure, and other tools worked. By understanding all of these things, he was able to help us architect code that was safer and faster to deploy - we rethought how our services were organized and designed tests which guaranteed that code we deployed was sufficiently stable to run in production. Start by learning how Github works - it's the easiest, friendliest, and most popular way to get acquainted with source control. From there you'll find that there are lots of services which offer direct Github --> Production deployment, like Azure websites. You'll look like a magician if you can do this and get a rapid prototype of your application up and running.
- Data modeling and data structures - This is the number one skill that separates people who were educated on computer science in college from those who weren't, in my experience. However, it's straightforward to learn on your own. Data structures are the "design pattern" equivalent for data - say, for instance, you need to maintain a list of objects that are always sorted in a certain order. There's a data structure for that. Or a list that can be searched by key. There's a data structure for that, too. Learn what a linked list is and how it's different from an array. Learn why a circular buffer is a great data structure for handling streaming video on mobile devices. Learn what a queue, stack, and tree are. Learn what a priority queue is and why binary heaps are often the right structure for implementing one.
None of these concepts are specific to any programming platform - they are universal skills. Once you learn these, you will discover how to take advantage of specific aspects of each programming language to do them better - Ruby's weak typing system makes it very easy to write testable code, for instance. Whereas C#'s strong typing system makes it very easy to enforce "design by contract." Don't worry about what these terms mean yet - you'll discover them with time.
You will be most successful in learning how to program if you begin by understanding what others have done. Do you think Hemmingway or Steinbeck became great writers by writing tons and tons of work from day one? No. They became great by reading tons and tons and tons of work from generations of great writers who preceded them. Programming is no different.
So find some successful .NET open source projects that you feel passionate about and attempt to understand what those developers have done - not merely what they did, but why and how. Then learn how to bring this knowledge to your own work. Eventually you will develop your own style, but it will be better served if you inform it with the best practices of people who were once in your shoes many years before your own time.
Best of luck!