ООП: Когда это объект? - PullRequest
       19

ООП: Когда это объект?

23 голосов
/ 30 ноября 2009

Я пытаюсь понять ориентацию объекта. Я немного понимаю, конечно, но иногда я не на 100% уверен. Как вы решаете, что следует превратить в объект (маленький объект - часть другого большого целого объекта) или что не стоит быть объектом, или, может быть, это должно быть просто свойство этого большого целого объекта?

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

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

Спасибо

Ответы [ 20 ]

30 голосов
/ 30 ноября 2009

Как всегда, ответ к сожалению: это зависит ...

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

Возьмите автомобиль и его колеса - если вы моделируете город и хотите немного трафика, вы можете создать класс 'Car' с атрибутом numberOfWheels. Но если вы проектируете автомобили, то, скорее всего, вы захотите создать класс «Колесо» и добавить четыре из них в класс «Автомобиль».

Правило большого пальца:

  1. если то, о чем вы думаете, имеет более одного атрибута, определите класс
  2. если то, о чем вы думаете, имеет какое-то поведение, определите класс
  3. если то, о чем вы думаете, может расти или расширяться, определите класс
  4. если то, о чем вы думаете, должно быть сортируемым, сопоставимым, определить класс
  5. если вы не уверены, определите класс;)

Редактировать

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

12 голосов
/ 30 ноября 2009

Во-первых: забудьте о физических объектах. Я знаю, что все учебники, «учебные примеры», используют их, но вы только запутаетесь, когда попытаетесь смоделировать реальную систему. Не существует прямой связи между физическими объектами и объектами.

Объект - это структура данных, объединенная с набором методов, которые могут работать с этой структурой данных. Свойства объекта содержат состояние объекта, а методы работают с ним.

Какое состояние системы вы пытаетесь смоделировать? Это находится в двери, ручке или некоторой комбинации этих двух?

Существуют некоторые методологии, которые пытаются четко определить объектную модель до начала кодирования. Другие методологии (например, TDD) позволяют объектной модели появляться в процессе кодирования. В вашем случае я бы порекомендовал кодировать некоторые приложения малого и среднего размера с использованием TDD, чтобы вы могли видеть преимущества и недостатки различных шаблонов. Существует редко один «правильный» способ моделирования конкретной ситуации, но некоторые модели намного проще в использовании и понимании, чем другие; Признание шаблонов, применимых к ситуации перед вами, приходит с опытом.

Итак, суть: сделайте много моделей. Думайте о доменах приложений, моделируйте их и кодируйте. При этом все станет намного яснее. Сделай песочницу и прыгай внутрь.

10 голосов
/ 30 ноября 2009

Решая, является ли что-то объектом или нет, спросите себя, имеет ли оно следующее ...

Состояние

Имеет ли кандидат значительное состояние? Если этого не произойдет, то все методы на нем, вероятно, будут только слабо связаны. В этом случае вы, вероятно, определили библиотеку модуля многоразовых функций.

Поведение

Действительно ли объект что-то делает в домене? Например, он просто полон аксессоров, которые манипулируют структурой или записью.

Идентичность

Действительно ли объект существует в домене как идентифицируемая сущность? Есть ли какой-то врожденный аспект сущности, который отличает ее от аналогичных других сущностей? Дверная ручка является примером - на самом деле она не имеет идентичности, поскольку одна дверная ручка, вероятно, будет такой же, как другая.

Если вы ответите «нет» на некоторые из них, то, вероятно, у вас нет объекта - и это прекрасно, библиотека или модуль могут быть ценным артефактом для повторного использования


Прежде всего, не беспокойтесь об этом ...

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

4 голосов
/ 30 ноября 2009

Это немного зависит от использования. Для примера: если дверная ручка является важной частью и может (потенциально) использоваться для другой двери (или для другой «ручки» может использоваться другая ручка), то, вероятно, это должен быть объект.

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

3 голосов
/ 30 ноября 2009

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

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

2 голосов
/ 30 ноября 2009

Это объект, если вам нужно думать о нем как о ... объекте.

То есть, если вам нужна абстракция.

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

1) Может быть boolean свойством, если вам просто нужно знать, что оно есть у вашей двери:


class Door
{
    bool HasKeyHole;
}

2) Может быть пара координат, если вы просто хотите нарисовать свою дверь и поставить круг вместо отверстия для ключа


 class Door
 {
    Point KeyHoleCoordinates;
 }

3) Может быть специально определенным классом KeyHole, если вы хотите инкапсулировать логику и некоторые свойства ключевой дыры и работать с ними вместе, возможно, передавая их или разрешая взаимодействие с Key


class KeyHole
{
    Point Coordinates;
    bool OpensWithKey(Key key);
}

class Door
{
    KeyHole Hole;
}

2 голосов
/ 30 ноября 2009

Учебным способом определения гранулярности объекта является сплоченность.

Если большинство методов вашего объекта работает с большинством полей объекта, то объект достаточно мал (для заданного значения «most»).

Объект почти никогда не бывает слишком маленьким.

2 голосов
/ 30 ноября 2009

Я бы посоветовал вам подумать о том, как вы собираетесь его использовать. Подумайте, какие операции вам придется делать с вашей «вещью», а затем подумайте, что будет самым простым способом сделать это. Иногда будет проще сделать его свойством другого объекта, иногда будет проще сделать его новым собственным объектом.

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

Добавлено: Если взять пример двери / дверной ручки / замочной скважины - что вы будете делать с замочной скважиной? Вот некоторые факторы, которые позволили бы сделать замочную скважину отдельным объектом:

  • Вы хотите сохранить многие свойства замочной скважины, такие как размер, форма, направление, количество штифтов, возможность поворота ключа один или два раза и т. Д .;
  • На дверной ручке может быть несколько замочных скважин;
  • Вы хотите присвоить замочной скважине некоторые свойства только для чтения (например, заблокированы они или нет), а затем разрешить их изменение только с помощью определенных методов (например, метод «разблокировать», который принимает объект «ключ» в качестве параметров);
  • Замочные скважины хранятся в отдельной таблице БД с одним замочным отверстием на строку БД (тогда может иметь смысл сделать объект замочной скважины имитирующим структуру БД);
  • В вашей системе есть методы, которые были бы элегантно реализованы, если бы они могли использовать замочную скважину в качестве параметра;

Сценарии для превращения его в свойство противоположны:

  • Каждая дверная ручка может иметь только одну замочную скважину, и она имеет только одно или очень мало свойств;
  • замочные скважины хранятся вместе с дверными ручками в БД;
  • Обычно вам не важна только одна замочная скважина, вы просто хотите, чтобы она была описательной собственностью дверной ручки (например, есть она или нет);
1 голос
/ 30 ноября 2009

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

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

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

1 голос
/ 30 ноября 2009

В общем, если вам требуется больше информации от него, чем просто одна вещь (не только состояние ручки, но также ее цвет, ее точное местоположение, есть ли у нее паз для ключа, возможность изменить его состояние / поведение и т. д.), а затем сделать его объектом. Таким образом, если вы не можете сохранить всю информацию, которую дверь должна знать о ручке, в виде простых String, Number или Boolean, то сделайте ее полноценной Knob.

Как и везде у вас есть "угловые шкафы". Я вижу это часто с парами. Два свойства, которые связаны друг с другом, но обычно ни с чем. Они не всегда группируются в отдельный объект реального мира. Например sortDirection и sortField. Принадлежность к их собственному объекту зависит от того, что представляет родительский объект. Это сортируемая реализация List? Хорошо, держи это там. Это Door? Ну, я бы, возможно, вывел это из себя.

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