Вопрос

Я давний разработчик (мне 49), но скорее новичок в объектно -ориентированном разработке. Я читал о ОО со времен Бертранда Мейера Эйфеля, но сделал действительно мало программирования ОО.

Дело в том, что каждая книга о дизайне OO начинается с примера лодки, автомобиля или любого общего объекта, который мы используем очень часто, и они начинают добавлять атрибуты и методы, и объясняют, как они моделируют состояние объекта и что можно сделать с Это.

Таким образом, они обычно делают что -то вроде «чем лучше модель, тем лучше она представляет объект в приложении, и тем лучше все выйдет».

Пока все хорошо, но, с другой стороны, я нашел несколько авторов, которые дают рецепты, такие как «класс должен поместиться только на одной странице» (я бы добавил «в какой размер монитора?» Теперь, когда мы не пытаемся не пытаться печатать код!).

Взять, к примеру PurchaseOrder класс, у которого есть конечная машина, управляющая его поведением и набором PurchaseOrderItem, один из аргументов здесь, на работе, заключается в том, что мы должны использовать PurchaseOrder простой класс, с некоторыми методами (чуть больше, чем класс данных), и имеет PurchaseOrderFSM «Экспертный класс», который обрабатывает конечную машину для PurchaseOrder.

Я бы сказал, что в классификации Джеффа Этвуда попадает в классификацию «зависть к функции» или «неуместная интимность» Код пахнет Сообщите о кодировании ужаса. Я бы просто назвал это здравым смыслом. Если я могу выпустить, утвердить или отменить свой реальный заказ на покупку, то PurchaseOrder Класс должен иметь issuePO, approvePO а также cancelPO методы

Разве это не связано с «максимизацией сплоченности» и «сведена к своему возрастам», которые я понимаю, как краеугольные камни ОО?

Кроме того, разве это не помогает в области обслуживания класса?

Это было полезно?

Решение

Класс должен использовать принцип единственной ответственности. Большинство очень больших классов, которые я видел со многими вещами, поэтому они слишком велики. Посмотрите на каждый метод и код, решайте, если он будет в этом классе или отдельном, дублированный код является подсказкой. У вас может быть метод EsuePo, но он содержит, например, он, например, 10 строк кода доступа данных? Этот код, вероятно, не должен быть там.

Другие советы

По моему мнению, размер класса не имеет значения, пока переменные, функции и методы имеют отношение к рассматриваемому классу.

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

Для аналогии с вашей машиной, если класс car слишком велик, это, вероятно, указывает на то, что его нужно разделить на класс engine, учебный класс doorS и класс windshieldS и т. д.

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

  1. Есть ли много переменных, которые не зависят друг от друга? (Моя личная терпимость в большинстве случаев около 10 ~ 20)
  2. Есть ли много методов, предназначенных для угловых чехлов? (Моя личная терпимость ... ну, это очень зависит от моего настроения, я думаю)

Что касается 1, представьте, что вы определяете свой размер ветрового стекла, размер колеса, модель лампочки хвоста и 100 других деталей в вашем классе car Анкет Хотя все они «актуальны» для автомобиля, очень трудно проследить поведение такого класса car. Анкет И когда когда -нибудь ваш коллега случайно (или, в некоторых случаях, намеренно) изменяет размер лобового стекла на основе модели лампочки хвостовых ламп, вам требуется вечно, чтобы выяснить, почему лобовое стекло больше не вписывается в ваш автомобиль.

Что касается 2, представьте, что вы пытаетесь определить все поведения, которые автомобиль может иметь в классе car, но car::open_roof() будет доступен только для кабриолетов, и car::open_rear_door() не относится к этим 2-дверным автомобилям. Хотя кабриолеты и 2-дверные автомобили по определению являются «автомобилями», внедряя их в классе car усложняет класс. Класс становится все труднее использовать и труднее поддерживать.

Кроме этих 2 рекомендаций, я бы предложил четкое определение масштаба класса. Как только вы определите сферу, внедрите класс строго на основе определения. Большую часть времени люди получают «слишком большой» класс из -за плохого определения объема или из -за произвольных функций, добавленных в класс

Скажи, что тебе нужно в 300 строках

Примечание. Это правило, предполагает, что вы следите за подходом «один класс на файл», который сам по себе является хорошей идеей обслуживания

Это не абсолютное правило, но если я вижу более 200 строк кода в одном классе, я подозрительно. 300 строк и предупреждающие колокольчики включаются. Когда я открываю чужой код и нахожу 2000 строк, я знаю, что это время рефакторинга, даже не читая первую страницу.

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

Я обнаружил, что сгибаю это правило в модели -> ViewModel -> View World, где я создаю «объект поведения» для страницы пользовательского интерфейса, потому что часто требуется более 300 строк, чтобы описать полную серию поведения на страница. Однако я все еще новичок в этой модели программирования и нахожу хорошие способы рефакторинга/повторного использования поведения между страницами/видомоделями, что постепенно уменьшает размер моих ViewModels.

Давай вернемся назад:

Разве это не связано с «максимизацией сплоченности» и «сведена к своему возрастам», которые я понимаю, как краеугольные камни ОО?

На самом деле, это краеугольный камень программирования, из которого ОО - всего лишь одна парадигма.

Я позволю Антуан де Сен-Эксупри Ответьте на ваш вопрос (потому что я ленивый;)):

Совершенство достигается, не когда больше нечего добавить, но когда нечего забрать.

Чем проще класс, тем увереннее вы будете правильно, тем легче будет от корки до корки Проверь это.

Я с OP в классификации функции. Ничто не раздражает меня больше, чем провести кучу классов с кучей методов, которые работают на внутренних группах другого класса. OO предлагает вам моделировать данные и операции по этим данным. Это не значит, что вы ставите операции в другое место, чем данные! Он пытается заставить вас поместить данные и эти методы вместе.

С car а также person модели настолько распространены, что было бы похоже person учебный класс. Я надеюсь, что это будет очевидно неправильно любому опытному программисту.

У меня на самом деле нет идеального размера класса или метода, но я предпочитаю, чтобы мои методы и функции были подходящими на одном экране, чтобы я мог видеть их все в одном месте. (У меня есть VIM, настроенный на то, чтобы открыть окно с 60 линии, которое, как оказалось, находится вокруг количества строк на печатной странице.) Есть места, где это не имеет большого смысла, но это работает для меня. Мне нравится следить за тем же руководством для определений классов и стараться держать мои файлы в течение нескольких «страниц» длиной. Все, что более 300, 400 строк начинают чувствовать себя громоздким (в основном потому, что класс начал брать на себя слишком много прямых обязанностей).

Когда определение класса имеет пару сотен методов, оно слишком велика.

Я полностью согласен с использованием Принцип единственной ответственности Для занятий, но если это следует и приводит к большим классам, пусть будет так. Реальное внимание должно быть в том, что отдельные методы и свойства не слишком велики, Цикломатическая сложность Должно быть руководство и следующее, что может привести к многим частным методам, которые увеличат общий размер класса, но оставит его читаемым и тестируемым до гранулированного уровня. Если код остается читаемым, то размер не имеет значения.

Выпуск заказа на покупку часто является сложным процессом, который включает в себя не только заказ на покупку. В этом случае, вероятно, поддерживать бизнес -логику в отдельном классе и упростить заказ на покупку, вероятно, правильное. В целом, вы правы - вам не нужны классы «структура данных». Например, ваш бизнес -класс "Pomanager" issue() Метод, вероятно, должен назвать PO issue() метод Затем PO может установить свой статус для «выпущенного» и отметить дату выпуска, в то время как пенсажер может затем отправить уведомление о кредиторской задолженности, чтобы сообщить им, чтобы ожидать счета -фактуры, и другое уведомление о инвентаре, чтобы они знали, что что -то приходит и в ожидаемая дата.

Любой, кто выдвигает «правила» для метода/размера класса, очевидно, не потратил достаточно времени в реальном мире. Как упоминали другие, это часто является индикатором рефакторинга, но иногда (особенно в «обработке данных»-работой), вам действительно нужно написать класс с одним методом, который охватывает более 500 линий. Не зацикливайтесь на этом.

Я нашел несколько авторов, которые дают рецепты, такие как «класс, должен соответствовать одной странице»

С точки зрения только физического размера класса, видение большого класса является показателем запаха кода, но не обязательно означает, что всегда есть запахи. (Как правило, они есть), как выразили бы пираты в «Пиратах Карибского моря», это скорее то, что вы бы назвали «руководящими принципами», чем фактические правила. Я пытался строго следовать за «не более ста loc в классе» один раз, и результатом было много ненужных чрезмерных инженеров.

Таким образом, они обычно делают что -то вроде «чем лучше модель, тем лучше она представляет объект в приложении, и тем лучше все выйдет».

Я обычно начинаю свои дизайны с этого. Что делает этот класс в реальном мире? Как мой класс должен отразить этот объект, как указано в его требованиях? Мы добавляем здесь немного состояния, поле, метод для работы на этих полях, добавить еще несколько и вуаля! У нас есть рабочий класс. Теперь заполните подписи надлежащими реализациями, и мы готовы идти, или вы так думаете. Теперь у нас есть хороший большой класс со всей необходимой нам функциональностью. Но проблема с этим в том, что это не учитывает то, как реализует реальный мир. И под этим я имею в виду, что это не учитывает «Изменение».

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

Кроме того, в вашем примере добавление IssuePo, CustpoPO и отмена PO в класс покупок кажется нелогичным. Заказы на покупку не выпускают, одобряют и не отменяют себя. Если PO должен иметь методы, то методы должны работать над его состоянием, а не на классе в целом. Это действительно просто классы данных/записи, над которыми работают другие классы.

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

Достаточно маленький, чтобы быть подлежащим обслуживанию и следуйте Принцип единственной ответственности.

Лицензировано под: CC-BY-SA с атрибуция
scroll top