time to read 8 min read

Write more efficient code

You may be a student, freelancer, software engineering professional, or simply an individual interested in coding. Yet, have you ever thought about how writing efficient code can be important for your software product? So let’s discuss some tips and concepts on how to make code more efficient.

Advantages of writing more efficient code

Suppose you are in a leading software company, and your manager asks you to have a look into an ongoing production incident. 

In such a case, first, you need to understand the issue and execute some debugging rounds to identify where the code is breaking. Then you need to understand the code and find a fix for the issue. However, it isn’t easy to understand the codebase and provide an ETA to deliver a fix if the codebase has,

  • Repeated the same function in multiple places
  • Unstructured folder structure and architecture
  • unnecessary loop executions
  • tightly coupled components
  • Unnecessary variable declarations

Hence the code should be clean and implemented using efficient coding techniques, best practices, and algorithms.

If so, that code can be reused (saving the efforts of rewriting the whole program from scratch) and modularized. Moreover, it will be easy to add new features to the existing codebase and easy to debug/ maintain with clear readability of the codebase.

Application performance is another significant benefit gained through efficient and optimized code. Suppose you have a shopping cart application with the following performance concerns.

  • Less page loading times and fast search results (i.e., Home page, item search results)
  • Less time to complete online transactions without unusual waitings or timeouts.

You need to have an efficient and optimized code to achieve the above performance benefits. It will definitely lead to more user interactions and help generate more revenue.

I believe now you have a clear idea of the importance of making code more efficient in your application. So let’s discuss some concepts and tips which you can follow to make code more efficient. 

Use appropriate design patterns and frameworks.

Utilizing a design pattern is a general solution for having a great software design against commonly occurring problems. In other words, design patterns provide solutions for previously occurred problems. A design pattern is not a complete design that can be directly transformed into code. Instead, it describes a proven template for a problem that occurred in the past. There are twenty-three design patterns that bring different solutions. Some most popular design patterns are Creational/Singleton, Decorator, Command Design Pattern, Factory Design Pattern, and the Observer Pattern.

After selecting the appropriate tech stack to implement your application, it is better to spend some time and conduct some POCs (Proof of Control) to find suitable design patterns and frameworks. Initially, you may find it time-consuming. However, it is really easy to manage all the SDLC phases after starting implementation with a strong design pattern. Besides, using a solid design pattern/ framework in your codebase provides numerous benefits, such as the following.

  • apply better & robust design and structure for the application
  • easy to apply new design solutions to an existing application
  • Speed up the development phase
  • Improved maintainability, and reusability of components
  • loosely coupled components, and high cohesiveness
  • reduced time, cost, and human efforts by reusing proven solutions and modules.

This way, you can write efficient code using a good design pattern. It is also highly recommended by experts and organizations in the industry. Most leading software organizations maintain their own customized frameworks and project structures for developing their products.

Use meaningful variable names and avoid declaring unnecessary variables

Always try to declare meaningful variable names when coding as it improves code readability. Even if the code is written by yourself and you refer to it after 1 or 2 months, you can forget the purpose of a variable or what kind of value is stored in it. Hence it can take additional time to carry out some debugging rounds to identify the purpose of the variable. 

So can you imagine how difficult it would be if someone else tried to understand or read that code? Hence, always declare meaningful variable names and try not to declare abbreviated variable names.

Another essential thing is to avoid declaring unnecessary variables. If you want to return a certain value instead of storing it in a separate variable, you can directly return the value. It will avoid declaring memory allocations in RAM. Thus it will improve the efficiency of the code as well as the application performance.

See the below example that includes meaningless & unnecessary variables.

getNetSalary = () => {
	double bsal = 10000;
	double ex = 2500;
	double netsal = bs - expenses;

	return ns;
}

You can make the above code more efficient by using meaningful variable names and avoiding unnecessary declarations.

getNetSalary = () => {
	double basicSalary = 10000;
	double expenses = 2500;

	return (basicSalary - expenses);
}

Use caching technologies & implement daemon jobs

What are caching technologies?

Caching service is a NoSQL database that stores key-value pairs. It can be used to store values against unique keys. You can store the value in the string, JSON, or any other format in key-value stores. Redis, Memcached, and AWS elastiCache are the most popular caching services these days. 

Now let’s see how caching services can help make your code more efficient.

Suppose your web application is a student LMS, and you are displaying the assignment submission count and the count of students enrolled for courses on the instructor homepage. 

You have to execute some database queries to get these counts. The easiest way to show these counts on the homepage is to execute queries while rendering the instructor homepage.

However, this method may cause performance degradation in the application and reduce efficiency. For instance, it will take a lot of time to finish query executions when new students enroll or add new submissions. It will lead to a high response time when loading the instructor’s home page. We can bring caching technologies to the table for such performance issues.

The tip is to implement a script to get enrollment/ submission counts and store them in a key-value store. This script is independent of instructor homepage loading and is daemonized (execute script in Linux background process). 

Daemon holds the responsibility of communicating with the database for new student enrollments or record submissions. When a new record is added, the daemon will execute the relevant queries and write counts in the key-value store. 

We only have to get the counts from the key-value store during the instructor homepage loading and display in the application frontend. It reduces the response time and removes the frequently executed heavy queries from the application during page loading. Thus the application code gets more efficient, and reliable by using caching technologies. 

Architecture diagram

This concept is a high-level solution for software products used in the industry to make the code highly efficient.

Apply Object-Oriented Concepts and identify common functionalities

It is valuable to identify the following facts instead of writing dirty and unstructured code.

  1. What are the main classes in our project?
  2. What are the parent and child classes?
  3. Common functionalities.
  4. Repetitive processes.
  5. What data should be hidden in subclasses?

You can implement the code using object-oriented concepts such as inheritance, polymorphism (method overloading & overriding), abstraction, and encapsulation to resolve the above issues. 

Now let’s discuss how to make the code more efficient using the above concepts.

You can implement/ identify parent classes and common functions and create subclasses by inheriting them. Then those inherited subclasses will be allowed access to the parent class functionalities. You can customize the common functionalities implemented in parent classes using operator overloading and overriding techniques in child classes.

Additionally, use encapsulation to protect and provide access levels to functions and variables.

You can enhance the efficiency of the code and implement uniform code using OOP concepts rather than writing the same code repeatedly. Check the following code to get a better idea of these concepts.

public class User {
	public int login(string username, string password) {
		//user login
	}

	public void draw() {
		//draw line
	}
}

public class Teacher extends User {
	login('teacher1', '123')

	//method overloading and overriding
	public void draw(string type) {
		if (type == 'Circle') {
			//draw circle
		}
	}
}

public class Student extends User {
	login('student1', '123')
	draw();
}

Reduce unnecessary code executions

Suppose you fetched some data from the database and stored it in an array as objects. Now you want to loop through the array and find a specific object. Once it is found, you don’t need to execute the loop or wait until it stops executing. You can use break; operator to immediately terminate the execution of the loop or the next; operator to skip the current iteration & jump into the next code block. You can eliminate unnecessary code executions by using this technique.

The following example shows how to break the loop and execute SendGiftCard() function when the 100th user is found.

var userData = getUserData(); //fetch user data
var userCount = userData.length
for (var currentUser = 1; currentUser <= userCount; currentUser++) {
	if (currentUser === 100) {
		SendGiftCard();
		break;
	}
}

Another tip is identifying repetitive operations, removing unnecessary costly operations from the loop, and storing them in a global state. The following code gets the word count of the text variable throughout the loop execution. Here, the problem is that the .length function executes throughout the loop execution even though it is unnecessary.

var text = 'Hello world'

for (var i = 0; i < 100; i++) {
	print `Word count is ${text.length}`
}

You can optimize and remove unnecessary calculations of the above code by storing the word count in a global variable.

var text = 'Hello world'
let wordCount = text.length

for (var i = 0; i < 100; i++) {
	print `Word count is ${wordCount}`
}

Declare constant variables in a single place & import them where necessary

You will have to declare numerous types of constant variables in your project, such as configurations, database connection string URLs, action types, constant names, and numbers.

For instance, declaring database connection string url within each db operation is not a good practice. Can you imagine how dull and risky it would be if you had to change the db username and password in every connection string? 

So the best way is to keep those kinds of constants in a single place and import them where necessary. Then you have to change only one place if you need to modify a certain value. Thus, this technique makes the code efficient by reducing developer efforts and typo errors.

i.e… Store constant values in a separate file as shown in the below code snippet.

export const FETCH_ALL = 'FETCH_ALL'
export const CREATE = 'CREATE'
export const PORT = 5000
export const CONNECTION_URL = "mongodb+srv://mongodb.net/myFirstDatabase?retryWrites=true&w=majority"

Then access those constants in separate files as shown below.

import {
	FETCH_ALL,
	CREATE,
	CONNECTION_URL
} from '../constants'

insertStudent = () => {
	mongoose.connect(CONNECTION_URL).then({
		//insert user
	}).catch({
		//error handling
	})
}

export default (posts = [], action) => {
	switch (action.type) {
		case FETCH_ALL:
			return action.payload;
		case CREATE:
			return [...posts, action.payload];
	}
}

Use and data structures and inbuilt functionalities

Instead of declaring multiple variables to store the same type of data, you can use data structures to store them using a single identifier name. 

The most commonly used data structures in the software industry are arrays, 2-dimensional arrays, linked lists, hashes, queues, and data dictionaries

The following tips make your code more efficient by using data structures.

Data structures such as arrays, lists, and hashes make repetitions more simple.

They allow users to store multiple pieces of data of the same type using a single identifier name rather than keeping multiple variables.

It is very efficient to store compound data sets using two-dimensional arrays and data dictionaries rather than declaring individual arrays.

In Some scenarios, we can avoid implementing loops and use data structures such as arrays or hashes with language-specific inbuilt functionalities such as grep, map, filter, and reduce.

The following two examples show code snippets on how to use grep and map functions.

Use grep instead of looping a whole array in Perl as shown below.

  my @array = [1, 2, 3, 4, 5, 6];
  my $match = 3;
  if (my($matched) = grep $_ eq $match, @array) {
  	print "found it: $matched\n";
  }

Use the map function in JavaScript to iterate an array instead of looping items and creating a new array.

const array1 = [2, 4, 6, 8]
const doubledArray = array1.map(arrayItem => {
	return arrayItem * 2
})

Conclusion

In this article, you learned the importance of writing efficient codes. Then you learned how to write efficient codes. In the end, it all comes down to having good knowledge of the subject. This is why you should learn coding from a good education platform. Sololearn is the perfect platform for you with courses developed by experts in the field. Sign up today to learn more about the Sololearn course.