ตัวแบ่งบรรทัดก่อน / หลังตัวดำเนินการ [ปิด]


29

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

String longVarName = a + b + c + d +
          e + f;

VS

String longVarName = a + b + c + d
          + e + f;

คุณช่วยกรุณาโพสต์ตัวอย่างรหัสง่ายๆที่แสดงทั้งอนุสัญญาได้ไหม
Michael

ก่อนอื่นฉันจะพยายามหลีกเลี่ยงสถานการณ์โดยใช้สิ่งนี้: download.oracle.com/javase/1.4.2/docs/api/java/lang/…
งาน

ลิงก์เสีย
Florian F

คำตอบ:


14

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

เมื่อมันยุ่งก็ถึงเวลาที่จะปรับโครงสร้าง :

  • เปลี่ยนชื่อ vars
  • แนะนำ vars / function ใหม่

ตัวอย่าง

subtotal = price * (100 + tax_ratio) / 100`

เมื่อเทียบกับ

tax = price * tax_ratio / 100
subtotal = price + tax

2
สูตรทางด้านซ้ายไม่ถูกต้อง ควรเป็นอย่างใดอย่างหนึ่งprice * (100 + tax_ratio) / 100หรือเพียงแค่price * (1 + tax_ratio)ขึ้นอยู่กับว่าtax_ratioเป็นเปอร์เซ็นต์หรือเป็นเศษส่วน
Rufflewind

4
สิ่งนี้ไม่ตอบคำถาม ควรมีกฎหมายที่ต่อต้านการตอบกลับประเภทนี้
Edward D'Souza

@ EdwardD'Souza ฉันรู้สึกเหมือนเดิม แต่ทำไมคำตอบจึงเป็นที่ยอมรับ?
Rudy Vissers

@RudyVissers คำตอบแก้ปัญหาในระดับที่ลึกกว่า มันช่วยแก้ปัญหาของการต้องขึ้นบรรทัดใหม่ในตอนแรก จากมุมมองดังกล่าว OP สามารถพิจารณาคำตอบสำหรับปัญหาของเขาหรือเธอ แต่ก็ยังไม่เหมาะสมจากมุมมองของการเป็นวิกิชุมชน
Edward D'Souza

เฮ้ฉันไม่ได้อยู่ที่นี่อีกแล้ว แต่มันง่ายมาก - ถ้าคุณพบว่าตัวเองอยู่ในสถานการณ์เช่นนี้คุณอาจทำผิดและคุณควรคิดเกี่ยวกับการปรับรหัสใหม่ เพียงแค่ไม่สนใจสิ่งต่าง ๆ อีกต่อไปสิ่งที่ฉันสนใจแทนคือความชัดเจนของรหัสความเรียบง่ายและทำให้คนอื่นช่วยฉันได้ง่ายขึ้น
Kamil Tomšík

36

ฉันสามารถจินตนาการได้ว่าการอ่านเป็นข้อโต้แย้ง

result = longidentifier +
   short -
   alittlelonger -
   c;

กับ

result = longidentifier
   + short
   - alittlelonger
   - c;

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


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

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

35

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

สไตล์ที่พบบ่อยที่สุดที่ฉันเคยเห็นคือสไตล์ที่สองในคำถาม ดูด้านล่างสำหรับรายการของพวกเขา:

คู่มือสไตล์ Google :

เมื่อสายถูกทำลายที่ผู้ประกอบการที่ไม่ได้รับมอบหมายการแบ่งมาก่อนสัญลักษณ์

อนุสัญญาการเข้ารหัสซัน :

แตกก่อนที่โอเปอเรเตอร์

ค่าเริ่มต้นของCheckstyle Operator Wrap การตรวจสอบคือ nl:

ผู้ประกอบการจะต้องอยู่ในบรรทัดใหม่


2
อัปเดตคำตอบของฉันเพื่อความชัดเจน + ระเบียบปฏิบัติการเข้ารหัสของ Sun
เพดาน

google.github.io/styleguide/javaguide.html (ลิงก์คำตอบขาด)
Martin Pfeffer

10

ในรหัสฉันมักจะทำให้ตัวแบ่งหลังจากผู้ประกอบการ:

foo = some_long_expression() +
      some_other_long_expression();

ที่นี่ผู้ประกอบการที่ห้อยอยู่ท้ายบรรทัดเป็นเบาะแสที่สำคัญสำหรับผู้อ่านว่ารหัสดำเนินการต่อ ในภาษาที่ไม่มีคำสั่งสิ้นสุดตัวดำเนินการที่ห้อยสามารถทำหน้าที่เป็นเบาะแสที่เพียงพอต่อคอมไพเลอร์ / ล่ามว่ารหัสดำเนินการต่อไป

เมื่อบันทึกการแสดงออกนั้น (ถ้าต้องการเอกสาร) ฉันมักจะหยุดพักต่อหน้าผู้ปฏิบัติงาน


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

3

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


3

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

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

if (ch>='A' && ch<='Z'
    || ch>='a' && ch<='z'
    || ch>='0' && ch<='9')
{...}

ด้านล่าง | | ผู้ประกอบการมีการเน้นน้อย มันชัดเจนน้อยกว่าว่ามันเป็น || ของการแสดงออก โดยเฉพาะอย่างยิ่งถ้าเส้นมีความยาวต่างกัน

if (ch>='A' && ch<='Z' ||
    ch>='a' && ch<='z' ||
    ch>='0' && ch<='9')
{...}

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

if ( ch>='A' && ch<='Z' || ch>='a'
     && ch<='z' || ch>='0' && ch<='9')
{...}

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

var note:Object =
    { key: key
    , type: 'P'
    , text: someLongProcedureCallGettingTheUserInitials()
       + ": " + getTheTextThatWasTyped()
    };

2

สำหรับสมการทางคณิตศาสตร์ที่ยาว ๆ ฉันมักจะทำหนึ่งในสองอย่างนี้

ทิ้งทุกอย่างไว้ในบรรทัดเดียว:

foo = bar + baz - fizz + buzz + alpha - beta;

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

รูปแบบที่สองที่ฉันใช้คือตัวดำเนินการแบบก้าวหน้า:

foo = bar;
foo += baz;
foo -= fizz;
foo += buzz;
foo /= alpha - beta;
foo *= spiff;

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


2

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

นิพจน์ทางคณิตศาสตร์แบบยาวนั้นจะเรียงพิมพ์เสมอเพื่อให้แต่ละบรรทัดใหม่เริ่มต้นด้วยโอเปอเรเตอร์ ไม่มีเหตุผลที่รหัสไม่ควรปฏิบัติตามอนุสัญญานี้


0

ปล่อยให้นิพจน์อยู่บนหนึ่งบรรทัดและถ้ามันยาวเกินไปให้แบ่งออกเป็นนิพจน์ที่เล็กกว่า:

days = ((year * months_per_year) + month) * days_per_month + day

กลายเป็น:

months = year * months_per_year + month
days = months * days_per_month + day

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

random = years * months_per_year 
         + month * days_per_month 
         + day * hours_per_day 
         + hour * minutes_per_hour 
         + minute * seconds_per_minute 
         + second

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