10/24/2018

10 small tips for better code readabilty

I can’t stop to write about the importance of code quality and code readability. I think this is one of the most important point at coding. On the other hand I have been already working for several companies and I sadly realised, that the code quality is really poor at most of the companies, even at the famous ones.
In this article I collected 10 small points. It is not so difficult to follow them and if you are following them your code will be much more readable. I added some examples in C++, but all these points can be easily adapted to any other object oriented programming language.
It can be that some of you will be against my points. First of all there are some mostly old-fashioned coding styles which are contradicting with my points. On the other hand some of these points can be a bit against performance. Of course there are special cases when not all of these points should be blindly followed. But I think these 10 small points can make your code quality much better. I hope you will like the points.

1. Use the right variable/function names


The rule in principle is pretty easy, in practise it is not always so easy: you should call everything based on that what it is. So avoid variables like i, j, x, y, value, return_value etc. Name your variables and functions well. I present it with an example:

vector<vector<int>> getThem()
{
  vector<vector<int>> vector1;
  for (vector<?int> x : theList)
  {
    if (x[0] == 4)
    {
      vector1.add(x);
    }
  }
  return vector1;
}
 


Do you understand not what is this function doing now? I’m sure, you have no real idea. Now I changed the names in the function, is it more clear now?



vector<vector<int>> getSelectedCells()
{
  vector<vector<int> selectedCells;
  for (vector int> cell : gameBoard)
  {
    if (cell[CELL_VALUES::STATUS_VALUE] == STATUS::SELECTED)
    {
      selectedCells.push_back(cell);
    }
  }
  return selectedCells;
}



What about now? Now it looks it is collecting the selected cells of a game board. Nothing changed, just the naming. That’s why naming is pretty important.


  1. Use constants instead of magic numbers 

    Try to avoid the usage of magic numbers in your code, it is making it unreadable. Let me have an example:
    
    int t = x * 24 * 3600 * 365;
    

    Where are these numbers coming from, what does it mean? It’s a bit unclean.
    int t = x * hours_per_day * seconds_per_hour * days_per_year;


    Is it easier to understand now?
    And let’s use what we already learnt in the first point:


    int seconds = years * hours_per_day * seconds_per_hour * days_per_year;
    

    Reorganise a bit:
    
    int seconds = years * days_per_year * hours_per_day * seconds_per_hour;
    
    

    Now it’s much more clear what is it, isn’t?


    1. Use enums instead of magic numbers
    In the code of inexperienced programmers I meet quite often with similar solutions:


    
    switch (status)
    {
      case 1:
        //do something
        break;
      case 2:
        //do something
       break;
    …
    }
    
    
    Ok, but what is the meaning of status = 2? Who knows. Use rather an enum for status like:

    Enum class Status { InProgress, NowAnswer, Error, Ok };

    It will make your code much more readable.


    1. Give a name to complicated conditions

      In most code there are a lot of complicated conditions, like:


      If (line > 5 && line < 100 && feature_enabled && !error_found && value == 5)
      


      In such case it is really complicated to figure out what is the condition about. It is a good idea to name the condition and/or the sub conditions. For that you can either use lambda functions or booleans, like:


      bool isLineInRange = line > 5 && line < 100;
      bool featureActived = feature_enabled && !error_found;
      if (isLineInRange && featureActivated && value == 5)
      


      Now it is much easier the figure out the meaning of the condition.



      1. Split up your function to smaller ones

        OK, this point is maybe trivial: if you have a function which is too long and/or is doing multiple things just create smaller functions which are decoupling a part of your function and call them from your function.

        1. Do one only one thing in your functions/methods

          This is connecting from the previous point. So for example if you call a function as SaveToFile I’m expecting from the function that it is saving something to a file and not changing anything on the current data. If you still need to change something on the data move that part of code to a new function. That’s really important, that your function need to do exactly one thing and nothing more: the thing what is in its name. So for example in a getter function don’t do complicated calculations. In that case just create a separate calculate and save function.


          1. Make a clear difference between functions and methods

            It is a personal opinion, but I’m following this point at coding and I think it makes the code readability really better.

            In my understanding a function is a subprogram with a return value. And in my view a function should not change the state of the object. So it should not change any object level private/public variable. Just read them, calculate the return value based on them and return. So for example in C++ they can be marked at const.

            The methods are subprograms without return value. So in C++ technically they are the void functions. The main goal of methods is to change the state of the object. Every change in the status of the object needs to be done by using methods.


            1. Organise your parameters/variables into structs

              There are several cases when a function have several (3+) parameters. Some functions have a really long parameter list over 10-15 parameters. When you are calling such functions it is pretty difficult to figure out which added value belongs to which parameter. That’s why I think it is better to organise your parameters in one or more structs, like:

              Instead of:


              
              drawRectangle(double x, double y, double width, 
                double height, int color_r, int color_b, int color_g)
              
              


              Rather use:


              
              struct Position
              {
                Position(double x, double y) :
                  x(x),
                  y(y)
                {};
              
                double x;
                double y;
              
              
              }
              
              struct Size
              {
                Size(double width, double height) :
                  width(width),
                  height(height)
                {};
              
                double with;
                double height;
              }
              
              struct Color
              {
                Color(int red, int green, int blue) :
                  red(red),
                  green(green),
                  blue(blue)
                  {};
                int red;
                int green;
                int blue;
              }
              
              drawRectangle(Position position, Size size, Color color);
              
              


              So that when you are calling it, instead of:


              drawRectangle(100.5, 54.3, 34.5, 23.3, 222, 144, 68);
              
              


              You can use:


              
              drawRectangle(Position(100.5, 54.3), Size(34.5, 23.3), Color(222, 144, 68));
              
              


              I think in this way it is much more clear what is the meaning of each parameter.



              1. Convert functions to classes if needed

                Especially in old code there are quite often function with multiple input and output parameters. Most cases I would avoid the usage of output parameters. But especially if there are multiple ones it is really better if you are creating a class, having all the parameters as private variables. Create  setter for inputs and getter for outputs.


                1. Cover your code with unit tests

                  Unit tests are really useful to verify your program and to avoid regressions. But it is even really good to have unit tests if you would like to understand a code. Simple you can see for each function and class what is their expected behaviour.


                  These were my points for this articles. I hope you like them, feel free to extend them if you have any other good idea.

                  10/18/2018

                  How to deal with bugs?

                  Introduction

                  Bugs are part of the daily work of programmers. Everyone hates them: the tester, the developer, the manager and the customer. So it is pretty clear, they should be removed as soon as possible. But what is the most effective way to do it. I can still remember, right at the beginnin of my career I needed to find a bug in a quite complex system and fix it and I was totally lost. So in the post I will share with you my way of “bug hunting”.

                  Before bug hunting

                  So the very first step is on the level of understanding: you should understand what should be the normal behavior of the programm and you should understand what is the bug itself and why is the buggy behavior not correct.
                  As next step you should be able to reproduce the bug. Never start to search for the root cause without reproducing it. It can also happen that the bug is not appearing at all on your system. At the reproduction phase make sure always about the following points: you are testing the same version of code as where the bug appeared, you are using the same operating system, all settings are the same, all other conditions are the same.
                  So if you would like to document a bug always write down the steps to reproduce the bug, the expected behavior, the current buggy behavior, the exact software version, all software settings and your system info.
                  Once you reproduced the bug you should find the bug, there are two ways from this point.

                  Finding the bug

                  The first one what I found really effective is based on the version controlling of the code. You should find the last version where the bug was still not present. Once you found it check which changes have happened between the last working version and the first buggy version, quite often you will find root cause at this point immediately.
                  The next method you really need to start with debugging. You need to try to identify first the component which includes the bug. For that you will check the inputs and the outputs of different components. One you found the component try to go one level down: on class level and later on do it on function level.
                  There are some things you need to think about always: if there is multithreading in your code think about the shared memory areas. If there is dynamic memory allocation always take a look if you did everything well with the memory. And if you are using 3rd party components always make sure if they are providing the currect values for you.
                  With a professional debugger software like gdb the duration of debugging can be much shorter. The other thing which can make the debugging faster is if the code is covered by unit tests. You simple need to check which unit tests are failing and it will lead you to the root cause.

                  These are my basic practices and I think with practice it will be just faster and faster to find the bugs, but the bugs can surprise you everytime.

                  10/11/2018

                  Being a specialist vs. being a generalist as a developer

                  Introduction
                  It is not easy for everyone to decide which carrier path would be the best for you as a developer, some of the developers know since their childhood in which field they would like to learn and others have an interest in almost everything. On the other hand it is not always up to you in which direction your carrier is going, sometimes your carrier is just driven by the opportunities which are coming. There are lot of different directions to improve yourself: different fields, programming languages, industries and roles. After some years of professional experience you will see for sure which is your direction: choosing one field, one language, one industry and one role and learning everything about that and being a specialist of the topic or working in multiple fields with multiple programming languages in multiple industries and changing between different roles, having a good overview of everything, but not really being a specialist in any of them. Both of them are quite typical and of course it’s not always binary, sometimes you are just half way between being a specialist and being a generalist, yes, life is complicated. But both situations have its own pros and cons, I tried to collect them.

                  Being a specialist

                  You count as a specialist if you have on really specific field and you are deep into that topic, but about other topics you don’t really have a knowledge.

                  Pros

                  • A lot of big companies are searching for these people
                  • You can reach a very good salary in that specific field
                  • If you are finding a position with that in that field then you have very good chances
                  • You are much better than most of the people in your field
                  • If there are good freelancer tasks in your field, then you can earn a lot of money as a freelancer
                  • You only need to be up to date in one topic

                  Cons

                  • It can be difficult to find a position very really your specialisation is needed
                  • Sometimes the specialisation is really company dependent
                  • If your used technology is getting obsolete, you need to start something new from scratch (like most of the Delphi programmers)
                  • As a freelancer the scope of tasks you can overtake is quite limited
                  • You are in trouble if you are getting a task where you used use an other technology

                  Typical work opportunities

                  • Senior software developer especially at big companies
                  • Freelancer with a specification
                  • Research projects at university or at a company or institute

                  Being a generalist

                  Pros

                  • You have a good wide-range overview on the topics happening in the tech world
                  • You can learn new technologies fast
                  • You are very flexible if you need a new job
                  • You are facing with any tasks you will find a solution
                  • At first round job interviews you can do a good discussion about a lot of topics
                  • You will find always new challenges
                  • As a freelancer you can overtake almost everything

                  Cons

                  • You need to follow the news regarding a lot of different languages and technologies
                  • There is not special field where you are the best
                  • However it is easy to find a new position, it is difficult to show that you are the best candidate
                  • Most of the cases you can not have such a good salary
                  • It is difficult to reach the next step of your carrier if you are changing your fields too often.

                  Typical work opportunities

                  • Start-ups/Small companies
                  • Consultancy companies
                  • Freelancer
                  • Start own business

                  Summary

                  As you can see both of them have advantages and disadvantages. I’m personally rather a generalist, maybe that’s why I could fine more pros there. I still think that to optimum is somewhere in the middle. For example a lot of companies are searching for people with “T-shaped” knowledge. Which means you are a generalist, but you are a bit deeper in one topic.

                  So I think it is always up to the person which sounds better. But I’m pretty sure that most of you have some experience in this topic. Feel free to share it as a comment!

                  10/04/2018

                  6 books you need to read as a software developer

                  There were some book which changed a bit my way of thinking regarding software development. I think everyone should read these books who have anything to do with programming.
                  The list is the following:


                  1. Robert C. Martin: Clean Code
                  I read this book shortly after I started to work as a software developer. At my first company it was a big problem, that all code was messy which caused quite a lot of issues. The book changed the way I’m thinking about programming and helped a lot during your carrier. But of course you need to handle it flexible: don’t follow blindly everything what you read.

                  1. Steve McConnel: Code Complete
                  This book is quite long, but it is covering almost everything what is connected to programming: requirements, debugging, refartoring, configuration management, documentation, integration, development, everthing.


                  1. Michael C. Feathers: Working Effectively with Legacy Code
                  This book was proposed for me by a colleague when we needed to refactor a quite complex old legacy tool. This refactoring was done succesfully, it was strongly decreasing the amount of bugs and it would not happen without this book.


                  1. Robert C. Martin: Agile Software Development
                  This book is much more about processes, but it is partially covering technical topics as well. It gave me a pretty good overview on agile processes. I read it when we started to work based on scrum at my current company and that was my first experience with scrum. It helped me to understand the whole process and gave me a lot of ideas for improvement.

                  1. Robert C. Martin: The Clean Coder
                  It is never enough to talk about code quality. If you liked Clean Code, you need to read this one as well!


                  1. Gayle Laakmann: Cracking the coding interview

                  The best book to read before starting job search and attending interviews. I got it a bit late, I read it before the first technical interview I lead at my place, but it was really helpful. I plan to write more about this topic later.

                  How I prepared my first online course

                  Since long I didn't publish anything here. It's because I was busy with some other topics, but now it's time to share the result...