มีกรณีพิเศษที่เราสามารถรับรหัสซ้ำได้หรือไม่


57

ฉันกำลังทำงานในโครงการซอฟต์แวร์ที่เราต้องสร้าง API สามตัว หนึ่งสำหรับบ้านธนาคารช่องทางหนึ่งสำหรับหน่วยงานและช่องทางที่สามสำหรับโทรศัพท์มือถือช่อง

API ของเอเจนซีนั้นสมบูรณ์ที่สุดเนื่องจากมีฟังก์ชั่นทั้งหมด .. จากนั้นเป็น Home API ที่เล็กกว่าและ API มือถือ

สถาปนิกที่นี่สร้างเลเยอร์ทั่วไป (บริการ EJB ข้ามแชนเนลที่แชร์โดย API ทั้งหมด) แต่ API นั้นแตกต่างกัน

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

โดยพื้นฐานแล้วคอนโทรลเลอร์กำลังทำการแมป BO กับ ChannelObject (ดูเหมือนว่าฉันไม่ใช่สถานที่ที่เหมาะสมในการทำเช่นนั้น) และยูทิลิตี้และซีเรียลไลเซอร์บางส่วน ทั้งหมดซ้ำกันในตอนนี้ พวกเขาบอกว่าสาเหตุของการทำซ้ำคือพวกเขาต้องการให้ API แยกต่างหาก "ถ้าพรุ่งนี้เราต้องการพฤติกรรมที่แตกต่างสำหรับบ้านมากกว่าเอเจนซี่หรือมือถือเราจะไม่ดิ้นรน !!"

มีกรณีที่เราควรยอมรับรหัสซ้ำหรือไม่


22
และหากสามวันข้างหน้าพวกเขาตัดสินใจว่าพวกเขาต้องการการเข้าถึงข้อมูลที่สอดคล้องกันและการเป็นตัวแทนระหว่าง API ทั้งหมด ... ดี ... "ต่อสู้!"
Becuzz

26
รหัสซ้ำไม่จำเป็นต้องเป็นสิ่งที่ไม่ดี คำว่า "DRY คือศัตรูของ decoupling" ไม่สามารถเน้นได้มากพอมีกล่าวไว้ว่าการออกแบบสำหรับอนาคตมากกว่าตอนนี้จริงๆแล้วมันเป็นสิ่งที่แย่มาก อนาคตนั้นแทบจะไม่เคยผ่านพ้นไป แต่ให้ออกแบบโซลูชันที่แยกออกจากกันอย่างมากโดยครอบคลุมการทดสอบอัตโนมัติที่ดีสำหรับสิ่งที่ต้องการในตอนนี้ จากนั้นในอนาคตหากต้องการสิ่งที่แตกต่างกันมันจะเปลี่ยนได้ง่ายขึ้น
David Arno

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

14
ที่ที่ฉันเคยทำงานก็มักจะสังเกตเห็นว่าควร (ซ้ำ) ควรจะซ้ำหนึ่งครั้งและสรุปความธรรมดาสามัญในครั้งที่สาม สิ่งนี้จะลบZeitgeistสำหรับช่วงต้นอาจเป็นไปได้ว่าสิ่งที่เป็นนามธรรมนั้นเพิ่มการมีเพศสัมพันธ์แทนการทำงานร่วมกัน เมื่อความต้องการในอนาคตเป็นที่เข้าใจกันดีแล้วแน่นอนว่ามีข้อยกเว้น
Pieter Geerkens

3
กรณีเล็ก ๆ น้อย ๆ ที่รหัสซ้ำสามารถยอมรับได้คือถ้ามันถูกสร้างขึ้นโดยอัตโนมัติ
samgak

คำตอบ:


70

การทำสำเนาอาจเป็นสิ่งที่ถูกต้องที่จะทำ แต่ไม่ใช่ด้วยเหตุผลนี้

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

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

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


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

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

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

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

3
@ HagenvonEitzen แต่นั่นก็ไม่จำเป็นต้องซ้ำซ้อนขึ้นอยู่กับเทคโนโลยีสแต็ค ตัวอย่างเช่นคุณอาจมีอินพุตการตรวจสอบ JavaScript ในเบราว์เซอร์จากนั้นตรวจสอบ Java บนเซิร์ฟเวอร์ดังนั้นคุณจึงมีฟังก์ชันการทำงานที่ซ้ำกัน แต่ถ้าคุณต้องเรียกใช้ Node.js บนเซิร์ฟเวอร์คุณสามารถใช้การตรวจสอบ JavaScript เดียวกันในเบราว์เซอร์และบนเซิร์ฟเวอร์โดยกำจัดการทำซ้ำ คุณยังต้องการให้โค้ดทำงานในหลาย ๆ ที่ (สภาพแวดล้อมที่เชื่อถือได้และไม่น่าเชื่อถือ) แต่รหัสนั้นไม่จำเป็นต้องทำซ้ำ
Joshua Taylor

87

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

การทำซ้ำนั้นถูกกว่าการทำผิดที่ผิด

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

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


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

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

34

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

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

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

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

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


3
สัญญาณเตือนภัยที่ยิ่งใหญ่กว่า "ถ้าพรุ่งนี้" สำหรับฉันคือ "นั่นจะไม่มีวันเปลี่ยนแปลง"
abuzittin gillifirca

@abuzittingillifirca: และสิ่งนี้เกี่ยวข้องกับคำถามหรือคำตอบของฉัน?
Doc Brown

1
ฉันขอท้าย่อหน้าแรกของคุณ
abuzittin gillifirca

2
@abuzittingillifirca: ดีอ่านคำถามอีกครั้ง: มันเกี่ยวกับการให้เหตุผลกับอาร์กิวเมนต์ "if tomorrow" สำหรับ justifiying การตัดสินใจสำหรับการทำซ้ำซึ่งเป็นการยากที่จะย้อนกลับเพื่อให้ซอฟต์แวร์จริงยากที่จะเปลี่ยนสำหรับบางกรณี อาจเป็นวิธีที่ใช้งานง่าย แต่วิธีที่ดีที่สุดในการเปลี่ยนแปลงซอฟต์แวร์ในอนาคตคือการไม่ตั้งสมมติฐาน (อาจผิด) เกี่ยวกับอนาคต แต่เพื่อให้ซอฟต์แวร์มีขนาดเล็กและมั่นคงที่สุด
Doc Brown

13

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

ดังนั้นคุณจะจ่ายราคาของรหัสซ้ำเพื่อให้ได้เอกราชและเป็นอิสระ


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

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