จะรับ API เริ่มต้นได้อย่างไรโดยใช้ TDD


12

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

สมมติว่าคุณกำลังเขียนไลบรารีแปลก ๆ คุณรู้ว่าสิ่งที่ต้องทำคุณรู้วิธีทั่วไปที่ควรนำไปใช้ (สถาปัตยกรรมที่ชาญฉลาด) แต่คุณ "ค้นพบ" ที่คุณต้องทำการเปลี่ยนแปลง API สาธารณะของคุณในขณะที่คุณรหัส บางทีคุณต้องเปลี่ยนวิธีการส่วนตัวนี้เป็นรูปแบบกลยุทธ์ (และตอนนี้ต้องผ่านกลยุทธ์ที่เยาะเย้ยในการทดสอบของคุณ) บางทีคุณอาจวางความรับผิดชอบผิดที่นี่และที่นั่นและแบ่งชั้นที่มีอยู่

เมื่อคุณพัฒนาโค้ดที่มีอยู่ TDD ดูเหมือนจะดีมาก แต่เมื่อคุณเขียนทุกอย่างตั้งแต่เริ่มต้น API ที่คุณเขียนการทดสอบจะค่อนข้าง "พร่ามัว" เว้นแต่คุณจะออกแบบหน้าใหญ่ คุณจะทำอย่างไรเมื่อคุณทำการทดสอบ 30 ครั้งในวิธีที่มีการเปลี่ยนแปลงลายเซ็น (และสำหรับส่วนนั้นพฤติกรรม) ที่เปลี่ยนแปลงไป นั่นคือการทดสอบมากมายที่จะเปลี่ยนแปลงเมื่อพวกเขารวมกัน


3
ทดสอบ 30 วิธีในหนึ่งวิธี? ดูเหมือนว่าวิธีการนั้นมีความซับซ้อนมากเกินไปหรือคุณกำลังเขียนการทดสอบมากเกินไป
Minthos

ฉันอาจพูดเกินจริงไปหน่อยเพื่อแสดงความคิดเห็นของฉัน หลังจากตรวจสอบรหัสฉันโดยทั่วไปมีน้อยกว่า 10 วิธีต่อการทดสอบโดยส่วนใหญ่อยู่ต่ำกว่า 5 แต่ส่วน "การย้อนกลับและเปลี่ยนมือ" ส่วนทั้งหมดนั้นค่อนข้างน่าผิดหวัง
Vytautas Mackonis

6
@Minnos: ฉันสามารถคิดถึงการทดสอบ 6 ครั้งที่ด้านบนของหัวของฉันว่าวิธีใด ๆ ในการใช้สตริงมักจะล้มเหลวหรือทำงานได้ไม่ดีเมื่อเทียบกับการเขียนแบบร่างครั้งแรก (null ว่างเปล่ายาวเกินไปไม่แปลเป็นภาษาท้องถิ่น . ในทำนองเดียวกันสำหรับวิธีการในการเก็บรวบรวม สำหรับวิธีการที่ไม่น่าสนใจ 30 เสียงมีขนาดใหญ่ แต่ไม่สมจริงเกินไป
Steven Evers

คำตอบ:


13

สิ่งที่คุณเรียกว่า"การออกแบบที่ยิ่งใหญ่ขึ้นไปข้างหน้า"ฉันเรียกว่า"การวางแผนที่สมเหตุสมผลของสถาปัตยกรรมคลาสของคุณ"

คุณไม่สามารถขยายสถาปัตยกรรมจากการทดสอบหน่วย แม้แต่ลุงบ๊อบก็พูดอย่างนั้น

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

http://s3.amazonaws.com/hanselminutes/hanselminutes_0171.pdf , หน้า 4

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

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


สิ่งนี้คือแม้จะมี "การวางแผนอย่างมีเหตุผล" คุณคาดหวังมากว่ามันจะเปลี่ยนแปลง ฉันมักจะปล่อยให้ประมาณ 80% ของสถาปัตยกรรมเริ่มต้นของฉันเหมือนเดิมกับการเปลี่ยนแปลงบางอย่างในระหว่าง 20% นั้นเป็นสิ่งที่รบกวนฉัน
Vytautas Mackonis

2
ฉันคิดว่าเป็นเพียงลักษณะของการพัฒนาซอฟต์แวร์ คุณไม่สามารถคาดหวังว่าจะได้รับสถาปัตยกรรมทั้งหมดในครั้งแรก
Robert Harvey

2
+1 และมันไม่ตรงกันข้ามกับ TDD TDD เริ่มต้นเมื่อคุณเริ่มเขียนโค้ดอย่างแม่นยำเมื่อการออกแบบสิ้นสุดลง TDD สามารถช่วยให้คุณเห็นสิ่งที่คุณพลาดในการออกแบบของคุณช่วยให้คุณสามารถปรับโครงสร้างการออกแบบและการใช้งานและดำเนินการต่อ
Steven Evers

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

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

3

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

คุณไม่สามารถเพิกเฉยสีแดง 30 ครั้งในวงจรสีแดง - เขียว - รีแฟคเตอร์ของคุณ?

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

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

บางครั้งคุณสามารถสร้างการทดสอบการรวมระบบที่เหมาะสมรักษาและลบส่วนที่เหลือ ขึ้นอยู่กับว่าคุณทำงานจากภายในหรือจากบนลงล่างและขั้นตอนขนาดใหญ่ที่คุณใช้


1

ดังที่โรเบิร์ตฮาร์วีย์เพิ่งพูดคุณอาจลองใช้ TDD สำหรับบางสิ่งที่ควรจัดการด้วยเครื่องมือแนวคิดอื่น (นั่นคือ "การออกแบบ" หรือ "การสร้างแบบจำลอง")

ลองออกแบบ (หรือ "model") ระบบของคุณด้วยวิธีที่ค่อนข้างเป็นนามธรรม ("ทั่วไป", "คลุมเครือ") ตัวอย่างเช่นหากคุณต้องสร้างแบบจำลองรถยนต์เพียงแค่มีคลาสรถยนต์ที่มีวิธีการและฟิลด์ที่คลุมเครือเช่น startEngine () และที่นั่งภายใน นั่นคือ: อธิบายสิ่งที่คุณต้องการเปิดเผยต่อสาธารณะไม่ใช่วิธีที่คุณต้องการนำไปใช้ พยายามที่จะเปิดเผยเพียงฟังก์ชั่นพื้นฐาน (อ่าน, เขียน, เริ่ม, หยุด, ฯลฯ ) และปล่อยให้รหัสไคลเอนต์อย่างละเอียดในมัน (PreparMyScene (), killTheEnemy (), ฯลฯ )

จดการทดสอบของคุณโดยถือว่าส่วนต่อประสานแบบสาธารณะที่เรียบง่ายนี้

เปลี่ยนพฤติกรรมภายในของคลาสและวิธีการของคุณเมื่อใดก็ตามที่คุณต้องการ

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

การเปลี่ยน API ไม่ใช่เรื่องผิดปกติ ระบบส่วนใหญ่ในเวอร์ชั่น 1.0 จะเตือนผู้เขียนโปรแกรม / ผู้ใช้อย่างชัดเจนเกี่ยวกับการเปลี่ยนแปลงที่อาจเกิดขึ้นใน API ของตน อย่างไรก็ตามสิ่งนี้การเปลี่ยนแปลง API ที่ต่อเนื่องและไม่มีการควบคุมเป็นสัญญาณที่ชัดเจนของการออกแบบที่ไม่ดี (หรือขาดหายไป)

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


0

ฉันมองจากมุมมองของผู้ใช้ ตัวอย่างเช่นถ้า API ของคุณให้ฉันสร้างวัตถุบุคคลที่มีชื่อและอายุก็ควรมีวิธีการสร้างตัวสร้างบุคคล (ชื่อสตริงอายุ int) และวิธีการเข้าถึงสำหรับชื่อและอายุ ง่ายในการสร้างกรณีทดสอบสำหรับบุคคลใหม่ที่มีและไม่มีชื่อและอายุ

ดั๊ก

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