Notes & software courses · Free to learn
Aph's Blog
On this page

SOLID 5 ข้อ

👋 อ่านฟรีทั้งหมดบน Aph's Blog — เนื้อหาภาษาไทย ทำตามทีละหน้าใน sidebar ได้เลย หากมีข้อเสนอแนะหรืออยากให้เพิ่มหัวข้อไหน บอกได้เสมอ

หลักการออกแบบ class/module 5 ข้อที่ทำให้โค้ดยืดหยุ่น แก้ง่าย และทดสอบง่าย

SOLID คือชุดหลักการออกแบบ 5 ข้อสำหรับเขียนโค้ดเชิงวัตถุ (OOP) ที่ดูแลและต่อยอดง่าย ไม่ต้องท่องตายตัว แต่เข้าใจแนวคิดแล้วจะออกแบบโค้ดได้ดีขึ้น

S — Single Responsibility

แต่ละ class ควรมีเหตุผลให้เปลี่ยนแค่เรื่องเดียว (รับผิดชอบเรื่องเดียว)

python
# ❌ class เดียวทำทั้งคำนวณและบันทึกไฟล์ (2 เหตุผลที่จะเปลี่ยน)
class Report:
    def calculate(self): ...
    def save_to_file(self): ...

# ✅ แยกความรับผิดชอบ
class Report:
    def calculate(self): ...

class ReportSaver:
    def save(self, report): ...

O — Open/Closed

เปิดให้ "ขยาย" (เพิ่มพฤติกรรมใหม่) แต่ปิดการ "แก้ของเดิม" — เพิ่มฟีเจอร์โดยไม่ต้องไปรื้อโค้ดที่ทำงานอยู่

python
# ✅ เพิ่มรูปร่างใหม่ได้โดยไม่แก้โค้ดเดิม
class Shape:
    def area(self): raise NotImplementedError

class Circle(Shape):
    def __init__(self, r): self.r = r
    def area(self): return 3.14159 * self.r ** 2

class Square(Shape):
    def __init__(self, s): self.s = s
    def area(self): return self.s ** 2

def total_area(shapes):       # ไม่ต้องแก้เมื่อเพิ่มรูปใหม่
    return sum(s.area() for s in shapes)

L, I, D โดยย่อ

ตัวอักษรหลักการใจความ
LLiskov Substitutionsubclass ต้องใช้แทน parent ได้โดยไม่พัง
IInterface Segregationอย่าบังคับให้ implement method ที่ไม่ใช้
DDependency Inversionพึ่ง abstraction ไม่ใช่ implementation ตายตัว
python
# D — Dependency Inversion: รับ dependency เข้ามา (ไม่สร้างเองตายตัว)
# ❌ ผูกกับ implementation
class Service:
    def __init__(self):
        self.db = MySQLDatabase()    # ผูกตาย

# ✅ รับเข้ามา (inject) — สลับ/mock ได้ง่าย
class Service:
    def __init__(self, db):
        self.db = db                  # จะเป็น MySQL หรือ mock ก็ได้
SOLID เป็นแนวทาง ไม่ใช่กฎตายตัว

อย่ายึด SOLID จนทำโค้ดซับซ้อนเกินจำเป็น (ละเมิด KISS/YAGNI) ใช้เมื่อมันแก้ปัญหาจริง โดยเฉพาะ Dependency Inversion ช่วยให้ mock ในเทสต์ได้ง่าย (เชื่อมบท Testing)

สรุปหัวข้อนี้

  • S: class รับผิดชอบเรื่องเดียว
  • O: เพิ่มพฤติกรรมใหม่ได้โดยไม่แก้ของเดิม
  • L: subclass แทน parent ได้; I: อย่าบังคับ method ที่ไม่ใช้
  • D: พึ่ง abstraction รับ dependency เข้ามา — ทำให้ mock/สลับง่าย
แบบฝึกหัด

1) หา class ที่ทำหลายหน้าที่แล้วแยกตาม SRP 2) ออกแบบ Shape ที่เพิ่มรูปใหม่ได้โดยไม่แก้ total_area (OCP) 3) แก้ class ที่สร้าง db เองให้รับเข้ามาแทน (DIP) 4) อธิบายว่า DIP ช่วยการเขียนเทสต์อย่างไร