ทำไมเขียนการทดสอบสำหรับรหัสที่ฉันจะ refactor


15

ฉันกำลังปรับโครงสร้างคลาสรหัสเดิมอีกครั้ง Refactoring (ฉันเข้าใจ) สนับสนุนสิ่งนี้:

  1. เขียนแบบทดสอบสำหรับคลาสดั้งเดิม
  2. refactor heck ออกจากชั้นเรียน

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

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

นั่นคือเหตุผลที่แท้จริงในการเขียนการทดสอบก่อน refactor - เพื่อช่วยให้ฉันเข้าใจรหัสได้ดีขึ้น? จะต้องมีเหตุผลอื่น!

กรุณาอธิบาย!

บันทึก:

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


1
หลักฐานของคุณไม่ถูกต้อง คุณจะไม่เปลี่ยนการทดสอบ คุณจะเขียนแบบทดสอบใหม่ ขั้นตอนที่ 3 จะเป็น "ลบการทดสอบใด ๆ ที่หมดอายุแล้ว"
pdr

1
ขั้นตอนที่ 3 สามารถอ่าน "เขียนการทดสอบใหม่ลบการทดสอบที่หมดอายุ" ฉันคิดว่ามันยังคงมีจำนวนมากที่จะทำลายงานต้นฉบับ
Dennis

3
ไม่คุณต้องการเขียนการทดสอบใหม่ในระหว่างขั้นตอนที่ 2 และใช่ขั้นตอนที่ 1 จะถูกทำลาย แต่มันเสียเวลาหรือเปล่า? ไม่เพราะช่วยให้คุณมั่นใจได้ว่าคุณไม่ได้ทำอะไรเลยในระหว่างขั้นตอนที่ 2 การทดสอบใหม่ของคุณไม่
pdr

3
@Dennis - ในขณะที่ฉันแบ่งปันความกังวลแบบเดียวกับที่คุณมีเกี่ยวกับสถานการณ์เราสามารถพิจารณาความพยายาม refactoring ส่วนใหญ่เป็น "การทำลายงานต้นฉบับ" แต่ถ้าเราไม่เคยทำลายมันเราจะไม่ย้ายออกจากสปาเก็ตตี้โค้ดด้วยบรรทัด 10k ในหนึ่งเดียว ไฟล์. อาจเหมือนกันสำหรับการทดสอบหน่วยพวกเขาไปจับคู่กับรหัสที่พวกเขากำลังทดสอบ เมื่อโค้ดวิวัฒนาการและสิ่งต่าง ๆ ถูกย้ายและ / หรือถูกลบดังนั้นหน่วยการทดสอบควรพัฒนาขึ้น
DXM

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

คำตอบ:


46

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

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

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

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


6
+1 อ่านใจเขียนคำตอบ จุดสำคัญ: คุณอาจต้องเขียนการทดสอบหน่วยเพื่อแสดงให้เห็นว่าข้อผิดพลาดเดิมยังคงมีอยู่หลังจากการปรับโครงสร้างใหม่!
david.pfx

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

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

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

2
จากการแก้ไขข้อผิดพลาดต่าง ๆ ในขณะที่ทำการ refactoring ฉันพบว่าฉันจะไม่ทำโค้ดเคลื่อนไหวอย่างง่ายดายโดยไม่ต้องทำการทดสอบ การทดสอบเตือนฉันถึงความแตกต่างเชิงพฤติกรรม / หน้าที่ที่ฉันแนะนำโดยเปลี่ยนรหัสของฉัน
Dennis

7

อารักษาระบบดั้งเดิม

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

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

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

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

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

นอกจากนี้การรักษาความรู้ของระบบเดิมเนื่องจาก "ความรู้ชั่วคราว" นั้นยังไม่เป็นไปด้วยดี การรู้วิธีที่เคยทำมาก่อนหน้านี้มีความสำคัญเมื่อพูดถึงระบบมรดก มีประโยชน์อย่างมากสำหรับคำถามเก่า ๆ ที่ว่า "ทำไมจึงเป็นเช่นนั้น"


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

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

4

คำตอบ / ความเข้าใจของฉันเอง:

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

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

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

UPDATE

ทีนี้ตอนนี้ฉันเปลี่ยนการทดสอบเป็นจำนวนมาก: / เพราะฉันได้ปรับฟังก์ชั่นดั้งเดิมออกใหม่ (ลบฟังก์ชั่นและสร้างคลาส Cleaner ใหม่แทนย้ายขนปุยที่เคยอยู่ในฟังก์ชั่นนอกคลาสใหม่) ดังนั้นตอนนี้ code-under-test ที่ฉันรันก่อนใช้ในพารามิเตอร์ที่แตกต่างกันภายใต้ชื่อคลาสที่แตกต่างกันและสร้างผลลัพธ์ที่แตกต่างกัน (โค้ดต้นฉบับที่มีปุยมีผลการทดสอบมากกว่า) ดังนั้นการทดสอบของฉันต้องสะท้อนการเปลี่ยนแปลงเหล่านี้และโดยทั่วไปฉันจะเขียนการทดสอบของฉันเป็นสิ่งใหม่

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


ฟังดูเหมือนคุณออกแบบแอปพลิเคชั่นอีกครั้งพร้อมปรับโครงสร้างอีกครั้ง
JeffO

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

3

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

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

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


ย่อหน้าแรกของคุณดูเหมือนจะไม่สนับสนุนขั้นตอนที่ 1 และเขียนข้อสอบขณะที่เขาไป ย่อหน้าที่สองของคุณดูเหมือนจะขัดแย้งกัน
pdr

อัปเดตคำตอบของฉัน
Michael Durrant

2

เป้าหมายของการเปลี่ยนโครงสร้างในกรณีเฉพาะของคุณคืออะไร?

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

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

  • การทดสอบจะช่วยให้คุณมั่นใจได้ว่างานใหม่ของคุณใช้งานได้จริง

  • การทดสอบอาจจะเปิดเผยกรณีที่งานต้นฉบับไม่ทำงาน

แต่คุณจะทำจริงๆ refactoring อย่างมีนัยสำคัญใด ๆ โดยไม่ส่งผลต่อพฤติกรรมการบางการศึกษาระดับปริญญา?

นี่คือรายการสั้น ๆ ของบางสิ่งที่อาจเกิดขึ้นระหว่างการรีแฟคเตอร์:

  • เปลี่ยนชื่อตัวแปร
  • เปลี่ยนชื่อฟังก์ชั่น
  • เพิ่มฟังก์ชั่น
  • ฟังก์ชั่นลบ
  • แยกฟังก์ชั่นเป็นสองฟังก์ชั่นหรือมากกว่า
  • รวมสองฟังก์ชั่นขึ้นไปไว้ในฟังก์ชั่นเดียว
  • ชั้นแยก
  • รวมชั้นเรียน
  • เปลี่ยนชื่อคลาส

ฉันจะเถียงว่าทุกกิจกรรมที่แสดงรายการนั้นเปลี่ยนแปลงพฤติกรรมในบางวิธี

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

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

เกี่ยวกับสถานการณ์นี้:

  • เข้าใจว่าคุณมี function bar()

  • function foo() ทำให้การโทร bar()

  • function flee() ยังทำให้การเรียกใช้ฟังก์ชัน bar()

  • เพียงเพื่อความหลากหลายflam()โทรไปfoo()

  • ทุกอย่างทำงานได้อย่างยอดเยี่ยม (อย่างน้อยก็เห็นได้ชัด)

  • คุณ refactor ...

  • bar() ถูกเปลี่ยนชื่อเป็น barista()

  • flee() เปลี่ยนเป็นสายแล้ว barista()

  • foo()จะไม่เปลี่ยนไปโทรbarista()

เห็นได้ชัดว่าการทดสอบของคุณสำหรับทั้งสองfoo()และflam()ตอนนี้ล้มเหลว

บางทีคุณอาจไม่รู้foo()ตัวbar()ตั้งแต่แรก แน่นอนคุณไม่ทราบว่าflam()ขึ้นอยู่กับโดยวิธีการbar()foo()

อะไรก็ตาม ประเด็นก็คือว่าการทดสอบของคุณจะค้นพบพฤติกรรมเสียใหม่ของทั้งสองfoo()และflam(), ในแฟชั่นที่เพิ่มขึ้นในระหว่างการทำงาน refactoring ของคุณ

การทดสอบจะช่วยให้คุณปรับโครงสร้างได้ดี

ถ้าคุณไม่มีการทดสอบใด ๆ

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

พิจารณาสถานการณ์อื่น

คุณกำลังสร้างอาคาร

คุณสร้างนั่งร้านเพื่อช่วยให้มั่นใจว่าอาคารนั้นสร้างขึ้นอย่างถูกต้อง

นั่งร้านช่วยให้คุณสร้างเพลาลิฟท์เหนือสิ่งอื่นใด หลังจากนั้นให้คุณนั่งร้านลง แต่เพลาลิฟต์ยังคงอยู่ คุณได้ทำลาย "งานต้นฉบับ" โดยการทำลายการนั่งร้าน

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

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