รหัสของฉันควรเป็น DRY หรือสามารถอ่านได้ถ้ามันไม่สามารถเป็นได้ทั้งคู่?


14

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

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

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

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

จนถึงตอนนี้ฉันมักจะเน้นรหัสรัดกุมมากกว่ารหัสที่อ่านได้


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

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

2
ไม่ซ้ำกัน กระชับโวลต์ที่อ่านได้และ DRY โวลต์ที่อ่านได้เป็นการเปรียบเทียบสองแบบที่แตกต่างกันมาก การไม่เป็น DRY นั้นอันตรายกว่าการรัดกุมมาก
djechlin

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

ฉันไม่เข้าใจสิ่งที่คุณหมายถึงโดย "ฟังก์ชั่นระดับสูงของการใช้คีย์เข้ารหัสกับข้อความ" หากคุณหมายความว่ามีการทับซ้อนกันระหว่างการเข้ารหัสและถอดรหัสให้พิจารณาใช้การแยกวิธีการแยกสัดส่วนเพื่อแยกส่วนที่พบบ่อยออก
Aaron Kurtzhals

คำตอบ:


20

DRY เป็นแนวทางไม่ใช่ศาสนา ผู้ที่นำไปยังจุดที่แห้งเหนือสิ่งอื่นใดได้นำมาไกลเกินไป

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

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

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

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


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

1
@lutze ฉันเป็น Perl และบางครั้งก็ทับทิม coder และแน่นอนสามารถเข้าใจสิ่งล่อใจในการเขียนรหัสฉลาดในนั้น รุ่นก่อนโพสต์ของคำตอบนี้รวมถึงคำพูดจาก Larry Wall ในความโอหัง - ฉันเชื่อว่านี่เป็นคุณธรรมที่สำคัญมากเมื่อทำงานกับรหัสที่จะรักษาวัน เนื่องจากความเป็นไปได้ที่ยากของภาษาบางครั้งจึงเป็นเรื่องยากที่จะได้รับประโยชน์จากการเขียนโค้ดมากกว่าที่จะลองใช้รหัสที่หนาแน่นอย่างชาญฉลาด ... จนกว่าคุณจะต้องรักษามันไว้

17

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

ที่นี่ฉันไม่แน่ใจว่าเรื่องใหญ่สำหรับตัวอย่างนี้คืออะไร ทำให้ฟังก์ชั่นการเข้ารหัส, ฟังก์ชั่นการถอดรหัส, ผู้ช่วยสำหรับการทำงานทั่วไป (mix bytes) และส่วนหน้าแบบง่าย ๆ ในการป้อนข้อมูลและตรวจสอบการเข้ารหัส / ถอดรหัส ... ไม่ต้องทำซ้ำตัวเอง

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

หากกดฉันต้องการอ่าน รหัสซ้ำยังสามารถทดสอบได้ - รหัสที่อ่านไม่ได้นำไปสู่การที่คุณทำ (และการทดสอบ) สิ่งที่ผิด


คะแนนที่ดีฉันได้รวมหลักการ DRY เข้ากับเป้าหมายของรหัสที่รัดกุม
lutze

12

ฉันไม่คุ้นเคยกับกรณีเฉพาะของคุณ แต่สามารถให้แนวทางทั่วไปบางอย่างได้

วัตถุประสงค์ของทั้งการอ่านและ DRY คือการบำรุงรักษาการบำรุงรักษา

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

น่าเสียดายที่ DRY มักเข้าใจผิด นี่เป็นส่วนหนึ่งเพราะมันดูเรียบง่าย แต่ก็เหมือนกับสิ่งเรียบง่ายมากมายที่สามารถซับซ้อนได้ ... ซับซ้อน

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

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

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

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

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

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

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

ในความสับสนคำตอบสำหรับคำถามของคุณคือทำทุกสิ่งที่ทำให้รหัสของคุณสามารถบำรุงรักษาได้มากที่สุด ความหมายในสถานการณ์ของคุณขึ้นอยู่กับคุณในการตัดสินใจ


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

+1 ขณะนี้ฉันกำลังจัดการกับระบบที่ละเมิดการคัดลอกและวางในระดับที่ไร้สาระ แยกออกเป็นวิธีการเดียวจากการคัดลอก / วางรหัสลบมากกว่า 400 บรรทัดจากหนึ่งในชั้นเรียนของฉันในวันนี้ แต่น่าเสียดายที่ผมพบว่ามันเป็นวิธีการ 900 สาย ...
KChaloux

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

7

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

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

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


2

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


0

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


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

0

มากน้อยมาก ๆ ในอาชีพของฉันฉันพบคดีที่ผิดกฎหมายซึ่งทำให้การอ่าน DRY ง่ายขึ้น ทำให้อ่านได้ก่อน บอกชื่ออย่างดี คัดลอกและวางหากจำเป็น

ทีนี้ลองย้อนกลับไปดูจำนวนทั้งสิ้นที่คุณสร้างขึ้นเช่นศิลปินย้อนกลับไปดูภาพวาดของพวกเขา ตอนนี้คุณสามารถระบุการทำซ้ำได้อย่างถูกต้อง

รหัสซ้ำควรถูกปรับเปลี่ยนใหม่ในวิธีการของตัวเองหรือดึงออกมาในชั้นเรียนของตัวเอง

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

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