Let AI write emails and messages for you 🔥

Linear code is better than non-linear code

Gourav Goyal

Gourav Goyal

Sep 15, 2023

Below are the characteristics of a well written code:

  1. Easy to understand by others.
  2. Easy to recall by you.
  3. Easy to refactor by you and others.

Linear coding style helps in that. When I refer to "linear code", I generally mean code that is written in a straightforward, top-down manner without nested structures, which can be more readable because it tends to follow a single, simple path of execution. Linear code simplifies debugging since developers can more easily predict the program’s behavior at each step. Going through the code step by step, it becomes straightforward to identify and isolate bugs. Remember that code is read much more often than it is written.

Example 1 using React

Let's explore this through an example where a component fetches and displays user data:

Linear code

import React, { useState, useEffect } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchUser = async () => {
      try {
        const response = await fetch(`https://api.example.com/users/${userId}`);
        const data = await response.json();
        setUser(data);
      } catch (err) {
        setError(err);
      }
    };
    
    fetchUser();
  }, [userId]);

  if (error) {
    return <div>Error loading user data</div>;
  }

  if (!user) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}

export default UserProfile;

Here, I have a linear and straightforward component that fetches and displays user data. The steps are sequentially ordered, and the data fetching logic is contained within a single useEffect.

Non-linear code

import React, { useState, useEffect } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [error, setError] = useState(null);

  const fetchUser = () => {
    fetch(`https://api.example.com/users/${userId}`)
      .then(response => response.json())
      .then(data => setUser(data))
      .catch(err => setError(err));
  };

  useEffect(() => {
    fetchUser();
  }, [userId]);

  const renderContent = () => {
    if (error) {
      return <div>Error loading user data</div>;
    }

    if (!user) {
      return <div>Loading...</div>;
    }

    return (
      <div>
        <h1>{user.name}</h1>
        <p>{user.email}</p>
      </div>
    );
  };

  return <div>{renderContent()}</div>;
}

export default UserProfile;

In the non-linear approach, while still performing the same task, I've split the rendering logic into a separate function, and I used Promises to handle the fetching logic, which creates multiple paths of execution and could potentially lead to a more complex structure with nested conditions and callbacks, known colloquially as "callback hell". While both approaches get the job done, my preference is the linear approach for its readability and maintainability.

Example 2 in Javascript

The task here is to find and log the first even number in an array.

Linear code

const numbers = [1, 3, 5, 2, 4, 6];

let firstEvenNumber = null;
for (let i = 0; i < numbers.length; i++) {
  if (numbers[i] % 2 === 0) {
    firstEvenNumber = numbers[i];
    break;
  }
}

if (firstEvenNumber !== null) {
  console.log('First even number:', firstEvenNumber);
} else {
  console.log('No even numbers found.');
}

In the linear example:

  1. I clearly initialize our variable firstEvenNumber to null.
  2. I have a straightforward loop that iterates over each element in the array until it finds an even number, at which point it breaks out of the loop.
  3. After the loop, I check the value of firstEvenNumber and log an appropriate message.

Non-linear code

const numbers = [1, 3, 5, 2, 4, 6];

numbers.find((number, index) => {
  if (number % 2 === 0) {
    console.log('First even number:', number);
    return true;
  } else if (index === numbers.length - 1) {
    console.log('No even numbers found.');
  }
});

In the non-linear example:

  1. I use the Array.prototype.find method with a callback function to find the first even number.
  2. Inside the callback function, I have nested conditional statements to handle the logging of the even number or the message indicating no even number was found.

While the non-linear example is more concise, the linear code can be seen as more readable because:

  1. Each step in the logic is clearly delineated with separate operations distinctly separated.
  2. The linear flow of the code makes it easier to follow the logic step by step, facilitating debugging and understanding, especially for those less familiar with JavaScript's array methods and callback functions.
  3. It avoids nested structures, which can sometimes introduce complexity and make the code harder to read and understand at a glance.

In summary, linear code tends to be more readable because it follows a straightforward, top-down approach with a clear flow of logic, making it easier to understand and debug.

That's all, folks!

Gourav Goyal

Gourav Goyal