ทำไมต้องแยกการเข้าถึงข้อมูลออก
จากหนังสือเล่มนี้ฉันคิดว่าสองหน้าแรกของบทการออกแบบแบบขับเคลื่อนขับเคลื่อนให้เหตุผลบางอย่างสำหรับเหตุผลที่คุณต้องการสรุปรายละเอียดการใช้งานด้านเทคนิคจากการใช้โมเดลโดเมน
- คุณต้องการให้การเชื่อมต่อแน่นระหว่างโมเดลโดเมนและรหัส
- การแยกข้อกังวลทางเทคนิคช่วยพิสูจน์ว่าแบบจำลองนั้นใช้งานได้จริง
- คุณต้องการภาษาที่แพร่หลายเพื่อซึมซาบผ่านการออกแบบของระบบ
สิ่งนี้น่าจะมีจุดประสงค์เพื่อหลีกเลี่ยง "รูปแบบการวิเคราะห์" แยกต่างหากที่แยกจากการใช้งานจริงของระบบ
จากสิ่งที่ฉันเข้าใจในหนังสือมันบอกว่า "รูปแบบการวิเคราะห์" นี้สามารถจบลงด้วยการออกแบบโดยไม่ต้องพิจารณาการใช้งานซอฟต์แวร์ เมื่อนักพัฒนาพยายามใช้โมเดลที่เข้าใจโดยฝ่ายธุรกิจพวกเขาสร้างนามธรรมของตัวเองเนื่องจากมีความจำเป็นทำให้เกิดกำแพงในการสื่อสารและความเข้าใจ
ในอีกทางหนึ่งนักพัฒนาที่แนะนำข้อกังวลทางเทคนิคมากเกินไปในรูปแบบโดเมนอาจทำให้เกิดการแบ่งเช่นกัน
ดังนั้นคุณอาจพิจารณาว่าการฝึกแยกข้อกังวลเช่นการติดตาสามารถช่วยป้องกันการออกแบบเหล่านี้ได้รูปแบบการวิเคราะห์เบี่ยงเบน หากรู้สึกว่าจำเป็นที่จะต้องแนะนำสิ่งต่าง ๆ เช่นการติดตาลงในแบบจำลองแสดงว่าเป็นธงสีแดง บางทีตัวแบบอาจไม่สามารถนำไปใช้งานได้จริง
พิเศษ:
"แบบจำลองเดี่ยวช่วยลดโอกาสที่จะเกิดข้อผิดพลาดเพราะตอนนี้การออกแบบเป็นผลพลอยได้โดยตรงของรูปแบบที่พิจารณาอย่างรอบคอบการออกแบบและแม้แต่รหัสก็มีการสื่อสารกับแบบจำลองด้วย"
วิธีที่ฉันตีความสิ่งนี้ถ้าคุณลงเอยด้วยรหัสของบรรทัดที่เกี่ยวข้องกับสิ่งต่าง ๆ เช่นการเข้าถึงฐานข้อมูลคุณสูญเสียการสื่อสารที่
หากความต้องการในการเข้าถึงฐานข้อมูลมีไว้สำหรับตรวจสอบความเป็นเอกลักษณ์ให้ดูที่:
Udi Dahan: ทีมผิดพลาดที่ใหญ่ที่สุดเกิดขึ้นเมื่อใช้ DDD
http://gojko.net/2010/06/11/udi-dahan-the-biggest-mistakes-teams-make-when-applying-ddd/
ภายใต้ "กฎทั้งหมดไม่ได้สร้างขึ้นเท่ากัน"
และ
ใช้รูปแบบโดเมน
http://msdn.microsoft.com/en-us/magazine/ee236415.aspx#id0400119
ภายใต้ "สถานการณ์จำลองสำหรับการไม่ใช้โมเดลโดเมน" ซึ่งสัมผัสกับหัวเรื่องเดียวกัน
วิธีแยกการเข้าถึงข้อมูล
กำลังโหลดข้อมูลผ่านอินเทอร์เฟซ
"data access layer" ได้รับการสรุปผ่านส่วนต่อประสานที่คุณเรียกใช้เพื่อดึงข้อมูลที่ต้องการ:
var orderLines = OrderRepository.GetOrderLines(orderId);
foreach (var line in orderLines)
{
total += line.Price;
}
ข้อดี: อินเทอร์เฟซจะแยกรหัสการประปา "data access" ซึ่งอนุญาตให้คุณยังคงเขียนการทดสอบ การเข้าถึงข้อมูลสามารถจัดการเป็นกรณี ๆ ไปช่วยให้ประสิทธิภาพดีกว่ากลยุทธ์ทั่วไป
จุดด้อย: รหัสการโทรจะต้องถือว่าสิ่งที่ถูกโหลดและสิ่งที่ไม่ได้
สมมติว่า GetOrderLines ส่งคืนออบเจกต์ OrderLine พร้อมคุณสมบัติ null ProductInfo สำหรับเหตุผลด้านประสิทธิภาพ ผู้พัฒนาจะต้องมีความรู้เกี่ยวกับโค้ดหลังอินเทอร์เฟซ
ฉันได้ลองวิธีนี้ในระบบจริง คุณจะต้องเปลี่ยนขอบเขตของสิ่งที่โหลดตลอดเวลาเพื่อพยายามแก้ไขปัญหาด้านประสิทธิภาพ คุณต้องมองหลังอินเทอร์เฟซเพื่อดูรหัสการเข้าถึงข้อมูลเพื่อดูว่ามีอะไรและไม่ได้โหลด
ตอนนี้การแยกข้อกังวลควรอนุญาตให้ผู้พัฒนามุ่งเน้นไปที่แง่มุมหนึ่งของรหัสในคราวเดียวให้มากที่สุด เทคนิคการอินเทอร์เฟซจะลบข้อมูลนี้ได้อย่างไร แต่ไม่โหลดข้อมูลมากแค่ไหนเมื่อมันถูกโหลดและที่ไหนมันถูกโหลด
สรุป: การแยกต่ำค่อนข้างยุติธรรม!
ขี้เกียจโหลด
ข้อมูลถูกโหลดตามต้องการ การเรียกเพื่อโหลดข้อมูลถูกซ่อนอยู่ภายในกราฟวัตถุเองซึ่งการเข้าถึงคุณสมบัติสามารถทำให้คิวรี sql ทำงานก่อนที่จะส่งคืนผลลัพธ์
foreach (var line in order.OrderLines)
{
total += line.Price;
}
ข้อดี: การเข้าถึงข้อมูล 'เมื่อไรที่ไหนและอย่างไร' ถูกซ่อนไว้จากนักพัฒนาซอฟต์แวร์ที่มุ่งเน้นไปที่ตรรกะของโดเมน ไม่มีรหัสในการรวมที่เกี่ยวข้องกับการโหลดข้อมูล ปริมาณข้อมูลที่โหลดได้อาจเป็นจำนวนที่แน่นอนตามรหัส
ข้อด้อย: เมื่อคุณประสบปัญหาเกี่ยวกับประสิทธิภาพการทำงานจะแก้ไขได้ยากเมื่อคุณมีโซลูชันทั่วไป "หนึ่งขนาดที่เหมาะกับทุกคน" การโหลดแบบ Lazy อาจทำให้ประสิทธิภาพโดยรวมแย่ลงและการใช้การโหลดแบบ lazy อาจเป็นเรื่องยุ่งยาก
บทบาทอินเทอร์เฟซ / การดึงข้อมูลกระตือรือร้น
แต่ละกรณีการใช้งานนั้นถูกทำให้ชัดเจนผ่านส่วนต่อประสานบทบาทซึ่งนำมาใช้โดยคลาสรวมทำให้สามารถจัดการกลยุทธ์การโหลดข้อมูลต่อกรณีการใช้งาน
กลยุทธ์การดึงข้อมูลอาจมีลักษณะเช่นนี้:
public class BillOrderFetchingStrategy : ILoadDataFor<IBillOrder, Order>
{
Order Load(string aggregateId)
{
var order = new Order();
order.Data = GetOrderLinesWithPrice(aggregateId);
return order;
}
}
จากนั้นการรวมของคุณจะมีลักษณะดังนี้:
public class Order : IBillOrder
{
void BillOrder(BillOrderCommand command)
{
foreach (var line in this.Data.OrderLines)
{
total += line.Price;
}
etc...
}
}
BillOrderFetchingStrategy ใช้เพื่อสร้างผลรวมแล้วผลรวมจะทำงานได้
จุดเด่น: อนุญาตให้ใช้รหัสที่กำหนดเองต่อกรณีการใช้งานช่วยให้มีประสิทธิภาพสูงสุด คือสอดคล้องกับการเชื่อมต่อแยกหลักการ ไม่มีข้อกำหนดด้านรหัสที่ซับซ้อน การทดสอบหน่วยมวลรวมไม่จำเป็นต้องเลียนแบบกลยุทธ์การโหลด กลยุทธ์การโหลดทั่วไปสามารถใช้สำหรับกรณีส่วนใหญ่ (เช่นกลยุทธ์ "โหลดทั้งหมด") และกลยุทธ์การโหลดพิเศษสามารถดำเนินการได้เมื่อจำเป็น
ข้อด้อย: ผู้พัฒนายังคงต้องปรับ / ตรวจสอบกลยุทธ์การดึงข้อมูลหลังจากเปลี่ยนรหัสโดเมน
ด้วยวิธีการดึงข้อมูลกลยุทธ์คุณยังอาจพบว่าคุณกำลังเปลี่ยนรหัสการดึงข้อมูลที่กำหนดเองสำหรับการเปลี่ยนแปลงในกฎเกณฑ์ทางธุรกิจ มันไม่ใช่การแยกข้อกังวลอย่างสมบูรณ์แบบ แต่จะจบลงด้วยการบำรุงรักษาได้ดีกว่าตัวเลือกแรก กลยุทธ์การดึงข้อมูลจะสรุปข้อมูล HOW, WHEN และ WHERE มันมีการแยกข้อกังวลที่ดีกว่าโดยไม่สูญเสียความยืดหยุ่นเหมือนขนาดเดียวที่เหมาะกับวิธีการโหลดแบบขี้เกียจทั้งหมด