poniedziałek, 30 maja 2016

Atomic code

Initially, when I was writing code 2 years ago, when I was a complete noob, I used to pack everything inside one huge function that was doing something. Whether it be some socket.on('event', function(){ ... } or some other functionality, I would literally try to do everything in one function, and it would grow and grow infinitely. Functions 200-300 lines of code long wouldn't impress me one bit back then. Now I would grab my head and probably start pulling hair off seeing such thing.

It was hard to read. I remember that feeling. It was really tiresome to read all that action happening in once place.
It was hard to maintain.
It was hard to understand after a while.

We, coders, are writers. We write stuff. We read stuff. We read more stuff than we write. And without proper training and approach we tend to screw things over and over.

I've been trying to change the way I write code. I try to divide code into smaller parts (functions) with meaningful names. Sometimes it's difficult to choose a good and short name for a function. It requires some active thought process. Now when I read my code, I notice most functions are quite small, 1-5 lines of code. Some are bigger (10-40) or even 80 but the general tendency is to make things smaller (I'm going to have another look at those 80 lines).

Now, atomic code is not to be confused with compact/short code. 1 letter variable names are good for minified, production ready code, but not for maintaining. It is good to know some shortcuts, sometimes they are useful, but it is important to remember that we write code mainly for humans to read and only sometimes for machines to execute.

Also, don't be afraid to split your code into separate files. I find it best to put 1 'class' into a file (+ dependencies etc) and name the given file with the name of the class.

That's it for this post.

niedziela, 29 maja 2016

Flat code

This is more of a philosophical approach to writing code in general. It is true that we, human beings, can do elaborate and create complicated things, but it is essential to notice that most of the time spent on 'programming' we actually spend 'maintaining' the code.

If you write 20 lines of code, then go to drink a cup of coffee and come back after 10 minutes, now you're maintaining the code you had written earlier. You might not remember what each part of the code does, you might need to read it again and recreate the whole picture in your mind. It doesn't matter how fast you write (being a programmer) because the time you spend on actual writing is, I would argue, far less than 10%, maybe even closer to 1% than the 10%.

I've noticed some uncomfortable habits people have when writing code, especially if statements. Nested if statements.

Let's say you have the following piece of code:

  • const condition_1 = ...;
  • const condition_2 = ...;
  • if(condition_1) {
    • if(condition_2) {
      • // do some stuff
    • }
  • }

Now let's have a closer look at this code. You have some 2 conditions (3 dots `...` represent some boolean value extracted from another method, ternary operator etc). What if I had more nested if's? What you can see here is the beginnig of so called 'Pyramid of Doom' where code marches to the right substantially fast (instead of downwards). My solution is this:
  • const condition_1 = ...;
  • const condition_2 = ...;
  • if(!condition_1) {
    • return; // end of story, nothing more to do here
  • }
  • if(!condition_2) {
    • return; // end of story, nothing more to do here
  • }
  • // do some stuff

If you are able to grasp the most basic if-then event chains then you surely have noticed that condition_2 cannot be executed if condition_1 isn't true, so everything after condition_1 doesn't matter if the condition equals false.

Obviously you might say 'Wait a second, but why are you returning? Shouldn't it all be wrapped in a function?'. It should indeed. My goal, when writing code, is to extract such nested if statements into a separate function and then inside the function I can use return to immediately stop any further execution. This way you have more atomic code, easier to understand and also easier to read. Seems more logical to me than terribly looking nested conditions.

That's it for this post, I might add/edit something soon.