General Programming Principles¶
This guide covers universal programming principles that apply across all programming languages and development scenarios.
🎯 Fundamental Principles¶
DRY (Don't Repeat Yourself)¶
Avoid duplicating code or logic throughout your application.
Problem¶
# Bad: Repeated logic
def calculate_discount_price(price, discount_percent):
discounted_price = price - (price * discount_percent / 100)
return discounted_price
def calculate_tax_price(price, tax_percent):
taxed_price = price + (price * tax_percent / 100)
return taxed_price
# Similar calculation logic repeated
Solution¶
# Good: Extract common logic
def calculate_percentage_adjustment(base_price, adjustment_percent):
return base_price + (base_price * adjustment_percent / 100)
def calculate_discount_price(price, discount_percent):
return calculate_percentage_adjustment(price, -discount_percent)
def calculate_tax_price(price, tax_percent):
return calculate_percentage_adjustment(price, tax_percent)
KISS (Keep It Simple, Stupid)¶
Write simple, readable code that's easy to understand and maintain.
Problem¶
// Bad: Overly complex
public boolean isValidEmail(String email) {
return email != null &&
email.contains("@") &&
email.indexOf("@") == email.lastIndexOf("@") &&
email.indexOf(".") > email.indexOf("@") &&
email.lastIndexOf(".") < email.length() - 2;
}
Solution¶
// Good: Simple and clear
public boolean isValidEmail(String email) {
if (email == null) return false;
int atIndex = email.indexOf("@");
int lastDotIndex = email.lastIndexOf(".");
return atIndex > 0 &&
atIndex == email.lastIndexOf("@") &&
lastDotIndex > atIndex &&
lastDotIndex < email.length() - 2;
}
// Better: Use regex or email validation library
public boolean isValidEmail(String email) {
return email != null && email.matches("^[A-Za-z0-9+_.-]+@(.+)$");
}
SOLID Principles¶
Five object-oriented design principles for maintainable software.
S - Single Responsibility Principle¶
A class should have only one reason to change.
# Bad: Multiple responsibilities
class User:
def save_to_database(self):
# Database logic
pass
def send_email(self):
# Email logic
pass
def validate_input(self):
# Validation logic
pass
# Good: Single responsibility
class User:
def __init__(self, name, email):
self.name = name
self.email = email
class UserRepository:
def save(self, user):
# Database logic only
pass
class EmailService:
def send_welcome_email(self, user):
# Email logic only
pass
class UserValidator:
def validate(self, user):
# Validation logic only
pass
O - Open/Closed Principle¶
Software entities should be open for extension, closed for modification.
# Bad: Need to modify for new shapes
class AreaCalculator:
def calculate_area(self, shape):
if shape.type == "circle":
return 3.14 * shape.radius ** 2
elif shape.type == "rectangle":
return shape.width * shape.height
# Need to modify for new shapes!
# Good: Open for extension
class Shape:
def area(self):
raise NotImplementedError
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class AreaCalculator:
def calculate_area(self, shape):
return shape.area() # Works for any shape
YAGNI (You Aren't Gonna Need It)¶
Don't add functionality until you actually need it.
Problem¶
// Bad: Adding features "just in case"
public class UserService {
public void createUser(User user) { /* ... */ }
public void updateUser(User user) { /* ... */ }
public void deleteUser(User user) { /* ... */ }
public void exportToCSV(User user) { /* ... */ } // Not needed yet
public void exportToXML(User user) { /* ... */ } // Not needed yet
public void exportToJSON(User user) { /* ... */ } // Not needed yet
}
Solution¶
// Good: Only implement what's needed now
public class UserService {
public void createUser(User user) { /* ... */ }
public void updateUser(User user) { /* ... */ }
public void deleteUser(User user) { /* ... */ }
// Add export features when actually needed
}
🔧 Code Quality Principles¶
Readability¶
Code should be written for humans to read, not just for computers to execute.
Guidelines¶
- Meaningful Names: Use descriptive variable and function names
- Consistent Style: Follow language conventions consistently
- Proper Comments: Explain why, not what
- Logical Organization: Group related code together
Example¶
# Bad: Unclear code
def p(x, y):
r = []
for i in range(len(x)):
if x[i] > y:
r.append(x[i])
return r
# Good: Clear and readable
def filter_greater_than_threshold(numbers, threshold):
"""Return numbers greater than the given threshold."""
filtered_numbers = []
for number in numbers:
if number > threshold:
filtered_numbers.append(number)
return filtered_numbers
# Better: Use built-in functions
def filter_greater_than_threshold(numbers, threshold):
"""Return numbers greater than the given threshold."""
return [num for num in numbers if num > threshold]
Maintainability¶
Code should be easy to modify and extend.
Guidelines¶
- Small Functions: Each function does one thing well
- Loose Coupling: Minimize dependencies between components
- High Cohesion: Group related functionality together
- Configuration: Externalize configuration values
Example¶
# Bad: Hard to maintain
def process_data():
# Database connection hardcoded
conn = sqlite3.connect("/path/to/database.db")
# Business logic mixed with data access
data = conn.execute("SELECT * FROM users WHERE age > 18").fetchall()
# Processing logic mixed with output
for row in data:
if row[3] > 1000: # Magic number
print(f"High value user: {row[1]}")
else:
print(f"Regular user: {row[1]}")
# Good: Easy to maintain
def process_data():
config = load_config()
db_connection = create_database_connection(config.database_url)
adult_users = get_adult_users(db_connection)
process_user_list(adult_users, config.high_value_threshold)
def get_adult_users(connection):
return connection.execute(
"SELECT * FROM users WHERE age > ?",
(18,)
).fetchall()
def process_user_list(users, high_value_threshold):
for user in users:
if user.balance > high_value_threshold:
print(f"High value user: {user.name}")
else:
print(f"Regular user: {user.name}")
Testability¶
Code should be easy to test.
Guidelines¶
- Pure Functions: Avoid side effects when possible
- Dependency Injection: Pass dependencies as parameters
- Single Responsibility: Easy to test small, focused functions
- Mock Dependencies: Use test doubles for external dependencies
Example¶
# Bad: Hard to test (depends on external API)
def get_user_data(user_id):
response = requests.get(f"https://api.example.com/users/{user_id}")
return response.json()
# Good: Easy to test (dependency injection)
def get_user_data(user_id, http_client):
response = http_client.get(f"https://api.example.com/users/{user_id}")
return response.json()
# Test
class MockHttpClient:
def get(self, url):
return MockResponse({"id": 123, "name": "Test User"})
def test_get_user_data():
mock_client = MockHttpClient()
user_data = get_user_data(123, mock_client)
assert user_data["name"] == "Test User"
🎯 Design Patterns¶
Strategy Pattern¶
Encapsulate algorithms and make them interchangeable.
# Strategy interface
class SortingStrategy:
def sort(self, data):
raise NotImplementedError
# Concrete strategies
class BubbleSort(SortingStrategy):
def sort(self, data):
# Bubble sort implementation
return sorted_data
class QuickSort(SortingStrategy):
def sort(self, data):
# Quick sort implementation
return sorted_data
# Context
class Sorter:
def __init__(self, strategy):
self.strategy = strategy
def sort_data(self, data):
return self.strategy.sort(data)
# Usage
sorter = Sorter(QuickSort())
result = sorter.sort_data([3, 1, 4, 1, 5])
Factory Pattern¶
Create objects without specifying exact classes.
# Product interface
class DatabaseConnection:
def connect(self):
raise NotImplementedError
# Concrete products
class MySQLConnection(DatabaseConnection):
def connect(self):
return "Connected to MySQL"
class PostgreSQLConnection(DatabaseConnection):
def connect(self):
return "Connected to PostgreSQL"
# Factory
class DatabaseConnectionFactory:
@staticmethod
def create_connection(db_type):
if db_type == "mysql":
return MySQLConnection()
elif db_type == "postgresql":
return PostgreSQLConnection()
else:
raise ValueError(f"Unknown database type: {db_type}")
# Usage
connection = DatabaseConnectionFactory.create_connection("mysql")
connection.connect()
📚 Related Resources¶
- Clean Code - Robert C. Martin
- The Pragmatic Programmer - Andrew Hunt & David Thomas
- Design Patterns - Gang of Four
- Refactoring - Martin Fowler
🔗 Related Guides¶
- Code Organization - Structuring your codebase
- Debugging Strategies - Troubleshooting techniques
- Documentation Standards - Writing good documentation
🔗 Language-Specific Best Practices¶
- Java Best Practices - Java-specific guidelines
- Python Best Practices - Python-specific guidelines
- C Best Practices - C-specific guidelines
- Oracle Best Practices - Oracle-specific guidelines