Skip to content

บทที่ 0 — Mindset ก่อนเขียน Code

สารบัญ | บทถัดไป →


1. ทำไม Design สำคัญ

🌏 หมายเหตุภาษา (language-agnostic) — ตัวอย่างในบทนี้เขียน Java เป็นหลัก แต่ หลักการใช้ได้กับทุกภาษา (TypeScript, Python, Go, ...) ถ้าคุณไม่คุ้น Java โฟกัสที่ "ทำไมโค้ดนี้ไม่ดี" ก่อน — ไม่ต้องเข้าใจทุก syntax

JDBC สั้น ๆ ก่อนอ่าน — โค้ดข้างล่างใช้ JDBC (Java Database Connectivity = วิธีต่อ Java กับ database):

  • DriverManager.getConnection(...) = ขอเปิดการเชื่อมต่อ DB
  • Statement = วัตถุที่ใช้ส่งคำสั่ง SQL
  • executeUpdate(...) = ยิงคำสั่ง INSERT/UPDATE/DELETE

ภาษาอื่นมีคำเทียบหมด — Python ใช้ psycopg2.connect(), Node.js ใช้ pg.Client() — concept เดียวกัน

java
// Code ที่ทำงานได้
public void processOrder(Map<String, Object> data) {
    Connection conn = DriverManager.getConnection(...);
    Statement stmt = conn.createStatement();
    stmt.executeUpdate("INSERT INTO orders ...");
    
    Email email = new Email();
    email.send((String) data.get("email"), "Order confirmed");
    
    Logger.log("Order " + data.get("id"));
    
    // ... 200 บรรทัด
}

📖 อ่านโค้ดข้างบน — method นี้ทำหลายงานในที่เดียว: เปิด DB connection → INSERT order ลงตาราง → สร้าง Email object → ส่ง email ยืนยัน → บันทึก log ((String) data.get("email") ต้อง cast เพราะ Map<String, Object> ไม่รู้ชนิด — ดูบทที่ 6 architecture)

ปัญหา:

  • ❌ ทำหลายอย่าง — db + email + log + business logic
  • ❌ Test ลำบาก (DB จริง, email จริง)
  • ❌ เปลี่ยน DB → แก้ method นี้
  • ❌ เพิ่ม payment → แก้ method นี้
  • ❌ ไม่เห็นว่า "process order" คืออะไร

Code ทำงานได้ ≠ Code ที่ดี


2. นิยาม "Code ดี"

📒 เจอศัพท์อังกฤษเยอะในตารางนี้และตลอดบท? มีตารางคำศัพท์พื้นฐาน (§13)รวมความหมายไว้ท้ายบท เปิดอ่านควบคู่ได้เลย

Quality (คุณภาพด้านไหน)คืออะไร
Correctness — ความถูกต้องทำงานตามที่ต้องการ
Readability — ความอ่านง่ายคนอื่น (และตัวเองในอนาคต) อ่านเข้าใจ
Maintainability — การบำรุงรักษาแก้ง่าย — ไม่ break อย่างอื่น
Testability — การทดสอบได้ทดสอบได้
Performance — สมรรถนะเร็วพอ
Security — ความปลอดภัยปลอดภัย
Scalability — การขยายระบบรองรับการเติบโต

กฎทอง: Code อ่าน 10 ครั้ง / เขียน 1 ครั้ง → optimize for reading


3. กฎ KISS, DRY, YAGNI

KISS — Keep It Simple, Stupid

🔤 KISS (อ่าน "คิส") — ย่อจาก Keep It Simple, Stupid (เคป-อิท-ซิม-เพิล สตู-พิด) แปลตรงตัวว่า "ทำให้มันง่ายเข้าไว้นะไอ้โง่" — เป็นมุกฝรั่งที่วิศวกรใช้ย้ำเตือน ตัวเอง ว่าอย่าทำซับซ้อนเกินจำเป็น (ไม่ได้ดูถูกคนอื่น) ต้นกำเนิดจาก Kelly Johnson วิศวกรของ Lockheed ปี 1960

💡 ที่มา: เครื่องบินที่ออกแบบควรซ่อมได้ในสนามรบด้วยเครื่องมือพื้นฐาน → "ออกแบบให้ง่ายจนคนโง่ก็เข้าใจ"

java
// ❌ Over-engineered — ใช้ Strategy pattern กับงานง่าย ๆ
public class UserNameFormatter {
    private FormatStrategy strategy;        // ⚠️ ไม่ต้องเข้าใจ FormatStrategy ตอนนี้ — เป็น pattern ที่จะเรียนในบทที่ 3
    public String format(User user) {
        return strategy.apply(user.getName());
    }
}

// ✅ Simple
String name = user.getName().trim();

ใช้ pattern + abstraction เมื่อจำเป็น — ไม่ใช่ "เพื่อให้ดูเทพ"

DRY — Don't Repeat Yourself

🔤 DRY (อ่าน "ดราย" = แห้ง) — ย่อจาก Don't Repeat Yourself (โดนท์ รี-พีท ยัวร์-เซลฟ์ = "อย่าทำซ้ำตัวเอง") — มาจากหนังสือ The Pragmatic Programmer (1999) โดย Andy Hunt และ Dave Thomas

หลักการ: ความรู้แต่ละชิ้นใน system ควรมี representation เดียวที่ชัดเจน — ถ้าต้องแก้กฎ ก็แก้ที่เดียว ไม่ต้องไล่หา

java
// ❌ ซ้ำ (ใช้ BigDecimal เพราะ ห้ามใช้ double กับเงิน — ดู Magic Number §4D ด้านล่าง)
// (.stream(), lambda — ดูบท 05 Functional ถ้ายังไม่คุ้น)
BigDecimal subtotal = items.stream()
    .map(i -> i.price().multiply(BigDecimal.valueOf(i.quantity())))
    .reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal tax = items.stream()
    .map(i -> i.price().multiply(BigDecimal.valueOf(i.quantity())))
    .reduce(BigDecimal.ZERO, BigDecimal::add)
    .multiply(new BigDecimal("0.07"));

// ✅ Extract
BigDecimal subtotal = items.stream()
    .map(i -> i.price().multiply(BigDecimal.valueOf(i.quantity())))
    .reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal tax = subtotal.multiply(new BigDecimal("0.07"));

⚠️ อย่า DRY มากเกิน — Wrong abstraction = แย่กว่า duplication

"Duplication is far cheaper than the wrong abstraction." — Sandi Metz (แซน-ดี้ เมตซ์ — ผู้เขียน Practical Object-Oriented Design in Ruby (POODR)) (โค้ดซ้ำกันยังถูกกว่าการเลือก abstraction ผิด — รวมโค้ดผิด ๆ เข้าด้วยกันแก้ยากกว่าปล่อยให้ซ้ำ)

YAGNI — You Aren't Gonna Need It

🔤 YAGNI (อ่าน "ยาก-นี่") — ย่อจาก You Aren't Gonna Need It (ยู อาเรนต์ กอน-นา นีด อิท = "คุณยังไม่ต้องใช้มันหรอก") — Gonna เป็นภาษาพูดของ Going to — มาจากกระบวนทัศน์ Extreme Programming (XP) โดย Kent Beck ปลายยุค 1990s

หลักการ: เขียนเฉพาะที่ต้องใช้ วันนี้ — feature "เผื่ออนาคต" ส่วนใหญ่ไม่เคยถูกใช้

java
// ❌ "เผื่ออนาคต" — ยังไม่ได้ใช้
public class User {
    private String name;
    private String middleName;        // ยังไม่ใช้
    private String maidenName;        // ยังไม่ใช้
    private List<String> aliases;     // ยังไม่ใช้
    private Map<String, String> meta;  // ยังไม่ใช้
}

// ✅ ใส่เมื่อ requirement มี
public class User {
    private String name;
}

→ ทำ เฉพาะที่ต้องการตอนนี้ — เพิ่มเมื่อ requirement มาจริง


4. Code Smell — กลิ่นไม่ดี

A. Long Method

java
public void processOrder() {
    // 300 บรรทัด
}

→ split เป็น method เล็ก ๆ ที่ทำ 1 อย่าง

B. God Class

java
public class OrderManager {
    // 50 method — query DB, calculate, send email, log, ...
}

→ split ตาม responsibility

C. Long Parameter List

java
void create(String name, String email, String phone, String address,
            String city, String country, int age, String role, ...)

// ✅ Object
record CreateUserRequest(String name, String email, ...) {}
void create(CreateUserRequest req)

D. Magic Number / String

java
if (status == 1) {        // ❌ 1 คืออะไร?
    discount = 0.07;       // ❌ 0.07 คืออะไร?
}

// ✅
final int STATUS_PREMIUM = 1;
final BigDecimal DISCOUNT_RATE = new BigDecimal("0.07");   // ⚠️ ห้ามใช้ double กับเงิน (ดูหมายเหตุข้างล่าง) — Money value object (บทที่ 6 §15)

if (status == STATUS_PREMIUM) {
    discount = DISCOUNT_RATE;
}

// ✅✅ better — enum
if (status == OrderStatus.PREMIUM) { ... }

⚠️ ทำไม double แย่กับเงิน?double ใช้ binary floating-point ที่เก็บ 0.1 ไม่ได้แม่นยำ (กลายเป็น 0.1000000000000000055511...) — บวกเงินซ้ำ ๆ จะคลาดเคลื่อนทีละนิด สุดท้ายตัวเลขผิดทศนิยมเป็นบาท ใช้ BigDecimal เก็บเป็น decimal-based ที่แม่นยำ 100% — หรือใช้ Money value object ห่อ (บทที่ 6 §15)

E. Comment ที่ไม่จำเป็น

java
// ❌ Comment ที่ code อ่านได้
i = i + 1;        // Increment i

// ❌ Outdated
// Calculate VAT (7%)
double tax = price * 0.10;        // 0.10 — ไม่ใช่ 7%

// ✅ อธิบาย "why" ไม่ใช่ "what"
// VAT 7% — applied to subtotal, exclude shipping (per Q3 finance memo)
double tax = subtotal * 0.07;

F. Inappropriate Intimacy (ความสนิทสนมเกินงาม)

คือ code smell ที่ class หนึ่งไป "ล้วงลึก" รู้รายละเอียดภายในของอีก class มากเกินไป (เช่นไปดึง field ย่อย ๆ ของมันมาประกอบเอง) — ควรให้เจ้าของข้อมูลจัดการเองแล้วเรียกผ่าน method แทน

java
class Order {
    User user;
    
    public void notify() {
        // ❌ Order ทำงานกับ internal ของ User
        emailService.send(user.getEmail(), 
            "Hi " + user.getFirstName() + " " + user.getLastName());
    }
}

// ✅ User มี method ของตัวเอง
public void notify() {
    emailService.send(user.getEmail(), "Hi " + user.getDisplayName());
}

5. กฎ Boy Scout (กฎลูกเสือ)

🔤 Boy Scout rule (บอย-สเกาท์ รูล = กฎลูกเสือ) — มาจากกฎที่ลูกเสือฝรั่งสอนเด็ก: "Always leave the campground cleaner than you found it" (ทิ้งค่ายให้สะอาดกว่าตอนมา) ถูกนำมาประยุกต์กับโค้ดโดย Robert C. Martin ในหนังสือ Clean Code (2008)

"Always leave the code better than you found it." — Robert C. Martin (โร-เบิร์ต ซี. มาร์-ติน หรือที่รู้จักในชื่อ Uncle Bob (อันเคิล บ็อบ) = ผู้นิยาม SOLID และผู้เขียน Clean Code, Clean Architecture) (ทิ้งโค้ดไว้ให้ดีกว่าตอนที่เจอเสมอ)

ทุกครั้งที่แตะ code:

  • ตั้งชื่อ variable ที่ดีขึ้นถ้าเห็นที่ผิด
  • Extract method ถ้าเห็น duplication เล็ก
  • ลบ dead code

อย่ารอ "refactor week" — ทำทีละนิด ทุกวัน


6. กฎ Two Hats (กฎสองหมวก)

🔤 Two Hats (ทู แฮทส์ = หมวกสองใบ) — เปรียบเทียบว่าตอนทำงานเรา "สวมหมวก" บทบาทไหน: หมวก เพิ่ม feature (สร้างของใหม่) หรือ หมวก refactor (จัดระเบียบของเก่า) — สำนวนนี้เป็นของ Kent Beck (เคนต์ เบ็ค — ผู้คิดค้น TDD/XP) ในหนังสือ Test-Driven Development: By Example (2002)

แยก mode:

  1. Adding feature mode — เพิ่ม code ใหม่
  2. Refactor mode — แก้ structure โดยไม่เปลี่ยนพฤติกรรม

ห้ามทำพร้อมกัน — ถ้า fix bug + refactor ใน PR เดียว → review ลำบาก, regression risk

Workflow:
1. Refactor → ทดสอบยังผ่าน (no behavior change)
2. Add feature → ทดสอบใหม่ผ่าน

7. กฎ Premature Optimization

มือใหม่มักอยากเขียนโค้ดให้ "เร็ว" ตั้งแต่แรก แต่นั่นคือกับดัก — ส่วนที่คิดว่าช้ามักไม่ใช่ตัวปัญหาจริง การ optimize ก่อน measure ทำให้โค้ดซับซ้อนโดยเปล่าประโยชน์

กฎ: เขียนให้ชัดก่อน → profile หาจุดช้าจริง → optimize เฉพาะตรงนั้น

"Premature optimization is the root of all evil." — Donald Knuth (โดนัลด์ คนู้ธ — ตัว K ไม่ออกเสียง — นักวิทยาการคอมพิวเตอร์ผู้เขียน The Art of Computer Programming) (การ optimize ก่อนเวลาอันควร คือต้นตอของปัญหาทั้งปวง)

java
// ❌ Optimize ก่อน measure
public void process(List<User> users) {
    // Use bitset + native pointer + SIMD ...
    // (เพื่อให้เร็ว)
}

// ✅ เขียนชัด → measure → optimize เฉพาะที่ช้าจริง
public void process(List<User> users) {
    users.stream()
        .filter(User::isActive)
        .forEach(this::sendNotification);
}

→ Profile + measure ก่อนทุกครั้ง — most optimization = wrong


8. ความเข้าใจระดับ Abstraction

📖 ระดับล่าง = hardware-levelbit (บิต = 0/1), byte (ไบต์ = 8 bits), register (รี-จิส-เตอร์ = หน่วยความจำใน CPU), assembly (แอส-เซ็ม-บลี = ภาษาเครื่องแบบมนุษย์อ่านได้) ไม่ต้องเข้าใจตอนนี้ — แค่รู้ว่าระดับยิ่งล่างยิ่งใกล้ hardware

กฎ: code ระดับเดียวกัน อยู่ด้วยกัน

java
// ❌ Mix levels
public void processOrder(Order order) {
    Connection conn = DriverManager.getConnection(url);  // ← low
    if (order.getTotal() > 1000) {                       // ← high
        applyDiscount(order);                             // ← high
    }
    conn.commit();                                        // ← low
}

// ✅ Same level
public void processOrder(Order order) {
    applyBusinessRules(order);
    orderRepository.save(order);
}

9. Trade-offs — ทุก decision = trade-off

ไม่มี "best practice" ที่ใช้ได้ทุกที่ — ขึ้นกับ context:

DecisionTrade-off
Microserviceflexibility ↑ vs complexity ↑
Cachespeed ↑ vs consistency ↓
Normalize DBintegrity ↑ vs query speed ↓
Type system strictsafety ↑ vs flexibility ↓
Abstractionreusability ↑ vs complexity ↑
Test coveragequality ↑ vs dev speed ↓

Senior engineer = รู้ trade-off + อธิบายได้


10. Mental Models ที่ใช้ตลอดเล่ม

A. Coupling vs Cohesion

🔤 สองคำคู่นี้คือหัวใจของ OOP design — Coupling (คับ-พลิ่ง = การเกาะเกี่ยว/พึ่งพา) vs Cohesion (โค-ฮี-ชั่น = การยึดเหนี่ยว/รวมกลุ่ม)

  • Coupling (คับ-พลิ่ง) = "ผูกพันกับสิ่งอื่นแค่ไหน" → ต้องการ low
  • Cohesion (โค-ฮี-ชั่น) = "ทำสิ่งที่เกี่ยวกัน" → ต้องการ high
java
// ❌ Low cohesion, high coupling
class Helper {
    void sendEmail() { ... }
    void parseJson() { ... }
    void connectDb() { ... }
    void calculateTax() { ... }
}

// ✅ High cohesion
class EmailSender { sendEmail() { ... } }
class JsonParser { parse() { ... } }
class TaxCalculator { calculate() { ... } }

B. Composition over Inheritance

📖 กางศัพท์ก่อน (สองคำนี้คือหัวใจของ OOP — บทนี้แตะผ่าน ๆ ไว้ก่อน นิยามเต็มอยู่บทที่ 1):

  • Composition (การประกอบ) = สร้างของใหญ่จาก "ชิ้นส่วนย่อย" ที่เอามาประกอบกัน — ความสัมพันธ์แบบ "มี-เป็น-ส่วนหนึ่ง" (has-a) เช่น รถ มี เครื่องยนต์
  • Inheritance (การสืบทอด) = class ลูก "สืบทอด" คุณสมบัติจาก class แม่ — ความสัมพันธ์แบบ "เป็น-ชนิดหนึ่งของ" (is-a) เช่น หมา เป็น สัตว์ชนิดหนึ่ง

"Composition over Inheritance" = เวลาเลือกได้ ให้ใช้การประกอบ (composition) มากกว่าการสืบทอด (inheritance) เพราะยืดหยุ่นกว่า

💡 โค้ดด้านล่างเป็นแค่ "ภาพประกอบ" ให้เห็นภาพคร่าว ๆ — ยังไม่ต้องเข้าใจทุกบรรทัดตอนนี้ เดี๋ยวบทที่ 1 อธิบายละเอียด

java
// ❌ Inheritance — rigid (สืบทอด — แข็งทื่อ ปรับยาก)
class FlyingCar extends Car implements Flyable { ... }
class AmphibiousCar extends Car implements Swimmable { ... }
class FlyingAmphibiousCar extends ??? { ... }   // ❌ multiple inheritance — Java สืบทอดได้แค่ class เดียว → ตัน

// ✅ Composition (pseudo-code — ใช้ Optional<T> ห่อ capability ที่อาจไม่มี)
class Vehicle {
    Engine engine;
    Optional<Flyable> flight;     // มีก็บินได้ ไม่มีก็ไม่บิน
    Optional<Swimmable> swim;     // มีก็ว่ายได้ ไม่มีก็ไม่ว่าย
}

💡 Walkthrough: Strategy pattern (composition แบบรูปธรรม) — สมมติออกแบบ "ระบบนกบิน":

java
// 1. แยก behavior เป็น interface (strategy)
interface FlyBehavior { void fly(); }

// 2. มี implementation หลายแบบ
class CanFly implements FlyBehavior { public void fly() { System.out.println("บินได้!"); } }
class CantFly implements FlyBehavior { public void fly() { /* no-op */ } }

// 3. Bird ใช้ composition — รับ strategy จากภายนอก
class Bird {
    private FlyBehavior flyBehavior;
    public Bird(FlyBehavior fb) { this.flyBehavior = fb; }
    public void fly() { flyBehavior.fly(); }
}

// 4. ใช้
Bird duck = new Bird(new CanFly());
Bird penguin = new Bird(new CantFly());      // เพนกวินไม่บิน — ไม่ต้อง override no-op
duck = new Bird(new CantFly());              // สลับ behavior ตอน runtime ได้

เทียบ inheritance: ถ้า Penguin extends Bird แล้วต้อง fly() ก็ต้อง throw new UnsupportedOperationException() — ผิด LSP (ดูบทที่ 1 + 2)

รายละเอียดเต็มอยู่บทที่ 1 §5 และบทที่ 3 Strategy pattern

C. Separation of Concerns

แต่ละ module ทำงาน 1 อย่าง:

  • Service = business logic
  • Repository = data access (เข้า DB)
  • Controller = HTTP handling (รับ request เว็บ)
  • View = presentation (UI)

→ เปลี่ยน 1 ที่ ไม่ break อื่น

📖 คำศัพท์ Service/Repository/Controller มาจากโลก framework (Spring สำหรับ Java, NestJS สำหรับ Node, ...) ดูตัวอย่างจริงในบทที่ 6 Architecture — ถ้ายังไม่เคยใช้ framework ก็เข้าใจตามความหมายไปก่อน

D. Tell, Don't Ask (สั่ง อย่าถาม)

🔤 Tell, Don't Ask (เทล โดนท์ อาสค์ = "สั่ง อย่าถาม") — สั่งให้ object ทำงานเอง อย่าไปดึงสถานะภายในออกมาแล้วตัดสินใจแทนข้างนอก — สำนวนนี้นิยมโดย Andy Hunt + Dave Thomas (The Pragmatic Programmer)

java
// ❌ Ask
if (order.getStatus() == Status.PENDING && order.getAge() > 30) {
    order.setStatus(Status.EXPIRED);
}

// ✅ Tell
order.expireIfStale();   // ภายในจัดการเอง

11. "เห็นโค้ดเร็วขึ้น" — Skill ที่ฝึก

อ่าน code คือทักษะที่ฝึกได้:

  1. อ่านโครงสร้าง — class, package, module structure ก่อน
  2. Trace flow — entry point → flow ของ request
  3. Test = doc — อ่าน test เพื่อเข้าใจ usage
  4. Type signature ก่อน body — รู้ว่าทำอะไรจาก signature
  5. Naming — ถ้า name ดี ไม่ต้องอ่าน body มาก

ฝึก

  • Clone open source project → อ่าน 1 feature
  • Code review เพื่อน → อธิบาย "why"
  • ดู PR ใน GitHub repo ที่ active

12. กฎสุดท้าย — Pragmatism > Purity

🔤 Pragmatism (แพร็ก-มา-ติ-ซึม = ความเป็นนักปฏิบัติ — เน้นว่าได้ผลจริง) > Purity (เพียว-ริ-ตี้ = ความบริสุทธิ์ — เน้นทฤษฎีตรงเป๊ะ)

กฎทุกข้อในเล่มนี้เป็น "แนวทาง" ไม่ใช่กฎตายตัว — เป้าหมายจริงคือระบบที่ทำงานได้ ทีมแฮปปี้ และดูแลได้ระยะยาว ไม่ใช่ 100% SOLID หรือ test coverage เต็ม บางครั้งการ break rule คือทางที่ถูก ใช้วิจารณญาณตามสถานการณ์เสมอ:

- หลักที่ดีในเล่มนี้ทุกอัน → ใช้ "ตามสถานการณ์"
- บางที่ break rule = ถูก
- เป้าหมาย: ระบบทำงาน + ทีมแฮปปี้ + ดูแลได้ระยะยาว
- ไม่ใช่: 100% SOLID, 100% test coverage, 100% functional

"Make it work, make it right, make it fast" — แนวคิดจาก Kent Beck (เคนต์ เบ็ค — ผู้คิดค้น TDD/XP, นิยมอ้างใน Test-Driven Development: By Example, 2002) (ทำตามลำดับนี้) (ทำให้มันทำงานได้ก่อน → แล้วทำให้ถูกต้อง → แล้วค่อยทำให้เร็ว)


13. คำศัพท์พื้นฐาน

คำคำอ่านความหมาย
Abstractionแอบ-สแตร็ก-ชั่นซ่อนรายละเอียด → expose interface เท่านั้น
Encapsulationเอน-แค็พ-ซู-เล-ชั่นรวม data + behavior ที่เกี่ยวกัน + ซ่อน internal
Inheritanceอิน-เฮอ-ริ-แทนซ์class ลูกสืบทอดจาก class แม่ (is-a relationship)
Polymorphismพอ-ลี-มอร์-ฟิ-ซึมinterface เดียวกัน แต่ behavior หลายแบบ
Couplingคับ-พลิ่งระดับที่ module ผูกกัน — ต้องการ low
Cohesionโค-ฮี-ชั่นระดับที่ method ใน module เกี่ยวข้องกัน — ต้องการ high
Dependencyดี-เพ็น-เด็น-ซีสิ่งที่ module ของเราต้องใช้
Inversion of Controlอิน-เวอร์-ชั่น ออฟ คอน-โทรลการพลิกบทบาทว่าใครคุมการเรียกใคร (framework เรียก code เรา ไม่ใช่เราเรียก framework)
DIดี-ไอDependency Injection — pass dependency เข้ามาผ่าน constructor/parameter
Refactorรี-แฟ็ก-เตอร์เปลี่ยน structure โดยไม่เปลี่ยนพฤติกรรม
Boilerplateบอย-เลอร์-เพลทcode ซ้ำที่ต้องเขียนเพื่อ setup (เปรียบเหมือนแบบหล่อหม้อต้ม)
SOLIDโซ-ลิด5 หลัก OOP design (SRP/OCP/LSP/ISP/DIP) — โดย Robert C. Martin
DDDดี-ดี-ดีDomain-Driven Design — เน้นโมเดลตาม business domain (Eric Evans, 2003)
TDDที-ดี-ดีTest-Driven Development — เขียน test ก่อน code (Kent Beck)
Design Patternดี-ไซน์ แพ็ท-เทิร์นsolution ที่ใช้ซ้ำสำหรับ problem ที่เจอบ่อย

📚 อ่านต่อ (modern references)

  • John Ousterhout (จอห์น เอาส์-เตอร์-เฮาท์) — A Philosophy of Software Design (2018, ฉบับที่ 2: 2021) — เสนอแนวคิด "deep modules" และวิจารณ์ Clean Code บางจุด ควรอ่านคู่กับ Uncle Bob เพื่อเห็นมุมมองที่ต่าง
  • Kent BeckTidy First? (2023) — refactor เป็นชุดเล็ก ๆ
  • Gary Bernhardt (แกรี่ เบิร์น-ฮาร์ด) — แนวคิด Functional Core, Imperative Shell (2014) — แยก logic บริสุทธิ์ออกจาก side effect
  • Bertrand Meyer (เบอร์-ทร็อง ไม-เยอร์) — Object-Oriented Software Construction (1988, 1997) — ผู้บัญญัติ Design by Contract และนิยาม Open/Closed Principle เดิม
  • Alan Kay (อลัน เคย์) — ผู้บัญญัติคำว่า "Object-Oriented Programming" และผู้สร้าง Smalltalk

14. Checkpoint

🛠️ Checkpoint 0.1 — Code Smell Hunt
เปิด code project ของคุณ — หา code smell:

  • Long method (> 50 บรรทัด)
  • Magic number
  • God class
  • Comment ที่ outdated รายงานเป็น list

🛠️ Checkpoint 0.2 — Refactor Practice
จาก method ใน 0.1 — refactor 1 ตัว

  • Extract method
  • Rename variable
  • Replace magic with constant/enum

🛠️ Checkpoint 0.3 — Trade-off Analysis
List 5 decision ใน project ของคุณ + ระบุ trade-off:

  • "ทำไมเราใช้ X แทน Y"
  • "What's the cost?"

15. สรุปบท

✅ Code ทำงานได้ ≠ Code ที่ดี — readability, maintainability, testability
✅ KISS, DRY (ใช้ระวัง), YAGNI
✅ Code smell: long method, god class, magic number, inappropriate comment
✅ Boy Scout rule: leave code better than you found it
✅ Two Hats: refactor mode vs feature mode — แยก
✅ Don't premature optimize — measure ก่อน
✅ Coupling ↓ + Cohesion ↑
✅ Composition over Inheritance
✅ ทุก decision = trade-off — context สำคัญ
✅ Pragmatism > Purity — make it work first


บทถัดไป → OOP ลึก


Glossary: ../glossary.md · Style guide: ../CONTRIBUTING.md last_verified: 2026-06-03 · review report: ../REVIEW-2026-06-03.md