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

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 khiến 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 trường hợp 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 vị trí.
     

 

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

 

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 khiến mã khó đọc và khó theo dõi.
       
    • Logic bị phân tán khắp phương thức, khiến khó hiểu mã làm gì chỉ bằng một cái nhì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 nhưng đóng để sửa đổi).
       
  3. Vi phạm Trách nhiệm Đơn 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 ở một phần của 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à vị trí.
       
    • 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ã liên quan.
       
    • Nguy cơ gây ra lỗi trong quá trình thay đổi như vậy là cao.
       
  6. Kết nối chặt chẽ:

    • Tất cả logic kinh doanh được kết nối 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 chia logic thành các lớp có thể tái sử dụng, tuân theo các nguyên tắc chính như tính mô đun, đóng gói và tách biệt mối quan tâm.
 

Những cải tiến chính trong 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ỏ nhu cầu về các điều kiện if-else lồng nhau trong lớp Order.
     
  • Cải tiến: Mỗi chiến lược giảm giá hiện đóng gói hành vi cụ thể của nó, làm cho nó có thể tái sử dụng và dễ mở rộng.
     

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

  • Tính toán 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 chính

  • Lớp Order hiện đóng vai trò là người điều phối 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 hiện nay sạch sẽ, tập trung và tuân thủ Nguyên tắc Trách nhiệm Đơn nhất.
     

4. Sử dụng Thành phần hơn là Kế thừa

  • Thay vì mã hóa logic kinh doanh vào một lớp duy nhất, việc tái cấu trúc sử dụng thành phần, 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 kịch bản 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 vị trí

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ế:

 

  • Tính khả đọ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 các 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 của 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 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ó trong 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

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.