ศูนย์รวมความรู้วิศวกรรมซอฟต์แวร์

แบ่งปันประสบการณ์การออกแบบสถาปัตยกรรมระบบ, การเขียนโค้ดด้วย Laravel และการจัดการ Server ระดับ Production เพื่อยกระดับทักษะของนักพัฒนาทุกคน

การใช้ dto แทนการใ้ช้ array

การใช้ dto แทนการใ้ช้ array


การเปลี่ยนจากการใช้ Associative Array มาเป็น DTO (Data Transfer Object) คือก้าวสำคัญของการเขียนโค้ดจากระดับ "แค่ทำงานได้" ไปสู่ระดับ "ระบบที่มีโครงสร้างดี (Maintainable Architecture)"

เนื้อหาต่อไปนี้สรุปมาเพื่อใช้เขียนบทความลง Knowledge Management (KM) และใช้ทบทวนความเข้าใจครับ

1. ทำไมเราถึงควรเลิกใช้ Array ส่งข้อมูล (The "Array Hell")

ในการพัฒนา Web Application ขนาดใหญ่ เรามักส่งข้อมูลข้าม Layer (เช่นจาก Controller ไปยัง Service หรือ Action) ซึ่งการใช้ Array มีข้อเสียที่น่าปวดหัวดังนี้:

  • ความไม่แน่นอน (Lack of Structure): เราไม่รู้เลยว่าใน Array นั้นมี Key อะไรบ้าง ถ้าไม่ไปไล่ดู Code ต้นทาง

  • ไม่มี Type Safety: ข้อมูลใน Array เป็นอะไรก็ได้ (String, Int, หรือ Null) ทำให้เสี่ยงต่อการเกิด Error ใน Runtime

  • IDE เดาทางไม่ถูก: เมื่อส่ง Array เข้าไปใน Method ตัว IDE (อย่าง VS Code หรือ Cursor) จะไม่ช่วยทำ Autocomplete ให้

  • ยากต่อการ Refactor: หากต้องการเปลี่ยนชื่อ Key หนึ่งที่ ต้องตามแก้กันทั้งโปรเจกต์เพราะค้นหา Reference ได้ยาก

2. DTO คืออะไร?

DTO (Data Transfer Object) คือ Object เรียบง่ายที่ถูกสร้างขึ้นเพื่อ "ขนส่งข้อมูล" ระหว่างกระบวนการ โดยหน้าที่เดียวของมันคือการรวมกลุ่มข้อมูลและกำหนดโครงสร้างที่ชัดเจน (Strict Contract)

ตารางเปรียบเทียบ: Array vs DTO

คุณสมบัติ | Associative Array | Data Transfer Object (DTO)โครงสร้าง | ยืดหยุ่นเกินไป (Schema-less) | ชัดเจน (Strict Schema)
การตรวจสอบ (Type) | ทำไม่ได้ทันที | มี Type Hinting ชัดเจน
IDE Support | ไม่มี (ต้องจำ Key เอง) | มี Autocomplete เต็มรูปแบบ
ความผิดพลาด | พิมพ์ Key ผิดได้ง่าย (Typo) | ตรวจสอบพบตั้งแต่ตอนเขียน (Static Analysis)
3. เปรียบเทียบด้วย Code (PHP 8+)

ลองดูความแตกต่างเมื่อเราต้องการจัดการข้อมูลการสมัครสมาชิก:

แบบเดิม: การใช้ Array (เสี่ยงและสับสน)


PHP

public function store(array $data) {
    // เราไม่รู้เลยว่า $data['user_name'] หรือ $data['username'] กันแน่?
    // และมันอาจจะเป็น null จนทำให้ระบบพังได้
    return User::create([
        'name' => $data['name'],
        'email' => $data['email'],
    ]);
}

แบบใหม่: การใช้ DTO (ปลอดภัยและเป็นมืออาชีพ)


PHP

readonly class UserRegistrationDTO {
    public function __construct(
        public string $name,
        public string $email,
        public ?string $phoneNumber = null, // บอกชัดเจนว่าเป็น Optional
    ) {}

    public static function fromRequest(Request $request): self {
        return new self(
            name: $request->validated('name'),
            email: $request->validated('email'),
            phoneNumber: $request->validated('phone'),
        );
    }
}

// การใช้งานใน Service/Action
public function execute(UserRegistrationDTO $data) {
    // IDE จะรู้ทันทีว่า $data มี property อะไรบ้าง
    return User::create([
        'name' => $data->name,
        'email' => $data->email,
    ]);
}

4. ข้อดีของการใช้ DTO ในโปรเจกต์จริง

1. Self-Documenting Code

DTO ทำหน้าที่เป็นเอกสารในตัวเอง (In-code Documentation) เมื่อ Developer คนอื่นมาอ่าน Code เขาจะรู้ทันทีว่าข้อมูลที่ไหลอยู่ในระบบมีหน้าตาเป็นอย่างไร

2. มั่นใจด้วย Type Safety

การใช้ DTO ร่วมกับฟีเจอร์ Readonly Property ใน PHP 8 ช่วยให้มั่นใจว่าข้อมูลจะไม่ถูกแก้ไขระหว่างทาง (Immutability) และมีชนิดข้อมูลที่ถูกต้องเสมอ

3. เชื่อมต่อกับ Action-DTO-Query Pattern

สำหรับใครที่ทำ Architecture แนวนี้ DTO คือสะพานเชื่อมที่สำคัญ:

  • Controller: รับ Request -> แปลงเป็น DTO

  • Action/Service: รับ DTO -> ประมวลผล Business Logic

  • Query: รับ DTO -> คัดกรองข้อมูลจาก Database

5. สรุปเพื่อการทบทวน (Key Takeaways)

  • Array เหมาะกับข้อมูลชั่วคราวภายใน Function สั้นๆ

  • DTO เหมาะกับการส่งข้อมูลข้าม Class หรือข้าม Layer

  • การใช้ DTO ช่วยลดเวลาการ Debug เพราะ Error จะฟ้องตั้งแต่ขั้นตอนการเขียน (ถ้าใช้ Static Analysis เช่น PHPStan)

  • แม้จะดูเหมือนต้องเขียน Code เพิ่มขึ้น (Boilerplate) แต่ในระยะยาว DTO ช่วยลด Technical Debt ได้มหาศาล

Tip สำหรับการเขียนบทความ: คุณอาจจะตั้งชื่อตอนว่า "บอกลา Array Hell สู่โลกที่ปลอดภัยด้วย DTO" เพื่อดึงดูดกลุ่ม Developer ที่กำลังเจอปัญหาเรื่องการ Maintain Code ครับ!


laravel