Quantcast
Channel: cc :: somkiat
Viewing all articles
Browse latest Browse all 1997

[Part 3] ว่าด้วยเรื่องของรูปแบบความสัมพันธ์ระหว่าง Boundary context ใน DDD

$
0
0

ในระบบงานหนึ่ง ๆ นั้นมักจะซับซ้อนเสมอ มี context หรือส่วนการทำงานจำนวนมาก
ดังนั้นจำเป็นต้องแยกและกำหนดกรอบทำงานที่ชัดเจนให้แต่ละ context
หรือเรียกว่า Boundary context
แต่ปัญหาที่เกิดตามมาก็คือ
แต่ละ Boundary context จะต้องติดต่อสื่อสาร
หรือต้องทำการแลกเปลี่ยนข้อมูลกัน
หรือเรียกว่าความสัมพันธ์ระหว่าง Boundary context
กันอย่างไร ?

รูปแบบความสัมพันธ์มีดังต่อไปนี้

  • Shared Kernel
  • Customer / Supplier
  • Conformist
  • Anticorruption Layer (ACL)
  • Separate Ways
  • Open Host Service
  • Published Language

มาดูกันว่าแต่ละความสัมพันธ์เป็นอย่างไร ?

1. Share Kernel

เป็นรูปแบบที่ context ต่าง ๆ
ทำการ share พวก Domain model หรือใช้ข้อมูลใน database เดียวกัน
เมื่อทำการเปลี่ยนแปลง Domain model นั้น ๆ
ผลที่ตามมาคือ จะกระทบต่อ context อื่น ๆ ที่ใช้ร่วมกันด้วยเสมอ !!

เรื่องนี้ต้องระมัดระวังกันอย่างมาก
แต่ประโยชน์ที่ได้รับคือ เปลี่ยนแปลงเพียงที่เดียว
ทำให้เราพบเจอการใช้งานความสัมพันธ์แบบนี้เยอะมาก ๆ แต่ ... !!!
Domain model ที่ share กันนี้เราเรียกว่า Kernel model แสดงดังรูป

2. Customer/Supplier

แปลง่าย ๆ คือ ลูกค้าและผู้ผลิต
หรืออาจจะเรียกว่า Consumer-Driven Contract Relationship
โดยจะเรียกผู้ผลิตหรือผู้ถูกเรียกใช้งานว่า Upstream context
เตรียม contract หรือจุดบริการให้ทาง customer หรือ Downstream context ไว้ใช้งาน

ทำให้ทั้งสองฝั่งทำงานกันเป็นอิสระ
ตราบเท่าที่ contract ไม่มีการเปลี่ยนแปลง !!
และ contract ที่ทาง supplier เตรียมให้จะเฉพาะเจาะจงให้กับแต่ละ consumer ไปเลย

ตรงนี้แหละที่ทั้งสองทีม
ควรต้องเขียน acceptance test สำหรับ interface ที่ตกลงกันไว้ (Contract Testing)
จากนั้นนำ acceptance test เหล่านี้ ไป run ไว้ที่
Upstream context ในทุกครั้งที่มีการเปลี่ยนแปลง (Continuous Integration)
เพื่อทำให้ทาง Downstream context หรือ customer นั้นมีความมั่นใจ
ว่าจะไม่เกิดความผิดพลาดขึ้นมา

สังเกตว่า  Supplier team นั้นจะมีข้อมูลและการทำงานต่าง ๆ เตรียมไว้ให้
แต่ว่าทาง Customer team นั้นสามารถขอเปลี่ยนแปลงตามที่ต้องการได้
ทำให้ทาง Supplier team ต้องสร้าง service เฉพาะเจาะจงกับ customer นั้น ๆ ไว้เลย
เรามักเรียกสิ่งที่เฉพาะเจาะจงของแต่ละ customer ว่า contract หรือสัญญานั่นเอง

ทำให้ทั้งสองทีมต้องมีการพูดคุยหรือสื่อสารกันมากขึ้น
เพื่อให้ได้ตามสิ่งที่ต้องการทั้งสองฝั่ง

3. Conformist

การทำงานจะมีลักษณะใกล้เคียงกับ Customer/Supplier
แต่ว่า conformist จะต่างออกไปคือ
ในส่วนของ Supplier นั้นจะทำการเตรียมข้อมูลและการทำงานที่เป็นมาตรฐานไว้
จะไม่เปลี่ยนไปตามที่ฝั่ง Customer ต้องการ
เพราะว่า Customer แต่ละที่ก็ต้องการต่างกัน !!
หนักกว่านั้นอาจจะทำให้เกิดความซับซ้อนในการทำงานของ Supplier ขึ้นมาอีก

ดังนั้นฝั่ง customer ต้องเอาข้อมูลที่ได้ไปแปลงตามที่ต้องการเอง
โดยเราจะเรียกข้อมูลในฝั่ง customer ว่า Value object

ดังนั้นทางฝั่ง Supplier หรือ Downstream ต้องดีด้วย
มิเช่นนั้นก็จะก่อให้เกิดปัญหาตามมามากมาย
ถ้าลองสังเกต แนวทางนี้จะเหมือนเอาเรื่อง Share kernel มาใช้งาน
เพียงแต่ไม่ให้ share model กันแบบตรง ๆ เท่านั้นเอง

ตัวอย่างแสดงดังรูป


จะเห็นได้ว่าฝั่ง Expense tracking context
จะทำการดึงข้อมูล Banking Account มาจากทาง Banking context
จากนั้นทางฝั่ง Expense tracking context ก็นำข้อมูล  Banking Account ไปใช้งานต่อ
เช่นการแปลงข้อมูลให้เข้ากับความต้องการของตนเอง
โดยที่ทางฝั่ง Banking context ไม่ต้องทำให้

ทำให้ทั้งสองทีมไม่ต้องพูดคุยอะไรกันมากนัก

4. Anti-corruption Layer (ACL)

เป็นอีกรูปแบบหนึ่งที่พบมาก
เมื่อทั้งสอง context แยกระบบกันอย่างชัดเจน
ทำให้ทั้งสอง context เป็นอิสระอย่างมาก
แต่ทั้งสองต้องทำงานร่วมกัน
คำถามคือ จะทำอย่างไรดี ?
เพราะว่าแต่ละฝั่งมีความต้องการต่างกัน ทำงานต่างกัน
วิธีการที่ชอบใช้กันคือ สร้าง Integation system ขึ้นมา
หรือเรียกว่า ACL นั่นเอง

ในส่วนของ ACL มันจะทำการสร้างด้วยชื่อต่าง ๆ ดังนี้

  • Facade
  • Adapter
  • Translator

ทำหน้าที่เป็นคนกลางแปลงข้อมูลจากฝั่ง suppiler ไปยังฝั่ง customer
และก็แปลงข้อมูลจากฝั่ง customer กลับไปยังฝั่ง supplier อีกที
ซึ่งเราจะพบมากในระบบขนาดใหญ่ ที่มีระบบงานแยกกันจำนวนมาก
หรือต้องทำงานร่วมกับ Legacy system
และเป้าหมายคือสร้างระบบใหม่เข้ามาทดแทน

ยกตัวอย่างเช่นระบบ Banking
อาจจะมีระบบ PFM (Personal Financial Management) ที่ทำงานดีอยู่แล้ว
จากนั้นต้องการสร้างระบบงาน Online Banking ขึ้นมา เช่น Mobile Banking เป็นต้น
สิ่งที่ต้องทำขึ้นมาคือการ integrate กันระหว่าง 2 ระบบ
แน่นอนว่า ทำไม่ได้แน่ ๆ 
ดังนั้นจึงต้องสร้าง ACL ขึ้นมา
เพื่อแปลงข้อมูลหรือ process บางอย่างก่อนเสมอ
ยกตัวอย่างเช่น การแปลงข้อมูลจากรูปแบบ Legacy มาในรูปแบบที่ใช้งานได้ง่าย
เช่น XML และ JSON เป็นต้น

บ่อยครั้งพบว่า เรามักจะทำ ACL บ่อยมาก ๆ 
บางครั้งก็เป็น ACL ซ้อน ACL ตามเทคโนโลยีที่เปลี่ยนไป
เช่น Legacy -> WebService -> RESTFul API -> GraphQL -> ???
แบบนี้น่ากลัวมาก ๆ ระวังกันด้วย

5. Separate Ways

เนื่องจากถ้ายังต้องติดต่อสื่อสารหรือแลกเปลี่ยนข้อมูลกันมันมีปัญหามากนัก
ดังนั้นทำการแยกแต่ละ boundary context ออกจากกันเด็ดขาดไปเลย
ทำให้แต่ละส่วนงาน ต่างทำกันไป ตามแนวทางของตนเอง
ทำให้แต่ละส่วนงานไปได้รวดเร็วและคล่องตัว
แต่อาจทำให้เกิดข้อมูลและ process ที่ซ้ำซ้อนกันได้

แต่ถ้าทั้งสองต้องทำงานร่วมกัน
มักจะมีหน่วยงานกลางมาจัดการ เช่น Middleware เป็นต้น
หรือทำงานเชื่อมผ่าน User Interface ก็ได้

6. Open Host Service

ถ้า boundary context หนึ่งถูกใช้งานจากส่วนอื่น ๆ เยอะมากแล้ว
การที่จะพัฒนาหรือสร้างหรือแปลงให้ตรงตามแต่ละระบบเรียกใช้งาน 
น่าจะเป็นสิ่งที่ยากและใช้เวลาเยอะ
ยกตัวอย่างเช่นสร้าง ACL เพียบเลย

ดังนั้นเพื่อลดปัญหานี้ 
จึงมีแนวคิดที่จะพยายามสร้างกลุ่มของ APIs ใน boundary context ที่ถูกเรียกใช้ไว้เลย
โดยใน API นี้จะมีกลุ่มของ service ที่ผู้เรียกใช้งานต้องการ
และมีมาตรฐานชัดเจน

พบว่ามีแนวคิดคล้าย ๆ Conformist เลย
แต่ต่างกันตรงที่ data model ของข้อมูลที่คุยกัน
กับ standard ของการเรียกใช้ที่เป็นกลาง 
เช่น WebService หรือ RESTFul API เป็นต้น
โดยที่ทั้งสองฝั่งคือ
ผู้เรียกใช้และผู้ให้บริการต้องตกลงกันไว้ หรือพูดคุยกันมากขึ้นนั่นเอง
ทำให้ทั้งสองฝั่งทำงานร่วมกันได้ง่ายขึ้น
เน้นไปที่ส่วนการ integration มากกว่า implementation

7. Published Language

ในส่วนนี้จะมีพัฒนาการมาจาก Open Host Service
แต่ Open Host Service นั้นยังต้องคุยกันระหว่างทีมสูง
ว่าแต่ละทีมจะมี data model ระหว่างกันอย่างไร
ถึงแม้จะมี standard ในการพูดคุยแล้วก็ตาม
ที่สำคัญยังคงผูกมัดกันอย่างมาก

จะดีกว่าไหมถ้าจะลดการผูกมัดกันลงไป
ด้วยการพูดคุยผ่านข้อมูลในรูปแบบที่กำหนดเช่น XML, JSON เป็นต้น
ให้แต่ละส่วนงานที่ต้องการทำงานร่วมกัน ให้ตกลงผ่านรูปแบบข้อมูลเท่านั้น
จากนั้นให้ทำการสร้าง message ขึ้นมา
เมื่อทำการสร้าง message ออกไปแล้ว
ส่วนงานอื่น ๆ ก็ทำงานตามความต้องการของระบบ ด้วย message ที่สร้างขึ้นมา

ยกตัวอย่างเช่น
จะสร้าง message เมื่อมีการสั่งซื้อเข้ามาในระบบ e-commerce
จากนั้นระบบอื่น ๆ ก็จะทำการ
ส่ง email ไปยังผู้ซื้อและผู้ขาย
ทำการตัด stock สินค้าที่ถูกซื้อ
ซึ่งแต่ละระบบจะใช้ message เดียวกัน

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

จะพบว่าความสัมพันธ์ทั้ง 7 แบบนั้น มันสะท้องเรื่องโครงสร้างขององค์กร

ทั้งรูปแบบการติดต่อสื่อสารและทีม
และที่สำคัญแต่ละระบบงานก็จะมีรูปแบบที่แตกต่างกันไปเช่นกัน
ไม่สามารถใช้รูปแบบใดรูปแบบหนึ่งได้

  • Upstream vs Downstream
  • Customer vs Supplier
  • Anti-corruption layer

หรือจะทำงานกันแบบ Partnership คือทำงานร่วมกันไปด้วยกัน

Reference Websites




Viewing all articles
Browse latest Browse all 1997

Trending Articles