20 Tips for becoming a better programmer

1. There should be only one single exit point to each method (use if-else whenever needed).

2. When using if-else, make sure to place the shorter code snippet in the if:

if (cond) {
   <only a few lines of code>
}
else {
<here you should write the "bigger" case>
<many many lines...>
...
...
.
.
.
}

3. Do not throw exceptions if you can avoid it, it makes your code much slower, if you feel like throwing something and then catching it – go play ball with your dog. If you don’t have a dog get one – they’re awesome!

4. Do not try to do many things on the same line – when you’ll get an error – it will be harder to debug, example how to NOT write your code:

String result = hasInformation()? getState() : (hasMoreInformation() ? getOtherState() : getState());

5. Look for code pieces that look the same and if you find any – refactor!

6. Meaningful names are a must. If you’re not sure, meditate on it for another minute. Still not sure? ask your colleagues for their opinion.

I’m still shocked everytime I find out that the following is not common knowledge:
7. Whenever you can use HashMap instead of List/Queue – use it!

And on the same note:
8. If you can use caching instead of I/O (usually DB) – use caching

9. If a nice and simple regex can do the job – use it!

10. Do not use regex for parsing (for example: HTML/XML/json) – there are special tools for that in every language, for example in Ruby, Java etc.

11. Print to Log. You should have at least two levels of logging: DEBUG and ERROR. The latter should be the default. Nice tip: you can send your self a text when a critical error occurs, by sending an email to your_mobile@your_carrier – look here for more details.

12. Use stackoverflow – not only for asking questions: Take a few minutes, every day, and try to answer questions – you’ll be surprised how much you’ll learn from it!

13. A rule of thumb: if your method is over 50 lines – split it. If your class is over 500 lines – split it. If you think you can’t split it – you’re doing something wrong. This recommendation is a “language dependent” and shouldn’t be taken “as is”: while 50-line method feels natural in Java/C# – it will be considered very long in more expressive languages such as Ruby & Python.

14. Writing a code which is “self explanatory” is great but also very hard, if you’re not sure how “obvious” your code is – use code-comments.

15. When writing code comments always assume that the reader doesn’t know what you’re trying to do. Be patient & explain. No one is going to *bug* you because your comment was too long…

16. You want to improve? read books, blogs, technical online newspapers join relevant groups on Linkedin, update yourself with the latest technologies, go to conferences, got the point ?

17. Practice makes perfect: solve code-challenges, join hackathons, go to meetups etc

18. Experiment with different IDEs until you find the one that “feels right”, study it carefully and make sure you know the major features (including plugins). Tune-up the keyboard shortcuts – it will make your workflow smoother.

19. Whenever you find a bug, before you fix it, write a unit-test that captures it. Make sure it does.

and my favorite:

20. Don’t get lazy – RTFM

We’ll finish with two quotes:

“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.”
- Brian Kernighan

“Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.”
- Rick Osborne

Update:
Many thanks for Jeff Grigg, Tom Burton and Keith M. O’Reilly for their feedback which helped me improve this post – cheers!

Be Sociable, Share!

14 thoughts on “20 Tips for becoming a better programmer

  1. Some great suggestions here but I would go a step further in some cases.

    3. Only throw exceptions for exceptional cases and don’t prematurely optimise your code.

    5. Not only the same but similar. I’ve seen many cases where similar code blocks were not refactored when they could have been.

    10. Maybe offer an alternative here.

    13. More than number of lines make sure it’s only doing one thing (Single Responsibility Principle).

    14. Save for regexes I’ve seen very few comments that could not be removed by refactoring out a method or class (plus automated tests)

    15. Sorry but I would. If you gotta explain yourself your code and tests are not doing their job. Remember your code is read far more than it’s written.

    I know the comments ones are a little contentious. It’s a bit like the old tabs vs spaces war so if you disagree, I understand.

    Thanks for the post.

    • Thanks for your comment Phil!
      I agree with you on 3, 5, 10 and 13 (I modified #10 to provide alternatives like you suggested).
      About #14 & 15 – comments that can be removed are bad comments. When we comment we should try to avoid describing what the code is doing (and there’s an exception to that as well*): assuming the reader is not stupid – she/he can figure it out without help. A good comment explains one (or more) of the three W’s: “what, why & where”:
      1. what is out goal
      2. why did I choose this implementation
      3. where can I find additional information (links & docs)
      None of the three is mandatory, and that’s fine cause writing a comment isn’t mandatory as well ;)
      Personally, I don’t mind reading code that has a lot of comments, most IDEs will gray out the comments and the only “effort” I’ll have is scrolling which I don’t mind, but like you said – it’s personal, and we should always aspire to write code which is self explanatory.

      * The exception, TMHO, is when you’re implementing a complex set of rules/logic

  2. Some nice stuff here.

    Refactoring especially I agree with. I think it’s one of the most underrated skills.

    Don’t agree necessarily with 1 if multiple return statements are clearer. I would say that code clarity overrules most if not all other rules. Ruby is one of the languages where this makes sense though.

    As for rule 2 I try to put the main path into the if clause. Provided all functions and methods are as short as later rules (e.g. 13) suggest, length will not be a big issue. Then there are occasions when you have to test the more general case last to catch the special cases if they occur. And if you don’t know in advance which one will be shorter or if the code changes over time, moving the snippets around will be error prone, time consuming and often unnecessary.

    Cheers.

  3. I would expand #19 a bit further.

    “Legacy code is untested code.”

    Capturing a bug in unit-testing before fixing it is great but to write tests in the first place is even better (TDD).

  4. Those are some nice tips!

    in tip 13 you advice to keep methods smaller then 50 lines.
    Is there also an advisable minimum of lines for a method?

  5. Codehunger

    I don’t think there should be a “minimum” for a method length. That said, if it’s only one or two lines you might want to consider “inlinning” it.
    Not that performance should be a big issue, but still, keep in mind that every method call opens a new frame on the stack and a “context switch” is being applied. Does it worth it ? in some cases the answer might be yes, but probably in most cases it won’t.

  6. For point 1 and 2, I would say: Get rid of most of if statements that you can. Use polymorphism, if in a OO paradigm, of course.
    I will also start for as first point: Write a test before writing any line of “business” code.

    For the number of lines of a method, the smaller, better. I sometimes even write methods with one or two lines of code, however the method conveys the meaning, so it’s worth to have very small methods just to convey meaning and create structure in the code. This bring me also the the comments point. If you write good code (code is to be read by other humans), is like telling a story with that code, so no need for comments at all.

    Still in the method length, if one have a lengthy method, it may mean one of two things:
    1 ) The method is full of complexity, having a lot of conditional branches, breaking OO design principle.
    2 ) Is procedural programming and if it happens that you’re with an OO programming language, something bad happened to the design.

    If is for an OO Programmer: Lean OO Design principle: https://code.google.com/p/javatrainings/

  7. Some comments to particular points:

    1: This one is very questionable. Especially in legacy code, this rule would make a huge mess, since usually such code is not well structured anyway.
    But even in standard code, if method has more than let’s say 20 lines, this approach would make it much more complex. From testing point of view, you’d get much more execution paths to test in comparison with case when you “return” immediately.
    I’ve seen this approach repeatedly, but honestly – reasoning behind it is flawed IMHO.

    3: If you throws exceptions only in really exceptional cases, then it is ok. Exceptions should not
    replace error handling.
    Btw from performance PoV (Point-of-View), using exception is still better than regex expressions.

    10: In general, always consider using regex thoroughly. In some cases, huge performance decrease
    can surprise you.

    13: Yes. But also opposite approach should be taken into account – too small methods and classes are
    contra-productive, mainly from maintenance PoV. So:
    a) If your method body has 1-2 lines (except e.g. properties getters/setters), ask the reason. Polymorphism is OK, but SRP must be considered and BALANCED well – fanatical SRP adherence replaces one type of complexity (long methods) with another type of complexity (lots of classes/methods) only.
    I’ve seen C# project where they had ~20000 classes and 80% of them had around 10 lines. This was
    stupidity of the greatest caliber.
    b) As for classes, the balancing line is more ambiguous. Small classes look pretty, but you have huge number of them. And then maintaining relationships between them becomes a nightmare – you can read
    content of “big” class much easier than browse 10-s or 100-s of files to find out the relationships.
    E.g. if you need (!!) pluggable architecture, then small classes are needed in many cases. Otherwise,
    reason about small classes based on your use-case AND architecture.

    15: Yes, but comment should answer “Why?” question at first place. At second place, I’d put “What? What it
    is doing?” answer, with rare occurences in the code. Answer to “How?” question should not be in the comment – code should be self-explanatory for this question (code structure, KISS + SOLID, …).

    Btw, good article… :)

  8. chains – I’m not sure what needs explanation ? if you’re looking for an item than finding it in a list is O(n) while using a Map takes O(1). Maybe this is too obvious to you – but apparently not to everyone…

    Jan – I’m with you on #1, but I think that usually it’s not the case (dealing with legacy code etc). As for #3,10 – I didn’t understand why regex vs. exceptions, but I’m totally with you on using regex when possible (emphasis: use but don’t abuse… ;) )

    As for #13 – length of methods/classes is language dependent: while in Ruby the following is perfectly fine:
    def fact(n) (1..n).inject{|r,i| r*i } end
    In Java 1-2 lines method – will almost always be too short. That said, I totally agree with you about bewaring from going to the other extreme!

    #15 – good point!

    Thanks for your comment!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>