Должны ли объекты в ООП представлять сущность?


82

Должен ли объект представлять сущность?

Под организацией я имею в виду нечто вроде Product, Motor, А и ParkingLotт.д., физическая, или даже четкий нефизических концептуального объекта - то , что хорошо определен, с некоторыми основными данными явно принадлежащими к объекту, а также некоторые функции / методы которые четко оперируют основными данными.

Например, у меня может быть объект Demon, сущность сама по себе, воображаемая, может быть, и не физическая, а, тем не менее, сущность

Может ли объект быть просто набором методов , общим набором процедур, которые связаны с общей целью?

Пример: может быть вызван класс MotorOperationsили MotorActions, где нет сущности, но методы внутри класса делают такие вещи, как

  • getMotorDataFromHTMLForm ()
  • getMotorManufacturers ()
  • selectMotorFromUserRequirements ($ требования)
  • canMotorCanHandleOperatingConditions ($ условие)
  • computePowerConsumptionForMotor ($ ID)

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

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

Вопрос

Могут ли классы представлять объекты без сущности? Если нет, то почему они плохие / неполные / не ООП-ориентированные? Существуют ли способы их концептуального изменения / улучшения, чтобы они соответствовали ООП?


2
+1. Но будет ли «да» означать, что он должен представлять сущность, или это может означать, что они могут представлять объекты без сущности?
Panzercrisis

1
Первое, что приходит мне в голову: java.awt и его классы "Op" (например, docs.oracle.com/javase/7/docs/api/java/awt/image/… ), если вы это имеете в виду. Это представляет операцию. Я не уверен, что это хорошая практика (она выглядит странно и безобразно), но она включена в стандартную библиотеку Java, а Java - ООП. По большей части.
Люк

1
Нет , это не так, но это не значит , MotorActionsили MotorOperationsхорошие идеи или нет.
user253751

1
Этот вопрос может выиграть от дальнейшей спецификации банок .
reinierpost

3
@ Денис Я действительно чувствую, что ты задаешь все неправильные вопросы. Во-первых, потому что нет единого окончательного определения ООП, во-вторых, потому что парадигмы являются лишь средством для достижения цели. Единственные вопросы, которые имеют значение, - «облегчает ли написание кода таким образом его правильность?» и "написание кода таким образом облегчает повторное использование?"
Довал

Ответы:


109

Нет , объект не должен представлять сущность.

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

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

Объекты о сообщениях. Они об обязанностях. Они не об автомобилях, пользователях или заказах.

Я знаю, что мы преподаем ОО таким образом, но после нескольких попыток становится очевидным, насколько фундаментально сложно расставаться, когда дела идут, когда вы пытаетесь сделать MVC, MVVM или MVW, что угодно. Либо ваши модели становятся смехотворно раздутыми, либо контроллеры. Для удобства навигации важно знать, что все, что касается транспортных средств, находится в файле Vehicle.ext, но когда ваше приложение относится к транспортным средствам, вы неизбежно получите 3000 строк спагетти в этом файле.

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

Давайте поговорим о мешках функций

Объект может быть просто набором методов и при этом быть ОО, но мои «правила» довольно строги.

  1. На коллекцию должна быть возложена одна ответственность, и эта ответственность не может быть такой же общей, как «Делает вещи для моторов». Я мог бы сделать такую ​​вещь, как фасад уровня сервиса, но я прекрасно осознаю, что мне лень по причинам навигации / обнаружения, а не потому, что я пытаюсь написать ОО-код.

  2. Все методы должны быть на согласованном уровне абстракции. Если один метод извлекает объекты Motor, а другой возвращает мощность, это, вероятно, слишком далеко друг от друга.

  3. Объект должен работать на тех же «видах» данных. Этот объект работает с двигателями (запуск / останов), этот работает с длинами кривошипа, этот обрабатывает последовательность зажигания, этот принимает форму HTML. Эти данные могут быть полями на объекте, и они могут показаться связными.

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

Я считаю, что сосредоточение на предметных обязанностях ведет меня к сплоченности. Чтобы быть объектом, должна быть некоторая сплоченность, но для того, чтобы он был объектом, не требуется никаких полей или поведения. Если бы я строил систему, которая нуждалась в этих 5 моторных методах, я бы начал с 5 разных объектов, которые делают эти вещи. Когда я нашел общность, я бы либо начал объединять вещи, либо использовал общие «вспомогательные» объекты. Это приводит меня к открытым / закрытым проблемам - как я могу извлечь эту часть функциональности, чтобы мне больше никогда не приходилось изменять этот конкретный файл, а использовать его там, где это необходимо?

Объекты о сообщениях

Поля почти не имеют значения для объекта - получение и установка регистров не изменяет мир вне программы. Сотрудничество с другими объектами делает работу. Однако сила OO в том, что мы можем создавать абстракции, поэтому нам не нужно думать обо всех отдельных деталях одновременно. Абстракции, которые утекли или не имеют смысла, проблематичны, поэтому мы глубоко (слишком много, может быть) думаем о создании объектов, которые соответствуют нашим ментальным моделям.

Ключевой вопрос: почему эти два объекта должны общаться друг с другом?

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

Представьте себе сценарий, когда вы находитесь на пешеходном переходе, и машина едет быстро. Как объект мозга, я обнаруживаю стрессор. Я говорю гипоталамусу отправлять кортикотрофин-рилизинг-гормон. Гипофиз получает это сообщение и выпускает кортикотрофный гормон надпочечников. Надпочечники получают это сообщение и создают адреналин. Когда мышечный объект получает это сообщение адреналина, он сжимается. Когда сердце получает то же сообщение, оно бьется быстрее. Есть целая цепь игроков, вовлеченных в запуск сложного поведения бега через улицу, и это сообщения, которые имеют значение. Объект мозга знает, как заставить гипоталамус отправлять оповещение, но он не знает цепочку объектов, которые в конечном итоге приведут к тому, что поведение будет происходить. Точно так же сердце не знает, откуда берется адреналин,

Таким образом, в этом ( упрощенном ) примере объект надпочечников должен знать, как принимать АКТГ и вырабатывать адреналин. Для этого не нужны никакие поля, но мне все еще кажется, что это объект.

Теперь, если наше приложение предназначено только для бега через улицу, мне могут не понадобиться объекты гипофиза и надпочечников. Или мне нужен только объект гипофиза, который выполняет лишь небольшую часть того, что мы можем концептуально рассматривать как «модель гипофиза». Все эти понятия существуют как концептуальные сущности, но это программное обеспечение, и мы можем создать AdrenalineSender или MuscleContractor или что-то еще и не беспокоиться о «неполноте» нашей модели.


4
Я согласен с фактическим содержанием этого ответа, но мне кажется, что он неправильно понимает вопрос. В частности, вопрос включает в себя сущность «или понятие, то, что хорошо определено». Контрпримеры к этому - " MotorOperationsили MotorActions". Исходя из этого, я вполне уверен, что как исходный, так и окончательный дизайн классов из примера CoffeeMaker подпадают под определение ОП «представлять сущность»
Бен Ааронсон,

1
Постмодернистская системная архитектура DCI справляется с этим без экстремальных абстракций, созданных любителями структуры. Компьютер должен думать о том, что думает пользователь, а не наоборот. fulloo.info/doku.php?id=what_is_dci
ciscoheat

@BenAaronson Я чувствую, что вы можете развить этот объект как связную концепцию с достаточным количеством согласованных усилий, но я обнаружил тенденцию к тому, чтобы фокус-сущность объединяла вещи, которые должны быть отделены друг от друга. Сущности поощряют границы в наших именах, что хорошо, но они также несут с собой понятие правильности / полноты, которое имеет тенденцию причинять боль. В самых нелепых терминах я за объект FirstNameValidator и против объекта Name, который также выполняет проверку имени и фамилии.
Стив Джексон

1
Еще один хороший пример: ericlippert.com/2015/04/27/wizards-and-warriors-part-one
Moby Disk

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

21

Могут ли классы представлять объекты без сущности? Если нет, то почему они плохие / неполные / не ООП-ориентированные? Есть ли способы их изменения / улучшения?

Короче говоря, вы можете делать что угодно, но этот конкретный сценарий противоречит принципам ООП :)

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

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

Вы должны взглянуть на общие архитектурные шаблоны - один из них - MVC (Model-View-Controller) .

Если бы я распространял методы, которые вы перечислили, используя MVC, я бы сделал следующее:

Посмотреть класс:

  • GetMotorDataFromHTMLForm ()

Класс модели (мотор по существу):

  • GetMotorManufacturer ()
  • CanMotorHandleOperationConditions ()
  • CalculatePowerConsumption ()

Класс контроллера (MotorsController):

  • GetAllMotors ()
  • GetMotorById ()
  • GetMotorByUserRequirements ()

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

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


Благодарю. По сути, мне кажется, что у меня есть класс Controller с несколькими примесями (Model, View и т. Д.). Означает ли это , что если я переименовать MotorOperationsв MotorsControllerи очистить его немного, мой набор функций будет осуществляться в соответствии с ООП?
Деннис

@Dennis, не обязательно, взгляните на мою коллекцию методов для каждого класса. Контроллер - это не класс, который содержит все это :) Это класс, который работает с вашими моделями, и ничего более. Единственными зависимостями контроллера, как правило, являются непосредственно DAL (уровень доступа к данным) или службы, предоставляющие вам доступ к DAL. Вы никогда не хотите обращаться к View из контроллера (пример: getMotorDataFromHTMLForm), вместо этого ваш View должен зависеть от контроллера.
Алексус

2
Не могли бы вы пояснить, почему Utilsкласс является примером запаха кода? Просто любопытно, так как мне самому нравилось иметь в Utilsклассе случайные функции утилит, а не просто быть автономными функциями ... по моему опыту это делает код немного более читабельным, но мой опыт ограничен.
HC_

3
@HC_ Наличие класса Utils - это то же самое, что наличие папки «Разное» в вашей коллекции изображений. Это указывает на то, что вам лень назначать обязанности своим объектам должным образом / потенциально отсутствующим объектам и использовать Utils для компенсации этого. Есть место для классов Util, особенно со статическими функциями и расширениями для других классов, но перед тем, как создавать такую ​​коллекцию, проверьте, можете ли вы включить их в ваши собственные классы ООП :) Другая причина - иногда класс может иметь только один метод. Но в дальнейшем вам нужно добавить больше, и класс Utils станет еще большим беспорядком.
Алексус

Я часто получаю библиотеку Utils, но обычно стараюсь группировать и называть свои классы утилит более наглядно. В наши дни существует множество библиотек с «общедоступными утилитами» с открытым исходным кодом, в которых уже есть утилиты общего назначения, которые нужны большинству людей, поэтому я бы немного огляделся, прежде чем писать свои собственные.
Гай Шалнат

15

Могут ли классы представлять объекты без сущности?

Можно? Да. Должен? Наверное, нет - или, по крайней мере, не так, как вы формулируете вещи.

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

Простое связывание связки тангенциально связанных функций - это пространство имен или модуль, а не объект на языке ООП. Они могут быть полезны, но они не одинаковы, и для их эффективной работы требуется другой тип использования / мышления.


3
bundling a bunch of tangentially related functions together is a namespaceэто больше похоже на процедурную парадигму, чем на объектно-ориентированную.
Деннис

@dennis - точно (или функционально, если вы называете это модулем). Смешивание парадигм может быть мощным. Или это может быть ужасно грязно.
Теластин

Или оба :) - - - - -
Алексус

@ Денис: Или ни то, ни другое - объединение только тангенциально связанных функций - сомнительная практика в любой парадигме.
Сденхэм

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

11

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

Удачи.


Да, это почти точно, что я бы сказал. Класс - это не что иное, как модель для существительного . Вот и все. Ни больше ни меньше. Класс - это существительное, а методы - это глаголы (или сообщения, если вы предпочитаете). Младший инженер, который думает в этих простых терминах, может пройти долгий путь, прежде чем эти аналогии разрушатся (в отличие от попыток притвориться, что классы являются описаниями физических объектов - аналогия, которая начинает разрушаться почти в вашем первом проекте).
Calphool

7

Нет. (Название отредактировано, чтобы задать противоположный вопрос!)

например:

Public class MyRepository
{
    public MyObject GetObject(string id)
    {
        //get data from the DB and build an object
    }
}

или же

Public class MyService
{
    public MyObject3 ProcessData(MyObject1 obj1, MyObject2 obj2)
    {
         //perform a process which is not a sole responsiblity of obj1 or obj2
    }
}

Однако в целом идеал, стоящий за ООП, - это отойти от

public struct Car
{
    public Wheel[] Wheels;
}

public int CountWheelsOnCar(MyCarStruct car)
{
   return car.Wheels.Length;
}

в

public class Car
{
    private Wheel[] wheels;
    Public int CountWheels()
    {
        return this.wheels.Length;
    }
}

Вы имеете в виду, что они могут представлять объекты без сущности? (См. Комментарий, который я оставил по этому вопросу.)
Panzercrisis

3
Думаю, я слишком долго программировал OO - когда я посмотрел на MyRepository, я сразу же изобразил стеклянную чашу на комоде с кучей монет и дерьмом в ней. Доберись и возьми пенни или кнопку ...
Билл К

@Pan Да, как и сервис и репо в моем примере
Ewan

@ Билл, ты, сумасшедший старый дурак !!! Это класс MyButtonAndOrPennyBowl! чистое кодирование ftw
Ewan

1
Ваш второй пример выглядит для меня как функция, одетая как объект, которая (на мой взгляд) не оправдана сама по себе, хотя может быть и другое обоснование (например, если функции не являются первоклассными сущностями в языке. )
sdenham

5

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

Фактически, в зависимости от того, насколько буквальным вы хотите быть, многие объекты, с которыми мы работаем, вообще не имеют физических представлений. Например, рассмотрим архитектуру MVC. В реальном мире нет моделей или контроллеров, даже если они обычно представлены классами. Три вместе часто представляют что-то, но не всегда - но, как я уже сказал, вы, вероятно, можете заставить что-то вписаться во что-то, если вы действительно этого хотите (и возможность представить, что ЧТО-ТО помогает! Вы бы когда-нибудь увидели в реальном мире).

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

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


5

Должен ли объект представлять сущность?

Вопрос: Какую сущность Loggerпредставляет?

Не в переносном смысле - в буквальном смысле.

При объяснении ООП студентам полезно объяснять объекты с аналогиями с физическим миром.

Алан Кей - один из отцов ООП - написал следующее:

[...]

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

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

[...]

ООП для меня означает только обмен сообщениями, локальное хранение и защиту и

сокрытие состояния-процесса и крайняя поздняя привязка всех вещей.

почти невероятная архитектура HW. Я понял, что

метафора сотовый / целый компьютер избавит от данных

источник

Исходя из этого, объекты лучше всего понимать как

  • автаркические объекты, инкапсулирующие / скрывающие данные

  • общение с другими объектами с помощью сообщений

Могут ли классы представлять объекты без сущности?

Определенно: подумайте о Math


По поводу вашего примера:

Пример: может ли класс называться MotorOperations или MotorActions, где нет сущности, но методы внутри класса делают такие вещи, как

  • getMotorDataFromHTMLForm ()

  • getMotorManufacturers ()

  • selectMotorFromUserRequirements ($ требования)

  • canMotorCanHandleOperatingConditions ($ условие)

  • computePowerConsumptionForMotor ($ ID)

Чтобы решить, куда поместить эти методы, вы должны взглянуть на responsibilities: кто за что отвечает .

getMotorDataFromHTMLForm ()

Контекстом такого метода будет конструирование моторного объекта . Мотор не несет ответственности за создание себя из данных, полученных с помощью формы . Есть как минимум два объекта; один - двигатель, а другой - создатель двигателя .

getMotorManufacturers ()

Типичный контекст, в котором можно написать такой метод, это service.

selectMotorFromUserRequirements ($ требования)

Это также будет использоваться в service-context

canMotorCanHandleOperatingConditions ($ условие)

Это вопрос к motor-объекту

computePowerConsumptionForMotor ($ ID)

Это тоже вопрос, который лучше всего задать самому двигателю.


ТЛ; др

Метафора objectsкак физически объектов более раздражающего , чем полезно.


вау твой ответ вдыхает жизнь в ООП! Я должен сказать, что я не имел в виду физическое как конец всего этого. цель моего вопроса заключалась в следующем: «должен ли объект быть thingс данными, когда данные явно принадлежат вещи, и функции, которые явно работают с данными, принадлежащими этой вещи». Таким образом, Logger в данном случае, хотя и не физическая вещь, это понятие, похожее на «физическую книгу журналов». Имеются ли у него данные, которые являются ключевыми для его состояния, а не просто кратковременны для него, это может зависеть от реализации и интерпретации ... и в большей степени от того, куда уходит мой вопрос ..
Деннис

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

3

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

На языке с процедурными модулями (я думаю, что в PHP есть процедурные модули), вы можете рассмотреть возможность использования только процедурного модуля.

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

Но используйте обозначение OO только тогда, когда оно дает вам дополнительную мощность, а не только ради того, чтобы быть OO!


3

По словам непрофессионала

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

Такие классы существуют, например, Java SDK имеет класс Collections, который состоит исключительно из статических методов, которые работают или возвращают коллекции.

Таким образом, ответ будет «нет», не все классы должны моделироваться из сущности домена.

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

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


2

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

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

.NETMath - отличный пример «профессионального» класса, который не представляет никакой сущности (если только вы не хотите философствовать о том, что такое математика ...), а также иллюстрирует законный вариант использования такого класса. Он имеет только методы и 2 поля (оба представляют отдельные константы).

Иерархия классов подобной библиотеки Math.Netгруппирует математические / численные методы по классам по типу. Здесь классы представляют не сущность, а логическую категорию.

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


1
Тот факт, что математические методы помещаются в .NET / BCL в отдельный класс в качестве статических методов, не является необходимостью или конструктивным соображением, а является следствием того факта, что в C # нет автономных методов. В C ++ такие функции могут быть просто сгруппированы в пространство имен.
Влад

1

Ответы на ваши вопросы в конечном счете зависят от того, насколько точно определены такие термины, как «класс» и «сущность». Вы проделали хорошую работу по определению последнего, допуская как физические, так и концептуальные сущности. Но термин «класс» для пуристов всегда будет «фабрикой для создания экземпляров объектов с определенным внутренним представлением», а для прагматиков этот термин будет охватывать те вещи Java или C ++, которые презирают пуристы. То же самое относится к термину «ООП», который прагматики могли бы сказать, что Java и C ++ делают, но который пуристы будут понимать, что имел в виду Алан Кей, когда он заметил [«Я изобрел термин объектно-ориентированный, и я могу сказать, что я этого не делал» иметь в виду C ++ "] ( Так что же на самом деле имел в виду Алан Кей под термином" объектно-ориентированный "? ).

Если вы придерживаетесь прагматического взгляда, вы можете принять ваши вспомогательные классы без экземпляра. Но пуристская точка зрения более интересна. По словам Кея, ООП всегда было больше связано с сообщениями, чем с классами. Итак, на ваши вопросы:

Могут ли классы представлять объекты без сущности?

Нет. Классы классифицируют объекты. Классы по определению являются теми объектами, которым вы отправляете сообщение, например, newдля создания объекта. Объект - это сущность, созданная из класса. Существуют классы для производства и классификации объектов. Это то, что делают классы. Классы делают объекты. Мы используем классы для классификации объектов. Так что, если C - это просто набор методов, которые не позволяют создавать экземпляры или создавать подклассы, не может быть никаких объектов, классифицированных по C, поэтому C не является классом.

Если нет, то почему они плохие / неполные / не ООП-ориентированные?

Они не плохие. Только не называй их классами. Пакет методов является OOPable: что-то, на что вы могли бы послать сообщение, чтобы вызвать метод, но это не класс, если он не может создать экземпляр объекта. Ты знаешь Руби? В Ruby модуль представляет собой набор методов. Класс представляет собой модуль , который может создавать объекты. В модуле нет ничего плохого . Но вещь, которая отличает класс от модуля (в чистом виде ООП), состоит в том, что у класса могут быть экземпляры. Модуль - это всего лишь несколько методов. Путаница заключается в том, что C ++, Java и другие языки используют термин «класс» как для класса, так и для модуля .

Теперь, чтобы взглянуть на один из ваших конкретных примеров, вы спрашиваете о MotorOperationsклассе, которому вы можете отправить сообщение computePowerConsumptionForMotorс аргументом id. Это плохо? По крайней мере, это не нарушает принцип «Не спрашивай» . У нас есть сделать класс двигателя и послать ему powerConsumptionсообщение? Возможно, не в 100% случаев, но, возможно, попытка сделать это приведет к хорошему пониманию вашего кода. Или это может привести к взрыву маленьких классов, что было бы плохо.

Существуют ли способы их концептуального изменения / улучшения, чтобы они соответствовали ООП?

Если «выполнение ООП» важно для вас, то вам нужно будет искать способы структурирования системы в компоненты, которые взаимодействуют путем отправки сообщений друг другу. То есть именно то , что ООП является или , по крайней мере , что монетоприемник термина имел в виду. С этой точки зрения служебные классы не являются ООП. Но для некоторых людей они могут быть.

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

TL; DR - метод связок не всегда плох. Попробуйте сначала использовать инстанцируемые классы. Вернитесь к «модулям» только при необходимости.


0

Принимая приведенные примеры:

getMotorDataFromHTMLForm()
selectMotorFromUserRequirements($requirements)

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

getMotorManufacturers()

Откуда ты их берешь? Вот к чему это должен быть метод.

canMotorCanHandleOperatingConditions($conditions)
computePowerConsumptionForMotor($id)

Похоже, они должны быть методами Motor.


Да. это «набор, возможно, не связанных между собой методов» (BOPUM для краткости). Я согласен с комментариями Фабрики и Мотора. getMotorManufacturersвернуть все производители двигателей из базы данных. Я не уверен, куда это идет. Мне понадобится некоторое время, чтобы разгадать этот BOPUM, чтобы положить вещи туда, куда им нужно идти ..
Деннис

Я получаю getMotorManufacturersиз базы данных. В базе данных не может быть метода ... В настоящее время у меня есть шаблон DataMapper, который запрашивает базу данных, инициализирует массив и заполняет его объектами Motor (также содержащими информацию о производителе), а затем возвращает этот массив вызывающей стороне. Вызывающая сторона - это мой MotorOperationsкласс, который, в свою очередь, вызывается из ProductSelectionкласса (который содержит алгоритм, который используется для выбора двигателей, а загруженная информация о двигателях - это данные для этого алгоритма)
Деннис

0

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

Это верно, независимо от того, используете ли вы большой предварительный дизайн и пытаетесь смоделировать все, или новый дизайн, когда вы повторяете и развиваете объект в соответствии с требованиями системы в данный момент.

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

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

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