รหัสไม่เกี่ยวข้องแห้ง แต่เกือบจะเหมือนกัน


33

ฉันมีรหัสบางอย่างที่เกือบจะเหมือนกัน แต่ใช้ประเภทที่แตกต่างกันอย่างสิ้นเชิงโดยไม่มีการสืบทอดระหว่างตัวแปรหลัก โดยเฉพาะฉันเขียนวิเคราะห์ด้วย Roslyn สำหรับ C # และ VB.NET ด้วยประเภทต่อไปนี้:

Microsoft.CodeAnalysis.CSharp.Syntax.AttributeSyntax Microsoft.CodeAnalysis.VisualBasic.Syntax.AttributeSyntax

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

แก้ไข:หนึ่งปีหรือหลังจากนั้นฉันก็ตีปัญหาเดียวกันนี้และทีม Roslyn ช่วยฉันแก้ปัญหา: เขียนคลาสพื้นฐานที่ใช้ชื่อสามัญและมีTAttributeSyntaxพารามิเตอร์ที่ใช้งานได้เกือบทั้งหมด จากนั้นให้เขียนคลาสที่ได้รับมาพร้อมกับข้อมูลขั้นต่ำสุดที่จำเป็นต้องใช้ประเภทเฉพาะ


มันจะทำงานเพื่อสร้างอินเตอร์เฟซ AttributeSyntax ของคุณเองที่ล้อมชั้นเรียนที่มีอยู่ แต่ให้มรดกที่แนวคิดควรจะมี?
Winston Ewert

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

@Lorehead โดยทั่วไปแล้วฉันจะทำเช่นนั้น แต่นี่เป็นวิธีการเดียวที่ถูกส่งผ่านชนิดที่มีโหนดเป็น payload จากวิธีการภายในฉันไม่สามารถควบคุมได้
Hosch250

@ WinstonEwert ฉันจะดูว่า ฉันไม่แน่ใจว่าฉันต้องการทำเช่นนั้นสำหรับ C # / VB.NET ทุกประเภท
Hosch250

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

คำตอบ:


110

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

โดยเฉพาะจากคำถามนั้น:

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

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

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


ที่ถูกกล่าวว่าเนื่องจากSRPและพยายามที่จะมีคลาสที่เล็กและยืดหยุ่นโดยทั่วไปมันอาจสมเหตุสมผลในการวิเคราะห์โค้ดของคุณด้วยเหตุผลนั้นแยกบิตของพฤติกรรมที่ใช้ประเภททั่วไป (คุณบอกว่าพวกมันเหมือนกันมากกว่าประเภท) ชั้นเรียนขนาดเล็ก แล้วคุณจะพบว่าบางส่วนของชั้นเรียนเหล่านี้เป็นจริงโดยสิ้นเชิงเหมือนกัน (ไม่เพียง แต่ส่วนใหญ่เหมือนกัน) Microsoft.CodeAnalysis.CPlusPlus.Syntax.AttributeSyntaxและจากนั้นคุณสามารถสร้างเครื่องมือในกรณีที่คุณต้องการเพิ่ม


32
TL; DR - DRY หมายถึงจุดจบ มุ่งเน้นไปที่จุดสิ้นสุดไม่ใช่วิธีการ ถ้าฉันสามารถลงคะแนน Lego Man สองครั้งได้

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