0
0
Lập trình
Sơn Tùng Lê
Sơn Tùng Lê103931498422911686980

Nguyên Tắc Thiết Kế SOLID trong Lập Trình Python: Hướng Dẫn Chi Tiết

Đăng vào 3 tuần trước

• 5 phút đọc

Chủ đề:

Basic PythonOOP

Nguyên Tắc Thiết Kế SOLID trong Lập Trình Python: Hướng Dẫn Chi Tiết

Lập trình hướng đối tượng (OOP) là một phương pháp phổ biến giúp tổ chức mã thành các lớp và đối tượng. Tuy nhiên, việc thiết kế các lớp và đối tượng hiệu quả không phải là điều dễ dàng. Về vấn đề này, Robert C. Martin đã giới thiệu một quy chuẩn quan trọng trong cuốn sách Design Principles and Design Patterns.

SOLID là từ viết tắt của 5 nguyên tắc thiết kế quan trọng khi làm việc với lập trình hướng đối tượng, bao gồm:

  • S - Nguyên tắc Đơn Trách Nhiệm (Single Responsibility Principle)
  • O - Nguyên tắc Mở Đóng (Open/Closed Principle)
  • L - Nguyên tắc Thay Thế Liskov (Liskov Substitution Principle)
  • I - Nguyên tắc Phân Tách Giao Diện (Interface Segregation Principle)
  • D - Nguyên tắc Đảo Ngược Phụ Thuộc (Dependency Inversion Principle)

1. Nguyên Tắc Đơn Trách Nhiệm (SRP)

Giải thích

Nguyên tắc SRP khẳng định rằng:

Mỗi lớp chỉ nên có một trách nhiệm duy nhất.

Mỗi lớp cần tập trung vào một chức năng cụ thể để tránh sự phức tạp không cần thiết trong việc bảo trì và mở rộng mã. Hãy tưởng tượng một máy có thể làm tất cả các công việc: nướng bánh, giặt đồ, và rửa bát. Nó có thể tiện lợi nhưng cũng dẫn đến khó khăn trong việc sử dụng và phát triển. Do đó, việc tách các chức năng theo từng nhiệm vụ là cần thiết.

Ví dụ vi phạm SRP:

python Copy
class Employee:
  def __init__(self, name, salary, vacation_days):
    self.name = name
    self.salary = salary
    self.vacation_days = vacation_days

  def calculate_paycheck(self):
    return self.salary / 2

  def request_vacation(self, days):
    if self.vacation_days >= days:
      self.vacation_days -= days
      return True
    else:
      return False

  def send_email(self, email_address, message):
    # Gửi email
    pass

Ví dụ tuân theo SRP:

python Copy
class EmployeeInfo:
  def __init__(self, name, salary, vacation_days):
    self.name = name
    self.salary = salary
    self.vacation_days = vacation_days

class Payroll:
  def __init__(self, employee_info):
    self.employee_info = employee_info

  def calculate_paycheck(self):
    return self.employee_info.salary / 2

class VacationTracker:
  def __init__(self, employee_info):
    self.employee_info = employee_info

  def request_vacation(self, days):
    if self.employee_info.vacation_days >= days:
      self.employee_info.vacation_days -= days
      return True
    else:
      return False

class Email:
  def __init__(self):
    pass

  def send_email(self, email_address, message):
    # Gửi email
    pass

class Employee:
  def __init__(self, name, salary, vacation_days):
    self.info = EmployeeInfo(name, salary, vacation_days)
    self.payroll = Payroll(self.info)
    self.vacation_tracker = VacationTracker(self.info)
    self.email = Email()

  def calculate_paycheck(self):
    return self.payroll.calculate_paycheck()

  def request_vacation(self, days):
    return self.vacation_tracker.request_vacation(days)

  def send_email(self, email_address, message):
    self.email.send_email(email_address, message)

2. Nguyên Tắc Mở Đóng (OCP)

Một lớp nên mở rộng cho hành vi mới, nhưng đóng đối với sửa đổi.

Điều này có nghĩa là bạn có thể thêm chức năng mới vào lớp mà không cần thay đổi mã hiện có của lớp. Phương pháp này giúp bảo trì và tái sử dụng mã hiệu quả hơn.

Ví dụ về OCP:

python Copy
class Car:
  def __init__(self, speed):
    self.speed = speed

  def move(self):
    print(f"Car is moving at {self.speed} km/h")

class SelfDrivingCar(Car):
  def __init__(self, speed):
    super().__init__(speed)

  def move(self):
    if self.is_self_driving:
      print("Car is driving itself")
    else:
      super().move()

  def enable_self_driving(self):
    self.is_self_driving = True

  def disable_self_driving(self):
    self.is_self_driving = False

3. Nguyên Tắc Thay Thế Liskov (LSP)

Có thể thay thế đối tượng lớp cha bằng đối tượng lớp con mà không làm thay đổi tính đúng đắn của chương trình.

Nguyên tắc này yêu cầu các lớp con phải tuân thủ hành vi của lớp cha. Nếu không, mã có thể không hoạt động như mong đợi.

Ví dụ về LSP:

python Copy
class Shape:
  def area(self):
    raise NotImplementedError

class Rectangle(Shape):
  def __init__(self, width, height):
    self.width = width
    self.height = height

  def area(self):
    return self.width * self.height

class Square(Rectangle):
  def __init__(self, side_length):
    super().__init__(side_length, side_length)

def print_area(shape):
  print(f"The area of the shape is {shape.area()}")

4. Nguyên Tắc Phân Tách Giao Diện (ISP)

Nên chia một giao diện lớn thành nhiều giao diện nhỏ hơn, mỗi giao diện phục vụ một mục đích cụ thể.

Điều này giúp cho việc triển khai và quản lý trở nên dễ dàng hơn.

Ví dụ về ISP:

python Copy
class Eater:
  def eat(self):
    raise NotImplementedError

class Sleeper:
  def sleep(self):
    raise NotImplementedError

class Mover:
  def move(self):
    raise NotImplementedError

class Dog(Eater, Sleeper, Mover):
  def eat(self):
    print("Dog is eating")

  def sleep(self):
    print("Dog is sleeping")

  def move(self):
    print("Dog is moving")

class Cat(Eater, Sleeper, Mover):
  def eat(self):
    print("Cat is eating")

  def sleep(self):
    print("Cat is sleeping")

  def move(self):
    print("Cat is moving")

5. Nguyên Tắc Đảo Ngược Phụ Thuộc (DIP)

Module cấp cao không nên phụ thuộc vào module cấp thấp. Cả hai nên phụ thuộc vào các trừu tượng.

Để áp dụng DIP, bạn cần sử dụng các giao diện để các lớp có thể tương tác qua trừu tượng, không phải qua chi tiết cài đặt.

Ví dụ về DIP:

python Copy
class Engine:
  def start(self):
    raise NotImplementedError

class Car:
  def __init__(self, engine: Engine):
    self.engine = engine

  def start_engine(self):
    self.engine.start()

class ElectricEngine(Engine):
  def start(self):
    print("Electric engine is starting")

class GasolineEngine(Engine):
  def start(self):
    print("Gasoline engine is starting")

Kết Luận

Áp dụng SOLID Design Principles là một bước quan trọng để tạo ra mã OOP chất lượng cao. Việc nắm rõ và vận dụng những nguyên tắc này sẽ giúp bạn viết mã có cấu trúc rõ ràng, dễ bảo trì và mở rộng hơn.
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào