การใช้รหัสที่ดีคืออะไรเมื่อทำฟังก์ชั่น / วิธีการสำหรับส่วนรหัสซ้ำขนาดเล็ก?


12

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

คำตอบ:


29

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

ตัวอย่างเช่นใน "Clean Code" Robert C. Martin ให้ตัวอย่างต่อไปนี้: คุณอยากเห็นอันไหน นี้:

// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) &&
    (employee.age > 65))

หรือสิ่งนี้

if (employee.isEligibleForFullBenefits())

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

ฉันไม่เคยเสียใจที่ต้องใส่อะไรในฟังก์ชั่นและถ้าคุณกังวลเกี่ยวกับการแสดง


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

11
ฉันรักตัวอย่างนี้ ทันใดนั้นคุณไม่ต้องการความคิดเห็นนั้นอีกต่อไป นี่เป็นกฎง่ายๆหากความคิดเห็นของคุณสามารถแปลงเป็นชื่อตัวแปรหรือฟังก์ชั่นทำมันได้!
Karoly Horvath

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

+1 รหัสประเภทนี้อาจจะเร็วกว่านี้อย่างน้อยก็ต้องเป็น JIT-ed - คุณจะจ่ายเฉพาะค่าที่คุณใช้
งาน

1
ยังเป็นที่รู้จักเจตนาชื่อเปิดเผย
rwong

13

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


1
ดูความยาวของโปรแกรมเมอร์ที่จะไปเพื่อหลีกเลี่ยงการเขียนความคิดเห็น?
Alger

1
@Alger เท่าที่ควร
MatrixFrog

6

หากมีการใช้งานมากกว่าหนึ่งแห่งและ

  • อาจมีการเปลี่ยนแปลงหรือ
  • มันยากที่จะทำถูก

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


3
คำถามคือทำไมคุณไม่เขียนฟังก์ชั่นสำหรับโค้ดซ้ำ ๆ กันถึงแม้ว่ามันจะไม่ใช่เรื่องยากที่จะถูกหรือเปลี่ยน (กฎง่ายๆของฉัน: ถ้ามันซ้ำแล้วซ้ำอีกแล้วเรียกฟังก์ชั่นทำให้มันเป็นฟังก์ชั่น)
Winston Ewert

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

@ Winston: ขึ้นอยู่กับภาษาที่ใช้ ไม่ใช่ทุกสิ่งที่สามารถบันทึกได้ตามธรรมชาติในฐานะที่เป็นฟังก์ชันฟังก์ชันอาจใช้พื้นที่มากกว่ารหัสต้นฉบับ (คิดว่า C และกลับมาจากตัวชี้) การเรียกใช้ฟังก์ชันอาจมีค่าใช้จ่าย
Fred Foo

@ larsman ฉันอยากรู้ว่าคุณหมายถึงอะไรโดย "(คิดว่า C และกลับมาโดยตัวชี้)" แต่สิ่งที่คุณกำลังพูดคือสิ่งที่ฉันพยายามที่จะได้รับด้วยกฎง่ายๆของฉัน การเรียกใช้ฟังก์ชั่นจะต้องง่ายขึ้น (เช่นการจับภาพตามธรรมชาติและการใช้พื้นที่น้อยลง) จากนั้นนำเนื้อหาของฟังก์ชั่น
Winston Ewert

หากมีชิ้นส่วนของรหัสคำนวณค่าหลายพูดfloat x, int yและdouble densityแล้วการตั้งค่าการคำนวณที่เป็นฟังก์ชัน C สามารถพลิกแพลงมากกว่าเพียงแค่การทำซ้ำรหัสเนื่องจากคุณจะต้องประดิษฐ์วิธีที่จะได้รับทั้งสามค่าออก หากการคำนวณซ้ำ ๆ นั้นไม่สำคัญบางครั้งก็เป็นการดีกว่าที่จะปล่อยให้พวกมันอยู่ในแนวเดียวกัน
Fred Foo

4

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

เหตุผลเดียวที่ฉันไม่สามารถทำได้คือการบำรุงรักษา: บางครั้งมันอาจจะสะดวกกว่าที่จะหลีกเลี่ยงการสร้างการพึ่งพาระหว่างสิ่งที่แยกจากกันแม้จะมีค่าใช้จ่ายในการทำซ้ำ


ระวังการพิมพ์เป็ดถ้าตอนนี้มีการใช้งานที่คล้ายกัน แต่ฟังก์ชั่นที่แตกต่างกันได้อย่างมีประสิทธิภาพแล้วการผสานทั้งสองทำให้มันน่ารำคาญเป็นนรกที่จะแยกกลับ โดยเฉพาะอย่างยิ่งในภาษาที่มีการสนับสนุน IDE ไม่ดี (เฮ้ฉันทำงานใน C ++ ... )
Matthieu M.

ในอีกทางหนึ่งโดยแยกพวกเขาออกจากกันคุณมีสองฟังก์ชั่นที่ทำสิ่งเดียวกันเพื่อทดสอบครึ่งหนึ่งของโอกาสในการใช้รหัสของคุณสองที่ซึ่งข้อผิดพลาดเดียวกันอาจคืบคลานขึ้นและคุณต้องจำไว้ว่า ข้อผิดพลาดที่ยังไม่ได้ตรวจพบ ฉันต้องการยังคงทำงานใน C ++, การสนับสนุน IDE ที่น่าสงสารแม้ว่า ;-)
Nicola Musatti

1

การค้นหา " refactoring " จะนำคุณไปสู่แหล่งข้อมูลมากมายสำหรับอุตสาหกรรม "แนวทางปฏิบัติที่ดีที่สุด" สำหรับกระบวนการทั่วไปนี้ บทความที่มีชื่อเสียงบ้างครั้งหนึ่งครั้งเดียวเป็นการอ้างอิงทางประวัติศาสตร์ที่ยิ่งใหญ่ซึ่งอธิบายว่า "แนวปฏิบัติที่ดีที่สุด" สำหรับความกังวลที่เกิดขึ้นจากคำถามของคุณ นอกจากนี้แนวคิดทั่วไปมากขึ้นแม้จะเป็นที่รู้จักกันจะไม่ทำซ้ำตัวเอง (แห้ง) สำหรับคำตอบสำหรับคำถามเชิงลึกของคุณโปรดอ่านการปรับโครงสร้างแบบคลาสสิกที่ยอดเยี่ยมของMartin Fowler : การปรับปรุงการออกแบบของรหัสที่มีอยู่ซึ่งครอบคลุมคำแนะนำที่รู้จักกันดีที่สุดสำหรับการปรับโครงสร้างซึ่งเป็นสิ่งที่คุณพยายามทำให้สำเร็จ !


0

หากรหัสซ้ำหลายครั้งมากกว่าหนึ่งครั้งและส่วนที่ทำซ้ำจะไม่เปลี่ยนแปลงในอนาคตอันใกล้จากนั้นฉันก็แยกออกเป็นฟังก์ชั่น


1
ถ้ามันจะเปลี่ยนไปก็ยิ่งมีเหตุผลมากขึ้นในการปรับโครงสร้างใหม่ จากนั้นคุณจะต้องเปลี่ยนเพียงครั้งเดียว
SHug

0

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

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

ดูบทความวิกิพีเดียแนวคิดของรหัสการทำงานร่วมกัน


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

0

คุณต้องแยกความแตกต่างระหว่างฟังก์ชั่นในการเขียนโปรแกรมที่มีโครงสร้างและวิธีการของชั้นเรียน

ในตัวอย่างของคุณสิ่งที่คุณแสดงเป็นวิธีที่ไม่ควรเขียนโค้ดในบรรทัด

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

ความแตกต่างนี้มีความสำคัญเป็นพิเศษในโครงการขนาดใหญ่

ให้มากที่สุดเท่าที่จะทำได้พยายามแยกกฎธุรกิจ (นั่นคือวิธีการ) ออกจากอัลกอริธึมการคำนวณ

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