Чи повинні об'єкти в ООП представляти сутність?


82

Чи повинен об'єкт представляти сутність?

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

Наприклад, я можу мати об'єкт Demon, суб'єкт сам по собі, уявний, можливо, а не фізичний, але все-таки сутність

Чи може об’єкт бути лише сукупністю методів , загальним набором процедур, які поєднуються із спільною метою?

Приклад: чи можна назвати клас MotorOperationsабо MotorActions, де немає сутності, але методи всередині класу роблять такі речі

  • getMotorDataFromHTMLForm ()
  • getMotorManufacturers ()
  • selectMotorFromUserRequirements ($ вимоги)
  • canMotorCanHandleOperatingConditions ($ умови)
  • computePowerConsumptionForMotor ($ id)

Клас зазвичай визначається як дані, центральні для об'єкта + операції над даними. Тому для a Motorможуть бути деякі моторні змінні, що стосуються технічних характеристик двигуна, і можуть бути операції, що поєднують ці дані, щоб щось виробляти.

У моєму випадку це більше схоже на те, що у мене є клас з операціями над даними + дані, які передаються через клас, немає даних, орієнтованих на "Рухові операції", крім тимчасових даних проходження класу.

Питання

Чи можуть класи представляти об'єкти без сутності? Якщо ні, то чому вони погані / неповні / не орієнтовані на ООП? Чи існують способи їх зміни / покращення концептуально, щоб вони відповідали OOP?


2
+1. Але чи означає "так", що він повинен представляти сутність, чи це означатиме, що вони можуть представляти об'єкти, що не мають сутності?
Panzercrisis

1
Перше, що мені спадає на думку: java.awt та його класи "Op" (наприклад, docs.oracle.com/javase/7/docs/api/java/awt/image/… ), якщо це саме ви маєте на увазі. Він являє собою операцію. Тепер я не впевнений, чи це хороша практика (це виглядає дивно і некрасиво), але вона входить у стандартну бібліотеку Java, а Java - OOP. Для більшої частини.
Лука

1
Ні , це не так, але це не означає , MotorActionsабо MotorOperationsхороші ідеї чи ні.
іммібіс

1
Це питання могло б отримати користь від подальшої специфікації кан .
reinierpost

3
@Dennis Я дуже відчуваю, що ти задаєш усі неправильні запитання. По-перше, тому що немає жодного остаточного визначення ООП, по-друге, тому що парадигми є лише засобом для досягнення мети. Єдине питання, яке має значення, "чи написання коду таким чином полегшує міркування про його правильність?" і "чи письмовий код таким чином полегшує повторне використання?"
Doval

Відповіді:


109

Ні , об'єкт не повинен представляти сутність.

Насправді я б заперечував, що коли ти перестаєш думати про об’єкти як про фізичні сутності, це коли ти нарешті отримуєш переваги, які обіцяє ООП.

Це не найкращий приклад, але дизайн кавоварки - це, мабуть, там, де для мене почало з’являтися світло.

Об’єкти - це повідомлення. Вони про відповідальність. Вони не про автомобілі, користувачів або замовлення.

Я знаю, що ми навчаємо ОО таким чином, але це стає очевидним після декількох спроб, як принципово засмучує з'ясувати, куди йдуть справи, коли ви намагаєтесь робити MVC, MVVM або MVWever. Або ваші моделі стають смішно роздуті, або це роблять ваші контролери. Щодо керованості, то чудово знати, що все, що стосується Транспортних засобів, є у файлі Vehicle.ext, але коли ваша заявка стосується Транспортних засобів, ви неминуче потрапляєте до 3000 рядків спагетті у цьому файлі.

Коли у вас є нове повідомлення для надсилання, у вас є принаймні один новий об’єкт і, можливо, пара з них. Отже, у вашому запитанні щодо набору методів я б заперечував, що ви потенційно говорите про пакет повідомлень. І кожен може бути власним об’єктом, з його власною роботою. І це нормально. Це стане очевидним, коли ви розділите речі, які речі дійсно повинні бути разом. І ви склали їх разом. Але ви не одразу опускаєте кожен метод у неясно підходящий ящик для зручності, якщо хочете насолодитися OO.

Поговоримо про сумки функцій

Об'єкт може бути просто набором методів і все ще бути ОО, але мої "правила" досить суворі.

  1. Колекція повинна нести єдину відповідальність, і ця відповідальність не може бути такою загальною, як "Чи є це моторам". Я можу зробити таку річ, як фасад рівня службового рівня, але я гостро усвідомлюю, що я лінуюсь з причин навігації / виявлення, а не тому, що намагаюся написати код OO.

  2. Усі методи повинні бути на послідовному шарі абстракції. Якщо один метод отримує об'єкти Motor, а інший повертає «Кінські сили», це, ймовірно, занадто далеко.

  3. Об'єкт повинен працювати над тим самим "видом" даних. Цей об’єкт робить двигуни (старт / стоп), цей робить речі з довжиною кривошипа, цей обробляє послідовність запалювання, цей має форму html. Ці дані можуть бути полями на об'єкті, і це може здатися згуртованим.

Я, як правило, будую такі об'єкти, коли я роблю перетворення, композицію або просто не хочу перейматися питаннями змін.

Я вважаю, що зосередженість на об'єктних обов'язках призводить мене до згуртованості. Щоб бути об’єктом, має бути якась згуртованість, але для того, щоб бути об'єктом, не потрібно бути ані поля, ані дуже великої поведінки. Якби я будував систему, яка потребувала цих 5 рухових методів, я б почав з 5 різних об'єктів, які роблять ці речі. Як я виявив спільність, я б або почав об'єднувати речі разом, або використовувати спільні "помічники" об'єкти. Це перетворює мене на відкриті / закриті занепокоєння - як я можу отримати цей функціонал, щоб мені більше ніколи не доводилося змінювати цей конкретний файл, але все-таки використовувати його там, де потрібно?

Об’єкти - це повідомлення

Поля ледь не мають значення для об'єкта - отримання та встановлення регістрів не змінює світ поза програмою. Співпраця з іншими об'єктами виконує роботу. Однак сила ОО полягає в тому, що ми можемо створювати абстракції, тому нам не потрібно думати про всі окремі деталі одразу. Абстракції, які протікають або не мають сенсу, є проблематичними, тому ми глибоко (надто багато, можливо,) думаємо про створення об'єктів, які відповідають нашим ментальним моделям.

Ключове питання: Чому ці два об’єкти потребують розмови один з одним?

Розглядайте об’єкт як орган у людині - він має за замовчуванням мету і змінює поведінку лише тоді, коли отримує певне повідомлення, яке його хвилює.

Уявіть сценарій, коли ви перебуваєте на пішохідному переході, і машина їде швидко. Як об'єкт мозку я виявляю стрессор. Я кажу гіпоталамусу надсилати гормон, що вивільняє кортикотрофін. Гіпофіз отримує це повідомлення і вивільняє кортикотрофний гормон надниркових залоз. Наднирники отримують це повідомлення і створюють адреналін. Коли м'язовий об'єкт отримує повідомлення про адреналін, він стискається. Коли серце отримує те саме повідомлення, воно б’ється швидше. Існує цілий ланцюг гравців, які беруть участь у започаткуванні складної поведінки спринтерської дороги, і саме повідомлення мають значення. Об'єкт мозку знає, як змусити гіпоталамус надсилати сповіщення, але він не знає ланцюжок об'єктів, який врешті змусить поведінку відбутися. Так само серце не має уявлення, звідки береться адреналін,

Тож у цьому ( спрощеному ) прикладі об’єкту надниркової залози потрібно лише знати, як приймати АКТГ та робити адреналін. Для цього йому не потрібні поля, але це все ще здається мені об'єктом.

Тепер, якщо наша програма призначена лише для спринту через вулицю, мені може не знадобитися гіпофіз і наднирники. Або мені потрібен лише предмет гіпофіза, який лише незначну частину того, що ми можемо концептуально розглядати як "модель гіпофіза", мені потрібен. Всі ці концепції існують як концептуальні сутності, але це програмне забезпечення, і ми можемо зробити 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 - це не те, що означає "обмін повідомленнями", як його задумав Батько ОО Алан Кей, який сказав, що велика ідея - це обмін повідомленнями . І далі, мені шкода, що я давно ввів у цю тему термін «об’єкти», оскільки це змушує багатьох людей зосередитися на меншій ідеї.
radarbob

21

Чи можуть класи представляти об'єкти без сутності? Якщо ні, то чому вони погані / неповні / не орієнтовані на ООП? Чи є способи їх змінити / вдосконалити?

Коротше кажучи, ви можете зробити що завгодно, але цей конкретний сценарій був би проти принципів ООП :)

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

Не кожен об’єкт у вашій програмі має бути пов’язаний із реальною суттю, як-от мотор чи автомобіль; це об'єкти бізнесу. У вашій заявці ви, ймовірно, використовуєте багато бізнес-об'єктів, але вам також знадобиться ще деяка сегрегація для інших операцій, які не входять до складу суб’єктів господарювання, як-от ті, які ви перерахували.

Ви повинні ознайомитись із загальними архітектурними зразками - один з них - MVC (Model-View-Controller) .

Якби я розповсюджував вказані вами методи за допомогою MVC, ось що я б робив:

Переглянути клас:

  • GetMotorDataFromHTMLForm ()

Клас моделі (по суті двигуна):

  • GetMotorManufacturer ()
  • CanMotorHandleOperationConditions ()
  • РозрахуватиPowerConsumption ()

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

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

Схоже, ви використовуєте PHP; хороша основа MVC , щоб подивитися на це Laravel . У своїх прикладах вони добре ілюструють, куди належать методи.

Іншим, більш загальним джерелом інформації, як визначити, куди належать методи, є принципи GRASP та SOLID .


Дякую. По суті, мені здається, що у мене є клас Controller з кількома домішками, змішаними (Model, View тощо). Чи означає це, що якщо я перейменую MotorOperationsїї MotorsControllerта трохи очищую, моя колекція функцій буде відповідати OOP?
Денніс

@Dennis, Не обов’язково, перегляньте мою колекцію методів під кожен клас. Контролер - це не клас, який містить його все :) Це клас, який працює над вашими моделями, і не більше того. Єдиними залежностями контролера, як правило, є безпосередньо DAL (рівень доступу до даних) або послуги, які надають вам доступ до DAL. Ви ніколи не хочете отримати доступ до View з контролера (наприклад: getMotorDataFromHTMLForm), натомість ваш перегляд повинен бути таким, який залежить від контролера.
Олексій

2
Не могли б ви детальніше пояснити, чому Utilsклас буде прикладом запаху коду? Цікаво, оскільки мені подобалося, що випадкові утилітні функції обгортаються в Utilsкласі, а не просто окремими функціями ... на моєму досвіді це робить код трохи читабельнішим, але мій досвід обмежений.
HC_

3
@HC_ Мати клас Utils - це те саме, що мати у колекції зображень папку "Різне". Це вказує на те, що ви лінувалися привласнювати відповідальність своїм об'єктам належним чином / потенційно відсутнім об'єктам і використовувати компенсації для цього. Є приміщення для класів Util, особливо зі статичними функціями та розширеннями до інших класів, але перед тим, як створити подібну колекцію, перевірте, чи можете ви включити їх у свої належні класи OOP :) Ще одна причина: іноді клас може мати лише один метод. Але йдучи вперед, вам потрібно додати більше, і клас Utils стає більшій безлад.
Алексус

Я часто закінчуюся бібліотекою Utils, але зазвичай намагаюся групувати і називати свої утилітні класи трохи більш описово. У наші дні існує багато бібліотек «загальних утиліт» з відкритим кодом, які вже мають утиліти загального призначення, які потребують більшість людей, тому я трохи озирнусь, перш ніж писати власні.
Хлопець Шалнат

15

Чи можуть класи представляти об'єкти без сутності?

Можна? Так. Повинен? Можливо, ні - або, принаймні, не так, як ви фразуєте речі.

Об'єкти насправді найкращі, коли фізичний об’єкт не представляє безпосередньо, оскільки реальність так рідко відображається на коді. Але їм потрібно представляти згуртовану концепцію або код-об'єкт. Вони повинні представляти єдину згуртовану відповідальність.

Просто поєднання купи тангенціально пов'язаних функцій разом є простором імен або модулем - не об'єктом в мові мови OOP. Вони можуть бути корисними, але вони не однакові і вимагають іншого використання / мислення для ефективної роботи.


3
bundling a bunch of tangentially related functions together is a namespace: це звучить скоріше як процедурна парадигма, ніж орієнтована на об’єкти.
Денніс

@dennis - точно (або функціонально, якщо ви називаєте його Модулем). Змішування парадигм може бути потужним. Або це може бути жахливо безладно.
Теластин

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

@ Денніс: Або і те, і інше - поєднання лише лише дотично пов'язаних функцій є сумнівною практикою в будь-якій парадигмі.
sdenham

Я маю справу з кодом, який почався як процедурна база даних. У якийсь момент було зроблено зусилля, щоб перетворити його на OOD, але, в основному, були створені класи для "утримування функцій та методів", без жодної фактичної ОО-конструкції. Я виявив дуже багато подібних речей, які намагаються усунути розрив між парадигмами, але вони не є ні в одній, ні в іншій
Денніс

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

@bill ти божевільний старий дурень !!! Ось клас MyButtonAndOrPennyBowl! чисте кодування ftw
Ewan

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

5

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

Насправді, залежно від того, яким буквальним ви хочете бути, багато об'єктів, з якими ми працюємо, взагалі не мають фізичних уявлень. Наприклад - розгляньте архітектуру MVC. У реальному світі немає Моделі чи Контролера, хоча вони, як правило, представлені класами. Ці троє разом часто щось представляють, але не завжди - але, як я вже сказав, ви, мабуть, могли змусити вписатись у щось, якщо дуже хочете (і вміти уявити, що НЕЩО допомагає! Я візуалізую більшість об'єктів якимось чином - просто не що-небудь ви коли-небудь бачили в реальному світі).

Переважно ці "Правила", які ви дізнаєтесь про ОО, - це лише вказівки, спрямовані на те, щоб орієнтуватися на мислення в ОО, не обов'язково те, про що ви хвилюєтеся, коли ви їх використовуєте для кодування щодня.

До речі, OO сам по собі не є панацеєю, і це зовсім не допомагає вам під час першого проходження при кодуванні якогось рішення, але я думаю, що якщо правильно зробити, це дійсно фантастичний спосіб організації коду, щоб він міг бути більше легко зрозуміли пізніше. Написання коду, що підтримується, є, мабуть, одним із найскладніших завдань у розробці програмного забезпечення, і в багатьох випадках (все, що вимагає постійної налагодження / обслуговування), це, безумовно, найважливіше.


5

Чи повинен об'єкт представляти сутність?

Питання: Яка організація Loggerпредставляє?

Не метафорично - буквально.

Пояснюючи ООП учням, корисно пояснити об'єкти з аналогіями фізичного світу.

Алан Кей - один із батьків OOP - написав наступне:

[...]

Первісна концепція його мала наступні частини.

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

[...]

OOP для мене означає лише обмін повідомленнями, локальне збереження та захист і

приховування державно-процесу, і крайнє пізнє зв’язування всіх речей.

майже неймовірна архітектура HW. Я зрозумів, що

метафора клітинки / цілого комп'ютера позбулася б даних

джерело

З цього об'єкти найкраще розуміти як

  • аутаркічні об'єкти, що інкапсулюють / приховують дані

  • спілкування з іншими об’єктами через повідомлення

Чи можуть класи представляти об'єкти без сутності?

Однозначно: подумайте Math


Щодо вашого прикладу:

Приклад: чи можна назвати клас MotorOperations або MotorActions, де немає сутності, але методи всередині класу роблять такі речі, як

  • getMotorDataFromHTMLForm ()

  • getMotorManufacturers ()

  • selectMotorFromUserRequirements ($ вимоги)

  • canMotorCanHandleOperatingConditions ($ умови)

  • computePowerConsumptionForMotor ($ id)

Щоб вирішити, куди подіти ці методи, вам слід поглянути responsibilities: хто за що відповідає .

getMotorDataFromHTMLForm ()

Контекстом такого методу буде побудова рухового об’єкта . Це не відповідальність мотора створити себе з даних, отриманих за допомогою форми . Задіяно щонайменше два об’єкти; один - мотор, а другий - творець двигуна .

getMotorManufacturers ()

Типовим контекстом, в якому можна було б написати такий метод, є service.

selectMotorFromUserRequirements ($ вимоги)

Це також буде використано в service-контексті

canMotorCanHandleOperatingConditions ($ умови)

Це питання до motor-об'єкта

computePowerConsumptionForMotor ($ id)

Це теж питання, яке найкраще задає сам мотор.


тл; д-р

Метафора objectsяк фізично об'єктів є більш дратівливою, ніж корисною.


вау, ваша відповідь вдихає деяке життя в ООП! Я мушу сказати, що я не мав на увазі фізичне як кінець усьому цьому. у мого питання було більше: "чи повинен об'єкт бути thingз даними, коли дані чітко належать до речі та функцій, які чітко діють на даних, що належать до речі". Тож Logger в даному випадку, хоча не є фізичною річчю, це концепція, схожа на концепцію "фізичної книги журналів". Чи є у нього дані, які є основними для його стану, і не є лише тимчасовими до них, це може залежати від впровадження та інтерпретації .. і, тим більше, де моє запитання йшло ..
Денніс

але так, відповіді мали відповідати моїм фізичним упередженням
Денніс

3

Так, ви можете це зробити. Але ви по суті створюєте клас, щоб забезпечити той самий функціонал, що і процедурна бібліотека. Єдина причина для цього - якщо у вашій мові бракує процедурних модулів (наприклад, Java або Ruby).

Мовою з процедурними модулями (я думаю, що в PHP є процедурні модулі), ви можете розглянути можливість просто використовувати процедурний модуль.

Ви також можете розглянути можливість створення свого класу, щоб екземпляр класу являв собою цілісний об'єкт.

Але використовуйте позначення OO лише тоді, коли це дає вам додаткову силу, а не тільки заради того, щоб бути ОО!


3

Словами мирян

  • Те, що ви описуєте, називається клас корисності.
  • Він не має стану, тобто вам ніколи не потрібно буде мати кілька примірників цього
  • Усі методи статичні, тобто ви повинні передати все як параметри

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

Отже, відповідь була б ні: не всі класи потрібно моделювати з об'єкта домену.

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

Було б як користуватися літаком, щоб їхати з одного місця в інше не літаючим, а керуючи ним по автострадах. У літаків є колеса, як у машин, але вони призначені для польоту.


2

Ні, клас просто представляє щось, що може бути ініційованим, має членів і від яких може бути успадковано.

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

.NETMath - чудовий приклад "професійного" класу, який не представляє жодної сутності (якщо ви не хочете отримати філософський характер про те, що таке математика ...), а також ілюструє законний випадок використання такого класу. У ньому є лише методи та 2 поля (обидва представляють окремі константи).

Ієрархія класів подібної бібліотеки, Math.Netоб'єднує математичні / числові методи в класи за типами. Тут класи представляють не сутність, а логічну категорію.

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


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

1

Відповіді на ваші запитання залежать від того, наскільки точно можна визначити такі терміни, як "клас" та "сутність". Ви добре зробили роботу з визначення останнього, дозволяючи як фізичним, так і концептуальним утворенням. Але термін "клас" для пуристів завжди буде "фабрикою для інстанції об'єктів з певним внутрішнім представленням", а для прагматиків цей термін охоплюватиме речі, які зневажають пуристи. Дітто для терміна "OOP", який прагматики можуть сказати, що роблять Java та C ++, але які пуристи мають на увазі те, що мав на увазі Алан Кей, коли він зауважив ["Я винайшов термін об'єктно-орієнтований, і я можу сказати, що я не майте на увазі C ++ "] ( Отже, що саме мав на увазі Алан Кей під терміном" об'єктно-орієнтований "? ).

Якщо ви поглянете на прагматичного погляду, ви можете прийняти ваші утилітні класи, що не стосуються екземплярів. Але пуристський погляд цікавіший. За словами Кей, OOP завжди більше стосувався повідомлень, ніж класів. Тож до ваших питань:

Чи можуть класи представляти об'єкти без сутності?

Ні. Класи класифікують об'єкти. Класи за визначенням - це ті сутності, яким ви надсилаєте повідомлення, наприклад, newщоб створити об'єкт. Об'єкт - це сутність, створена з класу. Класи існують для виготовлення об'єктів та їх класифікації. Ось що роблять заняття. Заняття складають предмети. Ми використовуємо класи для класифікації об’єктів. Отже, якщо C - це лише сукупність методів , яка не дозволяє інстанціювати або підкласифікувати, не може бути жодних об'єктів, класифікованих C, тому C не є класом.

Якщо ні, то чому вони погані / неповні / не орієнтовані на ООП?

Вони не погані. Просто не називайте їх класами. Пакет методів є OOPable: те, до чого ви можете надіслати повідомлення, щоб викликати метод, але це не клас, якщо він не може створити об'єкт. Ти знаєш Рубі? У Ruby модуль - це група методів. Клас являє собою модуль , який може створювати об'єкти. У модулі немає нічого поганого . Але річ, яка відрізняє клас від модуля (в чистому плані OOP), полягає в тому, що клас може мати екземпляри. Модуль - це лише деякі методи. Плутанина полягає в тому, що C ++ та Java та інші мови використовують термін "клас" і для класу, і для модуля .

Тепер, щоб переглянути один із ваших конкретних прикладів, ви запитуєте про MotorOperationsклас, до якого ви могли б надіслати повідомлення computePowerConsumptionForMotorз аргументом id. Це погано? Принаймні, це не порушує принципу «Не питай» . Чи треба робити мотоклас і відправляти йому powerConsumptionповідомлення? Можливо, не 100% часу, але, можливо, спроба зробити такі речі призведе до приємного розуміння вашого коду. Або це може призвести до вибуху невеликих класів, що було б погано.

Чи існують способи їх зміни / покращення концептуально, щоб вони відповідали OOP?

Якщо для вас важливо "робити OOP", тоді ви захочете шукати способи архітектури системи в компоненти, які спілкуються, надсилаючи повідомлення один одному. Це якраз те, що є ООП , або, принаймні, те, що мав на увазі монетник цього терміна. Класи утиліти не є OOP на цей погляд. Але для деяких людей вони можуть бути.

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

Набори методів TL; DR - не завжди погані. Спробуйте спочатку використовувати миттєві класи. Повертайтеся до "модулів" лише за потреби.


0

Беручи наведені приклади:

getMotorDataFromHTMLForm()
selectMotorFromUserRequirements($requirements)

Вони схожі на "фабричні" методи, які б повернули Motorоб'єкт. Другий означає, що ви створюєте новий об'єкт для задоволення вимог, або у вас є база даних або колекція двигунів в пам'яті, яку ви вивчаєте. У цьому випадку це повинен бути метод. Або це може бути метод на об'єкті вимог.

getMotorManufacturers()

Звідки ви їх отримуєте? Ось що це має бути методом.

canMotorCanHandleOperatingConditions($conditions)
computePowerConsumptionForMotor($id)

Вони схожі на те, що вони повинні бути методами Motor.


Так. це "пакет можливих непов'язаних методів" (BOPUM коротко). Я погоджуюся з коментарями заводу та мотора. getMotorManufacturersце повернути всіх виробників двигунів із бази даних. Я не впевнений, куди це йде. Знадобиться певний час, щоб розгадати цей БОПУМ, щоб помістити речі, куди їм потрібно їхати ..
Денніс

Я отримую getMotorManufacturersз бази даних. База даних не може мати метод ... В даний час у мене є шаблон DataMapper, який запитує базу даних, ініціалізує масив і заповнює його об'єктами двигуна (також містить інформацію про виробника), а потім повертає цей масив абоненту. Абонент - це мій MotorOperationsклас, який, в свою чергу, викликається з ProductSelectionкласу (який містить алгоритм, який використовується для вибору Motors, а завантажена інформація про двигуни - це дані для цього алгоритму)
Денніс

0

Об'єкт - це сукупність методів та даних, які мають високу згуртованість. Вони належать до класу, оскільки вони дуже взаємопов'язані і стан зберігається.

Це справедливо, незалежно від того, чи використовуєте ви великий дизайн спереду та намагаєтеся все моделювати, чи новий дизайн, де ви повторюєте та перетворюєте об'єкт на все, що відповідає потребам системи на той час.

Якщо у вас немає причин зберігати стан, ви, мабуть, не маєте причин створювати об'єкт, а це означає, що, ймовірно, немає причин мати клас. Якщо мова, якою ви користуєтеся, не має можливості визначати простір імен, крім використання класу. У якому використання класу повинно бути добре, оскільки це було б ідіоматично.

Я не можу придумати жодних негативних аспектів використання занять таким чином, крім типового. Ваші запрошені зайві витрати та складність, необхідність створити "простір імен". Кожен, хто підтримує цей код, задасться питанням, де ціна коштує додаткового когнітивного навантаження (швидше за все, разової вартості на людину). Це незвичне використання без додаткової вартості.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.