Bug Free Coding – Immutable or Immutable Variables
The code of every big project has more or less bugs, but if you write the code according to some rules, the bugs can be reduced. While doing software engineering I learned some rules which were not learned while doing contests. The most important of these I think is the concept of immutable variables/objects.
This text is for software engineers and advanced students, if you haven’t worked on a big project yet, you may not understand the concepts properly. I will give some examples using Java but the concepts are true for any programming language.
The only reason there are bugs in code is because the values of variables keep changing. If the value of a variable is one in line 10 and another in line 20 then it becomes quite difficult to debug.
The way to avoid that is immutable variable. An immutable variable is a variable whose value cannot be changed or mutated, i.e. the variable is a constant. Similarly, immutable objects can also be modified. In C++ we create immutable variables using const keyword, in Java we use final keyword.
Now you can tell how to perform a task without changing the value of the variable? The answer is ‘transformation’. Whenever we need to update the value of the variable we will use a new variable. Let’s look at a very simple example:
An employee’s bonus is calculated in this code. What is the problem with this code? Apparently there is no problem but if anyone tries to debug the part C part he has to notice how the value of salary is changing above. Debugging can become quite difficult if the code logic is complex.
Good practice is to declare salary as final and assign it to another variable when the value is changing, something like this:
Now in this code it will be much easier for the developer to keep track of the employee’s salary. The value of the salary variable is not changing, using another variable when there is an update.
Also notice that I’ve also made the function parameter userId final so that I’m sure I’m not changing the value of the parameter.
Still having problems with this code, the problem is with this line:
Here we change the value of the variable inside the employee object which again reduces the readability of the code. We could declare the object like this:
By doing this, no new object can be assigned to the employee variable. But the values of class variables can still be updated.
To solve this we look at the Employee class. Normally in Java we declare classes like this:
We declare class variables private and update their values using setters, access values using getters. This maintains the encapsulation property of object oriented programming, better than updating values directly.
But the big problem with using setter is that the variables values can be updated every time, the class is no longer immutable. Removing the setters and making the class variables final solves our problem:
This time no one else can update the value of this employee object (can still be updated using reflection but not going into that discussion). Now our first code will look like this:
Now we can be sure that no variable value is changing in this code.
One thing we often say in software engineering is “There is no silver bullet”. This means that there is no one method that will solve all your problems, all methods have negative aspects. For example, declaring a new object or variable for transformation takes extra space. But most of the time that’s not a problem because the size of the object is usually small and the garbage collector removes it from memory when the lifecycle is over. However, if for some reason the object is too big, you should think twice before declaring a new object.
Whether you work in Java or any other language, you have to learn to maintain some immutability in that language. But in many cases you will have problems maintaining your immutability in the imperative method. For example, if something needs to be done using a flag or counter, then maybe you have to write code like count++ or flag = true, in which case count or flag is no longer a constant.
The solution is to use functional programming. Nowadays many languages support functional programming, functional programming can be done in Java 8, Python can do it even earlier. Functional programming will make your code much cleaner and the number of bugs will be reduced. I will discuss that in detail another day.
After reading today’s post, it will be your job to educate your entire team about immutability and enforce it during code reviews. And refactoring old code when time permits. And if you can learn functional programming, then within 2 months you will see that your project code has improved a lot.
The time complexity of several problems can be reduced to O(Sqrt(n)) using the square-root decomposition technique. Let’s start with an example. Let’s say you are given an integer array and given some operations. The operation can be of two types, one is to find the sum of all the numbers in [l,r] index, the other is to update the value of the i-th index. Many may solve this using segment trees or binary indexed trees. Today we will learn another new method to solve it.
What do we do in a very general way? Every time I ask to find the sum, I will run a loop in [l,r] range to find the sum and the update operation will update only the i-th index. In that case the complexity of finding the sum is O(n).
Now we will try to divide the areta into some segments. Then, when calculating the sum, the sum of each segment must be calculated. See the picture below:
Our array size was 13. We want to partition such that the size of each segment is approximately the same, and the size of the segment and the number of segments are approximately the same. The square root of 13 is 3.61 3. If we divide the areta into segments of size 3, we get 13/3=4 segments, each of size 3 except the last segment.
If the size of the array is not itself a square number then we will get one more segment and the size of the last segment will be a little less, that is not a problem. We will understand why it is beneficial to share this way a little later.
Now if we have [l,r]
If we ask to query the range, we will only see which segments fall within our range and calculate the sum of those ranges.
First we need to pre-process the segments. See the code below:
We are traversing the input array and every time i
Moving on to the next segment.
The sum of the segments for the range is shown in the next figure.
The problem is that not all segments fall completely within our range. If the first and last segments do not cover the entire range, we need to loop over those two segments to find the sum. We have sqrt(n) segments, and the size of each segment is sqrt(n), at most two segments have to be looped, so the total complexity of the query is sqrt(n). That’s why we kept the segment number and segment size as close as possible.
Now a small question. How to know which segment i is located in for an index i? Very simple, i/segmentsize
Its value can be understood.
The following code shows how to query:
We have divided the query into 3 parts which we discussed earlier.
Finally updated. Update is very easy, i
To update the th index, find out which segment i is in and update its sum.
The update complexity is O(1).
This is a very simple problem. LCA of tree can also be calculated using this technique, if you want to learn that you can see this link. And those who are a little advanced level can see this PDF.
You must Join our Facebook Group and Subscribe YouTube Channel
All Links in Below:
Join Our FreeWebsiteCreate Facebook Group to get an instant update for projects, templates, design resources, and solutions.
Join Our YouTube Channel & Subscribe with Bell Icon for New Video:
Join Our Official Facebook Page For the Latest updates All Code Projects are Free:
Visit our service page to get premium services.
You must Join our Facebook Group and Subscribe YouTube Channel