Najlepsza praktyka: porządkowanie publicznego / chronionego / prywatnego w definicji klasy?

94

Rozpoczynam nowy projekt od podstaw i chcę, aby był czysty / miał dobre standardy kodowania. W jakiej kolejności doświadczeni programiści tutaj lubią układać rzeczy w klasie?

O: 1) metody publiczne 2) metody prywatne 3) metody publiczne 4) metody prywatne

B: 1) vary publiczne 2) vars prywatne 3) metody publiczne 4) metody prywatne

C: 1) metody publiczne 2) metody publiczne 3) metody prywatne 4) metody prywatne

Generalnie lubię umieszczać publiczne zmienne statyczne na górze, ale czy publiczna metoda statyczna powinna być wymieniona przed twoim konstruktorem, czy też konstruktor powinien być zawsze wyświetlany jako pierwszy? Coś w tym rodzaju...

Wiem, że jest to trudne, ale zastanawiałem się tylko: jakie są najlepsze praktyki w tym zakresie?

PS: nie, nie używam Cc #. Wiem. Jestem luddystą.

nazwa tymczasowa
źródło
9
Nie ma nic złego w nieużywaniu języka C #. Nigdy nie napisałem ściegu C # przez wszystkie lata jako profesjonalny programista. Używaj dowolnego języka odpowiedniego do zadania i powiedz każdemu, kto mówi coś innego, gdzie mogą to zrobić!
Ether
1
Możliwy duplikat stackoverflow.com/questions/150479/ ...
Michael Freidgeim

Odpowiedzi:

145

W Clean Code Robert C. Martin radzi programistom, aby zawsze umieszczali zmienne składowe na szczycie klasy (najpierw stałe, potem prywatne elementy członkowskie), a metody powinny być uporządkowane w taki sposób, aby czytały jak historię, która nie powoduje czytelnik musi za bardzo skakać po kodzie. Jest to bardziej rozsądny sposób organizowania kodu niż modyfikator dostępu.

Asaf
źródło
10
Miałem szczęście również dodać: getters / setters last. Dzięki temu zajęcia są mniej masywne.
Dean J
5
Konstruktory u góry, zaraz po zmiennych składowych. W OOP wykonanie rozpoczyna się od utworzenia instancji obiektu.
Asaph
6
Spowodowanie zbytniego przeskakiwania przez czytelnika po kodzie prawdopodobnie musi być zrównoważone przez zmuszenie czytelnika do przeczytania wszystkich podstawowych szczegółów metod prywatnych. Metafora gazetowa jest prawdopodobnie źle zrozumiana, ponieważ twoje metody publiczne powinny ogólnie reprezentować to, co robi twoja klasa, a twoje metody prywatne dostarczają szczegółów (prawie jak przypis, do którego możesz się odwołać, jeśli zajdzie taka potrzeba).
Kenny Hung
1
Jestem zmieszany. Powiedziałeś: (najpierw stałe, potem prywatni członkowie) . OK. Dokąd więc idą członkowie publiczni?
Kochanie,
1
@ Kochanie Oni poszliby zaraz po stałych i prywatnych członkach. To byłoby w następującej kolejności: stałe, członkowie prywatni, członkowie publiczni.
Pierre Gillet
49

Najlepszą praktyką jest konsekwencja .

Osobiście wolę stawiać publicnajpierw metody, potem protectedmetody, potem privatemetody. Dane członków powinny być generalnie zawsze prywatne lub chronione, chyba że masz dobry powód, aby tego nie robić.

Moje uzasadnienie dla umieszczania publicmetod na górze jest takie, że definiuje interfejs dla twojej klasy, więc każdy, kto przegląda twój plik nagłówkowy, powinien mieć możliwość natychmiastowego zobaczenia tych informacji.

W ogóle, privatea protectedczłonkami są mniej ważne dla większości ludzi szukających w pliku nagłówkowym, chyba że rozważa modyfikację wewnętrzne klasy. Utrzymywanie ich „z dala od drogi” zapewnia, że ​​informacje te są przechowywane tylko w przypadku konieczności ich poznania , co jest jednym z ważniejszych aspektów hermetyzacji.

LeopardSkinPillBoxHat
źródło
LeopardSkikPBH, całkowicie się zgadzam ... to ma sens! Wydaje mi się, że byłem zdezorientowany, czy w tym przypadku pierwszeństwo mają var lub funcs. Dzięki!
tempname
11
Nie zgadzam się, że najlepszą praktyką jest konsekwencja. Istnieje wiele sposobów na konsekwentne pisanie nieczytelnego, nie do naprawienia kodu.
jason
3
@Jason to tak, jakby powiedzieć, że pozostawanie po swojej stronie drogi nie jest najlepszą praktyką, ponieważ nadal możesz mieć wypadek.
Rex M
1
@Jason - Może powinienem był być bardziej jasny. W tym konkretnym, dość subiektywnym przypadku (porządkowanie metod) uważam, że najlepszą praktyką jest konsekwencja. Każdy będzie miał opinie na temat najlepszego sposobu zamawiania rzeczy, ale jeśli z natury jesteś konsekwentny, powinno to być dość łatwe do utrzymania. Zgadzam się, że „bądź konsekwentny” nie zawsze jest najlepszą praktyką we wszystkich obszarach kodu, zwłaszcza jeśli weźmiesz pod uwagę niską jakość kodu, z którą często masz do czynienia.
LeopardSkinPillBoxHat
4
@Rex M: Nie, to, co powiedziałem, wcale nie jest podobne do twojej interpretacji. Chodzi mi o to, że samo bycie konsekwentnym nie jest w tym przypadku mocnym argumentem. W niektórych przypadkach spójność jest dobra (np. Umieszczenie nawiasów klamrowych). Ale te wybory faktycznie wpływają na czytelność kodu. Dlatego potrzebny jest argument silniejszy niż konsekwencja.
jason
9

Myślę, że mam inną filozofię w tej sprawie niż większość. Wolę grupować powiązane elementy razem. Nie mogę znieść konieczności skakania dookoła do pracy z klasą. Kod powinien płynąć, a użycie raczej sztucznej kolejności opartej na dostępności (publicznej, prywatnej, chronionej itp.) Lub instancji w porównaniu ze statyczną lub składową w porównaniu z właściwością i funkcją nie pomaga w utrzymaniu ładnego przepływu. Więc jeśli nave sposób publiczny Method, który jest realizowany przez prywatnych metod pomocniczych HelperMethodA, HelperMethodBitd wtedy zamiast mieć te metody daleko od siebie w pliku, będę trzymać je blisko siebie. Podobnie, jeśli mam metodę wystąpienia, która jest implementowana metodą statyczną, zgrupuję je również razem.

Więc moje zajęcia często wyglądają tak:

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;
    }       
}
Jason
źródło
9

Osobiście lubię mieć publiczne na górze, chronione, a potem prywatne. Powodem tego jest to, że gdy ktoś otworzy nagłówek, najpierw zobaczy, do czego ma dostęp, a następnie więcej szczegółów, gdy przewinie w dół.

Nie trzeba patrzeć na szczegóły implementacji klasy, aby jej użyć, wtedy projekt klasy nie jest dobrze wykonany.

AndersK
źródło
3

Bardzo mnie to obchodziło. W ciągu ostatnich kilku lat, używając nowoczesnych IDE, prawie wszystko jest tylko 1 lub 2 naciśnięcia klawiszy, pozwoliłem moim standardom znacznie się rozluźnić. Teraz zaczynam od statyki, zmiennych składowych, a potem konstruktorów nie martwię się o to zbytnio.

W C # pozwalam Resharper automatycznie organizować rzeczy.

ScottS
źródło
Zgadzam się. Moim normalnym trybem poruszania się po członkach w pliku jest użycie narzędzia wbudowanego w dowolne IDE lub edytor, którego używam. Faktyczne grupowanie członków staje się drugorzędne. Zgadzam się jednak, że członkowie powinni być grupowani, aby uniknąć czystego losowego porządkowania, i używam resharper do automatycznego grupowania i porządkowania.
Phillip Ngan
2

To byłoby moje zamówienie

  1. Zmienne statyczne
  2. Metody statyczne
  3. Zmienne publiczne
  4. Zmienne chronione
  5. Zmienne prywatne
  6. Konstruktorzy
  7. Metody publiczne
  8. Metody chronione
  9. Metody prywatne

Stosuję następujące zasady:

  • statyczne przede wszystkim
  • zmienne przed konstruktorami przed metodami (uważam, że konstruktory należą do kategorii metod)
  • publiczny przed chroniony przed prywatnym

Chodzi o to, aby zdefiniować obiekt (dane) przed zachowaniami (metodami). Statyki należy oddzielić, ponieważ nie są one tak naprawdę częścią obiektu ani jego zachowania.

barkmadley
źródło
dziękuję barkmadley ... to interesujące! że należy umieścić 4 i 5 przed konstruktorem. Na pewno o tym
pomyślę
Jak ta kolejność, chociaż posiadanie metod statycznych u góry jest interesujące. Pracowałem z programistą, który umieścił zmienne prywatne na dole, widziałem pomysł, ale nie wydawał się właściwy
Carlton,
2

Generalnie zgadzam się z porządkiem publicznym, chronionym, prywatnym, a także z danymi statycznymi, danymi członków, porządkiem funkcji członków.

Chociaż czasami grupuję jak członkowie (pobierający i ustawiający), generalnie wolę wymieniać członków w grupie ALFABETYCZNIE, aby łatwiej było ich zlokalizować.

Lubię też układać dane / funkcje w pionie. I tabulację / spację w prawo, aby wszystkie nazwy były wyrównane w tej samej kolumnie.

AlanKley
źródło
1
Hej - „tab-spacer” po moim własnym sercu! :-) Nie jestem obsesyjno-kompulsywny. Szczerze, nie jestem!
tempname
1

Każdemu z nich, jak mówi Elzo, nowoczesne IDE ułatwiły znajdowanie członków i ich modyfikatorów dzięki kolorowym ikonom w rozwijanych menu i tym podobnych.

Uważam, że dla programisty ważniejsze jest, aby wiedział, do czego została zaprojektowana klasa i jak można się po niej spodziewać.

Tak więc, jeśli jest to Singleton, najpierw umieszczam semantykę (statyczna klasa getInstance ()).

Jeśli jest to konkretna fabryka, najpierw umieszczam funkcję getNew () i funkcje register / initialize.

... i tak dalej. Kiedy mówię najpierw, mam na myśli wkrótce po c'tors i d'tor - ponieważ są one domyślnym sposobem tworzenia instancji dowolnej klasy.

Następujące funkcje znajdują się wtedy w:

  1. logiczna kolejność wywołań (np. initialize (), preProcess (), process (), postProcess ()) lub
  2. powiązane funkcje (takie jak akcesoria, narzędzia, manipulatory itp.),

w zależności od tego, czy klasa miała być przede wszystkim magazynem danych z niektórymi funkcjami, czy dostawcą funkcji z kilkoma członkami danych.

Lis
źródło
0

Niektóre edytory, takie jak Eclipse i jego potomstwo, pozwalają na zmianę kolejności w widoku konspektu zmiennych i metod, alfabetycznie lub jak na stronie.

Elzo Valugi
źródło
0

Kolejność publicznych, po których następują chronione i prywatne, jest dla mnie bardziej czytelna. Lepiej jest opisać logikę klas w komentarzach na górze pliku nagłówkowego i rozkazami wywołania funkcji, aby zrozumieć, jaka dawka klasy i algorytmy są używane w środku.

Używam Qt c ++ od jakiegoś czasu i widzę nowe rodzaje słów kluczowych, takie jak signali slotwolę zamawiać dalej jak powyżej i podzielić się z wami moim pomysłem tutaj.

#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
saeed
źródło