Learning Domain Driven Design

สวีดัด สวัสดี ทุกๆท่านครับ เนื่องจากผมมีโอกาสได้ไปเรียน Domain Driven Design (DDD) กับ Roofimon (พี่รูฟ) เป็นเวลา 2 วัน ก็เลยอยากจะบันทึกไว้เพื่อแชร์มุมมองจาก Developer (ผมเอง) ให้คนอื่นๆที่สนใจครับ โดยเนื้อหาทั้งหมดนี้ ล้วนมาจากการเรียนและตกผลึกจากคอร์สพี่รูฟและประสบการ์ณอันน้อยนิดของผม ซึ่งไม่การันตีว่าสิ่งที่อยู่ในบทความนี้จะถูกต้อง ดังนั้นถ้าผิดพลาดประการใดรบกวนชี้แนะผมด้วยนะครับ

ทำไมเราควรรู้จัก DDD

ก่อนอื่นเลย ผมเชื่อว่า Developer หลายๆคน น่าจะเคยเจอสถานการ์ณแบบนี้

tree

เห็นไหมครับว่า ผลลัพธ์ไม่เหมือนกันสักรูป! แต่ละส่วนล้วนแตกต่างกันโดยสิ้นเชิง คำถาม คือ ทำไม เพราะอะไร ?

บ่อยครั้งที่การสื่อสารในการทำ Software Development มักมีลักษณะแบบนี้

Customer -> X (BA, SA or ...) -> Requirements -> Developer -> Code

เรามักจะเรียกสิ่งนี้ว่า Knowledge Sharing Flow แต่สังเกตไหมครับว่า Knowledge ถูกส่งต่อหลายสเต็ปมาก กว่าจะไปถึง Developer ซึ่งจริงๆมันก็ดีนะที่ BA, SA คอยแปลความต้องการต่างๆออกมาเป็นรูปแบบ Requirement Document แบบต่างๆ แต่ แต่ แต่ เราจะรู้ได้ยังไงล่ะว่า Knowledge ในแต่ละสเต็ป มันคือ สิ่งเดียวกันกับที่ต้นทางพยายามส่งมา, ไม่ถูกบิดเบือน หรือ Misunderstanding จากใครคนใดคนหนึ่ง

knowledge-sharing-flow

มาถึงจุดนี้แล้วทุกท่านคงพอจะเห็นภาพแล้วใช่ไหมครับว่า มันมีช่องว่างในการสื่อสารในแต่ละสเต็ป ดังนั้น ถ้าท่านเคยเจอสถานการ์ณแบบนี้ ผมคิดว่ามันถึงเวลาแล้วล่ะ ที่ท่านต้องฝึกปรือ DDD เพราะ DDD กล่าวว่า จะดีกว่าไหมถ้าเราสามารถสื่อสารกับทุกๆคนที่เกี่ยวข้องในโปรเจคเพื่อทำให้เข้าใจตรงกันได้

เรียนอะไรบ้างในคอร์ส DDD แบบ รูฟ รูฟ

ในคอร์สนี้ใช้หนังสือเล่มนี้เป็นหลัก(พี่รูฟแจก)ซึ่งเราสามารถแบ่งเนื้อหาได้ดังนี้

  • DDD Concepts
  • DDD Strategic Design + Workshop
  • DDD Tactical Design + Architecture Patterns + Workshop

DDD Concepts

อับดับแรกเลย Concepts สำคัญมาก เพราะ ถ้าเราไม่เข้าใจมัน เราจะจับต้นชนปลายไม่ถูกใน Stage ถัดๆไป ดังนั้นต้นชั่วโมงแรกของวันแรก พี่รูฟจะให้ทุกๆคนลืมสิ่งที่รู้หรือเคยทำมาก่อน ลดการเปรียบเทียบ เพื่อให้เราสามารถเปิดใจและรับรู้สิ่งต่างๆได้ง่ายขึ้น

เข้าเรื่องกันเลย ปกติแล้วเวลาเราคุยเรื่อง Requirement ตอนประชุม มันมักจะเป็นการสนทนากันระหว่าง ทีม Business กับ ทีม Technical ซึ่งแต่ละทีมมองกันคนละแบบ โดยทีม Business จะหยิบเรื่องปัญหาทางธุรกิจ (Problem Space) เข้ามาคุย ทีม Technical ก็คิดหาโซลูชั่นตาม (Solution Space) + Design ER-Diagram ไปในหัว ซึ่งเวลาทีม Technical คิดตามนี่แหละมันมักจะเกิดการ Design Database โดยอัตโนมัติ

สมมุติว่า ณ วันแรกที่เราคุยเรื่อง Requirement มันเป็นเพียงแค่ 10% ของทั้งหมด นั้นก็หมายความว่าใน Database เราจะได้ Schema ออกมาแค่ 10% และเมื่อเรารู้ Requirement เพิ่มขึ้นเรื่อยๆ เราจะเห็น Schema มันบวมตาม จาก 10 Tables อาจจะกลายเป็น 1000 Tables จน ณ จุดๆหนึ่งเราอาจจะอุทานออกมาว่า อุ้ย … เพราะ เมื่อเรามองย้อนกลับมาเราจะพบว่าทุกๆอย่างมันพันกันไปหมด เราเรียกสิ่งนี้ว่า Big Ball Of Mud สเกลก็ยาก, ระบบก็ช้าลงเรื่อยๆ สุดท้ายเราอาจจะต้องตัดสินใจรื้อแล้วทำใหม่! ถึงแม้ว่าเราจะเปลี่ยน Tech Stack แต่ถ้าวิธีคิดยังคิดแบบเดิม สุดท้ายก็คงจะต้องวนกลับมาอุทานว่า อุ้ย … เหมือนเดิม

ดังนั้น DDD จึงบอกว่า Key Concept ที่สำคัญ คือ เราต้องเปลี่ยน Mindset มาเป็น Software Design ไม่ใช่เรื่องของ ทีม Technical เพียงฝ่ายเดียว แต่เป็นเรื่องที่ทุกฝ่ายต้องทำร่วมกัน ระหว่างคนที่เข้าใจ Business หรือใน DDD เรียกว่า Domain Expert กับ Technical Expert โดยแบ่งเป็น 2 Stages ใหญ่ๆ คือ Strategic Design และ Tactical Design

DDD Strategic Design + Workshop

ใน Stage นี้ คือ การที่ Domain Expert และ Technical Expert ทำงานร่วมกัน โดยมี Step ดังนี้

หมายเหตุ : ใน Strategic Design เราจะไม่พูดถึง Technical! Kafka, gRPC, NoSQL ~ อะไรก็ตาม ลืมๆมันไปก่อนนะ 555

1. Domain Expert เล่า Requirement และเราต้องช่วยกัน Capture สิ่งต่างๆร่วมกัน ด้วยการทำ Model Driven Design (MDD) ซึ่งในคอร์สนี้เราใช้ Journey Flow ในการอธิบาย Scenario ต่างๆ แต่จริงๆแล้ว MDD สามารถเป็นอะไรก็ได้นะครับ เช่น UML, Flow Chart, การจดบันทึก เป็นต้น

Key word สำคัญใน Step นี้คือ Bounded Context และ Ubiquitous (ยู-บิ-คิว-ตัส) Language สองอย่างนี้มาพร้อมกันเสมอ มาดูกันครับว่ามันคืออะไร

ใน Workshop พี่รูฟเป็น Domain Expert และ ยก Scenario ของโรงพยาบาลมา ประมาณว่า

Context-1.1 มีคนเดินทางมา โรงพยาบาลพร้อมกับอาการปวดท้องเพื่อให้หมอตรวจ

Context-1.2 พนักงานต้อนรับ ถามผู้มารับบริการว่า เคยมาตรวจที่โรงพยาบาลนี้แล้วใช่ไหม

Context-1.3 คนที่เดินทางมา ตอบว่า ใช่ พนักงานต้อนรับจึงส่งคนไข้ไปหาพยาบาลเพื่อประเมินอาการเบื้องต้น และส่งไปรอที่หน้าห้องตรวจเพื่อรอพบหมอ

Context-1.4 คนไข้เข้าไปตรวจ และคุณหมอบอกว่าให้ไปตรวจเลือดที่ห้องแล็บเพื่อวินิฉัยเพิ่มเติม

Context-1.5 คนไข้เดินทางไปตรวจเลือดและกลับมาที่ห้องตรวจ และคุณหมออ่านผลแล็บและบอกว่าทุกอย่างปกติดี จึงสั่งยาและให้คนไข้กลับไปพักที่บ้าน

Context-1.6 คนไข้เดินไปที่ห้องการเงินเพื่อจ่ายเงิน พนักงานห้องการเงินออกใบแจ้งหนี้ เพื่อให้ลูกหนี้ชำระเงิน เมื่อชำระเงินเสร็จแล้วให้ไปรอรับยาที่หน้าห้องจ่ายยา

Context-1.7 สุดท้ายคนไข้รับยาจากเภสัชและกลับบ้าน

พอทำออกมาเป็น Journey Flow หน้าตาของมันจะได้ออกมาประมาณนิ

journey

สังเกตเห็นอะไรไหมครับ ติ๊กต๊อก ติ๊กต๊อก Naming ของคนที่เดินทางมาโรงพยาบาล ในแต่ละ Context ไม่เหมือนกัน!

เมื่อมาถึงแผนกต้อนรับ เราเรียกเขาว่า ผู้มาใช้บริการ หลังจากรู้ว่าเขาเคยมาใช้บริการแล้ว เราเรียกเขาว่า คนไข้ ไปจนจบกระบวนการตรวจ เมื่อไปจ่ายเงิน เราเรียกเขาว่า ลูกหนี้ และตอนไปรับยา เรากลับมาเรียกเขาว่า คนไข้ จนเขาเดินออกจากโรงพยาบาลกลับบ้าน

สิ่งเหล่านี้แหละเราเรียกมันว่า Bounded Context และ Ubiquitous Language หรือจะเรียกมันว่า ภาษาถิ่น ของแต่ละ บริบท ขยายความ Ubiquitous Language ก็คือ ภาษาถิ่น หรือ ภาษากลาง ที่เมื่อเราใช้ ทุกๆฝ่ายจะเข้าใจตรงกันว่า อ๋อ เมื่อเราพูดถึง สิ่งนี้ เราควรไปดูมันที่ จุดนี้ นะ

เอาล่ะๆ ลองมาทายเล่นๆกันครับว่าถ้าให้ Technical Team เป็นคนกำหนด มันจะถูกเรียกว่าอะไร ทา ดา ~ แน่นอนครับ ถ้าไม่เรียกว่า ผู้ป่วย ก็คงเรียก ผู้ใช้บริการ ตั้งแต่ต้นจนจบ เมื่อ Technical Team มองแบบนั้น สุดท้าย เขาจะ Design Model เก็บลงใน Database Table ที่เดียว ว่า ผู้ป่วย ปัญหาที่ตามมาคือเมื่อเราต้องการ Decompose อะไรสักอย่างออกมา เราจะพบว่ามันยากมาก เพราะ Technical Team มองว่าทุกๆอย่างคือ ผู้ป่วย และมันกำลังพันกันแน่นมากขึ้นเรื่อยๆ

ดังนั้นนี่เป็นเหตุผลว่าทำไม DDD จึงบอกว่า Software Design ไม่ใช่เรื่องของ ทีม Technical เพียงฝ่ายเดียว แต่เป็นเรื่องที่ทุกฝ่ายต้องทำร่วมกัน เพราะ DDD ต้องการให้ทุกฝ่ายที่เกี่ยวข้องมองทุกอย่างในแบบเดียวกัน

2. หลังจากที่เรามองเห็นภาพรวมผ่าน Journey Flow แล้ว ขั้นตอนต่อมา คือ การ กำหนด / หั่น / แบ่ง Subdomains ออกจาก Business Domain เพื่อให้เรารู้ว่าอะไรคือสิ่งที่สำคัญและเราควรจะลงทุนกับมันมากที่สุด ซึ่งแบ่งได้ 3 ประเภทดังนี้

2.1 Core Subdomain คือ สิ่งที่เราควรลงทุนมากที่สุด เช่น ใส่ใจรายละเอียดมันมากที่สุด, ใช้ทีมที่ดีที่สุด, Budget เยอะที่สุด เพราะ มันคือ หัวใจ ของธุรกิจ

2.2 Generic Subdomain คือ สิ่งที่เราสามารถซื้อมาใช้งานได้หรือจะเรียกว่าใครๆก็มี และไม่ควรลงแรงกับมันมาก เช่น ระบบ CRM, ระบบ Finance

2.3 Supporting Subdomain คือ สิ่งที่เราสามารถ Implement เองได้ แต่ไม่ค่อยมีน้ำหนักความสำคัญเท่า Core Subdomain เพราะหน้าที่หลักของมันคือการสนับสนุนการทำงานของ System

หมายเหตุ : แต่ละ Subdomain สามารถเปลี่ยนแปลงได้ตลอดเวลา ตามการแข่งขันทางธุรกิจ

Key word สำคัญใน Step นี้คือ Subdomain อย่างที่ได้บอกไป ถ้าเราสามารถ Divide And Conquer Business Domain จากภาพใหญ่ ออกมาเป็น Subdomain แบบต่างๆได้ เราจะรู้ว่าสิ่งไหนที่เราควรโฟกัสมากที่สุด

ใน Workshop พี่รูฟให้เราทำ Hospital Information System (HIS) โดย Step นี้ ผมเข้าใจว่าเรากำลังทำ Event Storming With Modeling Board (มั้ง) ซึ่งในคอร์สนี้ใช้หน้าตาบอร์ดแบบเดียวกับในหนังสือเลย ซึ่งผมเรียกมันว่า คูเมืองบอร์ด เพราะพี่รูฟบอกว่าหน้าตามันคล้ายๆกับ คูเมือง ที่เชียงใหม่ ฮ่า ~ สุดท้ายเราจะได้บอร์ดหน้าตาประมาณนิ

คูเมืองบอร์ด

3. เมื่อเราแบ่ง Subdomain แล้ว ต่อไปที่ต้องทำคือ การวางแผนความสัมพันธ์เพื่อ รับ (Downstrem) - ส่ง (Upstream) ข้อมูลระหว่าง Bounded Context เราเรียกกระบวนการนี้ว่า Context Map

ถ้าอ้างอิงจากหนังสือจะพบว่ามีการแยกเป็นความสัมพันธ์อยู่ 3 ประเภท 5 แบบ ดังนี้

3.1 Cooperation

- Partnership คือ ความสัมพันธ์แบบ 1 : 1 ที่ทั้งคู่สามารถตกลงกันได้ว่าจะ รับ - ส่ง ยังไง

- Shared Kernel คือ ความสัมพันธ์แบบ ใช้อะไรสักอย่างร่วมกัน ซึ่งถ้ามีการเปลี่ยนแปลงจะส่งผลต่อทั้งสองฝั่งทันที

3.2 Customer-Supplier

- Conformist คือ ความสัมพันธ์ที่ ฝ่ายรับ ไม่มีอำนาจต่อรองและต้องใช้แค่สเปคที่ ฝ่ายส่ง ส่งมาเท่านั้น

- Anti Corruption Layer (ACL) คือ ความสัมพันธ์แบบเดียวกับ Conformist แต่ต่างกันตรงที่ ฝ่ายรับ จะมี Intermediate Layer หรือ Middleware เพื่อใช้ติดต่อกับ ฝ่ายส่ง

- Open-Host Service คือ ความสัมพันธ์ตรงข้ามกับ ACL ซึ่ง ฝ่ายส่ง จะสร้าง Standard บางอย่าง เพื่อใช้ติดต่อกับ ฝ่ายรับ

3.3 Separate Ways คือ ความสัมพันธ์ที่แต่ละ Bounded Context แยกขาดกัน ถ้าการ รับ - ส่ง ข้อมูลมันมีปัญหานักก็แยกกันทำซะเลย 555

Key word สำคัญใน Step นี้คือ Context Map การทำ Context Map จะทำให้เรามองเห็นภาพการไหลของข้อมูลไปยังส่วนต่างๆของ System อีกทั้งยังช่วยในการตัดสินใจเวลา Implement ใน Tactical Design

ใน Workshop หลังจากที่เราแบ่ง Subdomain ต่างๆลงใน คูเมืองบอร์ด แล้ว เราจะเริ่มนำ Journey Flow มาวางไล่ เพื่อดูว่า Journey นั้นอยู่ใน Subdomain ไหน และมีการไหลของข้อมูลยังไง และแล้วเราจะได้ คูเมืองบอร์ดเวอร์ชั่นอัพเกรดแบบนี้

คูเมืองบอร์ด

ผมไม่ได้ถ่ายเก็บไว้เลยเอาไปทำใหม่คร่าวๆนะครับ แหะๆ

4. เอาล่ะ 3 Step ที่ผ่าน เท่าที่ผมเข้าใจคืออ้างอิงมาจาก DDD ทีนี้ Step ถัดๆไปจะเป็นฉบับ DDD แบบรูฟรูฟ แล้วนะครับ

พี่รูฟยก Scenario มาให้ใหม่เพื่อทำ Mobile Application แต่รอบนี้เราจะทำ Journey Flow + Wireframe (UI Screen) โดยพี่รูฟให้เหตุผลว่าการนำ Wireframe เข้ามาช่วย จะทำให้เราเห็นภาพสิ่งต่างๆได้ละเอียดขึ้น สิ่งสำคัญอีกอย่างหนึ่งคือ Naming ทุกส่วนให้ดีๆนะครับ เพราะมันสามารถ Refer ไปถึง Codebase ได้เลยนะ ย้ำ Naming ให้ดีๆ!

journey

4.1 เมื่อเราได้ Journey Flow + Simple Wireframe แล้ว ต่อไปที่เราต้องทำก็คือการเขียน Command และ Event ให้กับแต่ละ Journey ซึ่งเราอาจจะมองว่า Command คือ Action และ Event คือ เหตุการ์ณที่เกิดขึ้นและต้องการบอกให้คนอื่นรู้

ถ้าอ้างอิงจากหนังสือ การเขียน Command และ Event จะมีหลักการ ดังนี้

Command ควรจะขึ้นต้นด้วย Verb + Something เช่น Scan QR

Event ควรจะขึ้นต้นด้วย Someting + Verb (Past tense) เช่น QR scanned

4.2 ยังไม่หมดแค่นี้! เมื่อเราได้ Command และ Event แล้ว เราต้องทำการกำหนด Domain Model (ผมเข้าใจว่ามันคือ Domain Model นะ ถ้าเข้าใจผิดขออภัยเด้อ)

ถ้าอ้างอิงจากหนังสือ Domain Model (ในคอร์สเหมือนได้ยินแว่วๆว่า มันคือ Conceptual Model) หมายถึง โมเดลที่รวม พฤติกรรม และ ข้อมูล เพื่ออ้างถึง Subdomain ต่างๆ ใน System ของเรา อ่านแล้วอาจจะ เอ๊ะ อีหยังวะ เดี๋ยวลองไปดูตัวอย่างกันครับ เผื่อจะเข้าใจ (มั้ง 55)

journey

จากรูป เราทำทุกอย่างเสร็จเรียบร้อยแล้ว ทีนี้ลองดูในกรอบสีแดงครับ เราจะเห็นว่า Journey Lab staff do lab examination มี Domain Model คือ Medical record และ Lab result ดังนั้นเราสามารถอธิบายได้ว่า Journey นี้ มีการแตะไปที่ Medical record subdomain และ Lab subdomain ใน คูเมืองบอร์ด เห็นภาพมากขึ้นบ่ครับ 555 ส่วนอีกกรอบสีแดงผมให้ลองเดาๆดูละกันครับว่ามันจะไปแตะที่ Subdomain ไหนบ้าง

เอาล่ะ เมื่อมาถึงจุดนี้แล้ว สังเกตุเห็นไหมครับ ว่า Strategic Design พยายามสอน การ Modeling สิ่งต่างๆให้ออกมาชัดเจนและละเอียดที่สุด ผ่าน Ubiquitous Language ที่ทุกฝ่ายเข้าใจ เพื่อตอบคำถาม เรากำลัง ทำอะไร และ ทำทำไม ในเชิงธุรกิจ (What and Why) เพื่อนำไปใช้ใน Tactical Design เพื่อหา Solution (How) ในการ Implement นั้นเอง ~

DDD Tactical Design + Workshop

ใน Stage นี้ คือ Stage ของ Technical Expert ล้วนๆ ซึ่งเราจะเริ่มลงรายละเอียดในเรื่องของ Technical มากขึ้นเรื่อยๆ โดยมี Step ดังนี้

1. หลังจากที่เราได้ Journey Flow + Wireframe ทั้งหมดแล้ว ต่อไปที่เราจะทำคือ การกำหนด Aggregate Root

Aggregate Root คือ ชุดข้อมูลที่เกี่ยวข้องกับ Journey / Command นั้นๆ โดยมีหน้าที่ ห่อหุ้ม ชุดข้อมูลเพื่อนำไป Do something…

วิธีการกำหนด Aggregate Root ก็คือ เราจะพิจราณาจาก Domain Model และ UI Screen ว่ามันกำลังยุ่งอยู่กับอะไร

โดยพี่รูฟให้เทคนิคว่า ถ้าอยากรู้ว่ามันกำลังยุ่งอยู่กับอะไรให้ดูใน UI Screen

ทา ดา ~ ตอนนี้เราจะได้ ตารางแบบนี้ออกมา

aggregateRoot

ตอนนี้สิ่งที่เพิ่มเข้ามาคือ Entities และ Value Objects แต่ เอ๊ะ มันคืออะไรนะ

1.1 Entities : ขอเรียกมันว่า Changeable Object ละกัน หน้าที่ของมันคือเป็นส่วนประกอบภายใน Aggregate Root ที่สามารถเปลี่ยนแปลงค่าได้

1.2 Value Objects : ในหนังสือเรียกมันว่า Immutable Object หน้าที่ของมันคือเป็นส่วนประกอบที่คอยเติมเต็มใน Entities หรือจะบอกว่ามันคือ Properties ของ Entities ก็ได้

ตัวอย่างจากในรูป เช่น

class MedicalRecord : AggregateRoot
{
    private PatientProfile _patientProfile;

    public void doSomething() {...}
}
...
class PatientProfile : Entity
{
    private string _HN;
    private string _name';
    private string _surname';
    private string _gender';
    private int _age';
    private int _weight';
    private int _height';
    private string _bp';
    private string _primaryDiagnosis';

    public void doSomething(){...}
}

จะสังเกตุเห็นว่า Type ของแต่ละ Property ล้วนแต่เป็น Primitive Type ทั้งสิ้น ถ้าเราเอา Value Objects มาปรับใช้ หน้าตามันจะกลายเป็นแบบนิ

class PatientProfile : Entity
{
    private HN _HN;
    private Name _name';
    private Surname _surname';
    private Gender _gender';
    private Age _age';
    private Weight _weight';
    private Height _height';
    private BP _bp';
    private PrimaryDiagnosis _primaryDiagnosis';

    public void doSomething(){...}
}
...
class Age : ValueObject
{
    ...
    public Age(int a)
    {
        Validation logic (Optional)
        ...
        this.age = a;
    }
}

เห็นไหมครับว่า Value Objects กำลังทำอะไร มันกำลัง Encapsulate Data ให้เรานั้นเอง ถ้าเราต้องการ Validation เราก็แค่ไปทำใน Value Objects นั้นๆ (เหมือนเห็นภาพ Principle อะไรสักอย่างแบบลางๆมั้ง…) มาถึงตรงนี้แล้ว ก็หวังว่าจะเข้าใจสิ่งที่ผมจะสื่อนะครับ… ฮ่า

2. Step ต่อมาเป็น Step สุดท้ายใน Workshop ของคอร์สนี้แล้วครับ เราจะเอาทุกอย่างมาวางแบบนี้

architecture-pattern

มองแล้วรู้สึกเหมือน Architecture อะไรไหมครับ ผมขอไม่พูดถึงมันละกัน เพราะ จุดนี้ผมคิดว่า มันขึ้นอยู่กับประสบการ์ณของแต่ละทีม ว่าจะ Design หรือ มอง มันออกมายังไง มันอาจจะเป็น Clean Architecture, Hexagonal Architecture, Event Based Architecture, Modular หรือ MVC ก็ได้ มันอาจจะมี Port & Adapter (ในหนังสือแอบเชียร์ตัวนี้), CQRS บลาๆ แต่ แต่ แต่ อย่าลืมนะครับว่า สิ่งที่เรากำลังจะทำ มันต้องเหมาะสม, ไม่ Overengineer, สามารถตอบโจทย์ Business และทีมต้องสามารถดูแลได้ในระยะยาว ดังนั้น คิดและทบทวนให้ดี ว่าเรากำลังแก้ปัญหาตรงจุดไหม…

สุดท้ายๆ ถ้าเราไล่จาก ล่างขึ้นบน หรือ บนลงล่าง เราจะพบความมหัศจรรย์อย่างหนึ่ง คือ ทุกๆอย่างสามารถ เชื่อมถึง หรือ อ้างถึง กันได้หมด ผ่าน Ubiquitous Language ที่พี่รูฟย้ำอยู่บ่อยๆ อีกทั้งทุกๆอย่างที่ทำมาสามารถทำเป็น Document ที่เราสามารถนำมันมาปรับใช้เพื่อ Onboard, Debug, Change Request ได้

สรุป

จากมุมมอง Developer อย่างผม การนำ DDD มาปรับใช้ ช่วยให้เรา (ทีม) มองเห็นปัญหาได้ละเอียดและชัดเจนมากขึ้น อีกทั้งมันเหมือนเป็นการสร้าง Standard ไปในตัว ผ่านเจ้า Ubiquitous Language ที่เราพยายาม Naming ทุกๆอย่างให้ทุกฝ่ายเข้าใจตรงกันและสามารถอ้างถึงกันได้เสมอ จากที่เรียนมากับพี่รูฟ 2 วัน แน่นอนว่าผมได้อะไรมาคิดต่อยอดเยอะแยะ (จริงๆรายละเอียดเยอะกว่านี้มาก) แต่สิ่งหนึ่งที่ผมได้รับและคิดว่าสำคัญมากซึ่งเป็นเหมือนแก่นของ DDD สิ่งนั้นคือ การเรียนรู้การทำงานร่วมกันเพื่อตอบคำถามว่าธุรกิจของเรา ทำอะไร, ทำทำไม และ เราจะแก้ปัญหาทางธุรกิจนั้นให้เหมาะสมได้อย่างไร

ผมคิดว่าหลายๆคนน่าจะเคยคิดแบบนี้รวมถึงผม เช่น ได้ Requirement มา

ไอหยา เจอแบบนี้ต้อง Kafka, RabbitMQ เว้ยเฮ้ย

อยากได้แบบนี้ต้อง Realtime System

โห เจอแบบนี้ต้องแยก Microservice แล้วแหละ

เห็นไหมครับว่าบางครั้ง Developer อาจจะกำลังพยายามแก้ปัญหาด้วยการ Overengineer ทั้งๆที่ ณ ตอนนั้น เราอาจจะยังไม่เข้าใจบริบทของธุรกิจหรือสิ่งที่เราทำจริงๆ ซึ่งถ้าทำแบบนั้นเราอาจจะต้องใช้ Cost ที่สูงมาก แต่เมื่อเรามองผ่าน DDD แล้ว มันอาจจะไม่จำเป็นต้องทำขนาดนั้นก็ได้

ทั้งนี้ทั้งนั้นผมไม่ได้บอกว่าการหยิบ DDD เป็นทางเลือกที่ดีที่สุดนะครับ พี่รูฟแนะนำว่าให้เปรียบ DDD เหมือนกับ Tool ที่ช่วยเรา Organize สิ่งต่างๆ เพราะฉะนั้นอย่าพยายามมองว่า DDD เป็น Silver Bullet ที่ยิงปั้งเดียวแล้วจะแก้ปัญหาทุกอย่างได้ แต่มองมันเป็น Tool ที่ Provide แนวทางปฏิบัติที่เหมาะสมในการทำ Software ดีกว่า สิ่งสำคัญคือใช้มันอย่างเข้าใจ ถ้าอ่านในหนังสือจะเจอหัวข้อ When to use xxx ใน Tactical Design บ่อยมาก ซึ่งจุดนี้เองผมมองว่าหนังสือไม่ได้บังคับให้เราทำตามหรือใช้ทุกอย่างไปซะหมด แต่พยายามสื่อว่า จงใช้มันให้เหมาะสมที่สุด

เอาล่ะครับ ก่อนจะจากกันไป ขอขอบคุณทุกๆท่านๆที่ผ่านเข้ามาอ่านบทความนี้จนจบ (มั้ง) และ ขอทิ้งท้ายประโยคจากพี่รูฟไว้ว่า

ruvruv

ขอให้สนุกกับการทำ Software ครับ

หากต้องการเรียนและต้องการรายละเอียดเพิ่มเติมแบบเจาะลึก ติดตามพี่รูฟได้เลยครับ จิ้มตรงนี้

สำหรับวันนี้ ขอลาไปก่อน สวัสดีครับ…