10 steps to becoming a better programmer

stencylRules
Submit to StumbleUpon

Hi and welcome back to my blog!

I wanted to cover 10 of the things I’ve learned over the years being a professional programmer that really helped me improve the quality of my code and my overall productivity.

1. Never ever duplicate code

Avoid duplicating code at all costs. If you have a common code segment used in a few different places, refactor it out into its own function. Code duplication causes confusion among your colleagues reading your code, it causes bugs down the line when the duplicated segment is fixed in one location and not the others and it bloats the size of your code-base and executable. With modern languages its become possible to get really good at this, for example here is a pattern that used to be hard to solve before delegates and lambdas came along:

/// <summary>
/// Some function with partially duplicated code
/// </summary>
void OriginalA()
{
	DoThingsA();
 
	// unique code
 
	DoThingsB();
}
 
/// <summary>
/// Another function with partially duplicated code
/// </summary>
void OriginalB()
{
	DoThingsA();
 
	// unique code
 
	DoThingsB();
}

But now we can refactor the shared part of both functions and rewrite using a delegate:

/// <summary>
/// Encapsulate shared functionality
/// </summary>
/// <param name="action">User defined action</param>
void UniqueWrapper(Action action)
{
	DoThingsA();
 
	action();
 
	DoThingsB();
}
 
/// <summary>
/// New implmentation of A
/// </summary>
void NewA()
{
	UniqueWrapper(() =>
	{
		// unique code
	});
}
 
/// <summary>
/// New implementation of B
/// </summary>
void NewB()
{
	UniqueWrapper(() =>
	{
		// unique code
	});
}

2. Notice when you start distracting yourself

When you find yourself flicking to facebook or twitter instead of working on a problem its often a sign that you need to take a short break. Go grab a coffee away from your desk and talk to your colleagues for 5 minutes or so. Even though this seems counter intuitive, you will be more productive in the long run.

3. Don’t rush the solution out the door

When under pressure to produce a solution to a problem, or to fix a bug, its very easy to get carried away and find yourself rushing, or even missing out your usual crucial testing cycle completely. This can often result in more problems and will make you look less professional in the eyes of your boss and colleagues.

4. Test your finished code

You know what your code is supposed to do, and you’ve likely tested that it works, but you really need to prove it. Analyse all the potential edge cases and make a test which confirms that your code performs as expected under all possible conditions. If there are parameters, send values outside of the expected range. Send null values. If you can, show your code to a colleague and ask them to break it. Unit testing is a formalised approach to this.

5. Code review

Before you promote your code into source control, sit down with a colleague and explain exactly what your change does. Often just by doing this you’ll recognise mistakes in your own code without your colleague saying a word. It’s much, much more effective than just reviewing your own work.

6. Write less code

If you find yourself writing a lot of code to do something simple, you’re probably doing it wrong. A good example is the lowly boolean:

if (numMines > 0)
{
   enabled=true;
}
else
{
   enabled=false;
}

When you could just write:

enabled = numMines > 0;

The less code you write the better. Less to debug, less to refactor, less to go wrong. Use with moderation; readability is just as important, you don’t want to make your code less readable by doing this.

7. Strive for elegant code

Elegant code is highly readable and solves the problem at hand with the smallest amount of code and machine action possible. Its quite difficult to achieve elegant code in all circumstances but after programming for a while you start to get a feel for what it looks like. Elegant code cannot be improved by refactoring anything. It makes you happy to look at it. You are proud of it. For example here is what I consider to be an elegant way of computing the area of a convex polygon:

static public double GetConvexPolygonArea(Vector2[] vertices)
{
	double area = 0;
	for (int i = 0; i < vertices.Length; i++)
	{
		Vector2 P0 = vertices[i];
		Vector2 P1 = vertices[(i + 1) % vertices.Length];
 
		area += P0.Wedge(P1);
	}
 
	return area / 2;
}

8. Write self documenting code

Comments are a very important part of programming for obvious reasons, but self documenting code can be even better because it makes it possible to understand code just by reading it. Function and variable names can often be deftly chosen so that when put together with the language semantics the code becomes readable even to non programmers. For example:

void DamagePlayer(Player player, int damageAmount)
{
	if (!player.m_IsInvincible && !player.m_IsDead)
	{
		player.InflictDamage( damageAmount );
	}
}

Self documenting code is not a substitute for comments. Use comments to describe ‘why’, self documenting code describes ‘what’.

9. Don’t use magic numbers

Numbers just inserted into the code are bad practice because there is nothing to describe what they represent. This is compounded by duplication; where the same number is used in multiple different places in the code. One will get changed and the others missed leading to bugs. Always use a named constant to describe the value you want to represent, even if it is only used in one place.

10. Don’t do manual labour

Humans are very good at making mistakes when doing a series of actions. If you have a build deployment process which is more than one step long, you’re doing it wrong. Automate as much as possible, reduce the chance of human error. This is especially important with tasks which you perform a lot.

11. Avoid premature optimisation

When you start optimising part of your already functioning code you risk breaking the functionality. Optimisation should only be performed in response to performance analysis, hopefully carried out towards the end of a project. Optimising before this analysis stage wastes time and can introduce bugs.

Ok, well I said 10, but you get an extra one for free!

That’s it for now, I hope these little points will help you improve your programming and development process.

Until next time, have fun!

Cheers, Paul.

Submit to StumbleUpon

About Paul Firth

A games industry veteran of ten years, seven of which spent at Sony Computer Entertainment Europe, he has had key technical roles on triple-A titles like the Bafta Award Winning Little Big Planet (PSP), 24: The Game (PS2), special effects work on Heavenly Sword (PS3), some in-show graphics on the BBC’s version of Robot Wars, the TV show, as well as a few more obscure projects.   Now joint CEO of Wildbunny, he is able to give himself hiccups simply by coughing.   1NobNQ88UoYePFi5QbibuRJP3TtLhh65Jp
This entry was posted in Self improvement, Technical and tagged , , . Bookmark the permalink.

37 Responses to 10 steps to becoming a better programmer

  1. N0ll says:

    Would not following the official style guide for the language go hand in hand with number 7?

    Because I found it a bit interesting that you pointed to that readability is important and then went against the style-guide for Java :o)

  2. John says:

    Your self documenting code example could be better.

    With player.m_IsInvincible and player.m_IsDead the player is the active element.

    Then

    player.InflictDamage( damageAmount );

    reads to me as if the player is inflicting the damage. The method should be called takeDamage or sufferDamage.

  3. Sohaeb says:

    Good website/resource that teaches us to write less code ?

    Thanks for the tips. They were 11 :-/

  4. Milo Yip says:

    As a suggestion, in GetConvexPolygonArea(), the modulo operator and duplicated fetch can be eliminated by little rearrangement:

    Vector2 P0 = vertices[vertices.Length - 1];
    for (int i = 0; i &lt; vertices.Length; i++)
    {
    	Vector2 P1 = vertices[i]; 
    	area += P1.Wedge(P0);
    	P0 = P1;
    }
  5. Mark says:

    Excellent reading, thanks!

    To be honest – its amazing how much C# looks like Java, I thought the same as well :p. For an inexperienced programmer like myself do the same coding principality’s like camelCase not apply to C# also?

    Thanks again Paul!

  6. vamapaull says:

    Very good tips and very useful for any programming language.

  7. Kickpuncher says:

    I love the simplicity in the Write Less Code example of the lowly boolean. I don’t know why, but things like this never occur to me. Time for some tidying up :)

    Great article

  8. Johan Wendin says:

    The problem with # 11 is that if you ignore performance implications during development and simply react to reports at the end of the project, you will end up with equally slow code all over without clear bottlenecks. Optimisation at the end of the project also means real – proper – optimizations which might need refactoring is even more error prone, if at all possible to perform.

    Premature optimization might be bad, but failure to plan for performanve is even worse.

    • Paul Firth says:

      Not necessarily. The learned programmer will always intend to write good fast code using practices that he/she has learned over the years, so that what they produce as a first pass might very well be passable long term. Forcing these people to be overly analytical about the performance of their code before it’s shown to the profiler can waste valuable time.

  9. ctrahey says:

    “9. Don’t use magic constants”

    Let me suggest #12: “Be intentional with word choices.”. #9 here does not describe why not to use “magic constants” or even “constants”. You are advocating (rightly) against “literals”. In fact, “constants” are the solution, and “magic constants” are kinda a different topic.

  10. Ruud says:

    I consider the following to be more elegant, but it is of course a matter of taste.

          return vertices.Aggregate( new { Area = 0.0, Previous = vertices.Last() }
                                   , (acc, current) => new { Area = acc.Area + acc.Previous.Wedge(current), Previous = current }
                                   , acc =>; acc.Area / 2 );
  11. Viktor says:

    I would say that #8 isn’t OOP style at all. For better readability it should be player.MakeDamage(int damageAmount);

    And I would also add that every method should be named as action (verb) and not noun

  12. Simengie says:

    Your number 6 is a horrible example. If after all code is written that is the state of the code then it is a fair optimization. But during development the if else is the better structure. Unless you are all seeing there stands good reason and chance that more work will need to be done based on that result.

    As someone that did software maintenance on systems for many years after the first developers left the project I can say your number six advocates hard to maintain code over the total life cycle. Why? Well to add more work to your test I have to re-write the test and that increases the chance of errors getting in the code. It expands the testing required to validate the newly wrote test condition. If the if else structure had been left in place then the testing requirement would be simpler as it would need to make sure the code works for the conditions. Where as your example would have been re-written forcing a test for the condition still being correct as well as the old variable getting set properly.

    I find amazing that people think nothing about long term support of software in which an entire other group wil be doing the support. I have seen items based on your nu ber six actually add days to the testing cycle.

    I am going to assume that you have never worked on projects that have code base developed by 30-100 developers over a 3-5 year period numbering in the 2+ million lines of code size. Otherwise maintain ability would be the first thing you discussed.

    • Paul Firth says:

      You assume incorrectly. I’ve been part of just such a sized team over the course of 7 years on code-bases easily that size.

      Your objection makes no sense; its just as likely to be written incorrectly the first time in the long form as it is to be re-written incorrectly from the short form. The fact that the short form has less characters means there is less room for error from the start, thereby preventing potential bugs.

      Additionally, every change to the inner logic of a conditional will require more unit test code to check the functionality; that is just a fact of life.

      • Simengie says:

        It is clear that you and I have not worked remotely close to the same software worlds during our carriers. The simple point is that such simplification of coding would be against the standards of many companies I have worked with and for. I could write a book on why this point is an issue but instead I will just leave this alone.

        Elegance in coding does not always make for long term maintainable code. A random engineer 10 years from now that sees your code in commented long form will be much happier with you than seeing it in short form and knowing the extra work it means.

        Consider the US Air force has over 35 billion lines of Ada code that is nearing 25+ years since development still controlling very critical systems to this day. Would you as a maintainer hope for long form code that might give you a clue what is going on or elegant code that is just WTF were they thinking?

        Your C#, Java, C++ code could be part of the next code to be used for 25+ years and would need to survive all that time across many platform changes and compiler versions. So consider that before you go simplifying your code to reduce potential typo errors the first time it is written.

        • Paul Firth says:

          Lets just agree to disagree. You have your opinions about what’s been best in your experience and I have mine. Even if you disagree about this particular example of how to write less code, the general idea stands; less code means less bugs, less maintenance, less debugging and greater productivity.

          • typo says:

            I prefer the long version. Its way more easy to “grasp” what it does than the short version. If someone else has to read your code, it WILL take more time with these short versions (it adds up in large projects)

          • Paul Firth says:

            It depends on how long you’ve been programming I guess. To me its just as easy to parse as the long version. I’m beginning to think I picked a bad example of how to write less code because it seems this one is quite contentious :)

          • ph0nk says:

            I totally agree with you Paul. Long code = more error prone, longer to read, longer to analyse and understand… And your example is just perfect.
            Want to add more conditions? Use boolean logic, don’t imbricates if else statements in an unreadable mess of brackets just to output a boolean.
            Anyone who used it 2 or 3 times can read it instantly.

          • Fafase says:

            I somehow agree with Simengie.

            I think of ternary operator which will always take someone who did not write it a little while to grasp.

            Also that would mean you recommend this:

            fctA(FctB()FctC(parameter));

            Instead of

            a = FctC(parameter);
            b = FctB(a);
            FctA(b);

            Well, programming is like philosophy, everyone is right, everyone is wrong.

          • Paul Firth says:

            I think this point is quite a contentious one; I’m wishing I’d chosen a better example of what I meant in the article now.

            Of course I wouldn’t recommend your counter example because it would be unnecessarily confusing and would rule out the possibility of having self documenting code via variable names.

            Writing less code is good, but not at the expense of readability – the line must be drawn somewhere and that choice is down to you at the end of the day.

  13. Sounds to me like item 12 should be “Avoid off by one errors.”

  14. Thunk says:

    Nice article! I have to mention that Paul is absolutely right with no 6, its a good example, he’s spot on. I think item 12 should be, avoid multiple return statements.

  15. urshia says:

    I need some help to do my course work actually I was trying to make line segments of different color and it suppose to be moving and the starting point of each line segment should blink the width and color of the line segments is determine by via random numbers.

  16. George says:

    So many bashers. Only a handful of them have actually programmed enough to talk. Anyways, good article. I will be giving this a try with the Flex SDK to see if I can make a 2D platformer.

    I would have done it in XNA (as I have with several small projects), but the fact that XNA is getting old and Microsoft could pull the plug (take down the XNA redistrubitables) at any point, I’d be practically left with a dud that no one could play after spending months on it.

  17. Violetta says:

    I’m not a professional programmer, but I’m surprised number six was so controversial. Of course it’s possible to make optimized-but-undocumented code too confusing to be legible, but to me the example given seems equally readable in both forms.

    Anyway, thank you for the tips. I’ll try to keep them in mind when I get my software projects off the ground, at least to the extent possible without colleagues.

  18. Ruiz says:

    This was an excellent read. The philosophy behind your coding style matches more or less with mine. I’ll be graduating from college soon and will be working in a SCRUM-like environment, so steps 2, 3, 4, and 5 really stand out to me for some reason.

    I had a question about #3 though, as it didn’t really have a solution. In your experience of working, if you MUST rush meet a deadline, is it better to submit a non-functional masterpiece along with an explanation as to why it’s not working or a jerry-rigged contraption that at least works?

    I’m sure that many college programmers can agree that there are many situations where you’ll end up rushing to get an assignment done. You can have the most beautiful code imaginable, but if it doesn’t work or meet the assignment requirements, then it means nothing. You fail your assignment, end of story.

    I’ve worked on different team-based assignments with other students, many who have recently graduated. Some of their coding style tends to be bad and contradicts many, if not all of your points. By the time graduation comes, I feel like a lot of students have been taught to just “get it working.” Surely this isn’t right, but I was just wondering your thoughts on the matter.

    • Paul Firth says:

      Hi there,

      In my experience, academia is far more interested in the process you used to create the solution to a problem than the actual solution itself. I’ve seen many students submitting broken code with excellent write ups getting top marks.

      In the private sector things are very different, of course, but rushing code to meet a deadline will be worse in the long-run than the delay taken to do things properly up front IMO.

      Cheers, Paul.

  19. Arthur says:

    Another tip:

    Adopt guard based programming if at all possible. Guard based programming is using the pattern:

    void someMethod(void)
    {
    if (guard conditions == false)
    {
    handle failure of guard condition. logging / messaging / simply returning
    }

    apply the method behavior needed.
    }

    One nice thing about this model is that it tends to reduce the need for deeply nested methods. This may not be appropriate for languages like C (in some contexts, it may also be awesome. it depends on the domain).

    Tip 8 rewritten using this behavior would be:

    void DamagePlayer(Player player, int damageAmount)
    {
    if (player.m_IsInvincible || player.m_IsDead)
    return;

    player.InflictDamage( damageAmount );
    }

  20. Paul Firth says:

    The verb used in the article is ‘Inflict’ which is much more descriptive than ‘make’, not sure where you got that from?

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>

WP-SpamFree by Pole Position Marketing