Tối ưu hóa mã Python - Trường hợp thực tế: Hệ thống đặt món nhà hàng

By JoeVu, at: 13:07 Ngày 15 tháng 11 năm 2024

Thời gian đọc ước tính: __READING_TIME__ minutes

Python Refactoring - Real Case Scenario: Restaurant Ordering System
Python Refactoring - Real Case Scenario: Restaurant Ordering System

Tái cấu trúc Python - Trường hợp thực tế: Hệ thống đặt món nhà hàng

 

1. Giới thiệu

Mã code lộn xộn, chứa đầy các câu lệnh if-else lồng nhau, thường xuất hiện trong các ứng dụng thực tế khi chúng trở nên phức tạp hơn. Theo thời gian, điều này làm cho hệ thống khó bảo trì, gỡ lỗi và mở rộng hơn. Trong bài viết này, chúng ta sẽ giải quyết một tình huống như vậy: một hệ thống đặt món nhà hàng, và chỉ ra cách tái cấu trúc nó bằng thiết kế hướng đối tượng có thể đơn giản hóa logic và cải thiện khả năng mở rộng.

 

2. Vấn đề

Hệ thống đặt món nhà hàng của chúng ta xử lý:

  • Giảm giá dựa trên loại khách hàng (VIP, lần đầu tiên, v.v.).
     
  • Phụ phí cho các đơn đặt hàng giao hàng, ăn tại chỗ hoặc mang đi.
     
  • Thuế thay đổi theo địa điểm.
     

Đây là triển khai ban đầu lộn xộn:

class Order:
    def __init__(self, order_type, customer_type, base_price, location=None):
        self.order_type = order_type
        self.customer_type = customer_type
        self.base_price = base_price
        self.location = location

    def calculate_total(self):
        total = self.base_price
        
        # Giảm giá dựa trên loại khách hàng
        if self.customer_type == "VIP":
            total *= 0.9  # Giảm giá 10%
        elif self.customer_type == "first-time":
            total *= 0.85  # Giảm giá 15%

        # Phụ phí dựa trên loại đơn hàng
        if self.order_type == "delivery":
            if self.location == "urban":
                total += 5
            elif self.location == "rural":
                total += 10
        elif self.order_type == "dine-in":
            total += 2

        # Thuế
        if self.location in ["urban", "rural"]:
            total *= 1.05
        elif self.order_type == "takeout":
            total *= 1.02
        
        # Các điều kiện bổ sung
        if self.customer_type == "VIP" and self.order_type == "dine-in":
            total -= 5  # Khách VIP được giảm 5$ cho ăn tại chỗ

        return total

order = Order(order_type="delivery", customer_type="VIP", base_price=100, location="rural")
print(f"Tổng giá đơn hàng: ${order.calculate_total():.2f}")

 

Tại sao mã này tệ:

  1. Logic lồng nhau sâu:

    • Nhiều cấp câu lệnh if-else làm cho mã khó đọc và theo dõi.
       
    • Logic được phân tán khắp phương thức, làm cho việc hiểu mã đang làm gì chỉ bằng cái nhìn thoáng qua trở nên khó khăn.
       
  2. Khả năng mở rộng thấp:

    • Thêm các loại khách hàng, giảm giá hoặc loại đơn hàng mới yêu cầu sửa đổi phương thức đã phức tạp này.
       
    • Cách tiếp cận này vi phạm Nguyên tắc mở-đóng (mã nên mở rộng được nhưng đóng để sửa đổi).
       
  3. Vi phạm trách nhiệm duy nhất:

    • Phương thức calculate_total xử lý giảm giá, phụ phí và thuế ở một nơi, dẫn đến một "phương thức thần" làm quá nhiều việc.
       
    • Bất kỳ thay đổi nào trong một phần logic đều có nguy cơ làm hỏng các phần không liên quan của phương thức.
       
  4. Khó kiểm thử:

    • Kiểm thử hàm này yêu cầu bao phủ nhiều điều kiện cho loại khách hàng, loại đơn hàng và địa điểm.
       
    • Bất kỳ lỗi nào trong một khối điều kiện đều có thể lan truyền qua toàn bộ phương thức.
       
  5. Khó bảo trì:

    • Nếu quy tắc kinh doanh thay đổi (ví dụ: tỷ lệ giảm giá hoặc thuế mới), bạn phải cẩn thận xác định vị trí và cập nhật phần mã có liên quan.
       
    • Nguy cơ xảy ra lỗi trong quá trình thay đổi như vậy là rất cao.
       
  6. Kết hợp chặt chẽ:

    • Tất cả logic kinh doanh được kết hợp chặt chẽ trong phương thức calculate_total.
       
    • Nó không thể được sử dụng lại ở nơi khác, chẳng hạn như trong công cụ báo cáo hoặc dịch vụ khác.

 

3. Tái cấu trúc

Để giải quyết các vấn đề được xác định trong triển khai ban đầu, chúng ta tái cấu trúc hệ thống bằng cách sử dụng mẫu chiến lược và thiết kế hướng đối tượng. Những cải tiến này tập trung vào việc phân tách logic thành các lớp có thể sử dụng lại, tuân theo các nguyên tắc chính như tính mô-đun, đóng gói và tách biệt các mối quan tâm.
 

Những cải tiến chính trong việc tái cấu trúc

1. Giới thiệu các lớp chiến lược cho giảm giá

  • Logic giảm giá được trích xuất thành các lớp riêng biệt dựa trên loại khách hàng (ví dụ: VIPDiscount, FirstTimeDiscount).
     
  • Điều này loại bỏ sự cần thiết của các điều kiện if-else lồng nhau bên trong lớp Order.
     
  • Cải tiến: Mỗi chiến lược giảm giá giờ đây đóng gói hành vi cụ thể của nó, làm cho nó có thể sử dụng lại và dễ mở rộng.
     

2. Tạo các lớp chiến lược cho các loại đơn hàng

  • Các phép tính phụ phí cho delivery, dine-intakeout được chuyển sang các lớp chiến lược riêng của chúng (ví dụ: DeliveryOrder, DineInOrder).
     
  • Các lớp này xử lý logic dựa trên vị trí (ví dụ: phí giao hàng nội thành hoặc ngoại thành) mà không làm lộn xộn lớp Order chính.
     
  • Cải tiến: Việc thêm một loại đơn hàng mới, như "CateringOrder", chỉ yêu cầu tạo một lớp chiến lược mới mà không cần sửa đổi mã hiện có.
     

3. Đơn giản hóa lớp Order cốt lõi

  • Lớp Order hiện đóng vai trò là người phối hợp nhẹ:
    • Nó ủy quyền tính toán giảm giá cho một DiscountStrategy.
       
    • Nó ủy quyền tính toán phụ phí cho một OrderTypeStrategy.
       
    • Nó xử lý tính toán thuế dựa trên kết quả của các chiến lược này.
       
  • Cải tiến: Lớp Order giờ đây sạch sẽ, tập trung và tuân thủ Nguyên tắc trách nhiệm duy nhất.
     

4. Sử dụng soạn thảo thay vì kế thừa

  • Thay vì mã hóa cứng logic kinh doanh vào một lớp duy nhất, việc tái cấu trúc sử dụng soạn thảo, kết hợp các chiến lược một cách động.
     
  • Cải tiến: Điều này làm cho hệ thống linh hoạt và dễ tùy chỉnh hơn cho các trường hợp khác nhau.


Mã đã được tái cấu trúc

class DiscountStrategy:
    """Lớp cơ sở cho các chiến lược giảm giá."""
    def apply_discount(self, order):
        return order.base_price

class VIPDiscount(DiscountStrategy):
    def apply_discount(self, order):
        return order.base_price * 0.9  # Giảm giá 10% cho VIP

class FirstTimeDiscount(DiscountStrategy):
    def apply_discount(self, order):
        return order.base_price * 0.85  # Giảm giá 15% cho khách hàng lần đầu

class NoDiscount(DiscountStrategy):
    def apply_discount(self, order):
        return order.base_price


class OrderTypeStrategy:
    """Lớp cơ sở cho các chiến lược loại đơn hàng."""
    def apply_surcharge(self, order):
        return 0

class DeliveryOrder(OrderTypeStrategy):
    def apply_surcharge(self, order):
        return 5 if order.location == "urban" else 10  # Phí giao hàng dựa trên địa điểm

class DineInOrder(OrderTypeStrategy):
    def apply_surcharge(self, order):
        return 2  # Phí phục vụ cho các đơn hàng ăn tại chỗ

class TakeoutOrder(OrderTypeStrategy):
    def apply_surcharge(self, order):
        return 0  # Không phụ phí cho mang đi


class Order:
    def __init__(self, base_price, discount_strategy, order_type_strategy, location=None):
        self.base_price = base_price
        self.discount_strategy = discount_strategy
        self.order_type_strategy = order_type_strategy
        self.location = location

    def calculate_total(self):
        # Ủy quyền tính toán giảm giá và phụ phí
        discounted_price = self.discount_strategy.apply_discount(self)
        surcharge = self.order_type_strategy.apply_surcharge(self)
        
        # Logic thuế
        tax_rate = 0.05 if self.location in ["urban", "rural"] else 0.02
        tax = discounted_price * tax_rate

        # Tính toán tổng
        return discounted_price + surcharge + tax

 

4. Tại sao nó tốt hơn

Mã đã được tái cấu trúc cung cấp một số lợi thế:

  • Khả năng đọc: Mỗi trách nhiệm được xác định rõ ràng trong lớp của nó.
     
  • Khả năng mở rộng: Việc thêm giảm giá hoặc loại đơn hàng mới rất dễ dàng — chỉ cần tạo các lớp mới.
     
  • Khả năng kiểm thử: Các chiến lược riêng lẻ có thể được kiểm thử độc lập.
     
  • Khả năng bảo trì: Thay đổi một phần logic sẽ không ảnh hưởng đến các phần khác.

 

5. Kết luận

Bằng cách tái cấu trúc hệ thống đặt món nhà hàng, chúng ta đã biến một khối if-else lồng nhau lộn xộn thành một thiết kế hướng đối tượng có mô-đun. Cách tiếp cận này đảm bảo mã sạch sẽ, có thể mở rộng và dễ bảo trì hơn.

Nếu hệ thống của bạn đang bị nhấn chìm trong sự phức tạp, hãy xem xét áp dụng các nguyên tắc thiết kế tương tự để đơn giản hóa và bảo vệ nó cho tương lai!

 

Tag list:
- Python Refactoring
- Object-Oriented Programming in Python
- Python Design Patterns Tutorial
- Object-Oriented Design
- Improving Nested If-Else Logic
- Real-World Python Refactoring Example
- Best Practices for Python Development
- Clean Code Practices
- Code Readability
- Modular Programming
- Improve Code Scalability with OOP
- Strategy Pattern
- Refactor Nested If-Else Python
- Refactoring Code
- Restaurant Ordering System
- How to Refactor a Restaurant Ordering System
- Using Strategy Patterns for Clean Code
- Refactoring Complex Systems
- Scalable Design Patterns
- Simplify Complex Code

Liên quan

Python Optimization

Đọc thêm
Outsourcing Experience

Đọc thêm
Django Python

Đọc thêm

Theo dõi

Theo dõi bản tin của chúng tôi và không bao giờ bỏ lỡ những tin tức mới nhất.