ฟังก์ชั่นยาวเกินไปเมื่อไหร่? [ปิด]


130

35 เส้น, 55 เส้น, 100 บรรทัด, 300 บรรทัด? เมื่อไหร่ที่คุณควรเริ่มแยกมันออกจากกัน? ฉันถามเพราะฉันมีฟังก์ชั่นที่มี 60 บรรทัด (รวมถึงความคิดเห็น) และกำลังคิดที่จะแยกมันออกจากกัน

long_function(){ ... }

เป็น:

small_function_1(){...}
small_function_2(){...}
small_function_3(){...}

ฟังก์ชั่นจะไม่ถูกใช้นอก long_function ทำให้ฟังก์ชั่นที่เล็กลงหมายถึงการเรียกใช้ฟังก์ชั่นอื่น ๆ อีกมากมาย

เมื่อไหร่ที่คุณจะแยกฟังก์ชั่นออกเป็นฟังก์ชันย่อย ๆ ? ทำไม?

  1. วิธีการควรทำสิ่งเดียวที่เป็นตรรกะ (คิดเกี่ยวกับการทำงาน)
  2. คุณควรจะสามารถอธิบายวิธีการในประโยคเดียว
  3. ควรพอดีกับความสูงของจอแสดงผลของคุณ
  4. หลีกเลี่ยงค่าใช้จ่ายที่ไม่จำเป็น (ความคิดเห็นที่ชี้ให้เห็นอย่างชัดเจน ... )
  5. การทดสอบหน่วยง่ายขึ้นสำหรับฟังก์ชันตรรกะขนาดเล็ก
  6. ตรวจสอบว่าส่วนหนึ่งของฟังก์ชั่นสามารถนำมาใช้ใหม่โดยชั้นเรียนหรือวิธีการอื่น ๆ
  7. หลีกเลี่ยงการมีเพศสัมพันธ์ระหว่างคลาสมากเกินไป
  8. หลีกเลี่ยงโครงสร้างการควบคุมที่ซ้อนกันอย่างล้ำลึก

ขอบคุณทุกคนสำหรับคำตอบแก้ไขรายการและโหวตให้กับคำตอบที่ถูกต้องฉันจะเลือกแบบนั้น;)

ตอนนี้ฉันกำลังปรับโครงสร้างด้วยความคิดเหล่านั้นในใจ :)


มีคำถามที่พิมพ์ผิดฉันคิดว่าคุณหมายถึง "ฟังก์ชั่นนานเกินไปเมื่อไหร่"
Tom

1
คุณกำลังวางคำถามที่ผิดโดยการวางตัวในรูปของบรรทัดของรหัส ปัจจัยปัจจัยไม่ได้วัดในบรรทัดของรหัส
dkretz

คำถามนี้อาจซับซ้อนขึ้นอยู่กับรหัสและภาษา บางทีคุณสามารถโพสต์ได้
Ray Tayek

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

คำตอบ:


75

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

แม้ว่า "การทำอะไรบางอย่าง" อาจยังคงมีไม่กี่บรรทัดดังนั้นฉันจึงไม่แน่ใจว่ามีหลายบรรทัดที่เป็นตัวชี้วัดที่เหมาะสมที่จะใช้ :)

แก้ไข: นี่เป็นรหัสบรรทัดเดียวที่ฉันส่งไปทำงานเมื่อสัปดาห์ที่แล้ว (เพื่อพิสูจน์จุด .. ไม่ใช่สิ่งที่ฉันสร้างนิสัย :)) - แน่นอนว่าฉันไม่ต้องการเด็กชายเลว 50-60 คนในวิธีการของฉัน : D

return level4 != null ? GetResources().Where(r => (r.Level2 == (int)level2) && (r.Level3 == (int)level3) && (r.Level4 == (int)level4)).ToList() : level3 != null ? GetResources().Where(r => (r.Level2 == (int)level2) && (r.Level3 == (int)level3)).ToList() : level2 != null ? GetResources().Where(r => (r.Level2 == (int)level2)).ToList() : GetAllResourceList();

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

@Maxaxes ส่วนย่อยของโค้ดที่ฉันโพสต์เป็นคำสั่งเดียว แต่ไม่ได้มีหลายบรรทัดในหนึ่งบรรทัด .. ไม่มีเซมิโคลอนอยู่ในนั้น :) ฉันสามารถขยาย GetResources () ออกทุกครั้งเพื่อทำให้มันเลวร้ายยิ่งขึ้น: P
สตีเว่นร็อบบินส์

ใช่ว่าเหมาะสม ทำไมไม่เพียงแค่นำไฟล์ต้นฉบับทั้งหมดของคุณมาวางไว้ในบรรทัดเดียว ฉันหมายความว่าจริงๆแล้วคุณได้รับจะเป็นเว็บ 2.0 "นินจา" :)
BobbyShaftoe

ฉันจำได้ในนิตยสารเก่า (ฉันกำลังพูดถึง BBC Micro แก่) พวกเขาเคยมี "โปรแกรม 10 บรรทัด" ที่เพิ่งมีงบหลายรายการในแต่ละบรรทัดจนถึงความยาวสูงสุดที่ BBC สามารถจัดการ .. พวกเขามักจะเจ็บปวด พิมพ์เป็น: D
Steven Robbins

6
ฉันชอบแนวคิดของฟังก์ชั่นที่ทำเพียงสิ่งเดียว .... แต่ หากคุณมีฟังก์ชั่นที่ทำ 10 สิ่งและคุณย้าย 9 ของสิ่งเหล่านั้นไปยังฟังก์ชั่นแยกที่ยังคงถูกเรียกใช้โดยฟังก์ชั่นที่เหลืออยู่นั้นไม่ใช่ฟังก์ชั่นที่เหลืออยู่ ฉันคิดว่าการแบ่งฟังก์ชั่นแบบนี้ทำให้ง่ายต่อการทดสอบ
mtnpaul

214

นี่คือรายการของธงแดง (ตามลำดับโดยเฉพาะ) ที่อาจบ่งบอกว่าฟังก์ชั่นยาวเกินไป:

  1. โครงสร้างการควบคุมที่ซ้อนกันอย่างลึกล้ำ : เช่น for-loops 3 ระดับความลึกหรือเพียงแค่ 2 ระดับความลึกพร้อมคำสั่ง if-nested ที่มีเงื่อนไขที่ซับซ้อน

  2. พารามิเตอร์กำหนดสถานะมากเกินไป : โดยพารามิเตอร์กำหนดสถานะฉันหมายถึงพารามิเตอร์ฟังก์ชันที่รับประกันพา ธ การดำเนินการเฉพาะผ่านฟังก์ชัน รับพารามิเตอร์ประเภทนี้มากเกินไปและคุณมีการระเบิดของเส้นทางการดำเนินการ combinatorial (ซึ่งมักเกิดขึ้นควบคู่กับ # 1)

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

  4. การมีเพศสัมพันธ์มากเกินไประหว่างคลาส : การขาดการห่อหุ้มที่เหมาะสมส่งผลให้ฟังก์ชั่นที่เกี่ยวข้องกับลักษณะที่ใกล้ชิดของคลาสอื่น

  5. ค่าใช้จ่ายที่ไม่จำเป็น : ความคิดเห็นที่ชี้ให้เห็นชัดว่าคลาสที่ซ้อนกันอย่างลึกล้ำ getters ฟุ่มเฟือยและ setters สำหรับตัวแปรคลาสที่ซ้อนกันแบบไพรเวตและชื่อฟังก์ชัน / ตัวแปรที่ยาวผิดปกติสามารถสร้างเสียง syntactic ภายในฟังก์ชันที่เกี่ยวข้องซึ่งท้ายที่สุดจะเพิ่มความยาว

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

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

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


1
โพสต์ดี! เลวร้ายมาก
ชัคคอนเวย์

2
@PedroMorteRolo อย่างแน่นอน API ของมาตรฐานคือไม่เสมอรูปแบบของความสง่างาม นอกจากนี้ Java API ส่วนใหญ่ยังได้รับการพัฒนาด้วยความรู้อย่างใกล้ชิดของ Java Compiler และ JVM ดังนั้นคุณจะต้องพิจารณาถึงประสิทธิภาพที่อาจอธิบายได้ ฉันยอมรับว่าส่วนที่สำคัญของรหัสที่ไม่สามารถเสียเวลาหนึ่งมิลลิวินาทีอาจต้องทำลายกฎเหล่านี้บางส่วน แต่ควรถือว่าเป็นกรณีพิเศษเสมอ การใช้เวลาในการพัฒนาเพิ่มเติมล่วงหน้าคือการลงทุนครั้งแรกที่สามารถหลีกเลี่ยงหนี้สินทางเทคโนโลยีในอนาคต
Ryan Delucchi

2
โดยวิธีการ .. ฉันมีความเห็นว่าวิธีการระยะยาว - ไม่ดี - heuristic ยังใช้กับชั้นเรียน IMHO คลาสที่ยาวนั้นไม่ดีเพราะพวกเขามักจะละเมิดหลักการความรับผิดชอบเดี่ยว มันจะสนุกกับการมีคอมไพเลอร์ emiting คำเตือนสำหรับชั้นเรียนทั้งยาวและวิธี ....
เปโดรโรโล่

3
@PedroMorteRolo ฉันเห็นด้วยกับสิ่งนี้อย่างแน่นอน นอกจากนี้คลาสขนาดใหญ่มีแนวโน้มที่จะเปลี่ยนแปลงสถานะได้มากกว่าซึ่งนำไปสู่รหัสที่ยากต่อการบำรุงรักษา
Ryan Delucchi

1
คำตอบที่ดีที่สุด เงื่อนงำที่ดีอีกข้อคือความคิดเห็นในโค้ดมีลักษณะอย่างไร // fetch Foo's credentials where Bar is "uncomplete"จำนวนครั้งที่ฉันได้เจอรหัสของใครบางคนที่มีเส้นเช่น: นี่เป็นชื่อฟังก์ชันที่แน่นอนและควรแยกออก อาจต้องการที่จะได้รับการ refactored เป็นสิ่งที่ชอบ: Foo.fetchCredentialWhereBarUncomplete()
เจย์เอ็ดเวิร์ด

28

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


18

ฟังก์ชั่นควรทำเพียงสิ่งเดียวเท่านั้น หากคุณกำลังทำสิ่งเล็ก ๆ มากมายในฟังก์ชั่นให้ทำสิ่งเล็ก ๆ แต่ละฟังก์ชั่นและเรียกฟังก์ชั่นเหล่านั้นจากฟังก์ชั่นยาว

สิ่งที่คุณไม่ต้องการทำคือการคัดลอกและวางทุก ๆ 10 บรรทัดของฟังก์ชั่นยาวของคุณลงในฟังก์ชั่นสั้น ๆ


ใช่ทำฟังก์ชั่นเล็ก ๆ มากมายด้วยรูปแบบการคัดลอกและวางไม่ใช่ความคิดที่ดีฉันยอมรับฟังก์ชั่นควรพยายามทำสิ่ง

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

16

ฉันเห็นด้วยฟังก์ชั่นควรทำสิ่งเดียว แต่ในระดับสิ่งที่เป็นสิ่งที่

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

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

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

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

ฉันเชื่อว่าจุดสำคัญคือการมองหาการใช้ซ้ำในฟังก์ชั่นที่ยาวนานและดึงส่วนเหล่านั้นออก สิ่งที่คุณเหลืออยู่คือฟังก์ชั่นไม่ว่าจะเป็น 10, 20 หรือ 60 บรรทัด


2
+1 "ตัวชี้วัดที่จะใช้คือฟังก์ชั่นและไม่ใช่รหัส"
Cody Piersall

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

10

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

ทำไมฉันถึงเลิกฟังก์ชั่น:

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

3
จุดดีฉันเห็นด้วยถ้าคุณต้องตั้งชื่อฟังก์ชั่นนี้ ขอบคุณ :)

2
คุณเพิ่งจะเลิกกับคู่นี้ 60 บรรทัดจะมากเกินไปเสมอ ฉันว่าถ้าคุณปิดใน 10 บรรทัดคุณอาจใกล้ถึงขีด จำกัด
willcodejavaforfood

แต่ฟังก์ชั่นอื่นยังคงเรียกฟังก์ชั่นเหล่านี้และเป็นDoThisAndThisAndAlsoThisฟังก์ชั่นเดียวกันแต่มีจำนวนมากนามธรรมที่คุณยังต้องตั้งชื่ออย่างใด
ติโม Huovinen

6

ฮิวริสติกส่วนตัวของฉันคือมันนานเกินไปถ้าฉันไม่สามารถมองเห็นสิ่งทั้งหมดโดยไม่เลื่อน


4
... ในขณะที่ได้ตั้งขนาดตัวอักษรถึง 5?
EricSchaefer

5

ขนาดหน้าจอประมาณขนาดของคุณ (เพื่อรับหน้าจอกว้างแบบ pivot ขนาดใหญ่แล้วหมุน) ... :-)

โจ๊กกันสิ่งหนึ่งตรรกะต่อฟังก์ชั่น

และสิ่งที่ดีคือการทดสอบหน่วยทำได้ง่ายกว่าจริง ๆ กับฟังก์ชันตรรกะเล็ก ๆ ที่ทำ 1 สิ่ง ฟังก์ชั่นขนาดใหญ่ที่ทำสิ่งต่าง ๆ ยากต่อการตรวจสอบ!

/ Johan


จุดที่ดีเกี่ยวกับการทดสอบหน่วย :)

5

Rule of thumb: หากฟังก์ชั่นมีรหัสบล็อกที่ทำบางสิ่งบางอย่างที่ค่อนข้างแยกออกจากส่วนที่เหลือของรหัสวางไว้ในฟังก์ชั่นแยก ตัวอย่าง:

function build_address_list_for_zip($zip) {

    $query = "SELECT * FROM ADDRESS WHERE zip = $zip";
    $results = perform_query($query);
    $addresses = array();
    while ($address = fetch_query_result($results)) {
        $addresses[] = $address;
    }

    // now create a nice looking list of
    // addresses for the user
    return $html_content;
}

ดีกว่ามาก:

function fetch_addresses_for_zip($zip) {
    $query = "SELECT * FROM ADDRESS WHERE zip = $zip";
    $results = perform_query($query);
    $addresses = array();
    while ($address = fetch_query_result($results)) {
        $addresses[] = $address;
    }
    return $addresses;
}

function build_address_list_for_zip($zip) {

    $addresses = fetch_addresses_for_zip($zip);

    // now create a nice looking list of
    // addresses for the user
    return $html_content;
}

วิธีนี้มีข้อดีสองประการ:

  1. เมื่อใดก็ตามที่คุณต้องการดึงที่อยู่สำหรับรหัสไปรษณีย์ที่แน่นอนคุณสามารถใช้ฟังก์ชั่นที่ใช้งานได้ง่าย

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

[ในทางกลับกัน (ฉันจะปฏิเสธฉันบอกคุณว่าแม้จะถูกทรมาน): ถ้าคุณอ่านมากเกี่ยวกับ PHP optimization คุณสามารถรับความคิดที่จะรักษาจำนวนฟังก์ชั่นให้น้อยที่สุดเพราะการเรียกฟังก์ชั่นนั้นดีมาก แพงมากใน PHP ฉันไม่รู้เกี่ยวกับสิ่งนั้นตั้งแต่ฉันไม่เคยทำเกณฑ์มาตรฐานใด ๆ หากเป็นเช่นนั้นคุณอาจจะดีกว่าที่จะไม่ทำตามคำตอบของคำถามของคุณหากแอปพลิเคชันของคุณเป็น "ประสิทธิภาพที่อ่อนไหว" ;-)]


ขอบคุณตัวอย่างที่ดี :) ฉันจะ google สำหรับเกณฑ์มาตรฐานฟังก์ชั่นใน php

5

ลองดูที่ cyclomatic ของ McCabe ซึ่งเขาแบ่งรหัสของเขาออกเป็นกราฟโดยที่ "แต่ละโหนดในกราฟตรงกับบล็อกของรหัสในโปรแกรมที่การไหลเป็นลำดับและส่วนโค้งสอดคล้องกับกิ่งที่อยู่ในโปรแกรม "

ตอนนี้คิดว่าโค้ดของคุณไม่มีฟังก์ชั่น / วิธีการ มันแผ่กิ่งก้านสาขาขนาดใหญ่เพียงหนึ่งเดียวในรูปของกราฟ

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

ในการกำหนดขนาดของวิธีการที่คุณควรใช้ในแง่ของจำนวนบล็อกต่อวิธีหนึ่งคำถามที่คุณอาจถามตัวเองคือ: ฉันควรจะต้องมีวิธีการลดจำนวนการพึ่งพา (MPE) ระหว่างบล็อกทั้งหมดเท่าไหร่?

คำตอบนั้นได้มาจากสมการ ถ้า r คือจำนวนวิธีที่ลด MPE ของระบบให้น้อยที่สุดและ n คือจำนวนบล็อกในระบบดังนั้นสมการคือ: r = sqrt (n)

และสามารถแสดงให้เห็นว่าสิ่งนี้ทำให้จำนวนบล็อกต่อวิธีเป็นเช่นกัน, sqrt (n)


4

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

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

ดังนั้นมนต์ของตัวเองกลายเป็น: ถ้าคุณไม่สามารถคิดชื่อฟังก์ชั่น / วิธีการที่ดีสำหรับชิ้นของรหัสที่คุณกำลัง re-factoring ไม่ต้องกังวล


2

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

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

คุณแน่ใจหรือว่าไม่มีชิ้นส่วนใดที่จะมีประโยชน์ในที่อื่น? มันคือฟังก์ชั่นอะไร?


ฟังก์ชั่นนี้สร้างไฟล์แคชจากเทมเพลตโดยยึดตาม url เช่น post_2009_01_01.html จาก url / post /

2

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


2

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


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

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

ฉันเพิ่งเจอคำตอบนี้: stackoverflow.com/questions/406760/…ระบุว่า "ความคิดเห็นส่วนใหญ่ในรหัสในความเป็นจริงเป็นรูปแบบของการทำซ้ำรหัสอันตราย" นอกจากนี้ - มีสายยาวของความคิดเห็นที่นั่น
Olaf Kock

1

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

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

ฉันไม่ทราบว่ามีคำตอบที่ถูกหรือผิด (เช่นคุณอาจใช้จำนวนสูงสุดของบรรทัดที่ 67 ของคุณ แต่อาจมีบางครั้งที่เหมาะสมที่จะเพิ่มอีกสองสามบรรทัด)


ฉันก็ชอบที่จะเห็นฟังก์ชั่นที่สมบูรณ์ของฉันในหน้าจอ :) บางครั้งนั่นหมายถึงตัวอักษร Monospace 9 และความละเอียดขนาดใหญ่ในพื้นหลังสีดำฉันเห็นด้วยที่เข้าใจง่ายกว่าแบบนั้น

1

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

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

ดู ขนาดคลาสที่เหมาะสมที่สุดสำหรับซอฟต์แวร์เชิงวัตถุสำหรับการสนทนาเพิ่มเติม


ขอบคุณสำหรับลิงค์อ่าน :)

1

ฉันได้เขียนฟังก์ชัน 500 บรรทัดมาก่อนอย่างไรก็ตามสิ่งเหล่านี้เป็นเพียงงบสวิตช์ขนาดใหญ่สำหรับการถอดรหัสและตอบกลับข้อความ เมื่อรหัสสำหรับข้อความเดียวมีความซับซ้อนมากกว่า if-then-else เพียงครั้งเดียวฉันก็แยกมันออกมา

โดยพื้นฐานแล้วถึงแม้ว่าฟังก์ชั่นนี้จะมี 500 บรรทัด แต่ภูมิภาคที่ดูแลรักษาอย่างอิสระนั้นมีค่าเฉลี่ย 5 บรรทัด


1

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

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

สิ่งนี้ยังทำงานในทิศทางอื่น ฟังก์ชั่นจะต้องมีขนาดเล็กพอที่จะทดสอบได้อย่างมีประสิทธิภาพ ดังนั้นเมื่อทำงานกับรหัสดั้งเดิมฉันมักจะพบว่าฉันทำลายฟังก์ชั่นที่ใหญ่กว่าเพื่อทดสอบส่วนต่างๆของพวกเขา

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


1

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

แต่ละคำสั่งวนลูปถ้าคำสั่ง ฯลฯ จะไม่ถูกมองว่าเป็นสาขาในวิธีการเรียก

Cobertura สำหรับโค้ด Java (และฉันแน่ใจว่ามีเครื่องมืออื่น ๆ สำหรับภาษาอื่น ๆ ) คำนวณจำนวนหาก ฯลฯ ในฟังก์ชั่นสำหรับแต่ละฟังก์ชั่นและผลรวมสำหรับ "ความซับซ้อนตามวัฏจักรเฉลี่ย"

หากฟังก์ชั่น / วิธีการมีเพียงสามสาขามันจะได้สามในตัวชี้วัดนั้นซึ่งดีมาก

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

หากสาขาทั้งหมดอยู่ในวิธีการเดียวอินพุตจะต้องถูกติดตามตั้งแต่เริ่มต้นของวิธีซึ่งขัดขวางการทดสอบ


0

ฉันสงสัยว่าคุณจะพบคำตอบมากมายเกี่ยวกับเรื่องนี้

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

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

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


0

สมมติว่าคุณกำลังทำสิ่งหนึ่งความยาวจะขึ้นอยู่กับ:

  • คุณกำลังทำอะไรอยู่
  • คุณใช้ภาษาอะไร
  • คุณต้องจัดการกับนามธรรมในระดับใด

60 บรรทัดอาจยาวเกินไปหรืออาจไม่ถูกต้อง ฉันสงสัยว่ามันอาจจะนานเกินไป


ฉันทำแคชใน PHP ใช่อาจจะเป็น 60 บรรทัดมากเกินไป refactoring ...

0

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


0

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


0

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

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