Лучшие практики для класса с большим количеством участников - PullRequest
10 голосов
/ 26 октября 2010

Любые мнения о наилучшем способе организации членов класса (особенно, когда их много) в C ++.В частности, класс имеет множество пользовательских параметров, например, класс, который оптимизирует некоторую функцию и имеет ряд параметров, таких как количество итераций, размер шага оптимизации, конкретный метод для использования, веса функций оптимизации и т. Д. И т. Д. Я пробовал несколькообщие подходы и, кажется, всегда находят что-то неидеальное с ним.Просто любопытные переживания других.

  1. структура внутри класса
  2. структура вне класса
  3. открытые переменные-члены
  4. закрытые переменные-члены с функциями Set () и Get ()

Если говорить более конкретно, код, над которым я работаю, отслеживает объекты в последовательности изображений.Поэтому одним важным аспектом является то, что он должен сохранять состояние между кадрами (почему я не просто сделал кучу функций).Важные функции-члены включают initTrack (), trackFromLastFrame (), isTrackValid ().И есть множество пользовательских параметров (например, сколько точек для отслеживания на отслеживаемый объект, сколько точек может перемещаться между кадрами, используемый метод отслеживания и т. Д. И т. Д.)

Ответы [ 7 ]

5 голосов
/ 26 октября 2010

Если ваш класс БОЛЬШОЙ , то ваш класс ПЛОХОЙ .Класс должен уважать Принцип единой ответственности , то есть: класс должен делать только одно, но должен делать это хорошо.(Ну, «только одна» вещь экстремальна, но она должна иметь только одну роль, и она должна быть четко реализована).

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

БОЛЬШИЕ функции и БОЛЬШИЕ классы являются местом для ошибок, недопонимания и нежелательных побочных эффектов (особенно во время сопровождения), потому что НИКАКИЙ МУЖЧИНА не может выучить за минуты 700 строк кода.

Итак, политика для БОЛЬШИХ классов: Refactor, Composition с небольшими классами, нацеленными только на то, что они делают.

3 голосов
/ 26 октября 2010

Во-первых, я бы разделил членов на два набора: (1) те, которые предназначены только для внутреннего использования, (2) те, которые пользователь настроит для управления поведением класса.Первый набор должен быть просто закрытыми переменными-членами.

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

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

ObjectTracker tracker;  // invokes constructor which gets default params
TrackerParams params = tracker.GetTrackingParameters();
params.number_of_objects_to_track = 3;
params.other_tracking_option = kHighestPrecision;
tracker.SetTrackingParameters(params);
// Now start tracking.

Если вы позже изобрели новый параметр, вам просто нужнообъявить нового члена в TrackerParams и инициализировать его в конструкторе ObjectTracker.

3 голосов
/ 26 октября 2010

если бы мне пришлось выбрать одно из четырех перечисленных вами решений: закрытый класс внутри класса.

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

2 голосов
/ 26 октября 2010

Все зависит:

  1. Внутренняя структура будет полезна, только если вам нужно организовать ОЧЕНЬ много элементов. И если это так, вы должны пересмотреть свой дизайн.
  2. Внешняя структура будет полезна, если она будет использоваться совместно с другими экземплярами того же или другого класса. (Хороший пример - модель или класс / структура объекта данных)
  3. Рекомендуется только для тривиального одноразового кода.
  4. Это стандартный способ ведения дел, но все зависит от того, как вы будете использовать класс.
1 голос
/ 26 октября 2010

Похоже, это может быть работа для шаблона, способ, которым вы описали использование.

template class FunctionOptimizer <typename FUNCTION, typename METHOD, 
    typename PARAMS>

например, где PARAMS инкапсулирует простые параметры прогона оптимизации (# итераций и т. Д.) И METHOD содержит актуальный код оптимизации.FUNCTION описывает базовую функцию, которую вы нацеливаете на оптимизацию.

Суть не в том, что это «лучший» способ сделать это, а в том, что если ваш класс очень большой, то внутри, вероятно, есть меньшие абстракцииэто то, что поддается естественному рефакторингу в менее монолитную структуру.

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

0 голосов
/ 26 октября 2010

Предполагая, что параметры конфигурации применяются только к этому классу, используйте закрытые переменные, которыми манипулируют открытые функции со значимыми именами функций. SetMaxInteriorAngle() намного лучше, чем SetMIA() или SetParameter6(). Наличие методов получения и установки позволяет применять правила согласованности конфигурации и может использоваться для компенсации определенных изменений в интерфейсе конфигурации.

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

Публичные члены-данные, как правило, являются плохой идеей, поскольку они раскрывают реализацию класса и делают невозможным какое-либо гарантированное отношение между ними. Выделение их в отдельной внутренней структуре не кажется полезным, хотя я бы сгруппировал их в списке элементов данных и выделил их комментариями.

0 голосов
/ 26 октября 2010

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

Существует компромисс между открытыми членами и функциями Set / Get.Публичные участники гораздо менее шаблонны, но они раскрывают внутреннюю работу класса.Если это будет вызвано из кода, который вы не сможете реорганизовать, если вы реорганизуете класс, вы почти наверняка захотите использовать Get и Set.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...