Мови OO можуть використовуватися замість мов низького рівня, іноді для взаємодії безпосередньо з машиною. C ++ Напевно, але навіть для C # є адаптери і такі. Хоча письмовий код для керування механічними деталями та щохвилинного контролю над пам’яттю найкраще зберігати якомога ближче до низького рівня. Але якщо це питання пов'язане з поточним об'єктно-орієнтованим програмним забезпеченням, таким як Line Of Business, веб-додатки, IOT, веб-сервіси та більшість масово використовуваних додатків, то ...
Відповідь, якщо це застосовується
Читачі можуть спробувати працювати з сервісно-орієнтованою архітектурою (SOA). Тобто DDD, N-шаруваті, N-багаторівневі, шестикутні, як би там не було. Я не бачив, щоб програма для великого бізнесу ефективно використовувала "Традиційні" OO (Active-Record або Rich-Models), як це було описано в 70-х і 80-х дуже в останнє десятиліття +. (Див. Примітку 1)
Вина не в ОП, але є кілька проблем із питанням.
Наведений вами приклад - просто продемонструвати поліморфізм, це не виробничий код. Іноді приклади, точно такі, що приймаються буквально.
У FP та SOA дані відокремлюються від Business Logic. Тобто дані та логіка не йдуть разом. Логіка переходить у службу, а дані (доменні моделі) не мають поліморфної поведінки (див. Примітку 2).
Послуги та функції можуть бути поліморфними. На FP ви часто передаєте функції як параметри іншим функціям замість значень. Ви можете зробити те ж саме в OO Languages з такими типами, як Callable або Func, але це не розповсюджується (Див. Примітку 3). У FP та SOA ваші моделі не є поліморфними, а лише вашими послугами / функціями. (Див. Примітку 4)
У цьому прикладі є поганий випадок жорсткого кодування. Я говорю не лише про червону кольорову рядок «собачий гавкіт». Я також говорю про самих CatModel та DogModel. Що станеться, коли ви хочете додати Овець? Вам потрібно зайти в свій код і створити новий код? Чому? У виробничому коді я б швидше бачив просто AnimalModel з його властивостями. У гіршому випадку, AmphibianModel і FowlModel, якщо їх властивості та поводження настільки різні.
Це я б очікував побачити в поточній мові "ОО":
public class Animal
{
public int AnimalID { get; set; }
public int LegCount { get; set; }
public string Name { get; set; }
public string WhatISay { get; set; }
}
public class AnimalService : IManageAnimals
{
private IPersistAnimals _animalRepo;
public AnimalService(IPersistAnimals animalRepo) { _animalRepo = animalRepo; }
public List<Animal> GetAnimals() => _animalRepo.GetAnimals();
public string WhatDoISay(Animal animal)
{
if (!string.IsNullOrWhiteSpace(animal.WhatISay))
return animal.WhatISay;
return _animalRepo.GetAnimalNoise(animal.AnimalID);
}
}
Як перейти від класів в ОО до функціонального програмування? Як казали інші; Можна, але насправді це не так. Суть вищезазначеного полягає в тому, щоб продемонструвати, що ви навіть не повинні використовувати Класи (у традиційному розумінні світу) під час виконання Java та C #. Як тільки ви перейдете до написання коду в сервісно-орієнтованій архітектурі (DDD, багатошаровий, багаторівневий, шестикутний, що завгодно), ви будете на крок ближче до функціоналу, оскільки ви відокремлюєте свої дані (доменні моделі) від своїх логічних функцій (послуг).
Мова ОО на крок ближче до ПП
Ви можете взяти це трохи далі і розділити служби SOA на два типи.
Необов’язковий тип 1 класу : загальні послуги, що реалізують інтерфейс для вхідних точок. Це будуть "нечисті" точки вступу, які можуть викликати "чистий" або "нечистий" інший функціонал. Це можуть бути ваші вхідні точки з API RESTful.
Необов'язковий тип 2 : Чисті бізнес-логічні послуги. Це статичні класи, які мають "чистий" функціонал. У ФП «Чистий» означає, що немає побічних ефектів. Він прямо не встановлює Держави чи Персистенції ніде. (Див. Примітку 5)
Отже, коли ви думаєте про класи в об'єктно-орієнтованих мовах, використовувані в сервісно-орієнтованій архітектурі, це не тільки приносить користь вашому коду ОО, але і починає робити функціональне програмування зрозумілим дуже просто.
Примітки
Примітка 1 : Оригінальний об'єктно-орієнтований дизайн "Rich" або "Active-Record" все ще існує. З'явилося багато такого спадкового коду, як колись, коли люди «робили це правильно» десять років і більше тому. Востаннє я бачив, що такий код (зроблено правильно) був із відеоігри Codebase в C ++, де вони точно контролювали пам’ять і мали дуже обмежений простір. Не кажучи про архітектури, орієнтовані на FP та сервісні послуги, це звіри і не повинні враховувати обладнання. Але вони надають можливість постійно змінюватись, підтримуватися, мати змінний розмір даних та інші аспекти як пріоритетні. У відеоіграх та AI машин ви дуже точно керуєте сигналами та даними.
Примітка 2 : Моделі доменів не мають поліморфної поведінки, а також не мають зовнішніх залежностей. Вони "Ізольовані". Це не означає, що вони повинні бути на 100% анемічними. Вони можуть мати багато логіки, пов'язаної з їх конструкцією та зміною властивостей, що змінюються, якщо такі стосуються. Дивіться DDD "Ціннісні об'єкти" та об'єкти Еріка Еванса та Марка Семана.
Примітка 3 : Лінки та Ламбда дуже поширені. Але коли користувач створює нову функцію, він рідко використовує функцію або функцію Callable, тоді як на FP було б дивно бачити додаток без функцій, що слідують за цим шаблоном.
Примітка 4 : Не плутати поліморфізм із спадщиною. CatModel може успадкувати AnimalBase, щоб визначити, які властивості тварина зазвичай має. Але як я показую, подібні моделі - це кодовий запах . Якщо ви бачите цю схему, можете подумати про її розбиття та перетворення в дані.
Примітка 5 : Чисті функції можуть (і дійсно) приймати функції як параметри. Вхідна функція може бути нечистою, але може бути чистою. Для тестування це завжди було б чисто. Але у виробництві, хоча це трапляється як чисте, воно може містити побічні ефекти. Це не змінює той факт, що чиста функція є чистою. Хоча функція параметра може бути нечистою. Не плутати! : D