Лучшая практика: упорядочивание общедоступного / защищенного / частного в определении класса?


94

Я начинаю новый проект с нуля и хочу, чтобы он был чистым / имел хорошие стандарты кодирования. В каком порядке опытные разработчики здесь любят раскладывать вещи внутри класса?

A: 1) общедоступные методы 2) частные методы 3) общедоступные вары 4) частные вары

B: 1) публичные vars 2) частные vars 3) публичные методы 4) частные методы

C: 1) общедоступные вары 2) общедоступные методы 3) частные методы 4) частные вары

Обычно мне нравится размещать общедоступные статические переменные вверху, но тогда будет ли публичный статический метод перечисляться перед вашим конструктором или конструктор всегда должен быть указан первым? Что-то в этом роде...

Я знаю, что это сложно, но я просто подумал: каковы лучшие практики для этого?

PS: нет, я не использую Cc #. Я знаю. Я луддит.


9
Нет ничего плохого в том, чтобы не использовать C #. За все годы работы профессиональным разработчиком я ни разу не написал ни строчки на C #. Используйте тот язык, который подходит для задачи, и скажите любому, кто говорит что-то другое, куда они могут пойти!
Ether

Ответы:


146

В « Чистом коде» Роберт С. Мартин советует кодировщикам всегда помещать переменные-члены в начало класса (сначала константы, затем частные члены), а методы должны быть упорядочены таким образом, чтобы они читались как история, которая не вызывает читателю придется слишком много прыгать по коду. Это более разумный способ организации кода, нежели модификатор доступа.


10
Мне также повезло с добавлением: последние геттеры / сеттеры. Мне это помогает сделать занятия менее громоздкими.
Dean J

5
Конструкторы вверху, сразу после переменных-членов. В ООП выполнение начинается с создания экземпляра объекта.
Asaph

6
Принуждение читателя слишком много прыгать по коду, вероятно, должно быть сбалансировано с принуждением читателя читать все мельчайшие детали частных методов. Газетная метафора, вероятно, неправильно понимается в том смысле, что ваши общедоступные методы должны широко представлять то, что делает ваш класс, а ваши частные методы предоставляют детали (почти как сноска, на которую вы можете ссылаться, если вам нужно).
Кенни Хунг

1
Я в замешательстве. Вы сказали: (сначала константы, затем частные члены) . ОК. Куда же тогда деваются представители общественности?
Дорогая,

1
@Honey Они пойдут сразу после констант и частных членов. Итак, это будет в следующем порядке: константы, частные члены, открытые члены.
Pierre Gillet

49

Лучшая практика - быть последовательным .

Лично я предпочитаю ставить publicсначала методы, затем protectedметоды, а затем privateметоды. Члены данных должны вообще всегда быть частными или защищенными, если у вас есть веские основания для того , чтобы не быть так.

Мое объяснение для размещения publicметодов наверху состоит в том, что они определяют интерфейс для вашего класса, поэтому любой, кто просматривает ваш файл заголовка, должен иметь возможность немедленно увидеть эту информацию.

В общем, privateи protectedчлены менее важны для большинства людей , глядя на файл заголовка, если они не рассматривают изменения внутренних элементов класса. Хранение их «в стороне» гарантирует, что эта информация будет храниться только по мере необходимости , что является одним из наиболее важных аспектов инкапсуляции.


LeopardSkikPBH, я полностью согласен ... в этом есть смысл! Думаю, я был сбит с толку относительно того, имеют ли в этом преимущество var или funcs. Благодарность!
tempname

12
Я не согласен с тем, что лучшая практика - быть последовательной. Есть много способов постоянно писать нечитаемый и некрашиваемый код.
jason

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 для автоматического группирования и упорядочивания.
Филип Нган

2

Это будет мой заказ

  1. Статические переменные
  2. Статические методы
  3. Публичные переменные
  4. Защищенные переменные
  5. Частные переменные
  6. Конструкторы
  7. Публичные методы
  8. Защищенные методы
  9. Частные методы

Я использую следующие правила:

  • статика прежде всего
  • переменные перед конструкторами перед методами (я считаю, что конструкторы относятся к категории методов)
  • публичное прежде защищенное прежде частное

Идея состоит в том, что вы определяете объект (данные) до поведения (методов). Статику нужно разделять, потому что на самом деле они не являются частью объекта или его поведения.


спасибо barkmadley ... это интересно! что вы поставили бы 4 и 5 перед конструктором. Я обязательно подумаю об этом
tempname

Как этот порядок, хотя наличие статических методов вверху интересно. Я работал с разработчиком, который помещал частные переменные внизу, я видел идею, но это казалось неправильным
Карлтон

2

Я в целом согласен с публичным, защищенным, частным порядком, а также со статическими данными, данными-членами, порядком функций-членов.

Хотя я иногда группирую членов группы (геттеры и сеттеры), я обычно предпочитаю перечислять членов внутри группы БУКВЕННО, чтобы их было легче найти.

Мне также нравится выстраивать данные / функции по вертикали. Я делаю табуляцию / пробел вправо достаточно, чтобы все имена были выровнены в одном столбце.


1
Эй, «табуляция» в честь моего сердца! :-) Я не навязчивый. Честно говоря, нет!
tempname

1

Каждому свое, и, как говорит Эльзо, современные IDE упростили поиск участников и их модификаторов с помощью цветных значков в раскрывающихся меню и т. Д.

Я считаю, что программисту более важно знать, для чего был разработан класс и как от него ожидать поведения.

Итак, если это синглтон, я сначала ставлю семантику (статический класс getInstance ()).

Если это конкретная фабрика, я сначала помещаю функцию getNew () и функции регистрации / инициализации.

... и так далее. Когда я говорю «первый», я имею в виду вскоре после c'tors и d'tor - поскольку они являются способом создания экземпляра любого класса по умолчанию.

Следующие ниже функции находятся в:

  1. логический порядок вызова (например, initialize (), preProcess (), process (), postProcess ()) или
  2. связанные функции вместе (например, аксессоры, утилиты, манипуляторы и т. д.),

в зависимости от того, предназначался ли класс в первую очередь как хранилище данных с некоторыми функциями или поставщик функций с несколькими членами данных.


0

Некоторые редакторы, такие как Eclipse и его дочерние продукты, позволяют вам переупорядочивать в общем виде вары и методы в алфавитном порядке или как на странице.


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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.