วิธีที่เป็นมิตรกับมนุษย์มากที่สุดในการสั่งซื้อคำจำกัดความวิธีการเรียน?


38

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

  1. การสั่งซื้อมีความสำคัญหรือไม่
  2. มีคำสั่ง "ดีที่สุด" หรือไม่?
  3. ฉันเดาว่าไม่ได้ดังนั้นข้อดีและข้อเสียของกลยุทธ์การสั่งซื้อที่แตกต่างกันคืออะไร

1
คุณไม่ได้คาดหวังให้คนอื่นตัด / วางโค้ดเพื่อเรียงลำดับวิธีการใหม่ ถ้า IDE ทำมันโดยอัตโนมัติก็โอเค ไม่อย่างนั้นมันยากที่จะบังคับใช้
Reactgular

เพื่อชี้แจงคำถามของฉันเกี่ยวกับการอ่าน / การใช้งานไม่ใช่ไวยากรณ์
Johntron

1
ที่เกี่ยวข้อง: programmers.stackexchange.com/questions/186418/…
Anthony Pegram

คำตอบ:


52

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

คำพูดของมาร์ตินฟาวเลอร์ที่ฉันชอบคือ: Any fool can write code that a computer can understand. Good programmers write code that humans can understand.ดังนั้นฉันจะบอกว่าการจัดลำดับชั้นเรียนของคุณควรขึ้นอยู่กับสิ่งที่ทำให้มนุษย์เข้าใจได้ง่าย

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

แก้ไข:

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

บทที่ 5 ของClean Code (หนังสือยอดเยี่ยม btw) มีรายละเอียดมากมายเกี่ยวกับวิธีการที่ Mr. Martin แนะนำรหัสการสั่งซื้อ เขาแนะนำว่ารหัสการอ่านควรทำงานได้ดีเหมือนกับการอ่านบทความในหนังสือพิมพ์: รายละเอียดระดับสูงมาก่อน (ที่ด้านบน) และคุณจะได้รับรายละเอียดมากขึ้นเมื่อคุณอ่าน เขาบอกว่า "ถ้าฟังก์ชั่นหนึ่งเรียกอีกฟังก์ชั่นพวกเขาควรจะปิดในแนวตั้งและผู้เรียกควรอยู่เหนือ callee ถ้าเป็นไปได้" นอกจากนี้แนวคิดที่เกี่ยวข้องควรอยู่ใกล้กัน

ดังนั้นนี่คือตัวอย่างที่วางแผนไว้ซึ่งไม่ดีในหลาย ๆ ด้าน (การออกแบบ OO ที่ไม่ดีไม่เคยใช้doubleเงิน) แต่แสดงให้เห็นถึงแนวคิด:

public class Employee {
  ...
  public String getEmployeeId() { return employeeId; }
  public String getFirstName() { return firstName; }
  public String getLastName() { return lastName; }

  public double calculatePaycheck() {
    double pay = getSalary() / PAY_PERIODS_PER_YEAR;
    if (isEligibleForBonus()) {
      pay += calculateBonus();
    }
    return pay;
  }

  private double getSalary() { ... }

  private boolean isEligibleForBonus() {
    return (isFullTimeEmployee() && didCompleteBonusObjectives());
  }

  public boolean isFullTimeEmployee() { ... }
  private boolean didCompleteBonusObjectives() { ... }
  private double calculateBonus() { ... }
}

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

getFirstNameและgetLastNameเกี่ยวข้องกับแนวคิด (และgetEmployeeIdอาจจะเกินไป) ดังนั้นพวกเขาจึงอยู่ใกล้กัน เราสามารถย้ายพวกมันทั้งหมดลงไปด้านล่าง แต่เราไม่ต้องการเห็นgetFirstNameที่ด้านบนและgetLastNameด้านล่าง

หวังว่านี่จะช่วยให้คุณมีแนวคิดพื้นฐาน Clean Codeหากคุณสนใจในรูปแบบของสิ่งนี้ผมขอแนะนำให้อ่าน


ฉันจำเป็นต้องรู้ว่าจะต้องวาง setters และ getters ของตัวแปรอินสแตนซ์อย่างไร มันควรจะเกิดขึ้นทันทีหลังจากตัวสร้างคลาสหรือที่ด้านล่างของคลาส?
srinivas

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

ไม่ควรcalculateBonus()มาก่อนisFullTimeEmployee()และdidCompleteBonusObjectives()?
winklerrr

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

2

ฉันมักจะสั่งวิธีการของฉันตามความสัมพันธ์และลำดับการใช้งาน

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

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

ฉันทำแบบนั้นเพื่อการดีบั๊กมากกว่าสิ่งอื่นเมื่อฉันมีปัญหาและฉันต้องการข้ามไปยังวิธีการฉันไม่คิดว่ามันสะกดอย่างไรฉันคิดว่ามันต้องรับผิดชอบอะไรและไปที่ส่วนนั้น

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

มันเกี่ยวกับเรื่องนี้หรือไม่?

สำหรับการอ่านแน่นอน

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


0

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

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

จากนั้นภายในแต่ละสิ่งเหล่านี้ทำให้รู้สึกถึงวิธีการจัดกลุ่มตามฟังก์ชันการทำงาน: ตัวสร้างและ destructors ในหนึ่งบล็อก getters / setters ในอีกอันหนึ่งตัวดำเนินการโอเวอร์โหลดวิธีคงที่และส่วนที่เหลือของพวง ใน C ++ ฉันชอบที่จะoperator=อยู่ใกล้กับนวกรรมิกเพราะมันเกี่ยวข้องกับตัวสร้างการคัดลอกและเพราะฉันต้องการที่จะเห็นได้อย่างรวดเร็วว่า ctor เริ่มต้นทั้งหมด (หรือไม่มี) คัดลอก ctor, โอเปอเรเตอร์ = และ dtor ที่มีอยู่


-1

TL; DR

เฉพาะในกรณีที่ภาษาที่คุณใช้ต้องมีการสั่งซื้อที่เฉพาะเจาะจง นอกเหนือจากนั้นการสั่งซื้อขึ้นอยู่กับคุณ เลือกระบบที่มีความสอดคล้องและสมเหตุสมผลและพยายามใช้ให้มากที่สุด


1. การสั่งซื้อมีความสำคัญหรือไม่

เฉพาะในกรณีที่ภาษาที่คุณใช้งานจำเป็นต้องมีฟังก์ชั่นที่กำหนดไว้ก่อนหน้านี้ในไฟล์มากกว่าที่จะถูกเรียกเช่นในตัวอย่างนี้:

void funcA()
{
   funcB();
}

void funcB()
{
   //do something interesting...
}

คุณจะได้รับข้อผิดพลาดเพราะคุณโทรfuncB()ก่อนที่จะใช้ ฉันคิดว่านี่เป็นปัญหาใน PL / SQL และอาจเป็น C เช่นกัน แต่คุณสามารถมีการประกาศล่วงหน้าเช่น:

void funcB();

void funcA()
{
   funcB();
}

void funcB()
{
   //do something interesting...
}

นี่เป็นสถานการณ์เดียวที่ฉันสามารถนึกได้ว่าหากคำสั่งซื้อนั้น "ผิด" คุณจะไม่สามารถรวบรวมได้

มิฉะนั้นคุณสามารถสั่งซื้อใหม่ได้ตลอดเวลาตามที่คุณต้องการ คุณอาจจะสามารถเขียนเครื่องมือเพื่อทำสิ่งนั้นให้คุณได้ (ถ้าคุณไม่สามารถหาได้)

2. มีคำสั่ง "ดีที่สุด" หรือไม่?

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

บางภาษาเช่น C # มีความสามารถในการจัดกลุ่มรหัสใน"ภูมิภาค"ที่ไม่มีผลต่อการรวบรวม แต่อาจทำให้การทำงานที่เกี่ยวข้องกันง่ายขึ้นจากนั้นซ่อน / แสดงด้วย IDE ดังที่MainMa ชี้ให้เห็นมีบางคนที่คิดว่านี่เป็นการปฏิบัติที่ไม่ดี ฉันเห็นตัวอย่างที่ดีและไม่ดีของภูมิภาคที่ใช้วิธีนี้ดังนั้นหากคุณกำลังจะไปทางนี้ระวังตัวด้วย

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