แนวทางปฏิบัติที่ดีที่สุด: การสั่งซื้อสาธารณะ / ป้องกัน / ส่วนตัวภายในนิยามคลาส?


94

ฉันกำลังเริ่มโครงการใหม่ตั้งแต่ต้นและต้องการให้มันสะอาด / มีมาตรฐานการเข้ารหัสที่ดี นักพัฒนาที่ช่ำชองที่นี่ชอบจัดวางสิ่งต่างๆภายในชั้นเรียนในลำดับใด

ตอบ: 1) วิธีการสาธารณะ 2) วิธีการส่วนตัว 3) ตัวแทนสาธารณะ 4) ตัวแทนส่วนตัว

B: 1) ตัวแทนสาธารณะ 2) ตัวแทนส่วนตัว 3) วิธีการสาธารณะ 4) วิธีการส่วนตัว

C: 1) public vars 2) public method 3) private method 4) private vars

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

ฉันรู้ว่ามันฟิน แต่ฉันแค่สงสัย: แนวทางปฏิบัติที่ดีที่สุดสำหรับสิ่งนี้คืออะไร?

PS: ไม่ฉันไม่ใช้ Cc # ฉันรู้ว่า. ฉันเป็น luddite


9
ไม่มีอะไรผิดปกติที่จะไม่ใช้ C # ฉันไม่เคยเขียน C # เลยในช่วงหลายปีที่ผ่านมาในฐานะนักพัฒนามืออาชีพ ใช้ภาษาใดก็ได้ที่เหมาะสมกับงานและบอกใครก็ตามที่พูดอะไรที่แตกต่างออกไปพวกเขาสามารถติดได้!
Ether

1
เป็นไปได้ที่จะทำสำเนาstackoverflow.com/questions/150479/…
Michael Freidgeim

คำตอบ:


146

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


10
ฉันโชคดีที่เพิ่ม: getters / setters last มันช่วยให้ชั้นเรียนรู้สึกเทอะทะน้อยลงสำหรับฉัน
Dean J

5
ตัวสร้างที่อยู่ด้านบนหลังตัวแปรสมาชิก ใน OOP การดำเนินการจะเริ่มต้นด้วยการสร้างอินสแตนซ์วัตถุ
Asaph

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

1
ฉันสับสน คุณบอกว่า: (ค่าคงที่แรกสมาชิกแล้วเอกชน) ตกลง. แล้วสมาชิกสาธารณะไปไหน?
น้ำผึ้ง

1
@ น้ำผึ้งพวกเขาจะไปทันทีหลังจากค่าคงที่และสมาชิกส่วนตัว ดังนั้นจะเป็นไปตามลำดับต่อไปนี้: ค่าคงที่สมาชิกส่วนตัวสมาชิกสาธารณะ
Pierre Gillet

49

การปฏิบัติที่ดีที่สุดคือการให้สอดคล้อง

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

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

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


LeopardSkikPBH ฉันเห็นด้วยอย่างยิ่ง ... ที่สมเหตุสมผล! ฉันเดาว่าฉันสับสนว่าภายในนั้น var หรือ funcs มีความสำคัญมากกว่ากัน ขอบคุณ!
tempname

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

3
@ เจสันนั่นเหมือนกับการบอกว่ามันไม่ใช่แนวทางปฏิบัติที่ดีที่สุดที่จะอยู่ข้างถนนเพราะคุณยังสามารถเกิดอุบัติเหตุได้
Rex M

1
@ เจสัน - บางทีฉันควรจะชัดเจนกว่านี้ โดยเฉพาะอย่างยิ่งกรณีนี้ค่อนข้างเป็นส่วนตัว (ลำดับวิธีการ) ฉันคิดว่าแนวทางปฏิบัติที่ดีที่สุดคือต้องสอดคล้องกัน ทุกคนจะมีความคิดเห็นเกี่ยวกับวิธีที่ดีที่สุดในการสั่งซื้อสิ่งต่างๆ แต่ถ้าคุณมีความสม่ำเสมอโดยธรรมชาติก็ควรจะดูแลรักษาได้อย่างเป็นธรรม ฉันยอมรับว่า "สอดคล้องกัน" ไม่ใช่แนวทางปฏิบัติที่ดีที่สุดสำหรับทุกด้านของโค้ดเสมอไปโดยเฉพาะอย่างยิ่งเมื่อคุณพิจารณาถึงคุณภาพของโค้ดที่ไม่ดีที่คุณมักจะต้องรับมือ
LeopardSkinPillBoxHat

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

9

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

ดังนั้นชั้นเรียนของฉันมักจะมีลักษณะดังนี้:

class MyClass {
    public string Method(int a) {
        return HelperMethodA(a) + HelperMethodB(this.SomeStringMember);
    }

    string HelperMethodA(int a) { // returns some string }

    string HelperMethodB(string s) { // returns some string }

    public bool Equals(MyClass other) { return MyClass.Equals(this, other); }

    public static bool Equals(MyClass left, MyClass right) { // return some bool }

    public double SomeCalculation(double x, double y) {
        if(x < 0) throw new ArgumentOutOfRangeException("x");
        return DoSomeCalculation(x, y); 
    }

    const double aConstant;
    const double anotherConstant;
    double DoSomeCalculation(double x, double y) {
        return Math.Pow(aConstant, x) * Math.Sin(y) 
            + this.SomeDoubleMember * anotherConstant;
    }       
}

9

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

เราไม่ควรดูรายละเอียดการใช้งานของคลาสเพื่อใช้งานจากนั้นการออกแบบคลาสจะทำได้ไม่ดี


3

ฉันเคยแคร์มาก ในช่วงหลายปีที่ผ่านมาโดยใช้ IDE ที่ทันสมัยทุกอย่างอยู่ห่างออกไปเพียง 1 หรือ 2 ครั้งเท่านั้นฉันปล่อยให้มาตรฐานของฉันผ่อนคลายลงอย่างมาก ตอนนี้ฉันเริ่มต้นด้วยสถิตยศาสตร์ตัวแปรสมาชิกจากนั้นตัวสร้างหลังจากนั้นฉันก็ไม่กังวลกับมันมากนัก

ใน C # ฉันปล่อยให้ Resharper จัดระเบียบสิ่งต่างๆโดยอัตโนมัติ


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

2

นี่จะเป็นการสั่งซื้อของฉัน

  1. ตัวแปรคงที่
  2. วิธีการแบบคงที่
  3. ตัวแปรสาธารณะ
  4. ตัวแปรที่ได้รับการป้องกัน
  5. ตัวแปรส่วนตัว
  6. ตัวสร้าง
  7. วิธีการสาธารณะ
  8. วิธีการป้องกัน
  9. วิธีการส่วนตัว

ฉันใช้กฎต่อไปนี้:

  • คงที่ก่อนสิ่งใด
  • ตัวแปรก่อนตัวสร้างก่อนวิธีการ (ฉันถือว่าตัวสร้างอยู่ในประเภทของวิธีการ)
  • สาธารณะก่อนป้องกันก่อนส่วนตัว

แนวคิดคือคุณกำหนดวัตถุ (ข้อมูล) ก่อนพฤติกรรม (วิธีการ) สถิตยศาสตร์จำเป็นต้องแยกออกจากกันเนื่องจากไม่ได้เป็นส่วนหนึ่งของวัตถุหรือพฤติกรรม


ขอบคุณคุณ barkmadley ... ที่น่าสนใจ! ที่คุณใส่ 4 และ 5 ก่อนตัวสร้าง ฉันจะคิดถึงเรื่องนั้นอย่างแน่นอน
tempname

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

2

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

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

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


1
เฮ้ - 'แท็บเว้นวรรค' ตามหัวใจตัวเอง! :-) ฉันไม่ได้ครอบงำจิตใจ สุจริตฉันไม่!
tempname

1

สำหรับแต่ละคนของเขาเองและอย่างที่ Elzo กล่าว IDE สมัยใหม่ทำให้การค้นหาสมาชิกและตัวดัดแปลงของพวกเขาง่ายขึ้นด้วยวิธีง่ายๆด้วยไอคอนสีในเมนูแบบเลื่อนลงและอื่น ๆ

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

ดังนั้นถ้าเป็น Singleton ฉันใส่ความหมาย (คลาส getInstance () แบบคงที่) ไว้ก่อน

ถ้าเป็นโรงงานคอนกรีตฉันใส่ฟังก์ชัน getNew () และฟังก์ชัน register / initialize ก่อน

... และอื่น ๆ เมื่อฉันพูดก่อนฉันหมายถึงไม่นานหลังจาก c'tors และ d'tor - เนื่องจากเป็นวิธีเริ่มต้นในการสร้างอินสแตนซ์คลาสใด ๆ

ฟังก์ชั่นที่ตามมาจะอยู่ใน:

  1. คำสั่งเรียกตรรกะ (เช่น initialize (), preProcess (), process (), postProcess ()) หรือ
  2. ฟังก์ชั่นที่เกี่ยวข้องเข้าด้วยกัน (เช่น accessors, utilities, manipulators ฯลฯ )

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


0

ตัวแก้ไขบางตัวเช่น Eclipse และลูกหลานของมันอนุญาตให้คุณจัดลำดับใหม่ในเค้าร่างเพื่อดู vars และวิธีการตามลำดับตัวอักษรหรือในเพจ


0

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

ฉันใช้ Qt c ++ มาระยะหนึ่งแล้วและเห็นคีย์เวิร์ดใหม่ ๆ เช่นsignalและslotฉันชอบที่จะเรียงลำดับเหมือนข้างบนต่อไปและแบ่งปันความคิดกับคุณ

#ifndef TEMPLATE_H
#define TEMPLATE_H


class ClassName
{
    Q_OBJECT
    Q_PROPERTY(qreal startValue READ startValue WRITE setStartValue)
    Q_ENUMS(MyEnum)

public:

    enum MyEnum {
        Hello = 0x0,
        World = 0x1
    };

    // constructors

    explicit ClassName(QObject *parent = Q_NULLPTR);
    ~ClassName();

    // getter and setters of member variables

    // public functions (normal & virtual) -> orderby logic

public slots:

signals:

protected:

    // protected functions it's rule followed like public functions


private slots:

private:

    // methods

    // members

};

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