Дизайн на «змішаних» мовах: об’єктно-орієнтований дизайн або функціональне програмування?


11

В останні кілька років мови, які я люблю використовувати, стають все більш "функціональними". Зараз я використовую мови, які є свого роду "гібридом": C #, F #, Scala. Мені подобається розробляти свої програми за допомогою класів, які відповідають об’єктам домену, і використовую функціональні функції, де це робить кодування простішим, зручнішим та безпечнішим (особливо при роботі з колекціями або при передачі функцій).

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

Я спочатку робив це "функціонально" так:

producer.foo(item => { updateItemInDb(item); insertLog(item) })
// calls the function passed as argument as an item is processed

Але мені зараз цікаво, чи варто використовувати більш "ОО" підхід:

interface IItemObserver {
  onNotify(Item)
}
class DBObserver : IItemObserver ...
class LogObserver: IItemObserver ...

producer.addObserver(new DBObserver)
producer.addObserver(new LogObserver)
producer.foo() //calls observer in a loop

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

EDIT: У моєму конкретному сценарії мені це не потрібно, але .. як би ви реалізували функціональне усунення та додавання "спостерігачів"? (Тобто, як би ви реалізували всі функції у шаблоні?) Просто передаючи нову функцію, наприклад?


Що з акторами?
kiritsuku

Забудьте про заняття та все те, що OOPish марні речі. Натомість краще подумати над модулями (для натхнення див. Мови SML та OCaml).
SK-логіка

@Antoras Якщо ви можете порівняти з підходом, який базується на "Актори", було б
корисніше

2
@ dema80, OCaml є ідеально багатопарадигмою. Модулі взагалі не пов'язані з функціональним програмуванням. Наприклад, існує вдосконалена система модулів на суто імперативній Ada, наприклад. І вся слава, яку набув OOP, насправді має приділятися модулям - все хороше в OOP - це лише різні форми моделювання функціональності модулів. Ви можете повністю забути всі ці класи та використовувати їх синтаксис для вираження модулів, думаючи з точки зору модулів, а не OOP. До речі, саме це зробила Microsoft зі своїм mscorlib - не так багато OOP там, просто модулі та простори імен.
SK-логіка

1
Я думаю, що краще питання: "Чи є ясність чи організація, яку ви втрачаєте, роблячи це шляхом FP?"
djechlin

Відповіді:


0

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

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

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


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

"Склад чи спадкування, де у вас буде трохи більше свободи для повторного використання та розширення існуючої поведінки", ви говорите так, як це НЕ є однією з основних переваг чистого ПП. модульність, компонованість та повторне використання просто трапляються природно, коли ви кодуєте функціонально, це не "річ OOP"
sara

@ FilipDupanović Я намагався повторно використовувати та розширити існуючий код. чисті функції - це, мабуть, найбільш компоновані речі у всьому програмуванні. Ви написали так, ніби не можете керувати складністю в чистому функціональному середовищі. управління складністю шляхом складання простих частин у більші, але все ж прості та непрозорі частини - це все ядро ​​FP, і багато хто стверджує, що це навіть набагато краще, ніж OOP. Я не згоден з дихотомією між "функціональними однолінійками, які не масштабують VS твердий OOP, який не масштабує жодних проблем", який ви висунули.
сара

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

5

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

Багато - хоча далеко не всі зразки - це компенсувати відсутність функцій OOP, наприклад, спостерігачів. Вони набагато краще моделюються функціонально.


Я згоден і маю те саме почуття.
Лоренцо Дематте

Я погоджуюсь і маю те саме почуття. Але я свого роду "обманював" свій функціональний код: у моєму випадку це все, що мені потрібно, але що робити, якщо мені потрібно додати та видалити "спостерігачів"? Я відредагував своє запитання
Lorenzo Dematté

5

Ваш "гуру ФП" частково правий; багато моделей OO - це хаки, щоб робити функціональні речі. (Його твердження, що це є причиною того, що декілька мов FP здається в кращому випадку сумнівним.) Шаблони спостерігачів та стратегій намагаються імітувати функції першого класу. Шаблон відвідувача - це хак для імітації відповідності шаблонів. Ви IItemObserverпросто маскуєтесь до функції. Здається, що він відрізняється від будь-якої іншої функції, яка бере предмет, нічого не купує.

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


+1 за (ІМО) хороша відповідь. Також дякую за посилання на папір: я прочитав його деякий час тому, а потім втратив. Тепер я його знову знайшов.
Джорджіо

-1

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

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


1
"Ви можете, з великою обережністю, написати цілу програму, що містить об'єкти, які не мають стану, імітуючи FP.", Звичайно, і через дисципліну ви можете робити те ж саме і в імперативних мовах. :) Взагалі, я не вважаю дизайнерські малюнки як щось, щоб компенсувати обмеження, але розглядаю випадок шаблону відвідувачів ..
Лоренцо Дематте

Крім того, я не переймаюся кодом: однак, я хотів би зіткнутися з колегами-програмістами щодо підходу (наскільки я розумію, це те, для чого програмісти.se, інакше я би розмістив свій Q на SO)
Лоренцо Дематте

Кожен раз, коли ви помічаєте повторюваний шаблон, це не що інше, як вказівка ​​на серйозне обмеження вашої мови та моделювання. В ідеальному світі взагалі не повинно бути візерунків.
SK-логіка

@ SK-логіка: На жаль, світ не ідеальний, а реальний світ має закономірності. Ось чому мови OO мають спадщину, реалізовувати повторюваний код без необхідності переписувати їх заново. Справжній світовий об’єкт має стан, ось чому існує зразок State
DPD

1
@ SK-логіка: Я добре знаю, що деякі мови програмуються, а деякі дозволяють також застосовувати ефекти від типової системи. Моя думка полягає в тому, що, як і "OOP", "pattern" - це сумно неправильно зрозумілий термін. Шаблон - це те, що постійно з'являється у подібних, але різних формах , що не дозволяє прийняти рівномірне рішення . Іноді ви можете змусити ці квазірепетиції зникнути - багатометоди роблять Visitor / double dispatch надмірними. Це не означає, що "всі зразки є ознаками дефіциту", оскільки це означає, що реальний світ є дефіцитним. Візерунки виникли в архітектурі , а не в програмному забезпеченні.
Френк Ширар
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.