Introduction
Clean code is code that is easy to understand and easy to change. Writing clean code is a skill that takes practice and understanding of principles that make code more maintainable, readable, and professional.
Meaningful Names
Choose names that reveal intent and are easy to understand.
# Bad
d = 24
x = [1, 2, 3, 4, 5]
for i in x:
if i % 2 == 0:
print(i)
# Good
days_in_month = 24
even_numbers = [1, 2, 3, 4, 5]
for number in even_numbers:
if is_even(number):
print(number)
def is_even(num):
return num % 2 == 0
Functions
Keep functions small, focused, and with a single responsibility.
# Bad
def process_user_data(data):
# Validate
if not data.get("name"):
return None
if not data.get("email"):
return None
# Save to database
print("Saving to database")
# Send email
print("Sending email")
# Log activity
print("Logging activity")
return True
# Good
def validate_user_data(data):
required_fields = ["name", "email"]
return all(field in data and data[field] for field in required_fields)
def save_user(data):
print("Saving to database")
def send_welcome_email(email):
print(f"Sending welcome email to {email}")
def log_user_registration(name):
print(f"Logging registration for {name}")
def process_user_data(data):
if not validate_user_data(data):
return None
save_user(data)
send_welcome_email(data["email"])
log_user_registration(data["name"])
return True
Comments and Documentation
Use comments to explain "why" not "what", and prefer self-documenting code.
import hashlib
import time
class AuthenticationManager:
def __init__(self):
self.max_login_attempts = 5
self.lockout_duration = 300 # 5 minutes
def authenticate(self, username, password):
# Rate limiting to prevent brute force attacks
if self._is_account_locked(username):
raise AccountLockedError("Too many failed attempts")
if self._verify_credentials(username, password):
self._reset_failed_attempts(username)
return self._create_session(username)
self._record_failed_attempt(username)
raise AuthenticationError("Invalid credentials")
def _is_account_locked(self, username):
# Using constant-time comparison for security
failed_attempts = self.failed_attempts.get(username, 0)
return failed_attempts >= self.max_login_attempts
def _verify_credentials(self, username, password):
stored_hash = self.password_hashes.get(username)
if not stored_hash:
return False
return self._constant_time_compare(stored_hash, password)
def _constant_time_compare(self, expected, actual):
# Prevents timing attacks by ensuring consistent comparison time
if len(expected) != len(actual):
return False
result = 0
for a, b in zip(expected, actual):
result |= ord(a) ^ ord(b)
return result == 0
Code Formatting
Use consistent formatting with proper indentation, line length, and whitespace.
# Well-formatted code
class OrderProcessor:
def __init__(self, inventory, payment_gateway, notifier):
self.inventory = inventory
self.payment_gateway = payment_gateway
self.notifier = notifier
def process_order(self, order):
if not self._validate_order(order):
return ProcessingResult(success=False, error="Invalid order")
if not self._check_inventory(order):
return ProcessingResult(success=False, error="Out of stock")
if not self._process_payment(order):
return ProcessingResult(success=False, error="Payment failed")
self._update_inventory(order)
self._send_confirmation(order)
return ProcessingResult(success=True, order_id=order.id)
def _validate_order(self, order):
return order.items and order.customer_id
def _check_inventory(self, order):
return all(self.inventory.is_available(item) for item in order.items)
def _process_payment(self, order):
return self.payment_gateway.charge(order.total, order.payment_method)
def _update_inventory(self, order):
for item in order.items:
self.inventory.decrement(item)
def _send_confirmation(self, order):
self.notifier.send_order_confirmation(order)
Practice Problems
- Rename variables and functions to be more descriptive in a given code snippet.
- Break down a large function into smaller, focused functions.
- Convert poorly written comments into self-documenting code.
- Format a code block following PEP 8 style guidelines.
- Refactor code to follow the DRY (Don't Repeat Yourself) principle.