สามารถใช้วิธีการ TDD จากบนลงล่างได้หรือไม่


13

ฉันไม่ชัดเจนว่า TDD วิธีการจัดการกรณีต่อไปนี้อย่างไร สมมติว่าฉันต้องการใช้อัลกอริทึมการรวมใน Python ฉันเริ่มต้นด้วยการเขียน

assert mergesort([]) === []

และการทดสอบล้มเหลวด้วย

NameError: ไม่ได้กำหนดชื่อ 'การรวม'

ฉันเพิ่มแล้ว

def mergesort(a):
    return []

และการทดสอบของฉันผ่าน ต่อไปฉันเพิ่ม

assert mergesort[5] == 5

และการทดสอบของฉันล้มเหลวด้วย

AssertionError

ซึ่งฉันทำไปด้วย

def mergesort(a):
    if not a:
        return []
    else:
        return a

ต่อไปฉันเพิ่ม

assert mergesort([10, 30, 20]) == [10, 20, 30]

และตอนนี้ฉันต้องพยายามทำบัตรผ่านนี้ ฉัน "รู้" อัลกอริทึมการรวมดังนั้นฉันเขียน:

def mergesort(a):
    if not a:
        return []
    else:
        left, right = a[:len(a)//2], a[len(a)//2:]
        return merge(mergesort(left)), mergesort(right))

และสิ่งนี้ล้มเหลวด้วย

NameError: ไม่ได้กำหนดชื่อ 'ผสาน'

ตอนนี้เป็นคำถาม ฉันจะวิ่งออกไปและเริ่มนำไปmergeใช้โดยใช้ TDD ได้อย่างไร ดูเหมือนว่าฉันจะไม่ได้เพราะผมได้นี้ "แขวน" ไม่ได้ผล, ความล้มเหลวในการทดสอบmergesort, ซึ่งจะไม่ผ่านจนกว่าจะmergeเสร็จสิ้น! หากการทดสอบนี้แฮงค์รอบฉันไม่สามารถทำจริงๆ TDD เพราะผมจะไม่เป็น "สีเขียว" ในช่วงการทำซ้ำ TDD mergeของฉันก่อสร้าง

ดูเหมือนว่าฉันติดอยู่กับสามสถานการณ์ที่น่าเกลียดดังต่อไปนี้และต้องการที่จะรู้ว่า (1) สิ่งใดที่ชุมชน TDD เหล่านี้ชื่นชอบหรือ (2) มีวิธีอื่นที่ฉันขาดหายไปหรือไม่ ฉันเคยดูคำแนะนำเกี่ยวกับ Uncle Bob TDD หลายครั้งแล้วและจำไม่ได้ว่าเคยเห็นกรณีเช่นนี้มาก่อน!

นี่คือ 3 กรณี:

  1. ใช้การผสานในไดเรกทอรีอื่นด้วยชุดการทดสอบที่แตกต่างกัน
  2. ไม่ต้องกังวลเกี่ยวกับการเป็นสีเขียวเมื่อมีการพัฒนาฟังก์ชั่นผู้ช่วยเหลือตนเองเพียงติดตามซึ่งการทดสอบคุณจริงๆต้องการที่จะผ่าน
  3. ใส่ความคิดเห็น (GASP!) หรือลบบรรทัดในการmergesortโทรmergeนั้น หลังจากนั้นmergeไปทำงานให้ใส่พวกเขากลับมา

ทั้งหมดเหล่านี้ดูโง่สำหรับฉัน (หรือฉันกำลังดูผิดนี้หรือไม่) ไม่มีใครรู้วิธีการที่ต้องการ?


2
ส่วนหนึ่งของเป้าหมายของ TDD คือช่วยคุณสร้างการออกแบบซอฟต์แวร์ ส่วนหนึ่งของกระบวนการออกแบบนั้นกำลังค้นหาสิ่งที่จำเป็นในการสร้างผลลัพธ์ที่ต้องการ ในกรณีของmergesortเนื่องจากมันเป็นอัลกอริธึมที่กำหนดไว้ดีมากกระบวนการค้นหานี้จึงไม่จำเป็นและจากนั้นจะกลายเป็นเรื่องของการทำแผนที่สิ่งที่คุณรู้อยู่แล้วว่าเป็นการออกแบบให้กับชุดการทดสอบหน่วยต่างๆ สันนิษฐานว่าการทดสอบระดับบนสุดของคุณยืนยันว่าวิธีการของคุณภายใต้การทดสอบยอมรับคอลเลกชันที่ไม่เรียงลำดับและส่งคืนหนึ่งการเรียงลำดับ ...
Robert Harvey

1
... การทดสอบหน่วยที่ตามมาก็จะค่อย ๆ mergesortขุดลึกลงกลศาสตร์จริงของ หากคุณกำลังมองหาวิธี "ถูกต้อง" ในการทำสิ่งนี้ไม่มีวิธีอื่นนอกจากความแม่นยำในการทำแผนที่mergesortอัลกอริทึมของคุณไปยังชุดการทดสอบหน่วยต่างๆ เช่นพวกเขาควรสะท้อนสิ่งที่mergesortจริงทำ
Robert Harvey

4
การออกแบบไม่ได้เติบโตจากการทดสอบหน่วยเพียงอย่างเดียว หากคุณคาดหวังว่าการmergesortออกแบบจะเกิดขึ้นเองตามธรรมชาติจากสีแดง - เขียว - refactor นั้นจะไม่เกิดขึ้นถ้าคุณไม่แนะนำกระบวนการตามความรู้ที่มีอยู่ของmergesortคุณ
Robert Harvey

3

1
ใน TDD mergeจะต้องคิดค้นในขั้นตอน "refactoring" เท่านั้น หากคุณเห็นmergeวิธีการนั้นสามารถนำมาใช้สำหรับการผ่านการทดสอบของmergesortคุณก่อนอื่นให้ทำการทดสอบผ่านโดยไม่มีmergeวิธีการ จากนั้นปรับโครงสร้างการใช้งานของคุณโดยการแนะนำmergeวิธีการ
Fabio

คำตอบ:


13

นี่คือวิธีอื่นในการดูตัวเลือกของคุณ แต่ก่อนอื่นกฎของ TDD จากลุงบ๊อบโดยฉันให้ความสำคัญ:

  1. คุณไม่ได้รับอนุญาตให้เขียนรหัสการผลิตใด ๆ เว้นแต่ว่าจะทำการทดสอบหน่วยที่ล้มเหลว
  2. คุณไม่ได้รับอนุญาตให้เขียนการทดสอบหน่วยเกินกว่าที่จะล้มเหลว และความล้มเหลวในการรวบรวมเป็นความล้มเหลว
  3. คุณไม่ได้รับอนุญาตให้เขียนรหัสการผลิตมากกว่าที่เพียงพอที่จะผ่านการทดสอบหน่วยที่ล้มเหลว

ดังนั้นวิธีหนึ่งในการอ่านกฎข้อที่ 3 คือคุณต้องใช้mergeฟังก์ชันเพื่อผ่านการทดสอบเพื่อให้คุณสามารถใช้งานได้ - แต่อยู่ในรูปแบบพื้นฐานที่สุดเท่านั้น

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

การตีความอีกอย่างก็คือคุณกำลังเขียนการรวมกันคุณรู้ว่าคุณจะต้องมีmergeการดำเนินการ (เช่นไม่ใช่ YAGNI ซึ่งเป็นสิ่งที่กฎ "เพียงพอ" จะพยายามกำจัด) ดังนั้นคุณควรเริ่มต้นด้วยการทดสอบการผสานและดำเนินการทดสอบการเรียงลำดับโดยรวมเท่านั้น


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

@ RayToal - จริง ๆ แล้วฉันพึ่งพาวิธีการทดสอบการmergeดำเนินการอย่างเต็มที่ก่อนที่จะทำการเรียงลำดับ (เช่นเดียวกับการทดสอบแยกการpartitionดำเนินการ) ฉันคิดว่าประโยชน์ที่ได้รับจากการออกแบบมาจากการทำงานอย่างช้า ๆ ไปสู่เป้าหมายที่ทราบ ในกรณีของการรวมฉันไม่คิดว่าเป้าหมายจะเรียงลำดับโดยทั่วไป (เพราะคุณจะจบลงด้วยการจัดเรียงฟอง) คุณรู้การดำเนินงานขั้นพื้นฐานดังนั้นคุณจึงมุ่งไปสู่การปฏิบัติงานเหล่านั้น การเรียงลำดับเป็นส่วนใหญ่ภายหลัง
kdgregory

1
มีตัวเลือกออกมา ผ่านmergeฟังก์ชั่นmergesortและเยาะเย้ยพฤติกรรมของมัน จากนั้นย้อนกลับและดำเนินการmergeทดสอบก่อน ผู้ได้รับมอบหมายนั้นยอดเยี่ยม™
RubberDuck

@RubberDuck การเยาะเย้ยส่วนที่สำคัญของโดเมนหลักอาจนำไปสู่ปัญหาบางอย่างโดยเฉพาะอย่างยิ่งเมื่อคุณเรียกใช้โปรแกรมและฟังก์ชันการเยาะเย้ยและผสานจะแตกต่างกันในรายละเอียดน้อยที่สุด วิธีการเช่นนั้นควรถูกทิ้งไว้สำหรับอินสแตนซ์ที่คุณทำงานกับทรัพยากรภายนอกเช่นจากที่รายการเรียงลำดับมาจาก
cllamach
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.