Bỏ qua

THỰC HÀNH TỔNG HỢP 4 - LẬP TRÌNH NÂNG CAO

I. Mục tiêu buổi học

Mục tiêu chính

Buổi học này nhằm củng cố và thực hành kiến thức từ Buổi 16-18, tập trung vào:

  • Functions (Hàm) - Tổ chức code hiệu quả
  • Error Handling - Xử lý ngoại lệ chuyên nghiệp
  • Modules và Packages - Quản lý dự án lớn
  • Code Architecture - Thiết kế phần mềm tốt

Kỹ năng đạt được

Sau buổi học, học viên sẽ có khả năng:

  • Viết code chuyên nghiệp với function design tốt
  • Xử lý errors một cách robust và user-friendly
  • Tổ chức project với modules và packages
  • Apply best practices trong software development

II. Cấu trúc buổi học (90 phút)

Hoạt động Thời gian Nội dung
Code Architecture Review 20 phút Best practices & design patterns
Advanced Functions 30 phút Decorators, lambda, advanced concepts
Project Development 30 phút Mini framework development
Code Review & Optimization 10 phút Professional code review

III. Code Architecture Review (20 phút)

SOLID Principles trong Python

1. Single Responsibility Principle:

# Không tốt - class làm quá nhiều việc
class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email

    def save_to_database(self):
        # Database logic
        pass

    def send_email(self):
        # Email logic
        pass

    def validate_email(self):
        # Validation logic
        pass

# Tốt - chia thành nhiều class chuyên biệt
class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email

class UserRepository:
    def save(self, user):
        # Database logic
        pass

class EmailService:
    def send(self, user, message):
        # Email logic
        pass

class EmailValidator:
    def validate(self, email):
        # Validation logic
        pass

2. Function Design Best Practices:

def calculate_order_total(items, tax_rate, discount_code=None, shipping_cost=0):
    """
    Tính tổng tiền đơn hàng

    Args:
        items (list): Danh sách sản phẩm
        tax_rate (float): Tỷ lệ thuế (0.0 - 1.0)
        discount_code (str, optional): Mã giảm giá
        shipping_cost (float): Phí vận chuyển

    Returns:
        dict: {
            'subtotal': float,
            'tax': float,
            'discount': float,
            'shipping': float,
            'total': float
        }

    Raises:
        ValueError: Khi tax_rate không hợp lệ
        TypeError: Khi items không phải list
    """
    if not isinstance(items, list):
        raise TypeError("Items phải là list")

    if not 0 <= tax_rate <= 1:
        raise ValueError("Tax rate phải từ 0 đến 1")

    subtotal = sum(item['price'] * item['quantity'] for item in items)
    tax = subtotal * tax_rate
    discount = calculate_discount(subtotal, discount_code)
    total = subtotal + tax - discount + shipping_cost

    return {
        'subtotal': round(subtotal, 2),
        'tax': round(tax, 2),
        'discount': round(discount, 2),
        'shipping': round(shipping_cost, 2),
        'total': round(total, 2)
    }

def calculate_discount(subtotal, discount_code):
    """Tính số tiền giảm giá"""
    if not discount_code:
        return 0

    discount_rules = {
        'SAVE10': 0.1,
        'SAVE20': 0.2,
        'NEWUSER': 0.15,
    }

    rate = discount_rules.get(discount_code.upper(), 0)
    return subtotal * rate

Error Handling Strategy

class AppError(Exception):
    """Base exception cho ứng dụng"""
    pass

class ValidationError(AppError):
    """Lỗi validation dữ liệu"""
    pass

class DatabaseError(AppError):
    """Lỗi database"""
    pass

class NetworkError(AppError):
    """Lỗi network"""
    pass

def safe_execute(func, *args, **kwargs):
    """
    Decorator/wrapper để execute function safely
    """
    try:
        return func(*args, **kwargs)
    except ValidationError as e:
        print(f"❌ Lỗi dữ liệu: {e}")
        return None
    except DatabaseError as e:
        print(f"❌ Lỗi database: {e}")
        return None
    except NetworkError as e:
        print(f"❌ Lỗi mạng: {e}")
        return None
    except Exception as e:
        print(f"❌ Lỗi không xác định: {e}")
        return None

# Usage
result = safe_execute(risky_function, param1, param2=value)
if result is not None:
    print("Success!")

IV. Advanced Functions (30 phút)

Bài 1: Function Decorators (10 phút)

Đề bài: Tạo các decorators để mở rộng chức năng của functions.

Phân tích đề

Decorators cần tạo:

  1. Timer Decorator: Đo thời gian thực thi function
  2. Retry Decorator: Tự động thử lại khi function fail
  3. Validation Decorator: Kiểm tra kiểu dữ liệu input
  4. Logging Decorator: Ghi log các lần gọi function

Pattern Decorator:

def decorator_name(func):
    def wrapper(*args, **kwargs):
        # Code trước khi gọi function
        result = func(*args, **kwargs)
        # Code sau khi gọi function
        return result
    return wrapper

Ứng dụng thực tế: - Timer: Performance monitoring - Retry: Network calls, database operations - Validation: API endpoints, user input

Gợi ý code
import time
import functools

def timer(func):
    """Decorator đo thời gian thực thi"""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"⏱️ {func.__name__} took {end_time - start_time:.4f} seconds")
        return result
    return wrapper

def retry(max_attempts=3, delay=1):
    """Decorator retry khi function fail"""
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_attempts - 1:
                        raise e
                    print(f"Attempt {attempt + 1} failed: {e}")
                    time.sleep(delay)
            return None
        return wrapper
    return decorator

def validate_types(**expected_types):
    """Decorator validate kiểu dữ liệu input"""
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # Validate kwargs
            for param_name, expected_type in expected_types.items():
                if param_name in kwargs:
                    value = kwargs[param_name]
                    if not isinstance(value, expected_type):
                        raise TypeError(
                            f"Parameter '{param_name}' must be {expected_type.__name__}, "
                            f"got {type(value).__name__}"
                        )
            return func(*args, **kwargs)
        return wrapper
    return decorator

# Example usage
@timer
@retry(max_attempts=3, delay=0.5)
@validate_types(name=str, age=int, score=float)
def process_student_data(name, age, score):
    """Process student data with validation and retry"""
    if age < 0:
        raise ValueError("Age cannot be negative")

    if not 0 <= score <= 10:
        raise ValueError("Score must be between 0 and 10")

    # Simulate processing
    time.sleep(0.1)

    return {
        'name': name.title(),
        'age': age,
        'score': round(score, 2),
        'grade': 'A' if score >= 8 else 'B' if score >= 6 else 'C'
    }

# Test
try:
    result = process_student_data(name="john doe", age=20, score=8.7)
    print(f"Result: {result}")
except Exception as e:
    print(f"Error: {e}")

Bài 2: Functional Programming (10 phút)

Đề bài: Áp dụng functional programming để xử lý dữ liệu.

Phân tích đề

Functional Programming Concepts:

Function Mục đích Ví dụ
map() Transform dữ liệu Tính điểm trung bình cho từng học sinh
filter() Lọc dữ liệu Chọn học sinh giỏi (avg >= 8.0)
reduce() Tổng hợp dữ liệu Tính tổng điểm của tất cả học sinh
lambda Function ngắn gọn lambda x: x['average'] >= 8.0

Workflow xử lý dữ liệu: 1. Raw data → Transform (map) 2. Transformed data → Filter (filter)
3. Filtered data → Aggregate (reduce)

Gợi ý code

from functools import reduce
import operator

def functional_data_processing():
    """Demo functional programming concepts"""

    # Sample data
    students = [
        {'name': 'An', 'age': 20, 'scores': [8, 9, 7, 8.5]},
        {'name': 'Bình', 'age': 19, 'scores': [7, 8, 6, 7.5]},
        {'name': 'Cường', 'age': 21, 'scores': [9, 9.5, 8.5, 9]},
        {'name': 'Dung', 'age': 18, 'scores': [6, 7, 5, 6.5]},
        {'name': 'Em', 'age': 20, 'scores': [8.5, 9, 8, 8.5]},
    ]

    # 1. Map - Transform data
    students_with_avg = list(map(
        lambda s: {
            **s, 
            'average': round(sum(s['scores']) / len(s['scores']), 2)
        },
        students
    ))

    # 2. Filter - Select data
    excellent_students = list(filter(
        lambda s: s['average'] >= 8.0,
        students_with_avg
    ))

    # 3. Reduce - Aggregate data
    total_average = reduce(
        lambda acc, s: acc + s['average'],
        students_with_avg,
        0
    ) / len(students_with_avg)

    # 4. Sort with custom key
    sorted_students = sorted(
        students_with_avg,
        key=lambda s: (-s['average'], s['age'])  # Desc by avg, asc by age
    )

    # Display results
    print("FUNCTIONAL DATA PROCESSING DEMO")
    print("="*60)

    print("\n1. Students with averages:")
    for student in students_with_avg:
        print(f"   {student['name']}: {student['average']}")

    print(f"\n2. Excellent students (avg >= 8.0): {len(excellent_students)}")
    for student in excellent_students:
        print(f"   {student['name']}: {student['average']}")

    print(f"\n3. Class average: {total_average:.2f}")

    print("\n4. Sorted by average (desc) then age (asc):")
    for student in sorted_students:
        print(f"   {student['name']} (age {student['age']}): {student['average']}")

if __name__ == "__main__":
    functional_data_processing()
total_average = reduce( lambda acc, s: acc + s['average'], students_with_avg, 0 ) / len(students_with_avg)

4. Sort with custom key

sorted_students = sorted( students_with_avg, key=lambda s: (-s['average'], s['age']) # Desc by avg, asc by age )

5. Group by age

from itertools import groupby grouped_by_age = {} for age, group in groupby( sorted(students_with_avg, key=lambda s: s['age']), key=lambda s: s['age'] ): grouped_by_age[age] = list(group)

Display results

print("="60) print("FUNCTIONAL DATA PROCESSING DEMO") print("="60)

print("\n1. Students with averages:") for student in students_with_avg: print(f" {student['name']}: {student['average']}")

print(f"\n2. Excellent students (avg >= 8.0): {len(excellent_students)}") for student in excellent_students: print(f" {student['name']}: {student['average']}")

print(f"\n3. Class average: {total_average:.2f}")

print("\n4. Sorted by average (desc) then age (asc):") for student in sorted_students: print(f" {student['name']} (age {student['age']}): {student['average']}")

print("\n5. Grouped by age:") for age, students_list in grouped_by_age.items(): names = [s['name'] for s in students_list] print(f" Age {age}: {', '.join(names)}")

Advanced lambda examples

def lambda_examples(): """Advanced lambda function examples"""

# 1. Lambda with multiple parameters
calculate_bmi = lambda weight, height: round(weight / (height ** 2), 2)

# 2. Lambda for sorting complex data
products = [
    {'name': 'Laptop', 'price': 1000, 'rating': 4.5, 'stock': 10},
    {'name': 'Mouse', 'price': 25, 'rating': 4.2, 'stock': 50},
    {'name': 'Keyboard', 'price': 75, 'rating': 4.7, 'stock': 30},
]

# Sort by rating desc, then by price asc
sorted_products = sorted(
    products,
    key=lambda p: (-p['rating'], p['price'])
)

# 3. Lambda for conditional operations
grade_calculator = lambda score: (
    'A' if score >= 90 else
    'B' if score >= 80 else
    'C' if score >= 70 else
    'D' if score >= 60 else
    'F'
)

# 4. Lambda with filter for complex conditions
available_expensive_products = list(filter(
    lambda p: p['price'] > 50 and p['stock'] > 0 and p['rating'] >= 4.0,
    products
))

print("\nLAMBDA EXAMPLES:")
print(f"BMI calculation: {calculate_bmi(70, 1.75)}")
print(f"Grade for 85: {grade_calculator(85)}")
print(f"Available expensive products: {len(available_expensive_products)}")

if name == "main": functional_data_processing() lambda_examples()

### Bài 3: Advanced Module System (10 phút)

**Tạo package structure:**

my_project/ ├── main.py ├── config.py ├── utils/ │ ├── init.py │ ├── file_operations.py │ ├── data_processing.py │ └── validators.py ├── models/ │ ├── init.py │ ├── user.py │ └── product.py └── services/ ├── init.py ├── database.py └── email_service.py

**config.py:**

```python
import os
from pathlib import Path

class Config:
    """Application configuration"""

    # Base paths
    BASE_DIR = Path(__file__).parent
    DATA_DIR = BASE_DIR / 'data'
    LOGS_DIR = BASE_DIR / 'logs'

    # Database
    DATABASE_URL = os.getenv('DATABASE_URL', 'sqlite:///app.db')

    # Email
    EMAIL_HOST = os.getenv('EMAIL_HOST', 'smtp.gmail.com')
    EMAIL_PORT = int(os.getenv('EMAIL_PORT', '587'))

    # Application
    DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'
    VERSION = '1.0.0'

    @classmethod
    def create_directories(cls):
        """Create necessary directories"""
        cls.DATA_DIR.mkdir(exist_ok=True)
        cls.LOGS_DIR.mkdir(exist_ok=True)

utils/init.py:

"""
Utilities package for common functions
"""

from .file_operations import FileManager
from .data_processing import DataProcessor
from .validators import Validator

__all__ = ['FileManager', 'DataProcessor', 'Validator']

utils/file_operations.py:

import json
import csv
import pickle
from pathlib import Path
from typing import Any, Dict, List

class FileManager:
    """Handle file operations with different formats"""

    @staticmethod
    def read_json(file_path: str) -> Dict[str, Any]:
        """Read JSON file"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                return json.load(f)
        except FileNotFoundError:
            raise FileNotFoundError(f"File not found: {file_path}")
        except json.JSONDecodeError as e:
            raise ValueError(f"Invalid JSON format: {e}")

    @staticmethod
    def write_json(data: Dict[str, Any], file_path: str, indent: int = 2) -> None:
        """Write data to JSON file"""
        Path(file_path).parent.mkdir(parents=True, exist_ok=True)
        with open(file_path, 'w', encoding='utf-8') as f:
            json.dump(data, f, indent=indent, ensure_ascii=False)

    @staticmethod
    def read_csv(file_path: str) -> List[Dict[str, str]]:
        """Read CSV file as list of dictionaries"""
        with open(file_path, 'r', encoding='utf-8') as f:
            reader = csv.DictReader(f)
            return list(reader)

    @staticmethod
    def write_csv(data: List[Dict[str, Any]], file_path: str) -> None:
        """Write data to CSV file"""
        if not data:
            return

        Path(file_path).parent.mkdir(parents=True, exist_ok=True)
        with open(file_path, 'w', encoding='utf-8', newline='') as f:
            writer = csv.DictWriter(f, fieldnames=data[0].keys())
            writer.writeheader()
            writer.writerows(data)

    @staticmethod
    def save_pickle(obj: Any, file_path: str) -> None:
        """Save object using pickle"""
        Path(file_path).parent.mkdir(parents=True, exist_ok=True)
        with open(file_path, 'wb') as f:
            pickle.dump(obj, f)

    @staticmethod
    def load_pickle(file_path: str) -> Any:
        """Load object from pickle file"""
        with open(file_path, 'rb') as f:
            return pickle.load(f)

main.py - Demo application:

#!/usr/bin/env python3
"""
Main application demonstrating advanced module usage
"""

import logging
from config import Config
from utils import FileManager, DataProcessor, Validator
from models import User, Product

def setup_logging():
    """Setup application logging"""
    Config.create_directories()

    logging.basicConfig(
        level=logging.DEBUG if Config.DEBUG else logging.INFO,
        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        handlers=[
            logging.FileHandler(Config.LOGS_DIR / 'app.log'),
            logging.StreamHandler()
        ]
    )

def demo_application():
    """Demo the complete application"""
    logger = logging.getLogger(__name__)
    logger.info(f"Starting application v{Config.VERSION}")

    try:
        # Create sample data
        users = [
            User("U001", "Nguyễn Văn An", "an@email.com", 25),
            User("U002", "Trần Thị Bình", "binh@email.com", 30),
            User("U003", "Lê Văn Cường", "cuong@email.com", 28),
        ]

        products = [
            Product("P001", "Laptop", 1500.00, 10),
            Product("P002", "Mouse", 25.00, 50),
            Product("P003", "Keyboard", 75.00, 30),
        ]

        # Save data to files
        users_data = [user.to_dict() for user in users]
        products_data = [product.to_dict() for product in products]

        FileManager.write_json(users_data, Config.DATA_DIR / 'users.json')
        FileManager.write_csv(products_data, Config.DATA_DIR / 'products.csv')

        logger.info("Data saved successfully")

        # Process data
        processor = DataProcessor()

        # Load and validate
        loaded_users = FileManager.read_json(Config.DATA_DIR / 'users.json')
        loaded_products = FileManager.read_csv(Config.DATA_DIR / 'products.csv')

        print("="*60)
        print("APPLICATION DEMO")
        print("="*60)
        print(f"Loaded {len(loaded_users)} users and {len(loaded_products)} products")

        # Statistics
        total_inventory_value = sum(
            float(p['price']) * int(p['stock']) 
            for p in loaded_products
        )

        avg_age = sum(u['age'] for u in loaded_users) / len(loaded_users)

        print(f"Total inventory value: ${total_inventory_value:,.2f}")
        print(f"Average user age: {avg_age:.1f}")

        logger.info("Application completed successfully")

    except Exception as e:
        logger.error(f"Application error: {e}")
        raise

if __name__ == "__main__":
    setup_logging()
    demo_application()

V. Project Development: Task Management System (30 phút)

Đề bài: Tạo một mini framework cho quản lý tasks với các tính năng:

  • Task creation, modification, deletion
  • Priority and status management
  • File-based persistence
  • Search and filtering
  • Statistics and reporting
# File: task_manager/core.py
from datetime import datetime, timedelta
from enum import Enum
from typing import List, Dict, Optional
import uuid

class Priority(Enum):
    LOW = 1
    MEDIUM = 2
    HIGH = 3
    CRITICAL = 4

class Status(Enum):
    TODO = "todo"
    IN_PROGRESS = "in_progress"
    COMPLETED = "completed"
    CANCELLED = "cancelled"

class Task:
    """Task model with all necessary attributes"""

    def __init__(self, title: str, description: str = "", 
                 priority: Priority = Priority.MEDIUM,
                 due_date: Optional[datetime] = None):
        self.id = str(uuid.uuid4())
        self.title = title
        self.description = description
        self.priority = priority
        self.status = Status.TODO
        self.due_date = due_date
        self.created_at = datetime.now()
        self.updated_at = datetime.now()
        self.completed_at = None

    def update(self, **kwargs):
        """Update task attributes"""
        for key, value in kwargs.items():
            if hasattr(self, key):
                setattr(self, key, value)
        self.updated_at = datetime.now()

    def complete(self):
        """Mark task as completed"""
        self.status = Status.COMPLETED
        self.completed_at = datetime.now()
        self.updated_at = datetime.now()

    def is_overdue(self) -> bool:
        """Check if task is overdue"""
        if not self.due_date or self.status == Status.COMPLETED:
            return False
        return datetime.now() > self.due_date

    def to_dict(self) -> Dict:
        """Convert task to dictionary"""
        return {
            'id': self.id,
            'title': self.title,
            'description': self.description,
            'priority': self.priority.value,
            'status': self.status.value,
            'due_date': self.due_date.isoformat() if self.due_date else None,
            'created_at': self.created_at.isoformat(),
            'updated_at': self.updated_at.isoformat(),
            'completed_at': self.completed_at.isoformat() if self.completed_at else None
        }

    @classmethod
    def from_dict(cls, data: Dict) -> 'Task':
        """Create task from dictionary"""
        task = cls(data['title'], data.get('description', ''))
        task.id = data['id']
        task.priority = Priority(data['priority'])
        task.status = Status(data['status'])

        if data.get('due_date'):
            task.due_date = datetime.fromisoformat(data['due_date'])

        task.created_at = datetime.fromisoformat(data['created_at'])
        task.updated_at = datetime.fromisoformat(data['updated_at'])

        if data.get('completed_at'):
            task.completed_at = datetime.fromisoformat(data['completed_at'])

        return task

class TaskManager:
    """Main task management system"""

    def __init__(self, storage_file: str = 'tasks.json'):
        self.storage_file = storage_file
        self.tasks: Dict[str, Task] = {}
        self.load_tasks()

    def create_task(self, title: str, **kwargs) -> Task:
        """Create a new task"""
        task = Task(title, **kwargs)
        self.tasks[task.id] = task
        self.save_tasks()
        return task

    def get_task(self, task_id: str) -> Optional[Task]:
        """Get task by ID"""
        return self.tasks.get(task_id)

    def update_task(self, task_id: str, **kwargs) -> bool:
        """Update task"""
        task = self.get_task(task_id)
        if task:
            task.update(**kwargs)
            self.save_tasks()
            return True
        return False

    def delete_task(self, task_id: str) -> bool:
        """Delete task"""
        if task_id in self.tasks:
            del self.tasks[task_id]
            self.save_tasks()
            return True
        return False

    def complete_task(self, task_id: str) -> bool:
        """Mark task as completed"""
        task = self.get_task(task_id)
        if task:
            task.complete()
            self.save_tasks()
            return True
        return False

    def search_tasks(self, query: str) -> List[Task]:
        """Search tasks by title or description"""
        query = query.lower()
        results = []
        for task in self.tasks.values():
            if (query in task.title.lower() or 
                query in task.description.lower()):
                results.append(task)
        return results

    def filter_tasks(self, status: Optional[Status] = None,
                    priority: Optional[Priority] = None,
                    overdue_only: bool = False) -> List[Task]:
        """Filter tasks by criteria"""
        results = list(self.tasks.values())

        if status:
            results = [t for t in results if t.status == status]

        if priority:
            results = [t for t in results if t.priority == priority]

        if overdue_only:
            results = [t for t in results if t.is_overdue()]

        return results

    def get_statistics(self) -> Dict:
        """Get task statistics"""
        total = len(self.tasks)
        if total == 0:
            return {}

        status_counts = {}
        priority_counts = {}
        overdue_count = 0

        for task in self.tasks.values():
            # Status counts
            status = task.status.value
            status_counts[status] = status_counts.get(status, 0) + 1

            # Priority counts
            priority = task.priority.name
            priority_counts[priority] = priority_counts.get(priority, 0) + 1

            # Overdue count
            if task.is_overdue():
                overdue_count += 1

        completion_rate = (status_counts.get('completed', 0) / total) * 100

        return {
            'total_tasks': total,
            'status_breakdown': status_counts,
            'priority_breakdown': priority_counts,
            'overdue_tasks': overdue_count,
            'completion_rate': round(completion_rate, 2)
        }

    def save_tasks(self):
        """Save tasks to file"""
        from utils import FileManager
        data = {task_id: task.to_dict() for task_id, task in self.tasks.items()}
        FileManager.write_json(data, self.storage_file)

    def load_tasks(self):
        """Load tasks from file"""
        try:
            from utils import FileManager
            data = FileManager.read_json(self.storage_file)
            self.tasks = {
                task_id: Task.from_dict(task_data)
                for task_id, task_data in data.items()
            }
        except FileNotFoundError:
            self.tasks = {}

# Demo usage
def demo_task_manager():
    """Demo the task management system"""
    tm = TaskManager('demo_tasks.json')

    # Create sample tasks
    task1 = tm.create_task(
        "Complete Python project",
        description="Finish the task management system",
        priority=Priority.HIGH,
        due_date=datetime.now() + timedelta(days=7)
    )

    task2 = tm.create_task(
        "Review code",
        description="Code review for team project",
        priority=Priority.MEDIUM,
        due_date=datetime.now() + timedelta(days=3)
    )

    task3 = tm.create_task(
        "Write documentation",
        description="Update project documentation",
        priority=Priority.LOW,
        due_date=datetime.now() - timedelta(days=1)  # Overdue
    )

    # Update and complete tasks
    tm.update_task(task2.id, status=Status.IN_PROGRESS)
    tm.complete_task(task1.id)

    # Display statistics
    stats = tm.get_statistics()
    print("TASK MANAGEMENT DEMO")
    print("="*50)
    print(f"Total tasks: {stats['total_tasks']}")
    print(f"Completion rate: {stats['completion_rate']}%")
    print(f"Overdue tasks: {stats['overdue_tasks']}")
    print("\nStatus breakdown:")
    for status, count in stats['status_breakdown'].items():
        print(f"  {status}: {count}")

    # Search and filter
    overdue_tasks = tm.filter_tasks(overdue_only=True)
    print(f"\nOverdue tasks: {len(overdue_tasks)}")
    for task in overdue_tasks:
        print(f"  - {task.title} (due: {task.due_date.strftime('%Y-%m-%d')})")

if __name__ == "__main__":
    demo_task_manager()

VI. Code Review & Optimization (10 phút)

Performance Optimization Tips

1. Use appropriate data structures:

# Slow for lookups
valid_ids = ['id1', 'id2', 'id3', ...]
if user_id in valid_ids:  # O(n)
    pass

# Fast for lookups
valid_ids = {'id1', 'id2', 'id3', ...}
if user_id in valid_ids:  # O(1)
    pass

2. Use generators for large datasets:

# Memory intensive
def get_all_numbers():
    return [i for i in range(1000000)]

# Memory efficient
def get_all_numbers():
    return (i for i in range(1000000))

3. Use caching for expensive operations:

from functools import lru_cache

@lru_cache(maxsize=128)
def expensive_calculation(n):
    # Some expensive computation
    return result

VII. Bài tập về nhà

Bài 1: Advanced Web Scraper Framework

Yêu cầu:

  • Design a modular web scraping framework
  • Support multiple data sources
  • Implement caching and rate limiting
  • Error handling and retry mechanisms
  • Export data to multiple formats

Bài 2: Personal Finance Manager

Yêu cầu:

  • Income/expense tracking with categories
  • Budget planning and monitoring
  • Financial goal setting
  • Report generation with charts
  • Data encryption for security

Bài 3: Code Quality Analyzer

Yêu cầu:

  • Analyze Python code files
  • Check for code smells and anti-patterns
  • Generate complexity metrics
  • Suggest improvements
  • Create HTML reports

VIII. Chuẩn bị cho buổi sau

Buổi tiếp theo sẽ học về Tkinter cơ bản - tạo ứng dụng với giao diện đồ họa. Hãy chuẩn bị:

  • Ôn lại event-driven programming concepts
  • Tìm hiểu về GUI design principles
  • Cài đặt và test Tkinter trên máy

💡 Tip học tập: Clean code is not just about working code - it's about code that's easy to read, maintain, and extend. Always think about the next developer who will read your code!