DEV Community

Cover image for 5 essential tips to writing readable code
Tebogo Nomnqa
Tebogo Nomnqa

Posted on • Originally published at tebza.dev

5 essential tips to writing readable code

Code is often read than written, making code readability a crucial aspect of software development. Readable code is easy to understand, allowing developers to follow the logic effortlessly through the lines. In this article, drawing from my experience as a tutor for Rhodes University's Computer Science students, I'll share five essential tips for writing code that is not just functional but also a pleasure to read.

We will begin by looking at the following Python program

Before 🙃

def cc(s, k):
    r = ""
    for i in s:
        if i.isalpha(): 
            r += chr((ord(i) + k - 97) % 26 + 97) if i.islower() else chr((ord(i) + k - 65) % 26 + 65)
        else:
            r += i
    return r
t = "readable code?"
ct = cc(t,3)
print(f'{t} encrypted => {ct}')
Enter fullscreen mode Exit fullscreen mode

At first glance, can you tell what it does?

💡 ord(char) Given a string representing one Unicode character, return an integer representing the Unicode code point of that character.

chr(i) Return the string representing a character whose Unicode code point is the integer i

Let's go! 🚀

Whitespace: The visual guide

Whitespace is not just a formatting choice; it's a visual guide for developers. Avoid one-liner tricks that may save space but sacrifice readability. Use indentation consistently to indicate code blocks and create a visual hierarchy within your code.

def cc(s, k):
    r = ""
    for i in s:
        if i.isalpha():
            if i.islower(): # good ol if statement instead of tenary
                r += chr((ord(i) + k - 97) % 26 + 97)
            else:
                r += chr((ord(i) + k - 65) % 26 + 65)
        else:
            r += i
    return r
# add line breaks between sections
t = "readable code?"
ct = cc(t,3)

print(f'{t} encrypted => {ct}')
Enter fullscreen mode Exit fullscreen mode

Variable Names: The art of clarity

Picking descriptive variable names is like giving your code a friendly tour guide. When names are straightforward and welcoming, your code becomes a pleasant journey for anyone reading it.

It would help if you embraced a consistent naming convention across your codebase. Whether it's CamelCase or snake_case, be consistent to enhance readability.

Don't shy away from lengthy variable names if they accurately describe the content. A variable named user_input is far more informative than u_i. Descriptive names reduce the need for excessive comments, making your code self-explanatory.

For variables that represent a boolean value indicating true or false, it is advisable to use a naming convention that includes the "is" prefix.

ALPHABET_SIZE = 26
LOWER_A_ASCII = ord('a')
UPPER_A_ASCII = ord('A')

def caesar_cipher(text, shift_key):
    result = ""
    for char in text:
        if char.isalpha():
                if char.islower():
                    result += chr((ord(char) + shift_key - LOWER_A_ASCII) % ALPHABET_SIZE + LOWER_A_ASCII) 
                else :
                    result += chr((ord(char) + shift_key - UPPER_A_ASCII) % ALPHABET_SIZE + UPPER_A_ASCII)
        else:
            result += char
    return result

text = "readable code?"
cipher_text = caesar_cipher(text,3)

print(f'{text} encrypted => {cipher_text}')
Enter fullscreen mode Exit fullscreen mode

We also replaced our code's "magic numbers" with constants ALPHABET_NUMBER, LOWER_A_ASCII, and UPPER_A_ASCII.

Functions: The power of modularity

Functions in your code should have a single responsibility, encapsulating a specific task. The name of a function should precisely convey what it does. Break down your code into smaller, reusable functions. This not only enhances readability but also promotes maintainability and reusability.

ALPHABET_SIZE = 26
LOWER_A_ASCII = ord('a')
UPPER_A_ASCII = ord('A')

def shift_letter(char, shift_key):
    if char.islower():
        return chr((ord(char) + shift_key - LOWER_A_ASCII) % ALPHABET_SIZE + LOWER_A_ASCII)
    elif char.isupper():
        return chr((ord(char) + shift_key - UPPER_A_ASCII) % ALPHABET_SIZE + UPPER_A_ASCII)
    else:
        return char

def caesar_cipher(text, shift_key):
    result = ""
    for char in text:
            result += shift_letter(char, shift_key)
    return result

text = "readable code?"
cipher_text = caesar_cipher(text,3)

print(f'{text} encrypted => {cipher_text}')
Enter fullscreen mode Exit fullscreen mode

To comment or not to comment?

Comments are a double-edged sword. While they can be helpful, they are often overlooked and must be updated, leading to confusion. Prioritize writing self-explanatory code, using comments sparingly for complex algorithms or unconventional solutions.

ALPHABET_SIZE = 26
LOWER_A_ASCII = ord('a')
UPPER_A_ASCII = ord('A')

def shift_letter(char, shift_key):
    '''
    "The normalization step (using LOWER_A_ASCII and UPPER_A_ASCII)
    is employed to adjust the ASCII values of letters, 
    ensuring that they are shifted within the
    range of 0 to 25, corresponding to the positions in the alphabet.
    ''' 
    # Check if the character is a lowercase letter 
    if char.islower():
        return chr((ord(char) + shift_key - LOWER_A_ASCII) % ALPHABET_SIZE + LOWER_A_ASCII)
    # Check if the character is an uppercase letter 
    elif char.isupper():
        return chr((ord(char) + shift_key - UPPER_A_ASCII) % ALPHABET_SIZE + UPPER_A_ASCII)
    else:
        # If the character is not a letter, return it unchanged 
        return char

def caesar_cipher(text, shift_key):
    result = ""
    for char in text:
        # Apply the shift to each character in the text 
        result += shift_letter(char, shift_key)
    return result

# Example usage 
text = "readable code?"
cipher_text = caesar_cipher(text,3)

print(f'{text} encrypted => {cipher_text}')
Enter fullscreen mode Exit fullscreen mode

Our code looks cluttered because of the unnecessary comments. But, since we have used descriptive names, we should be able to trim out some comments.

After 🙂

ALPHABET_SIZE = 26
LOWER_A_ASCII = ord('a')
UPPER_A_ASCII = ord('A')

def shift_letter(char, shift_key):
    '''
    "The normalization step (using LOWER_A_ASCII and UPPER_A_ASCII)
    is employed to adjust the ASCII values of letters, 
    ensuring that they are shifted within the
    range of 0 to 25, corresponding to the positions in the alphabet.
    ''' 
    if char.islower():
        return chr((ord(char) + shift_key - LOWER_A_ASCII) % ALPHABET_SIZE + LOWER_A_ASCII)
    elif char.isupper():
        return chr((ord(char) + shift_key - UPPER_A_ASCII) % ALPHABET_SIZE + UPPER_A_ASCII)
    else:
        # If the character is not a letter, return it unchanged
        return char

def caesar_cipher(text, shift_key):
    result = ""
    for char in text:
        # Apply the shift to each character in the input string
        result += shift_letter(char, shift_key)
    return result

# Example usage 
text = "readable code?"
cipher_text = caesar_cipher(text,3)

print(f'{text} encrypted => {cipher_text}')
Enter fullscreen mode Exit fullscreen mode

💡 In cryptography, a Caesar cipher ... is one of the simplest and most widely known encryption techniques. It is a type of substitution cipher in which each letter in the plaintext is replaced by a letter some fixed number of positions down the alphabet. For example, with a left shift of 3, D would be replaced by A, E would become B, and so on.

-Wikipedia

Consistency is key

Consistency ties all these tips together. Adopting a consistent coding style, variable naming convention, and commenting approach across your projects promotes a seamless reading experience for anyone who encounters your code.

Some tools help you with this. Use them. When writing Python code, I use autopep8, a tool that automatically formats Python code to conform to the PEP 8 style guide. A supporting VS code extension is available.

When I'm writing JavaScript   😅 Typescript, I use eslint and Prettier.

In conclusion, writing readable code is not just a best practice, it's a professional courtesy to your future self and collaborators. By implementing these tips, you'll produce code that works and is a pleasure to read and maintain.

Top comments (0)