เหตุผลในการวางประเภทฟังก์ชั่นและชื่อวิธีการในบรรทัดที่แตกต่างกันในค


16

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

void foo() {
}

ควรเป็นแบบนี้

void
foo() {
}

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


3
นี่เป็นมาตรฐานของ GNU (ไม่จำเป็นต้องบอกว่ามันเป็นสิ่งที่ดีรูปแบบการค้ำยันแปลก) gnu.org/prep/standards/standards.html#Formatting
Gauthier

คำตอบ:


19

สงสัยว่ามีเหตุผลอื่นนอกเหนือจากความชอบส่วนตัวทำไมคนถึงใช้สไตล์ที่สอง?

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

อีกเหตุผลคือชื่อฟังก์ชันเริ่มต้นในคอลัมน์แรกเสมอ ประเภทส่งคืนมีความยาวแตกต่างกันไปและค่อนข้างซับซ้อน - การวางประเภทลงบนบรรทัดของตัวเองทำให้ชื่อฟังก์ชันง่ายต่อการค้นหา

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


2
ฉันเดาว่ามันเชื่อมต่อกับขีด จำกัด บรรทัด 80 chars ที่ยังคงใช้และปกป้องโดยโปรแกรมเมอร์จำนวนมาก หากคุณต้องการ จำกัด 80 ตัวอักษรและคุณต้องการใช้ชื่อวิธีการ / ฟังก์ชั่นอธิบายคุณต้องทำการประนีประนอม การแยกส่วนหัวเมธอดเป็นหนึ่งในนั้น
Sulthan

การประกาศอาจยาวขึ้น - ลองคิดเกี่ยวกับตัวดัดแปลง (ที่ไม่ได้มาตรฐาน) ที่แตกต่างกันเช่นตัวระบุการเรียกประชุม (stdcall ฯลฯ ) ข้อมูลเกี่ยวกับการมองเห็นสัญลักษณ์ (DLLEXPORT) หรือ__attributes และเมื่อดูที่ C ++ คุณสามารถมีประเภทผลตอบแทนที่ค่อนข้างซับซ้อนได้ดังนั้นบางที่อาจต้องเพิ่มตัวแบ่งบรรทัด
johannes

@Sulthan ไม่ใช่แค่โปรแกรมเมอร์ (ผู้ที่คุ้นเคยกับเทอร์มินัล windows และใช้เทอร์มินัลเทอร์มินัล) อย่างน่าสนใจ ในการเรียงพิมพ์ตัวอักษร 72-80 โดยทั่วไปถือว่าเป็นความกว้างในอุดมคติสำหรับคอลัมน์ของข้อความในแง่ของความสามารถในการอ่าน (ดังนั้นทำไมเท็กซ์และอนุพันธ์เริ่มต้นกับสิ่งที่บางคนพิจารณาคอลัมน์แคบผิดปกติ.)
JAB

1
@JAB ตอนนี้ฉันจริง ๆ แล้ว ฉันรู้ด้วยว่าการอ่านข้อความที่ถูกต้องและซอร์สโค้ดการอ่านเป็นสองสิ่งที่แตกต่างกันมากและแทบไม่มีอะไรเหมือนกันดังนั้นความกว้างในอุดมคติจึงไม่เกี่ยวข้อง
Sulthan

1
"อีกเหตุผลหนึ่งคือชื่อฟังก์ชันเริ่มต้นในคอลัมน์แรกเสมอและหาง่ายกว่า" และนี่เป็นมากกว่าประโยชน์ที่ได้รับภาพ: ตอนนี้เราสามารถค้นหา regex ^start_of_a_long_funcและนำไปใช้กับฟังก์ชันที่เราค้นหาได้ทันที
underscore_d

7

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

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

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

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

double dot(x, y);

ยังคงย่อยสลายได้สวย

C ++ ทำให้สิ่งนี้เลวร้ายลงเล็กน้อย มันย้ายข้อมูลจำเพาะชนิดอาร์กิวเมนต์ไปยังลายเซ็นทำให้ลายเซ็นยาวขึ้น ไวยากรณ์นี้ถูกนำมาใช้ในภายหลังในช่วงมาตรฐานของ C.

static struct origin *find_origin(struct scoreboard *sb,
                  struct commit *parent,
                  struct origin *origin)

ย่อยได้น้อยลง แต่ไม่เลวร้ายเกินไป (ข้อความที่ตัดตอนมาจาก Git)

ในตอนนี้ให้พิจารณาวิธีการเขียนโปรแกรมที่ทันสมัยด้วยชื่อที่สื่อความหมายยาวยาวและประเภท parametrized และดูว่าทางเลือกนี้กลายเป็นหายนะอย่างไร ตัวอย่างจากส่วนหัวของ Boost:

template <class A1, class A2, class A3, class A4, class A5, class A6>
inline typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type make_policy(const A1&, const A2&, const A3&, const A4&, const A5&, const A6&)
{ 
   typedef typename normalise<policy<>, A1, A2, A3, A4, A5, A6>::type result_type;
   return result_type(); 
}

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

C, C ++, และอนุพันธ์ของพวกเขา, Java และ C #, ดูเหมือนจะเป็นข้อยกเว้นสำหรับการประกาศ / คำจำกัดความที่อ่านได้ ผู้บุกเบิกและเพื่อนยอดนิยมของพวกเขา (Fortran, ALGOL, Pascal) วางชื่อก่อนประเภทผลลัพธ์และต้องขอบคุณผู้สืบทอดหลายคน (Go, Scala, TypeScript และ Swift เพื่อชื่อไม่กี่คน) ได้เลือกไวยากรณ์ที่อ่านได้มากขึ้นเช่นกัน


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

2
ใส่ประเภทในการประกาศฟังก์ชั่นที่คิดค้นโดย C ++ หรือไม่? ฉันไม่เคยได้ยินเรื่องนี้มาก่อนและกำลังพยายามหาการอ้างอิง
underscore_d

1
ดูการพัฒนาของภาษา C ในส่วน Standardization Ritchie กล่าวถึงไวยากรณ์ที่ยืมมาจาก C ++
user2313838

5

ฉันพบรูปแบบนี้เป็นครั้งแรกในปีที่ 19 ทำงานกับ C & C ++ ค่อนข้างงุนงงว่าจะมีใครประดิษฐ์สิ่งชั่วร้ายนี้ขึ้นมาได้อย่างไร

จุดบวก (ที่อาจเกิดขึ้น) เพียงอย่างเดียวที่ฉันสามารถหาได้คือคุณสามารถค้นหานิยาม funciton ได้โดยใช้ grep ^ FuncName อาจเป็นปัจจัยที่เกี่ยวข้องทศวรรษที่ผ่านมาในบางชุมชนเครื่องมือจริงเกลียด ... ในสถานที่ที่ฉันเห็นมันถูกนำไปใช้กับ C ++ และ funcitons สมาชิกชั้นเรียนที่ฆ่าแม้คุณลักษณะนี้

เดาความคิดเห็นของฉัน :)


1
grep -P '^(\w+::)?FuncName'
Kyle Strand

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