Thực tiễn tốt nhất: thứ tự của công khai / bảo vệ / riêng tư trong định nghĩa lớp?


92

Tôi đang bắt đầu một dự án mới từ đầu và muốn nó phải sạch / có tiêu chuẩn mã hóa tốt. Các nhà phát triển dày dạn ở đây muốn sắp xếp mọi thứ trong một lớp theo thứ tự nào?

A: 1) phương thức công khai 2) phương thức riêng tư 3) kho tiền công cộng 4) kho tiền riêng

B: 1) vars công khai 2) vars private 3) public method 4) private method

C: 1) kho tiền công cộng 2) phương thức công khai 3) phương thức riêng tư 4) kho tiền riêng

Nói chung, tôi muốn đặt public static vars ở trên cùng, nhưng sau đó một phương thức public static sẽ được liệt kê trước hàm tạo của bạn, hay phương thức khởi tạo phải luôn được liệt kê trước? Đại loại là ...

Tôi biết nó hơi khó nhưng tôi chỉ tự hỏi: những phương pháp hay nhất cho việc này là gì?

Tái bút: không, tôi không sử dụng Cc #. Tôi biết. Tôi là một người luddite.


9
Không có gì sai khi không sử dụng C #. Tôi chưa bao giờ viết một câu nào về C # trong suốt những năm làm nhà phát triển chuyên nghiệp. Sử dụng bất kỳ ngôn ngữ nào phù hợp với nhiệm vụ và nói với bất kỳ ai nói bất kỳ điều gì khác biệt ở nơi họ có thể tiếp tục thực hiện!
Ether

Câu trả lời:


143

Trong Clean Code , Robert C. Martin khuyên các lập trình viên nên luôn đặt các biến thành viên ở đầu lớp (trước tiên là hằng số, sau đó là các thành viên riêng) và các phương thức nên được sắp xếp theo cách sao cho chúng đọc như một câu chuyện mà không gây ra người đọc cần phải nhảy xung quanh mã quá nhiều. Đây là một cách hợp lý hơn để tổ chức mã hơn là bằng công cụ sửa đổi truy cập.


10
Tôi cũng đã may mắn thêm: getters / setters last. Với tôi, nó giúp các lớp học bớt cồng kềnh hơn.
Dean J

5
Các hàm tạo ở trên cùng, ngay sau các biến thành viên. Trong OOP, việc thực thi bắt đầu bằng việc tạo đối tượng.
Asaph

6
Việc khiến người đọc phải nhảy xung quanh mã quá nhiều có lẽ cần phải cân bằng với việc buộc người đọc phải đọc tất cả các chi tiết khó hiểu của các phương thức riêng tư. Phép ẩn dụ báo chí có thể bị hiểu nhầm ở chỗ các phương thức công khai của bạn phải đại diện rộng rãi cho những gì lớp của bạn thực hiện và các phương thức riêng tư của bạn cung cấp thông tin chi tiết (gần giống như một chú thích mà bạn có thể tham khảo nếu cần).
Kenny Hung

1
Tôi bối rối. Bạn đã nói: (đầu tiên là hằng số, sau đó là thành viên riêng) . ĐỒNG Ý. Sau đó các thành viên công chúng sẽ đi đâu?
Honey

1
@Honey Họ sẽ đi ngay sau các hằng số và các thành viên riêng. Vì vậy, đó sẽ là theo thứ tự sau: Hằng số, thành viên riêng tư, thành viên công khai.
Pierre Gillet

48

Cách tốt nhất là phải nhất quán .

Cá nhân tôi thích đặt publicphương pháp trước, sau đó là protectedphương pháp, sau là privatephương pháp. Nói chung, dữ liệu thành viên phải luôn ở chế độ riêng tư hoặc được bảo vệ, trừ khi bạn có lý do chính đáng để không làm như vậy.

Cơ sở lý luận của tôi khi đặt publiccác phương thức ở trên cùng là nó xác định giao diện cho lớp của bạn, vì vậy bất kỳ ai xem qua tệp tiêu đề của bạn sẽ có thể thấy thông tin này ngay lập tức.

Nói chung, privateprotectedcác thành viên ít quan trọng hơn đối với hầu hết mọi người khi xem tệp tiêu đề, trừ khi họ đang xem xét sửa đổi nội bộ của lớp. Giữ chúng "tránh xa" đảm bảo thông tin này chỉ được duy trì trên cơ sở cần biết , một trong những khía cạnh quan trọng hơn của việc đóng gói.


LeopardSkikPBH, tôi hoàn toàn đồng ý ... điều đó có lý! Tôi đoán rằng tôi đã bối rối không biết trong đó, var hoặc funcs được ưu tiên hơn. Cảm ơn!
tempname

11
Tôi không đồng ý rằng cách tốt nhất là phải nhất quán. Có rất nhiều cách để viết một cách nhất quán mã không thể đọc được, không thể viết được.
jason

3
@Jason điều đó giống như nói rằng cách tốt nhất không phải là đứng bên lề đường của bạn vì bạn vẫn có thể gặp tai nạn ở đó.
Rex M

1
@Jason - Có lẽ tôi nên rõ ràng hơn. Trong trường hợp cụ thể, khá chủ quan này (thứ tự các phương pháp), tôi nghĩ cách tốt nhất là nhất quán. Mọi người sẽ có ý kiến ​​về cách tốt nhất để đặt hàng, nhưng nếu bạn nhất quán về bản chất, thì điều đó sẽ khá dễ bảo trì. Tôi đồng ý rằng "hãy nhất quán" không phải lúc nào cũng là phương pháp hay nhất cho tất cả các lĩnh vực mã, đặc biệt khi bạn xem xét chất lượng mã kém mà bạn thường phải đối phó.
LeopardSkinPillBoxHat

4
@Rex M: Không, những gì tôi đã nói không giống với cách diễn giải của bạn chút nào. Quan điểm của tôi là chỉ đơn thuần nhất quán không phải là một lập luận mạnh mẽ trong trường hợp này. Đối với một số trường hợp, sự nhất quán là tốt (ví dụ: vị trí niềng răng). Nhưng các lựa chọn ở đây thực sự ảnh hưởng đến khả năng đọc của mã. Vì vậy, một lập luận mạnh mẽ hơn tính nhất quán là cần thiết.
jason

8

Tôi nghĩ rằng tôi có một triết lý khác về vấn đề này. Tôi thích nhóm các mục liên quan với nhau. Tôi không thể chịu được việc phải nhảy xung quanh để làm việc với một lớp học. Mã phải chảy và sử dụng một thứ tự khá giả tạo dựa trên khả năng truy cập (công khai, riêng tư, được bảo vệ, v.v.) hoặc trường hợp so với tĩnh hoặc thành viên so với thuộc tính so với chức năng không giúp giữ một luồng tốt. Vì vậy, nếu tôi tìm thấy một phương thức công khai Methodđược triển khai bởi các phương thức của người trợ giúp riêng HelperMethodA, HelperMethodBv.v. thì thay vì đặt các phương thức này cách xa nhau trong tệp, tôi sẽ giữ chúng gần nhau. Tương tự, nếu tôi có một phương thức thể hiện được thực hiện bằng một phương thức tĩnh, tôi cũng sẽ nhóm chúng lại với nhau.

Vì vậy, các lớp học của tôi thường trông như thế này:

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;
    }       
}

8

Cá nhân tôi thích đặt công khai ở trên cùng, được bảo vệ và sau đó là riêng tư. Lý do cho điều này là khi ai đó bẻ khóa mở tiêu đề, anh ấy / cô ấy sẽ thấy những gì anh ấy / cô ấy có thể truy cập đầu tiên, sau đó sẽ biết thêm chi tiết khi anh ấy / cô ấy cuộn xuống.

Người ta không nên nhìn vào các chi tiết thực thi của một lớp để sử dụng nó, khi đó việc thiết kế lớp không được thực hiện tốt.


3

Tôi đã từng quan tâm rất nhiều. Trong vài năm qua bằng cách sử dụng các IDE hiện đại, hầu hết mọi thứ chỉ còn 1 hoặc 2 lần nhấn phím, tôi đã để các tiêu chuẩn của mình được nới lỏng đáng kể. Bây giờ, tôi bắt đầu với statics, biến thành viên, sau đó là constructor, sau đó tôi không lo lắng về nó nhiều.

Trong C #, tôi để Resharper sắp xếp mọi thứ tự động.


Tôi đồng ý. Chế độ thông thường của tôi để điều hướng các thành viên trong tệp là sử dụng một công cụ được tích hợp sẵn trong bất kỳ IDE hoặc trình chỉnh sửa nào mà tôi đang sử dụng. Việc nhóm các thành viên thực sự trở thành thứ yếu. Tuy nhiên, tôi đồng ý rằng các thành viên nên được nhóm lại để tránh thứ tự ngẫu nhiên thuần túy và tôi sử dụng resharper để phân nhóm và sắp xếp tự động.
Phillip Ngan

2

Đây sẽ là đơn đặt hàng của tôi

  1. Biến tĩnh
  2. Phương pháp tĩnh
  3. Biến công khai
  4. Các biến được bảo vệ
  5. Biến riêng
  6. Người xây dựng
  7. Phương thức công khai
  8. Phương pháp được bảo vệ
  9. Phương thức riêng tư

Tôi sử dụng các quy tắc sau:

  • tĩnh trước bất cứ điều gì
  • biến trước các hàm tạo trước các phương thức (tôi coi các hàm tạo nằm trong danh mục các phương thức)
  • công khai trước khi bảo vệ trước khi riêng tư

Ý tưởng là bạn xác định đối tượng (dữ liệu), trước các hành vi (phương thức). Tin học cần được tách biệt bởi vì chúng không thực sự là một phần của đối tượng, cũng không phải là hành vi.


cảm ơn bạn sủa ... thật thú vị! mà bạn sẽ đặt 4 và 5 trước hàm tạo. Tôi chắc chắn sẽ nghĩ về điều đó
tempname

Giống như thứ tự này mặc dù có các phương thức tĩnh gần đầu là điều thú vị. Tôi đã làm việc với một nhà phát triển đặt các biến riêng tư ở dưới cùng, tôi có thể thấy ý tưởng này nhưng cảm thấy không ổn
Carlton

2

Tôi thường đồng ý với trật tự công khai, được bảo vệ, riêng tư cũng như dữ liệu tĩnh, dữ liệu thành viên, thứ tự chức năng thành viên.

Mặc dù đôi khi tôi nhóm như các thành viên (getters & setters), tôi thường thích liệt kê các thành viên trong một nhóm MỘT CÁCH RÕ RÀNG để họ có thể được định vị dễ dàng hơn.

Tôi cũng thích sắp xếp dữ liệu / chức năng theo chiều dọc. Tôi đặt tab / khoảng trắng sang phải đủ để tất cả các tên được căn chỉnh trong cùng một cột.


1
Này - một 'tab-spacer' sau trái tim của chính tôi! :-) Tôi không ám ảnh cưỡng chế. Thành thật mà nói, tôi không!
tempname

1

Đối với mỗi người của riêng mình, và như Elzo nói, các IDE hiện đại đã giúp dễ dàng tìm thấy các thành viên và công cụ sửa đổi của họ một cách dễ dàng hơn với các biểu tượng màu trong menu thả xuống và những thứ tương tự.

Tôi nghĩ rằng điều quan trọng hơn là lập trình viên phải biết lớp được thiết kế cho mục đích gì và nó có thể hoạt động như thế nào.

Vì vậy, nếu nó là một Singleton, tôi đặt ngữ nghĩa (lớp getInstance () tĩnh) trước.

Nếu đó là một nhà máy bê tông, tôi đặt hàm getNew () và các hàm đăng ký / khởi tạo trước.

... và như thế. Khi tôi nói đầu tiên, tôi muốn nói ngay sau c'tors và d'tor - vì chúng là cách mặc định để khởi tạo bất kỳ lớp nào.

Các chức năng tiếp theo sau đó có trong:

  1. thứ tự lệnh gọi logic (ví dụ: khởi tạo (), preProcess (), process (), postProcess ()) hoặc
  2. các chức năng liên quan với nhau (như trình truy cập, tiện ích, trình điều khiển, v.v.),

tùy thuộc vào việc lớp có ý nghĩa chủ yếu là một kho lưu trữ dữ liệu với một số chức năng hay trình cung cấp chức năng với một vài thành viên dữ liệu.


0

Một số trình soạn thảo, như Eclipse và con đẻ của nó, cho phép bạn sắp xếp lại thứ tự trong dạng xem phác thảo các vars và các phương thức, theo thứ tự bảng chữ cái hoặc trong trang.


0

Trình tự công khai theo sau bởi bảo vệ và riêng tư dễ đọc hơn đối với tôi, Tốt hơn là mô tả logic lớp trong các nhận xét ở đầu tệp tiêu đề một cách đơn giản và lệnh gọi hàm để hiểu liều lượng lớp và các thuật toán được sử dụng bên trong là gì.

Tôi đang sử dụng Qt c ++ một thời gian và thấy một số loại từ khóa mới như thế signalslottôi muốn tiếp tục đặt hàng như trên và chia sẻ ý tưởng của tôi với bạn tại đây.

#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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.