code garden Code Garden (Beta)
Back to Blog

Clean Code Principles: 7 Rules That Turn You from Amateur to Pro

2026-02-14 Best Practices

Writing code that works is the first step. Writing code that others can read, maintain, and extend is what separates professionals from hobbyists.

There is a moment in every developer journey where the code works but nobody including yourself can understand it two weeks later. That is the moment where clean code stops being a nice-to-have and becomes a necessity.

Clean code is not about aesthetics. It is about communication. Code is read far more often than it is written, and the primary audience is not the computer. It is the human who has to change it next.

Rule 1: Name things as if a stranger will read them

Variable names like `x`, `temp`, and `data` tell the reader nothing. Compare for yourself:

python

# Bad
x = get_d()
t = x * 0.19
r = x + t

# Good
net_amount = calculate_item_value()
vat = net_amount * 0.19
gross_amount = net_amount + vat

The cost of a long name is a few keystrokes. The cost of a cryptic name is minutes of confusion multiplied by every person who reads it.

Rule 2: Keep functions small and focused

A function should do one thing and do it well. If you need the word *and* to describe what it does, it does too much:

python

# Bad – does two things
def process_order(order):
    # Validation
    if not order.get("product"):
        raise ValueError("Product missing")
    if order["quantity"] < 1:
        raise ValueError("Invalid quantity")
    # Saving
    db.execute("INSERT INTO orders ...")
    send_email(order["customer"])

# Good – separated concerns
def validate_order(order):
    if not order.get("product"):
        raise ValueError("Product missing")
    if order["quantity"] < 1:
        raise ValueError("Invalid quantity")

def save_order(order):
    db.execute("INSERT INTO orders ...")
    send_email(order["customer"])

Rule 3: Avoid deep nesting

Use early returns to eliminate nesting:

python

# Bad – deeply nested
def user_access(user, resource):
    if user:
        if user.is_active:
            if user.has_permission(resource):
                return resource.data
            else:
                raise PermissionError()
        else:
            raise ValueError("User inactive")
    else:
        raise ValueError("No user")

# Good – flat with early returns
def user_access(user, resource):
    if not user:
        raise ValueError("No user")
    if not user.is_active:
        raise ValueError("User inactive")
    if not user.has_permission(resource):
        raise PermissionError()
    return resource.data

Rule 4: DRY, but do not over-abstract

If you find yourself copying the same five lines three times, extract a function. But if two pieces of code look similar today but serve different purposes, forcing them into a shared abstraction will cause pain later when they need to diverge.

Rule 5: Handle errors explicitly

Swallowing exceptions with an empty `catch` block is one of the fastest ways to create impossible-to-diagnose bugs:

python

# Bad – error swallowed
try:
    result = api_call()
except Exception:
    pass  # What happened? Nobody knows.

# Good – explicit handling
try:
    result = api_call()
except ConnectionError:
    logger.warning("API unreachable, using cache")
    result = load_from_cache()
except ValueError as e:
    logger.error(f"Invalid API response: {e}")
    raise

Rule 6: Code explains itself, comments explain the why

python

# Bad – obvious
counter += 1  # Increment counter

# Good – explains a non-obvious business rule
# Orders under 10 EUR get bundled because
# shipping costs would exceed the item value
if order.value < 10:
    mark_for_bundling(order)

Rule 7: Refactor continuously, not in big rewrites

Clean code is not achieved in a heroic session. It emerges from small improvements. Every time you touch a file, leave it slightly better. Rename a confusing variable. Extract a helper. Remove dead code.