Area 2.9

Design and Practices

Master programming design principles including logical ordering, data structure selection, naming conventions, and code readability. Learn to evaluate algorithm suitability and apply best practices.

4
Design Areas
4
Activities
~3hrs
Study Time

Learning Objectives

  • Understand the importance of logical ordering in program structure
  • Make informed choices about appropriate data structures for different scenarios
  • Apply consistent naming conventions for variables, functions, and classes
  • Write readable code that is maintainable and self-documenting
  • Evaluate algorithm suitability based on efficiency and problem requirements
  • Implement design patterns and best practices in programming

Programming Design Principles

Logical Ordering

Organizing code in a logical sequence that follows natural program flow

Best Practices:

  • Sequential execution - statements in logical order
  • Function placement - helper functions before main logic
  • Import statements at the top of files
  • Constants and global variables declared early

Python Example:

# Good logical ordering

# Constants
MAX_ATTEMPTS = 3
PI = 3.14159

# Helper functions
def validate_input(value):
    return isinstance(value, int) and value > 0

# Main function
def calculate_area(radius):
    if validate_input(radius):
        return PI * radius ** 2
    return None

Data Structure Selection

Choosing the most appropriate data structure based on access patterns and operations

Best Practices:

  • Lists for ordered collections with frequent additions
  • Dictionaries for key-value mappings and fast lookups
  • Sets for unique collections and membership testing
  • Tuples for immutable sequences and structured data

Python Example:

# Appropriate data structure choices
student_grades = {}  # Dictionary for fast lookup by student ID
task_queue = []      # List for ordered processing
unique_tags = set()  # Set for unique collection
coordinates = (x, y) # Tuple for immutable position data

# Adding data
student_grades['S12345'] = 85
task_queue.append('process_payment')
unique_tags.add('python')
point = (10, 20)

Naming Conventions

Using consistent, descriptive names that clearly indicate purpose and functionality

Best Practices:

  • snake_case for variables and functions in Python
  • UPPER_CASE for constants
  • Descriptive names that explain purpose
  • Avoid abbreviations and single-letter variables

Python Example:

# Good naming conventions
MAX_LOGIN_ATTEMPTS = 3
user_email_address = "user@example.com"
is_authenticated = False

def calculate_monthly_payment(loan_amount, interest_rate, term_years):
    monthly_rate = interest_rate / 12
    total_months = term_years * 12
    return loan_amount * (monthly_rate / (1 - (1 + monthly_rate) ** -total_months))

# Bad naming - avoid these
m = 3  # unclear meaning
usr_em = "user@example.com"  # abbreviated
x = False  # generic name

def calc(a, b, c):  # unclear purpose and parameters
    return a * (b / (1 - (1 + b) ** -c))

Code Readability

Writing code that is easy to read, understand, and maintain

Best Practices:

  • Proper indentation and consistent spacing
  • Meaningful comments that explain why, not what
  • Breaking complex operations into smaller functions
  • Using whitespace to separate logical sections

Python Example:

# Readable code example
def process_student_enrollment(student_data):
    """
    Process new student enrollment, validate data, and update records.
    
    Args:
        student_data (dict): Contains student information
        
    Returns:
        bool: True if enrollment successful, False otherwise
    """
    # Validate required fields
    required_fields = ['name', 'email', 'course_id']
    if not all(field in student_data for field in required_fields):
        return False
    
    # Check if student already exists
    existing_student = find_student_by_email(student_data['email'])
    if existing_student:
        update_student_course(existing_student['id'], student_data['course_id'])
    else:
        create_new_student(student_data)
    
    # Send confirmation email
    send_enrollment_confirmation(student_data['email'])
    return True

Algorithm Suitability Evaluation

Time Complexity

How execution time grows with input size

Key Considerations:

  • O(1) - constant time, best for lookups
  • O(n) - linear time, acceptable for small datasets
  • O(n²) - quadratic time, avoid for large datasets

Code Examples:

# Time complexity examples
# O(1) - Dictionary lookup
user = users_dict[user_id]

# O(n) - Linear search
def find_user(users_list, target_name):
    for user in users_list:
        if user.name == target_name:
            return user

# O(n²) - Nested loops (avoid for large data)
def find_duplicates_slow(numbers):
    duplicates = []
    for i in range(len(numbers)):
        for j in range(i + 1, len(numbers)):
            if numbers[i] == numbers[j]:
                duplicates.append(numbers[i])
    return duplicates

Space Complexity

How memory usage grows with input size

Key Considerations:

  • In-place operations use O(1) additional space
  • Recursive algorithms may use O(n) stack space
  • Creating new data structures increases space usage

Code Examples:

# Space complexity examples
# O(1) space - in-place reversal
def reverse_list_inplace(arr):
    left, right = 0, len(arr) - 1
    while left < right:
        arr[left], arr[right] = arr[right], arr[left]
        left += 1
        right -= 1

# O(n) space - creating new list
def reverse_list_new(arr):
    return arr[::-1]  # Creates new list

Maintainability

How easy the algorithm is to understand and modify

Key Considerations:

  • Simple algorithms are easier to debug and extend
  • Well-documented complex algorithms can be acceptable
  • Consider team skill level and project timeline

Code Examples:

# Maintainable approach - clear and simple
def calculate_discount(price, customer_type):
    discount_rates = {
        'student': 0.10,
        'senior': 0.15,
        'employee': 0.20
    }
    discount = discount_rates.get(customer_type, 0)
    return price * (1 - discount)

# Less maintainable - requires domain knowledge
def calculate_discount_complex(price, customer_type):
    # Complex business rules embedded in algorithm
    if customer_type == 'student':
        return price * 0.9 if price > 50 else price * 0.95
    elif customer_type == 'senior':
        return price * 0.85 if price > 100 else price * 0.9
    # ... more complex logic

Common Design Mistakes & Solutions

Magic Numbers and Strings

Example:

if status == 42: # What does 42 mean?

Problem:

Code is unclear and hard to maintain

Solution:

Use named constants: STATUS_COMPLETE = 42

Overly Complex Functions

Example:

Single function doing multiple unrelated tasks

Problem:

Hard to test, debug, and reuse

Solution:

Break into smaller, focused functions

Inconsistent Code Style

Example:

Mixing camelCase and snake_case in same project

Problem:

Reduces readability and professionalism

Solution:

Follow established style guides (PEP 8 for Python)

No Comments for Complex Logic

Example:

Complex algorithms without explanation

Problem:

Other developers cannot understand intent

Solution:

Add comments explaining why, not what

Learning Activities

Code Review Challenge

Analysis
45 minutes

Review poorly written code samples and identify design and practice improvements

Data Structure Selection

Decision
30 minutes

Given different scenarios, choose and justify the most appropriate data structure

Algorithm Efficiency Analysis

Evaluation
50 minutes

Compare different algorithms for the same problem and evaluate their suitability

Code Refactoring Practice

Practice
60 minutes

Transform poorly designed code into well-structured, readable implementations