จะรวม TDD และ DDD ที่เข้มงวดได้อย่างไร


15

TDD เป็นเรื่องเกี่ยวกับการออกแบบโค้ดซึ่งได้รับคำแนะนำจากการทดสอบ
ดังนั้นเลเยอร์ทั่วไปมักจะไม่สร้างล่วงหน้า พวกเขาควรปรากฏขึ้นเล็กน้อยผ่านขั้นตอนการรีแฟคเตอร์

การออกแบบที่ขับเคลื่อนด้วยโดเมนนั้นเกี่ยวข้องกับรูปแบบทางเทคนิคมากมายการกำหนดเลเยอร์ที่ได้รับการยอมรับเช่นแอพพลิเคชั่นเลเยอร์โครงสร้างพื้นฐานเลเยอร์โดเมนเลเยอร์คงอยู่

ในการเริ่มต้นการเข้ารหัสส่วนของโครงการ DDD ตั้งแต่เริ่มต้นจะทำอย่างไร?
ฉันควรปล่อยให้การออกแบบโผล่ออกมาจากการทดสอบอย่างเคร่งครัดหรือไม่หมายถึงไม่มีการแยกข้อกังวล (ไม่มีเลเยอร์) และ refactor เพื่อให้พอดีกับรูปแบบทางเทคนิคของ DDD?

หรือฉันควรสร้างเลเยอร์ที่ว่างเปล่าเหล่านั้น (แอปพลิเคชันหน่วยงาน / บริการโดเมนโครงสร้างพื้นฐาน) และให้ TDD เหมาะสมกับแต่ละชั้นอย่างอิสระ (ใช้ mocks เพื่อแยกระหว่างเลเยอร์)


คำตอบ:


12

ให้แน่ใจว่าคุณตรวจสอบความคิดเห็นที่ผ่านมาลุงบ๊อบเกี่ยวกับบทบาทของการออกแบบใน TDD

การออกแบบที่ขับเคลื่อนด้วยโดเมนนั้นเกี่ยวข้องกับรูปแบบทางเทคนิคมากมายการกำหนดเลเยอร์ที่ได้รับการยอมรับเช่นแอพพลิเคชั่นเลเยอร์โครงสร้างพื้นฐานเลเยอร์โดเมนเลเยอร์คงอยู่

Udi Dahan: "พระเจ้าฉันเกลียดการฝังรากลึก" เขาใช้เวลาพูดคุยกันในเรื่องการพูดคุยเรื่องCQRSของเขา- แต่ต่างกัน (การฝังรากเริ่มที่ 18m30s)

ฉันจะสะกดประโยคของคุณแตกต่างกันเล็กน้อย "DDD ตระหนักว่ามีจำนวนของความกังวลร่วมกันในการใช้งานทางธุรกิจมากที่สุดและว่าการแก้ปัญหาเพื่อความกังวลเหล่านั้นมีชีวิตที่แตกต่างกัน"

ตัวอย่างเช่นข้อกังวลเกี่ยวกับโดเมนจำเป็นต้องมีความยืดหยุ่นโดยเฉพาะเมื่อคุณกำหนดโซลูชันเองสำหรับธุรกิจเฉพาะ ท้ายที่สุดโดเมนเกี่ยวข้องกับวิธีการทำธุรกิจของ บริษัท ซึ่งกล่าวได้ว่า บริษัท สร้างรายได้อย่างไรและสามารถส่งมอบการปรับปรุงธุรกิจได้อย่างรวดเร็วคือรายได้ฟรี

ในทางกลับกันคุณอาจไม่จำเป็นต้องเปลี่ยนองค์ประกอบการคงอยู่บ่อยๆ โซลูชันฐานข้อมูลที่ทำงานในรีลีสล่าสุดอาจใช้งานรีลีสนี้ได้เช่นกัน

ข้อกังวลของแอปพลิเคชันอยู่ตรงกลาง; พวกเขามักจะมีเสถียรภาพเพื่อให้ผู้ใช้ไม่จำเป็นต้องเรียนรู้แอพใหม่ทุกครั้ง

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

ในขณะเดียวกัน CTO ต้องการแอปเวอร์ชันที่ทำงานบนโทรศัพท์ของเขา ซีอีโอเพิ่งได้ยินจากผู้ชายคนหนึ่งที่เผยแพร่ API เป็นเรื่องใหญ่

นอกจากนี้ทีมขายใช้รูปแบบที่แตกต่างกันดังนั้นให้แอปเดียวกันกับเราด้วยรูปแบบที่แตกต่างกัน โอ้ แต่เรากำลังเดินทางบ่อยดังนั้นรุ่นของเราต้องทำงานเมื่อเราออฟไลน์และซิงค์ในภายหลัง ...

กล่าวอีกนัยหนึ่งคุณใช้รูปแบบยุทธวิธีจากไม่ใช่โดยใช้ตัวยึดตำแหน่งที่ว่างเปล่าและสมมติว่าพวกเขาจะได้รับการเติมเต็มในภายหลัง แต่แทนที่จะจำได้เมื่อคุณข้ามลำธาร "เฮ้นั่นคือรหัสติดตัวในรูปแบบโดเมนของฉันฉันต้องไม่ เสร็จสิ้นการปรับโครงสร้างแล้ว "


11

Test Driven Development (TDD)ไม่ใช่การออกแบบ มันเป็นข้อกำหนดที่ส่งผลกระทบต่อการออกแบบของคุณ ราวกับว่าคุณจำเป็นต้องมีความปลอดภัยต่อเกลียวนั่นไม่ใช่การออกแบบ มันเป็นข้อกำหนดที่ส่งผลต่อการออกแบบของคุณอีกครั้ง

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

สิ่งหนึ่งที่ดีเกี่ยวกับอึที่ทดสอบได้คือมันเป็นอึที่สามารถปรับเปลี่ยนได้ดังนั้นสำหรับบางคนที่ดีพอ เราจะได้รับแฟนซีเมื่อจำเป็นเท่านั้น คนอื่นเกลียดสิ่งนี้และตำหนิ TDD ไม่นี่คือสิ่งที่คุณทำ

การออกแบบโดเมนขับเคลื่อน (DDD)เป็นสิ่งที่คุณทำก่อนวัฏจักร refactor สีเขียวสีแดงของ TDD

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

ระบบ DDD สามารถมีสถาปัตยกรรมที่มีลักษณะดังนี้:

ป้อนคำอธิบายรูปภาพที่นี่

สถาปัตยกรรม DDD นี้มีหลายชื่อ: Clean , Onion , Hexagonal , ฯลฯ

นี่คือการปลดการเชื่อมต่อที่ฉันเห็นหลายคนมีเมื่อพวกเขาดูการออกแบบนี้ นี่ไม่ใช่รูปธรรม ฉันสามารถติดตามการออกแบบนี้และไม่เคยเขียนอะไรที่คุณเห็นไดอะแกรมที่นี่ ฉันเห็นคนอื่นยืนยันว่าจะต้องมีวัตถุกรณีการใช้งานหรือชั้นเรียนนิติบุคคล สิ่งเหล่านี้คือชุดของกฎที่บอกคุณว่าคุณสามารถพูดคุยกับใครและอย่างไร

แค่นั้นแหละ. ปฏิบัติตามกฎของการออกแบบนี้และคุณสามารถ TDD ใจเล็ก ๆ ของคุณออกมา TDD ไม่สนใจว่าคุณจะคุยกับใคร มันใส่ใจว่าทุกอย่างที่ทำบางสิ่งสามารถพิสูจน์ได้ว่าทำงานได้หรือไม่เพียงแค่คลิกปุ่ม ไม่บางสิ่งบางอย่างเสีย มันบอกคุณว่ามีอะไรแตกหัก

ยังคลุมเครือ ดูที่Controler- Use Case Interactor- Presenterแผนภาพที่มุมขวาล่าง ต่อไปนี้เป็นสิ่งที่เป็นรูปธรรมสามประการที่สื่อสารกัน แน่ใจว่านี่คือ DDD แต่คุณจะเพิ่ม TDD ที่นี่ได้อย่างไร เพียงแค่เลียนแบบสิ่งที่เป็นรูปธรรม ผู้นำเสนอต้องได้รับข้อมูล PresenterMockชั้นจะเป็นวิธีที่ดีที่จะตรวจสอบว่าได้รับสิ่งที่คุณคาดหวังที่จะได้รับ ยื่นมือเข้าUse Case InteractorมาPresenterMockและขับUse Case Interactorราวกับว่าคุณเป็นControllerและคุณมีวิธีที่ดีในการทดสอบหน่วยUse Case Interactorเนื่องจากการเยาะเย้ยจะบอกคุณว่ามันได้สิ่งที่คุณคาดหวังว่าจะได้รับ

ดูนั่นสิ TDD พอใจและเราไม่ต้องไปเจรจากับการออกแบบ DDD ของเรา มันเกิดขึ้นได้อย่างไร? เราเริ่มต้นด้วยการออกแบบที่แยกออกจากกัน

หากคุณใช้ TDD ในการออกแบบไดรฟ์ (ไม่ใช่แค่Evelopment D ) คุณจะได้รับการออกแบบที่สะท้อนถึงความพยายามที่คุณใส่เข้าไป ถ้านั่นคือสิ่งที่คุณต้องการ แต่นั่นไม่ใช่สิ่งที่ TDD มีความหมาย สิ่งนี้กลายเป็นสิ่งที่ขาดไปไม่ใช่ความผิดของ TDD

TDD ไม่ได้เกี่ยวกับการออกแบบ หากคุณต้องทำการเปลี่ยนแปลงการออกแบบเพื่อใช้ TDD คุณมีปัญหาใหญ่กว่าการทดสอบ


ฉันไม่เคยพูดว่า TDD เป็นงานออกแบบ แต่มันเกี่ยวกับการออกแบบ
Mik378

1
ลุงบ๊อบบอกให้คุณออกแบบ เขาไม่ได้บอกคุณว่า "เดี๋ยวก่อนถ้าคุณกำลังทดสอบงานที่ใส่ใจคนอื่น"
candied_orange

1
ตามที่ฉันได้กล่าวไปแล้วเพียงทำตามกฎของคนที่คุณได้รับอนุญาตให้คุยด้วย สถาปัตยกรรมที่สะอาดไม่ใช่สิ่งที่จะต้องมีการถกเถียงกันใน BDUF เพียงระบุว่าคุณมีส่วนร่วมอย่างไรและคิดว่าควรสื่อสารกับใครและอย่างไร มันคล่องตัวกว่าที่คุณคิด หลังจากนั้นถามว่า TDD นั้นทดสอบได้หรือไม่ ถ้าไม่ใช่คุณทำอะไรผิด ถ้าเป็นฉันหวังว่าคุณจะให้ความสนใจเพราะการออกแบบที่ดีเป็นมากกว่าแค่การทดสอบ
candied_orange

6
อืม ... ฉันไม่สามารถยืนเรียกชื่อผิด "Test Driven Design" ได้ คุณยังคงต้องออกแบบนิดหน่อยก่อนที่จะเริ่มต้นการหาความสุขที่แป้นพิมพ์อย่างไม่ว่าคุณจะเขียนการทดสอบหรือไม่ก็ตาม
RubberDuck

1
ที่จะพูดลุงบ๊อบในประเด็นนี้แน่นอน, "คุณมีระยะเวลาการออกแบบ" คลิกที่นั่นและหากคุณใจร้อนเกินกว่าจะอ่านคำเหล่านั้นทั้งหมด คุณจะพบว่า Mr Martin นั้นค่อนข้างยืนยงว่า TDD นั้นไม่มีกระสุนวิเศษและคุณต้องออกแบบไม่เพียง แต่รหัสของคุณ แต่การทดสอบของคุณเช่นกันหากคุณไม่ต้องการอยู่ในฐานรหัสที่เปราะบาง
candied_orange

4

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

DDD คือทั้งหมดที่เกี่ยวกับการออกแบบระดับสูงภาษาระหว่างผู้เชี่ยวชาญด้านโดเมน & วิศวกรการแมปบริบท ฯลฯ นี่ควรเป็นตัวขับเคลื่อนของการออกแบบระดับสูงของแอปพลิเคชัน

เหล่านี้เป็นคำอธิบายที่ตื้นทั้งสองวิธีการเขียนโปรแกรมที่มีประสิทธิภาพ แต่ในตอนท้ายของวันพวกเขาบรรลุสองสิ่งที่แตกต่างกันมาก

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

ฉันคิดว่ามันเป็นสิ่งสำคัญที่ควรทราบ: คุณควรฝึก DDD เฉพาะเมื่อแอปพลิเคชันนั้นซับซ้อนเพียงพอ


1
ฉันไม่เห็นด้วย TDD ไม่ได้เกี่ยวกับการทดสอบ แต่เป็นการออกแบบ
Mik378

ฉันกำลังอ้างอิงกฎ 3 ข้อของ TDD ตามที่ลุงบ๊อบอธิบายไว้
Matt Oaxaca

Steve Freeman ผู้แต่งหนังสือ GOOS ระบุ: คุณไม่ควรระบุเลเยอร์หรือโครงสร้างพื้นฐานใด ๆ ก่อนเริ่มรอบ TDD
Mik378

ฉันไม่คุ้นเคยกับหนังสือเล่มนั้น แต่ฉันต้องไม่เห็นด้วย ฉันไม่ต้องการให้ TDD สร้างกราฟ DI & class ของฉัน
Matt Oaxaca

3
@ Mik378: TDD ไม่ได้เกี่ยวกับการทดสอบ แต่ยังไม่เกี่ยวกับการออกแบบเป็นหลัก - การออกแบบที่ชักนำโดย TDD คือการออกแบบสำหรับการทดสอบหน่วย ทุกส่วนของการออกแบบจะต้องมาจากที่อื่น ฉันเห็น TDD มากขึ้นเป็นเทคนิคการใช้งาน
Doc Brown

3

DDDเป็นเรื่องเกี่ยวกับการออกแบบซอฟต์แวร์
TDDเกี่ยวกับการออกแบบรหัส

ใน DDD "model" หมายถึงนามธรรมของโดเมนความรู้ทั้งหมดจากผู้เชี่ยวชาญโดเมน

เราสามารถใช้ TDD สำหรับรูปแบบการออกแบบซอฟต์แวร์เริ่มต้นของรหัส โดเมนมีกฎเกณฑ์ทางธุรกิจและรูปแบบโดเมนที่การทดสอบที่เขียน (ที่หนึ่ง) ควรเป็นสีเขียว

ผลที่ได้คือเราสามารถเขียนรหัสการทดสอบได้หลังจากออกแบบโมเดลที่ขับเคลื่อนด้วยโดเมน
หนังสือเล่มนี้"เติบโตเชิงวัตถุซอฟท์แวแนะนำโดยการทดสอบ" การเชื่อมโยงสำหรับซื้อ
ใช้วิธีนี้กับโครงกระดูกเดิน , สถาปัตยกรรมหกเหลี่ยมและ TDD

แหล่งที่มาจาก: DDD อย่างรวดเร็ว - InfoQ


1
ซอฟต์แวร์และรหัสที่ดีสำหรับฉันเป็นสิ่งเดียวกัน
Konrad

1
มันอาจจะเหมือนกันเช่นกัน ฉันพยายามพูดว่า: ซอฟต์แวร์เป็น "วิธีแก้ปัญหา", "ระบบ", "ระดับสูง" และรหัสเป็น "การใช้งาน", "ระดับต่ำ", "รายละเอียด"
JonyLoscal

ฉันคิดว่าสิ่งสำคัญคือ "ครั้งแรกที่เราทดสอบ แต่เราต้องการโครงกระดูกที่เล็กที่สุดที่เราจะเริ่มการทดสอบ" คุณ
JonyLoscal

1

ฉันควรปล่อยให้การออกแบบโผล่ออกมาจากการทดสอบอย่างเคร่งครัดหรือไม่

ไม่ (การขับเคลื่อนด้วยโดเมน) การออกแบบตามคำจำกัดความควรเกิดจากข้อกำหนดของโดเมน นี่เป็นความคิดที่ดีที่จะปล่อยให้สิ่งอื่น ๆ ขับเคลื่อนการออกแบบของคุณไม่ว่าจะเป็นชุดทดสอบสคีมาฐานข้อมูลหรือ ... (จะดำเนินการต่อ)

หรือฉันควรสร้างเลเยอร์ที่ว่างเปล่าเหล่านั้น (แอปพลิเคชันหน่วยงาน / บริการโดเมนโครงสร้างพื้นฐาน) และให้ TDD เหมาะสมกับแต่ละชั้นอย่างอิสระ

(ต่อ) ... หรือเลเยอร์คลาสที่เป็นที่ยอมรับในภาษา OO ที่คุณเลือกแม้ว่ามันจะเป็นผู้ใหญ่มากและเป็นที่นิยมก็ตาม .

เมื่อพูดถึง DDD OOP จะแสดงความต้องการสั้น ๆ ในรูปแบบที่มนุษย์สามารถอ่านได้ซึ่งเป็นสิ่งที่ชัดเจนสำหรับผู้ที่ไม่ใช่โปรแกรมเมอร์ ภาษา FP ที่พิมพ์อย่างเคร่งครัดจะทำงานได้ดีขึ้น ฉันแนะนำให้อ่านหนังสือเกี่ยวกับ DDD โดยใช้การเขียนโปรแกรมฟังก์ชั่น "การสร้างแบบจำลองโดเมนทำหน้าที่" โดย Scott Wlaschin

https://pragprog.com/book/swdddf/domain-modeling-made-functional

คุณไม่จำเป็นต้องใช้ภาษา FP เพื่อขอยืมแนวคิดบางอย่างจากที่นั่น (ไม่ใช่ทั้งหมดที่น่าเสียดาย) แต่ถ้าคุณอ่านมันจริง ๆ แล้วคุณอาจต้องการใช้ภาษาที่ใช้งานได้

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

ในการสร้างวงกลมเต็มลองกลับไปที่คำถามไตเติ้ลนั่นคือ "จะรวม TDD และ DDD ที่เข้มงวดได้อย่างไร" คำตอบนั้นตรงไปตรงมา: ไม่มีอะไรที่จะรวม / ไม่มีความขัดแย้งทางผลประโยชน์ ออกแบบตามความต้องการพัฒนาตามการออกแบบ (โดยการทดสอบก่อนถ้าคุณต้องการจะทำ TDD)


+1 สำหรับหนังสือ FP DDD และคำอธิบายโดยรวม
Roman Susi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.