📌 ทบทวนแนวคิด Clean Architecture และวิเคราะห์โปรเจคของตัวเองว่าเข้าเกณฑ์หรือไม่

Clean Architecture เป็นแนวทางการออกแบบซอฟต์แวร์ที่ แยกความรับผิดชอบ (separation of concerns) อย่างชัดเจน เพื่อให้ระบบ:

  • ทดสอบง่าย (Testable)
  • ปรับเปลี่ยนง่าย (Flexible)
  • ยืดอายุระบบ (Maintainable)
  • ไม่ผูกติดกับ framework, database, UI

🧱 โครงสร้างของ Clean Architecture

🔄 กฎสำคัญ: Dependency Rule

โค้ดชั้นนอก สามารถเรียกใช้ ชั้นในได้
โค้ดชั้นใน ห้ามรู้จัก หรืออิงกับชั้นนอกเด็ดขาด

เช่น:

  • Entity ห้ามรู้จัก Controller หรือ Database
  • Use Case ห้ามรู้จัก UI หรือ Framework

Tips & Tricks การเขียน “Clean Code” ที่อ่านง่าย เข้าใจง่าย และดูแลง่าย

✨ 1. Meaningful Names – ตั้งชื่อให้รู้ว่าใช่

ข้อควรทำตัวอย่าง
✅ ใช้ชื่อสื่อความหมาย (ไม่ย่อมั่ว)calculateSalary() ดีกว่า cal()
✅ ใช้ชื่อที่ตอบว่า “ทำอะไร”isValidEmail() ดีกว่า check1()
❌ หลีกเลี่ยงใช้ชื่อทั่วไปเกินไปdata, info, temp
✅ ใช้ชื่อที่ consistentถ้าใช้ getX() ก็ใช้ setX() ด้วย

🔧 2. Function – ฟังก์ชันควร “ทำอย่างเดียว”

Guidelineตัวอย่าง
✅ ควรสั้น < 20 บรรทัดถ้าเกิน → แยกย่อย
✅ ชื่อฟังก์ชันต้องบอกได้ว่าทำอะไรsendWelcomeEmail()
✅ ทำงานอย่างเดียว (Single Responsibility)validateEmail() แยกจาก sendEmail()
❌ อย่าให้มี side-effect ลับ ๆเช่น แก้ state global โดยไม่แจ้ง

💬 3. Comment – อย่าใช้แทนชื่อที่ดี

ข้อควรทำตัวอย่าง
✅ ใช้ comment อธิบาย “เหตุผล” ไม่ใช่ “ว่าโค้ดทำอะไร”// ใช้ Retry เพราะ endpoint ไม่เสถียร
❌ หลีกเลี่ยง comment ซ้ำกับโค้ดi++; // เพิ่มค่า i ขึ้น 1
✅ ถ้าต้องใส่ comment → โค้ดอาจไม่ clean แล้วพิจารณา refactor แทน

🧾 4. Formatting – อ่านง่าย = ดูแลง่าย

แนวปฏิบัติอธิบาย
✅ เว้นบรรทัดให้เห็นกลุ่มของ logic ชัดเจนตัวอย่าง: ระหว่าง if, loop
✅ จัด indent ให้สม่ำเสมอใช้ tab หรือ space ให้ทีมตกลงกัน
❌ อย่ายัดทุกอย่างไว้บรรทัดเดียวอ่านยาก
✅ ใช้ linter / formatterเช่น Prettier, ESLint, Checkstyle

🏷️ 5. Classes – ควร “รับผิดชอบเรื่องเดียว”

หลักการตัวอย่าง
✅ 1 class = 1 responsibilityReportGenerator, EmailSender แยกกัน
❌ ไม่ควรมี Util.java ที่ทำทุกอย่าง
✅ ใช้ interface เพื่อกำหนด contractแล้ว implement แยกใน service class
✅ ควร test ได้ง่ายclass ที่ดีต้อง test ได้แบบ isolated

🧱 6. Object & Data Structures – ใช้ OOP อย่างเหมาะสม

แนวคิดตัวอย่าง
✅ ซ่อนการเข้าถึง field (encapsulation)ใช้ private + getter/setter
✅ พิจารณาใช้ record / DTO แยกจาก entity
❌ อย่าทำ data object ที่ไม่ฉลาดเลย (anemic model)
✅ สร้าง method ให้ object ทำงานแทนที่ logic อยู่ข้างนอก

⚠ 7. Error Handling – อย่าซ่อนบั๊ก

ข้อควรทำตัวอย่าง
✅ ใช้ try/catch เฉพาะจุดที่จำเป็น
✅ ให้ข้อความ exception ชัดเจนthrow new InvalidEmailException("Email is not valid")
❌ อย่าจับ exception แล้วไม่ทำอะไรcatch (Exception e) {}
✅ ใช้ custom exception class แยกเฉพาะ domain

🧪 8. Unit Tests – โค้ดดี = test ได้ง่าย

Guidelineอธิบาย
✅ 1 test = 1 case = 1 assertion
✅ ชื่อฟังก์ชันควรบอกว่า test อะไรshouldReturnTrueWhenEmailIsValid()
✅ ใช้ Mock ให้เหมาะสมเช่น Mockito
❌ อย่า test logic ที่ framework ทำให้แล้ว
✅ Run test อัตโนมัติใน CI/CD

🛠 วิธีปรับปรุงโปรเจคของคุณให้เข้าสู่ Clean Architecture

สิ่งที่ควรทำตัวอย่าง
แยก Entity ออกจาก DTOสร้าง Employee กับ EmployeeDTO
สร้าง Use Case class แยก เช่น CreateEmployeeUseCaseไม่เขียน logic ใน Controller ตรง ๆ
สร้าง interface เช่น EmployeeRepository ใน Use Case Layerแล้วให้ Infra Layer implements มัน
อย่าให้ Use Case หรือ Entity ใช้ Spring, Hibernate, หรือ HttpServletRequestใช้ Dependency Injection เท่านั้น
ทดสอบ Use Case แยกเดี่ยวได้ด้วย JUnit + Mockitoไม่ต้องโหลด Spring Context
// Domain Layer
public class Employee {
    private String id;
    private String name;
}

// Use Case Layer
public interface CreateEmployeeUseCase {
    void execute(Employee employee);
}

// Interface Adapter
@RestController
public class EmployeeController {
    private final CreateEmployeeUseCase useCase;

    @PostMapping("/employee")
    public ResponseEntity<Void> create(@RequestBody EmployeeDTO dto) {
        Employee employee = mapper.toEntity(dto);
        useCase.execute(employee);
        return ResponseEntity.ok().build();
    }
}

✅ ทำไมต้องใช้ Clean Architecture?

Clean Architecture ถูกออกแบบมาเพื่อแก้ปัญหาคลาสสิกของซอฟต์แวร์ที่โตไปแล้วดูแลยาก เช่น…

  • โค้ดพันกัน (Spaghetti Code)
  • เปลี่ยน UI แล้วต้องแก้ Business Logic
  • ย้าย Database หรือ Framework แล้วระบบพัง
  • ทดสอบโค้ดยากมาก

แนวคิดนี้ แยก concerns ชัดเจน ทำให้ ทดสอบง่าย ปรับเปลี่ยนง่าย ขยายต่อได้สบาย

ข้อดีอธิบาย
✅ ทดสอบง่ายUnit test Use Case โดยไม่ต้องโหลด Spring หรือ DB
✅ เปลี่ยน UI / DB ได้ไม่กระทบ logicUI, DB อยู่ “วงนอก”
✅ ขยายระบบได้ง่ายเพิ่ม Use Case, Service ใหม่โดยไม่รบกวนโค้ดเดิม
✅ แยกทีมทำงานได้แต่ละ layer รับผิดชอบชัดเจน
✅ Code Maintainability สูงแยก layer ช่วยให้เข้าใจเร็ว
ข้อเสียคำอธิบาย
❌ โค้ดยาวขึ้นใช้หลายชั้น + interface เยอะ
❌ อาจ Overkillถ้าใช้กับโปรเจคเล็กหรือไม่ซับซ้อน
❌ เรียนรู้ยากสำหรับมือใหม่ต้องเข้าใจ Layering, DI, และ SOLID
❌ ต้องวางแผนโครงสร้างดีตั้งแต่ต้นถ้าไม่วางให้ดีจะซ้ำซ้อน/เยิ่นเย้อ
ประเด็นคำอธิบาย
🧩 อย่า over-engineerถ้า logic ง่าย แค่แยก Service กับ Controller ก็พอ
🧩 อย่าลืมสื่อสารกับทีมทุกคนต้องเข้าใจแนวทางเดียวกัน
🧩 อย่าให้ Use Case รู้จัก DB หรือ Webใช้ Interface และ Dependency Injection เสมอ
🧩 อย่าทำแต่ structure ละเลย business logicสุดท้าย software ต้อง “ทำงานได้” ไม่ใช่แค่ “มี structure ดี”

โค้ดที่ดี = คนอื่น (รวมถึงตัวคุณในอนาคต) อ่านแล้วเข้าใจง่าย
Clean code ไม่ใช่แค่ให้คอมไพล์ผ่าน แต่คือ “ภาษาที่ทีมสื่อสารกันได้”

Posted in

ใส่ความเห็น