Ineffective Coding Habits - What To Avoid

There are two kinds of people in our field, i.e., programmers and good programmers. Well, we all have been programming for ages but not all of us write the code so effectively that we can qualify as good programmers. In this article, I’m going to talk about the habits which hinder us from coding effectively. Not only that; we’ll also be looking into how one can code cleanly and effectively. But let’s start by looking into ineffective coding habits.

Cluttered Code

We have always been told to practice commenting. Comment what you write for others to understand it. Well, in my opinion, comments are sometimes stupid. Have a look at the following.

  1. /* 
  2. set the value of the number integer to 32 
  3. */  
  4. int number = 32;  

There’s no need for such comments to be added as the code is simple and self-explanatory. Comments are ignored by the compiler and usually by programmers too. Do you read instructions unless you get stuck? I remember my first year at college when one of my professors said something like “Good Code is self-documenting” And, I pretty much agree with that. If your code is incomprehensible in the first place, why do you think you’ll be able to express yourself clearly with words?

A common fallacy is to assume authors of incomprehensible code will somehow be able to express themselves lucidly and clearly in comments. But, does that mean you should never comment your code?

 Coding Best Practices

Oops! That hurts. There are places where commenting can save you curses. Here’s a good example from Lodash (A JS library).

  1. function addSetEntry(set, value) {   
  2. /*  
  3. Don't return `set.add` because it's not chainable in IE 11. 
  4. */   
  5.     set.add(value);   
  6.     return set;   
  7. }  

Also, documenting comments are sometimes necessary. Best practice is to know when and how to comment and also to write a simple, compact, and self-explanatory code.

Off-Line writing

Have you ever come across something like this?

  1. for (int i = 0; i < 10; ++i) { if (i % 2 == 0) continue; array[i] += 2; }  

This is pretty short of a line. Imagine if you have to scroll horizontally to read the code and how annoying that is. Also this piece of code is not very readable. Let me write it in a bit better way.

  1. for (int i = 0; i < 10; ++i)   
  2. {    
  3.     if (i % 2 == 0) continue;    
  4.     array[i] += 2;    
  5. }    

Introducing some spacing and indentation makes our code more readable, less confusing, and undoubtedly less annoying. Be nice! Not everyone has 2 monitors to look at a single line of code.

Agglutination

Most of you won’t be familiar with this term and wonder what the heck is it. Agglutination is a linguistic process in which complex words are formed by stringing together words each with a single grammatical or semantic meaning. And the reason I brought up this term up is that the concept I’m trying to explain is pretty much the same. When coding, most programmers join different words together to come up with a function or method name, e.g. -

  1. public interface ConditionChecker  
  2. {  
  3.       boolean checkCondition();  
  4. }  

Yet, there exists a better way to do the same.

  1. public interface Condition  
  2. {  
  3.     boolean isTrue();  
  4. }  

See the difference. Which one do you think is better? Also, it’s a common practice to write something like this.

  • OverflowException
  • IndexOutOfRangeException
  • InvalidOperationException

Well, you might say that these are some good names. But do we really need to state the word Exception? We don’t name our other classes as Non-Exception then why this? You don’t need 256 character long complex names for your methods to make sense. Omitting some extra words make much more sense, i.e.

  • Overflow
  • IndexOutOfRange
  • InvalidOperation 

So, omit all the extra words whenever you can and try to practice simply to be a more effective programmer.

Under-abstraction

Before talking about under-abstraction, we need to know what abstraction is. Abstraction means to hide the complexity details from the outside world. Think of a car. You don’t need to know how the engine works, rather just how to drive the car. That’s what abstraction is all about. Now that we’re talking about under-abstraction, some programmers spill the implementation details over to the user just as you’re made to know the underlying working of a car. Would that make much sense or be useful? Just not that people tend to use the data types and structures that are already there. In cases, this is not really effective. Observe the following.

  1. If (profileByUserId.get(user.getId())    
  2.      .containsKey(profile.getId())    
  3.   {    
  4.          ……    
  5.   }    

 Coding Best Practices

This is exactly what happens to most of us when we look at our code later but nobody wants that. How about we code the above lines somewhat differently?
  1. if (user.canView(profile))  
  2.   {  
  3.        ……  
  4.   }  

Isn’t that more elegant and readable? All we need to do is to convey the meaning of the object and that cannot necessarily be done using string literals, integers etc. Rather, you’re free to use your classes, your layers of abstractions. So, abstract whenever it is convenient and think hard when it isn’t.

Un-Encapsulation

Again let’s talk about what is encapsulation first. This is another OOP concept meaning enclosing something in or as if in a capsule. You only provide an interface to the user to allow access. Let me get back to the car analogy to explain what I mean. The car on the whole can be thought of as a class. It contains the data as well as operations (service mechanism) which are wrapped under a single unit; i.e. Car. You can only interact with the provided interface; i.e., steering wheel to drive the car. That’s the whole concept of encapsulation that you hide the details and provide an interface to access the object. One common way to do it is to set the objects and methods to private and use getters and setters to access and manipulate them.

If you’ve ever worked with encapsulation (which I’m assuming you did), you would know the getters and setters. Unfortunately, most programmers think that encapsulation is all about getters and setters (That’s where lousy encapsulation lays its feet on the ground). Creating getters or setters methods is not something just to access the private attributes (pretty much what most people think it is). But when creating getters and setters for all attributes we should think if they are really necessary or not. We are exposing “things” that shouldn’t be exposed. Let me explain it with a simple example.

  1. public class WashingMachine {  
  2.    private String state;  
  3.    public WashingMachine() {  
  4.        this.state = “stop”;  
  5.    }   
  6.    public void nextState(){  
  7.        if (state.equals (“clear”)) {  
  8.             state = “caution”;  
  9.        } else if (state.equals(“stop”)) {  
  10.             state = “clear”;  
  11.        } else {  
  12.             state = “stop”;  
  13.         }  
  14.    }  
  15.    public string getState() {  
  16.        return state;  
  17.       }  
  18. }  

In this example, we’re able to get the current state and also change it. However, the rules for changing are something internal with complex details and aren’t the responsibility of the user. The washing machine would work fine without exposing these implementation details as well. Observe the following.

  1. public class WashingMachine {  
  2.      private String state;  
  3.      public WashingMachine(WashingMachine machine) {  
  4.           state = machine.getstate();  
  5.      }  
  6.      public String getState() {  
  7.           return state;  
  8.      }  
  9. }  

The above code is more compact and is more effective. The point is not to make use of common software development principles; rather, use them effectively.

Poisonous Tests

Anyone who has been in software development for a long time can easily relate to the importance of unit testing. The most common practice is making a test function for each function in the code.

  1. Public class RecentlyUsedTests {  
  2.      [Test]  
  3.      public void TestConstructor() …  
  4.   
  5.      [Test]  
  6.      public void TestAdd() ……  
  7.   
  8.      [Test]  
  9.      public void TestSub()……  
  10.   
  11.      [Test]  
  12.      public void TestDestructor()….  
  13.          …..  
  14. }  

But, this makes for a testing that’s often incomplete and also hard to read. And then, there’re bad tests to add to the burden. It's overwhelmingly easy to write bad unit tests that add very little value to a project while inflating the cost of code changes exponentially. Let’s take a look at a test for reading current system time.

  1. [Test]  
  2. public void GetTimeOfDay () {  
  3.     try {  
  4.          //At 6AM it returns morning  
  5.         string timeOfDay = GetTimeOfDay();  
  6.         // Assert  
  7.         Assert.AreEqual("Morning", timeOfDay);  
  8.       }  
  9.     finally {  
  10.         ...  
  11.      }  
  12. }  

And yet, this test is expensive to write and unreliable as it may fail even if there are no bugs in the system under the test, due to system permission issues. There’s no guarantee it will run fast too. So this is not exactly a unit test (though it pretends to test and edge the case but requires a special environment setup for that) and so is not worth it.

Now, to sum it up all, let’s bullet out some points to code effectively.

  1. Readability first
    Always write code that is simple to read and understandable for developers.

  2. Architecture matters
    Coding without an understanding of its architecture is useless. Before writing the first line of the code, you should know what it will be doing, how, what it will use, how modules, services will work with each other, what structure will it have, how it will be tested and debugged, and how it will be updated.

  3. Tests are nutrients
    They are good if they make sense and add value to the project. They will shine brightly when you’re writing modules, microservices, or open source. Remember that badly written tests are more harmful than not test at all. So, be careful when testing.

  4. Comment only when necessary.

Now, sit back, get a paper pen, maybe, and write that you won't write bad code again.

Coding Best Practices 
 
Happy effective coding to you all. :) 


Similar Articles