Thursday, July 20, 2017

How do I know if I’m good at programming?

I was talking to a very junior programmer recently and he asked me a great question. A question so good, it made me stop and think about my perspective on how learning happens. The question was:

“How do I know if I’m good at programming?”

I’ve often been asked the other side of this question “How do I get good at programming?”, or “What can I do to get good at programming”. The answer to which is some combination of experiment on your own projects, do courses, read books, work with good programmers and contribute to open source projects. But if you think about the problem in terms of “how do I know if I’m good?” it becomes much more of an engineering approach. You have a metric, optimize it.

Aside from practice, the most important thing for improving at any task is good feedback. When starting in a new domain without a good teacher, good feedback is difficult.
 A course for example may have exams or projects on which you get feedback. But once you’ve completed a course, how do you get the higher level feedback on your overall improvement? If you have a good mechanism for feedback, the answers for which thing to pursue next flow much more easily.

So how do I know if I’m good at programming? A good place to start is to ask “what is good code?”. If a programmer can’t produce good code, they aren’t a good programmer.

What is good code?

All code exists to complete tasks. The first mark of good code is that it completes the desired task. The task may vary massively in level of complexity, but the code can never do better than complete the task. Feedback for this is simple, “does the code achieve the desired aim?”. The code should only complete the desired task, there should not be other undesirable side-effects. Writing a good sets of unit tests around your code can act as a success metrics.

If you cannot successfully complete the task, here is your first good piece of feedback which, will show you exactly what you need to learn next. Identify the knowledge you lack and seek out the most relevant resource. Systems theory tells us if you're not optimizing on the constraint, you're wasting your energy. This is the constraint, learn only this thing.

Is the code readable?

A well written piece of code is a clean concise expression of ideas. It should be as easy as possible for another programmer to understand what you’ve written. Get familiar with idioms and syntactic sugar of your language. There might be nice ways to write what you’ve written in 3 lines in just one, while still maintaining readability. Make sure your code is correctly documented, explaining why not what is the code is doing. To test this, if you don’t have friends who can look at your code, I would recommend posting your code to https://codereview.stackexchange.com/ or some other similar sites. Yourself 6 months in the future is also a pretty good substitute for a stranger.

Is it easy to extend or modify?

It's a lot of programmers favorite complaint, “the requirements changed”. This is reality, you're not programming exam questions with clearly stated features and aims. In the real world requirements are always changing and that's a good thing. If a task took you 3 months to complete and you have no new requirements, someone is not doing a good job. More time should bring in new information and requirements.

In an interview I like to ask a candidate to complete a fairly simple programming task, such as programming an elevator system. Once they’ve finished that, I ask them to implement a crazy feature that they could never have foreseen. There response to this, both interpersonal and technical, tells you a huge amount about their skill.

A good programmer should be planning for this. If you wrote a program to complete task x, see how easy it is to modify it to do task x and y but not when conditions k through q occur(unless k and m occur at the same time then execute y but not x). CS 101 concepts - like polymorphism and the difference between inheritance and composition - that seemed meaningless at the time, may now feel interesting.
Writing code to change is a thing you get a feel for with more experience, but don’t add more abstraction layers too soon. Premature abstraction leads things like Enterprise FizzBuzz (https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition). 

Is the code Efficient?

Efficiency has a few different components, speed to finish and various resource components such as memory usage, CPU usage, etc. Luckily all of these are easy to track, and there are profilers in every language that can show you where program time and resources are being used. Get familiar with these tools and then see how much you can shave off these metrics. If you are reengineering an existing problem, such as writing your own LRU cache, you can look up the theoretical best performance and compare it to your own. Here you may want to start thinking about your code from a big-O perspective, it is also useful to know roughly how long different operations take https://people.eecs.berkeley.edu/~rcs/research/interactive_latency.html.

Can you write it quickly?

Especially early on in learning it’s important not to focus on speed. Competing in speed coding competitions is impressive, but when it comes to the craft of programming, it's a poor way to learn. Speed should not be the goal, more the measure of progress. If you are mastering a domain then you should be able to write code that completes it’s task, is efficient, readable, and easy to extend in a shorter amount of time.

It is easy to measure time taken to complete a task, but that metric is difficult to act upon. Instead maybe try to analyze the amount time spent on the various sub tasks. Are these are the areas you need to deepen your understanding of? Maybe you are spending large amounts of time doing manual testing of your code, could this be speeded up through automation? You could start to look at the tools you are using. Your IDE has all kinds useful hotkeys that can improve speed and free up your brain from mechanical tasks so it can focus on the higher level problems. 

Finishing up

If your code achieves all these things to a high standard then you are good at programming for that task. If not there are clear areas on which to improve. You can then look towards more complex tasks or tasks in other areas that you wish to be a good.

I would like to add one more thing to this article to finish. Given the hard limit on hours in the day, and a harder limit on productive hours, there is only so much a single programmer can do. Elon Musk has a reputation as a productive guy, but if he was the only engineer at PayPal they would not have gotten far. At a certain level if you want to build great things you need to be working in a team. At this point programming becomes a social activity. You want to be able program not just with your own hands and brain but on some level through the whole team you work with. At this point being a good programmer is about not just how good your code is, but about how good the code of people you work with is.

There are many ways to get feedback on this. After you code review a colleagues work, do they produce better code? The next question is have they just improved the specific code you reviewed or has their general code improved as well? Getting people to improve in this way is not simply a matter of technical feedback, but also motivation. Can you get them excited about the task, to understand why different improvements or approaches are important. Are you improving the overall skills of the people around you? The famous 27x research says that the best programmers are 27 times better than the worst. Well if you are a 7x programmer and you help 4 other people in your team go from 1x to 7x then you're far more productive than a 27x.

For me these are essential skills of a good programmer and if you are achieving any of them even in some small way, you can sleep soundly knowing you know you are a good programmer.

16 comments:

  1. And the only way to know if you have communicated code effectively... is to ask someone else. :)

    ReplyDelete
  2. all this makes you a good code manufacturer, if you add the proper soft skills then you can be a code developer

    ReplyDelete
  3. I like the structure of your answer to the question. One should move away from asking "Am I good," because that is not the mindset for continual growth. The answer to that question is, "No, never; there is always more to learn. The best programmers, especially, are not good at programming, and have learned to process feedback to continuously improve."

    ReplyDelete
    Replies
    1. Well said :) "goodness" in any field is probably better represented as a continuous scale than a binary good or not good.

      Delete
  4. What do you know about coding, reading through your article feels like read through the gang of four. Fuck that seriously. Are you in a a position to teach people how to code. If I where in that position and start coding like you propose i would definitely end up building Windows. What in the wold motivates you to write about good coding ????

    ReplyDelete
    Replies
    1. Wow, What do you know about coding yourself? reading through your comment makes me feel like you're asserting you're better than the writer. So, can you at least give us constructive criticism so that we will learn if there are things lacking in this article?

      Delete
    2. Apologies if upset you unknown. If you want to give more details, happy to discuss further, though if you could temper the bad language a little I would appreciate it. The question in the title is one I was literally asked in real life, the post is a write up of my response. Not everyone will agree on everything.

      Delete
  5. Another technique I found helpful was to keep looking back at your code every 6 months. If you think the code you wrote 6 months ago was the best you could've ever written, you haven't learned anything in the last 6 months. Often I find that the code I wrote 6 months ago looks juvenile. But I can't complain for that was the best I could do then. So I open up a new branch on git and try to restructure the code in my free time - this also helps in maintaining consistency, by the way.

    ReplyDelete
    Replies
    1. Yeah I also found this incredibly useful. Taking the time to rewrite it to see how it could be better, like you did, is a great way to improve, maybe I should add a line about this..

      Delete
  6. Agree with most of what you have said. I would like to understand your thought process behind your opinion regarding requirements. If you have designed for a specific set of requirements and have started coding it up and say the requirements wildly change, isn't that a bad thing? Now you have to spend time and resources to architect for these new set of requirements.

    ReplyDelete
    Replies
    1. As I see it: In an ideal world requirements are perfect first time, you have an exact brief and you work to it, everything is great. In the real world ahead of time people don't know exactly what they want, and with every day new information comes in that allows us to better understand what we want. To do a good job you should be planning for change, because it is 100% going to happen for any non trivial work. It will cost resource to change requirements, so you should try to plan so when the change happens it takes the minimum of resources.
      Also planning for change is a stretch goal, the more important things are completes task, then is readable, but after that its a good factor to think about.

      Delete
  7. Great article, but I have one issue to point out.

    "Well if you are a 6x programmer and you help 4 other people in your team go from 1x to 6x then you're far more productive than a 27x."

    Although I agree with this point, that math is off:
    6x + (4 * 6x) = 30x
    27x + (4 x 1x) = 31x

    So unless you're comparing 1 person to team of 4, in which case I don't think its fair, the 27xers team is more productive.

    ReplyDelete
  8. Been a coder for 20 years, but about to quit and do something more interesting.

    The worst coders I have worked with have been those who read Gang of Four books. Seriously. Their code is usually so over-engineered that nobody else can work on it.

    Why do you need to write good code anyway? Code is usually scrapped after 3-4 years if you work in something like web development or business apps.

    Am I a good coder? My code has allowed me to retire in my 40's. There's your answer.

    ReplyDelete