TDD - Outside In vs Inside Out


53

อะไรคือความแตกต่างระหว่างการสร้างแอปพลิเคชันOutside Inกับการสร้างInside Outโดยใช้ TDD

นี่คือหนังสือที่ฉันอ่านเกี่ยวกับ TDD และการทดสอบหน่วย:
การทดสอบพัฒนาขับเคลื่อน: โดยตัวอย่าง
การพัฒนาขับเคลื่อนทดสอบ: คู่มือปฏิบัติ: แนวทางปฏิบัติ: แนวทางปฏิบัติ
โซลูชั่นโลกแห่งความจริงสำหรับการพัฒนา PHP Framework คุณภาพสูงและ
การพัฒนาทดสอบขับเคลื่อนแอพพลิเคชันใน Microsoft
รูปแบบการทดสอบNET xUnit: รหัสการทดสอบการปรับ
โครงสร้างใหม่ศิลปะการทดสอบหน่วย: ด้วยตัวอย่างใน. Net
การพัฒนาซอฟต์แวร์เชิงวัตถุแนะนำโดยการทดสอบ ---> อันนี้ยากที่จะเข้าใจจริงๆเพราะ JAVA ไม่ใช่ภาษาหลักของฉัน :)

เกือบทั้งหมดอธิบายถึงพื้นฐานของ TDD และการทดสอบหน่วยโดยทั่วไป แต่ด้วยการกล่าวถึงเพียงเล็กน้อยถึงวิธีต่างๆในการสร้างแอปพลิเคชัน

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

อย่างไรก็ตามฉันเจอย่อหน้าในรูปแบบการทดสอบ xUnit ที่กล่าวถึงวิธีการที่ผู้คนเข้าหา TDD มี 2 โรงเรียนออกมีนอกใน VS Inside Out

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


ทั้งสองวิธีจะมีคำอธิบายในเว็บไซต์รูปแบบ xUnit ทดสอบ: xunitpatterns.com/Philosophy%20Of%20Test%20Automation.html มันแปลกที่พวกเขาไม่ได้อยู่ในหนังสือ
guillaume31

คำตอบ:


45

ภายในออกนอกและในเงื่อนไขที่หายากค่อนข้างบ่อยขึ้นผมเคยได้ยิน / อ่านข้อมูลเกี่ยวกับโรงเรียนคลาสสิกและโรงเรียนลอนดอน

  • Inside-Out (โรงเรียนคลาสสิก, จากล่างขึ้นบน ): คุณเริ่มต้นที่ระดับองค์ประกอบ / คลาส (ภายใน) และเพิ่มการทดสอบตามความต้องการ เมื่อโค้ดวิวัฒนาการ (เนื่องจากการปรับโครงสร้างใหม่) ผู้ทำงานร่วมกันใหม่การโต้ตอบและส่วนประกอบอื่น ๆ จะปรากฏขึ้น TDD เป็นแนวทางในการออกแบบอย่างสมบูรณ์

  • Outside-In (โรงเรียนในลอนดอน, จากบนลงล่างหรือ"ผู้เยาะเย้ย TDD"ตามที่ Martin Fowler จะเรียกมันว่า): คุณรู้เกี่ยวกับการโต้ตอบและการร่วมมือกันโดยเฉพาะ (โดยเฉพาะผู้ที่อยู่ในระดับสูงสุด) และเริ่มต้นที่นั่น ด้วยทุกองค์ประกอบที่เสร็จแล้วคุณย้ายไปยังผู้ทำงานร่วมกันที่ล้อเลียนก่อนหน้านี้และเริ่มต้นด้วย TDD อีกครั้งที่นั่นสร้างการใช้งานจริง (ซึ่งแม้ว่าจะใช้แล้วก็ไม่จำเป็นต้องใช้มาก่อนด้วยabstractions ) โปรดทราบว่าวิธีการจากภายนอกเข้ากันได้ดีกับหลักการYAGNI

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

ไม่ว่าคุณจะใช้อะไรบ่อยกว่านั้นจะเป็นสถานการณ์

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


2
น่าสนใจ คุณสรุปได้ว่าข้างนอกใน TDD คือ "ผู้เยาะเย้ย" TDD? ฉันชอบความคิดและการออกแบบจากภายนอกมากและการทดสอบ (ดูsoftwareonastring.com/2015/01/10/… ) บทความของ Fowler ทำให้ฉันมี Fowler ในค่ายคลาสสิคอย่างแน่นหนา ในขณะที่ผู้เยาะเย้ยอาจใช้วิธีการจากภายนอก แต่คุณไม่สามารถพลิกกลับและบอกว่าการออกแบบและการทดสอบจากภายนอกเป็นการเยาะเย้ย TDD ข้างนอกสามารถเป็นอย่างมากและมีการฝึกฝนโดย TDD-ers คลาสสิกเช่นกัน
Marjan Venema

@jimmy_keen - ด้วยภายนอกคุณทำในจุดใดแทน mocks ในการทดสอบระดับที่สูงขึ้นด้วยการใช้งานจริงที่สร้างขึ้นในภายหลัง? หรือคุณปล่อยให้พวกเขาเป็นการอ้างอิงที่เยาะเย้ยแล้วออกกำลังกายรหัสการผลิตทั้งหมดเป็นการทดสอบการรวม?
thehowler

1
ฉันไม่เห็นด้วยที่เกี่ยวข้องกับ Classic / Mockist และ Inside-Out / Outside-In พวกเขาเป็นมุมฉาก คุณสามารถใช้ Inside-Out / Outside-In ได้เช่นกัน
Daniel Kaplan

เห็นด้วยกับแดเนียล คุณกำลังเปรียบเทียบสอง taxonomies ที่แตกต่างกัน แม้ว่าการพัฒนาจากภายนอกมักเกี่ยวข้องกับโรงเรียนในลอนดอน (ผู้เยาะเย้ย) แต่ก็ไม่ได้เป็นเช่นนั้นเสมอไป
guillaume31

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

15

คำตอบสั้น ๆ :ตามปกติมันจะขึ้นอยู่กับการตั้งค่าการเข้ารหัสและวิธีการของทีมของคุณ

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

ฉันเชื่อว่าทั้งสองรูปแบบของการพัฒนามีความสำคัญและในความเป็นจริงแล้วมันมีประโยชน์ในการผสมผสานสไตล์ในทีม แนวคิดก็คือข้างในออกมานั้นยอดเยี่ยมสำหรับการสร้างแบบก่อสร้างและภายนอกในการคิดให้โครงสร้างและทิศทางของแบบฟอร์ม

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


8

คุณควรเพิ่มAgile Prinicples รูปแบบและการปฏิบัติใน C #ลงในรายการนั้น ฉันไม่รู้ว่าทำไมเขาถึงติด "ใน C #" ในตอนท้าย หนังสือไม่ใช่ภาษาที่ทุกคนและเหตุผลเดียวที่ทำให้มันไม่ได้รับ 5 ดาวในอเมซอนนั้นมาจากคนที่ผิดหวังในภาษา C # -ness จากตัวอย่างของเขา

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

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

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


7

อย่างที่ฉันเห็นมันแนวคิดของการพัฒนาภายนอกมีการแพร่กระจายใน 2 ระดับ Gerard Meszaros อธิบายสั้น ๆว่า " การออกแบบภายนอก - ด้านใน" และ " การเข้ารหัสภายนอก - ใน / นอก - ออก"

  • ระดับแรกคือระดับองค์กรและระดับกระบวนการ การออกแบบภายนอกมีความหมายเมื่อเทียบกับแบบบนลงล่าง (น้ำตก / เทย์เลอร์) และจากล่างขึ้นบน ด้วยวิธีการจากภายนอกเรามุ่งเน้นไปที่มุมมองของผู้ใช้ เราเริ่มต้นด้วยการทดสอบเรื่องราวการทดสอบ ATDD หรือ BDD และไปที่การทดสอบทางเทคนิคที่อนุมานและรหัส ดังนั้นการออกแบบภายนอกคือสิ่งที่คุณต้องทำในบริบทของ Agile Dan North มีการพูดคุยที่ยอดเยี่ยมเกี่ยวกับ BDD แนวทางจากบนลงล่างล่างขึ้นบนและนอก

  • ระดับที่สองเป็นเรื่องทางเทคนิคและเกี่ยวข้องกับชั้นการสมัคร โดยทั่วไปการเข้ารหัสนอกหมายถึงเริ่มต้นจาก UI และเข้าสู่ชั้นกลาง (โดยทั่วไปคือชั้นธุรกิจ / โดเมน) มันมีความหมายซึ่งตรงข้ามกับการเข้ารหัส Inside-Out ซึ่งเริ่มต้นจากชั้นกลางและการเข้ารหัสชั้นภายนอกที่ผ่านมา

ดังนั้นคุณสามารถออกแบบภายนอกด้วยการเข้ารหัสภายนอกหรือเข้ารหัสภายนอก

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

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

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

โรเบิร์ต "ลุงบ๊อบ" มาร์ตินกล่าวสั้น ๆ ว่าการเขียนโค้ดจากภายในและวิธีการที่ไม่จำเป็นต้องขัดแย้งกับสถาปัตยกรรมที่แยกจากกันในโพสต์ของเขา " สถาปัตยกรรมสะอาด "

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