Best Practices
Modular Design Principles
1. Single Responsibility Principle
## Bad example: Multiple responsibilities
class UserManager:
def create_user(self, username, password):
## User creation logic
self.validate_password(password)
self.save_to_database()
self.send_welcome_email()
## Good example: Separated responsibilities
class UserValidator:
def validate_password(self, password):
## Password validation logic
pass
class UserRepository:
def save_user(self, user):
## Database saving logic
pass
class NotificationService:
def send_welcome_email(self, user):
## Email sending logic
pass
Dependency Management
Dependency Injection
graph TD
A[High-Level Module] -->|Depends on Abstraction| B[Abstraction Interface]
C[Concrete Implementation 1] -.-> B
D[Concrete Implementation 2] -.-> B
from abc import ABC, abstractmethod
class DatabaseConnector(ABC):
@abstractmethod
def connect(self):
pass
class MySQLConnector(DatabaseConnector):
def connect(self):
## MySQL specific connection logic
pass
class PostgreSQLConnector(DatabaseConnector):
def connect(self):
## PostgreSQL specific connection logic
pass
class DataProcessor:
def __init__(self, connector: DatabaseConnector):
self._connector = connector
def process_data(self):
connection = self._connector.connect()
## Process data using the connection
Error Handling and Logging
Comprehensive Error Management
import logging
from typing import Optional
class CustomError(Exception):
"""Base custom error class"""
pass
def configure_logging():
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
filename='application.log'
)
return logging.getLogger(__name__)
def safe_division(a: float, b: float) -> Optional[float]:
logger = configure_logging()
try:
result = a / b
logger.info(f"Successfully divided {a} by {b}")
return result
except ZeroDivisionError:
logger.error(f"Division by zero: {a} / {b}")
raise CustomError("Cannot divide by zero")
Code Quality Metrics
Practice |
Description |
Benefit |
Type Hinting |
Use type annotations |
Improved code readability |
Docstrings |
Comprehensive documentation |
Better understanding |
Unit Testing |
Extensive test coverage |
Reduced bug introduction |
Code Linting |
Static code analysis |
Consistent code quality |
Lazy Loading and Generators
def large_file_processor(filename):
def line_generator():
with open(filename, 'r') as file:
for line in file:
## Process line lazily
yield line.strip()
for processed_line in line_generator():
## Memory-efficient processing
process(processed_line)
Design Patterns
Factory Method Pattern
class DatabaseFactory:
@staticmethod
def get_database(db_type: str):
if db_type == 'mysql':
return MySQLDatabase()
elif db_type == 'postgresql':
return PostgreSQLDatabase()
else:
raise ValueError(f"Unsupported database type: {db_type}")
Security Considerations
import re
from typing import Optional
def validate_email(email: str) -> Optional[str]:
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if re.match(email_pattern, email):
return email
else:
raise ValueError("Invalid email format")
Continuous Integration Recommendations
- Use virtual environments
- Implement automated testing
- Use version control (Git)
- Set up CI/CD pipelines
LabEx emphasizes that following these best practices will significantly improve your Python project's maintainability, readability, and overall quality.