OOP проти функціонального програмування проти процедурного [закрито]


237

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

Приклади архітектури оцінені!


Це не повна відповідь, але я пишу трохи про те, як "функціональний" впливає / протиставляє стилю "OO" (в контексті F #) тут: lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!511. запис
Брайан

Ви можете подумати про те, щоб прочитати це! Існує багато прикладів того, коли користуватися мурашкою, які основні відмінності, плюси та мінуси тощо
Микита Ігнатов


1
Дивіться також: stackoverflow.com/questions/1530868
dreftymac

Дядько Боб твітнув про це. А також тут .
jaco0646

Відповіді:


129

Всі вони хороші по-своєму - Просто різні підходи до одних і тих же проблем.

У чисто процедурному стилі дані, як правило, сильно відокремлюються від функцій, які працюють на ньому.

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

У функціональному стилі дані та функції, як правило, мають більше спільного між собою (як у Lisp та Scheme), пропонуючи при цьому більшу гнучкість у відношенні того, як функції реально використовуються. Алгоритми, як правило, визначаються з точки зору рекурсії та складу, а не циклів та ітерацій.

Звичайно, сама мова впливає лише на те, якому стилю віддається перевага. Навіть на чистофункціональній мові, як Haskell, ви можете писати в процедурному стилі (хоча це сильно не відштовхується), і навіть на процедурній мові, як C, ви можете програмувати в об'єктно-орієнтованому стилі (наприклад, в GTK + і API EFL).

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

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


5
Те, що ви сказали, схоже, не відображає те, що ви написали. Ви кажете, що вони не мають "плюсів і мінусів", а потім кажете, як вони різні підходи. Чому хтось обирає один підхід над іншим, виходячи з будь-якої ситуації? сильні та слабкі сторони, плюси і мінуси, як би ви їх не називали, вони існують! Я не кажу, що одне по суті краще, і ні ви. Я вважаю, що це ви справді намагалися сказати. якщо ви справді не вважаєте, що будь-який обраний підхід не має позитивів і негативів щодо іншого підходу.
Дж. М. Бекер

1
@TechZilla: Я погоджуюся, що моє формулювання було поганим, але я мав на увазі те, що насправді не існує списку функцій, на які можна вказати та сказати мовою X краще, ніж Y, не кваліфікуючи, що мова X краще підходить для алгоритму написання U та мови Y може бути краще підходить для алгоритму написання V, тоді як обидва можуть бути легко реалізовані на будь-якій мові.
greyfade

2
Різниця між процедурною та функціональною для мене незрозуміла. Я вивчаю схему / ракетку в коледжі, але я дійсно не бачу великої різниці між нею та процедурними C або PHP, чи можете ви навести приклад?
Леонель

7
@Leonel: Найбільша різниця, яку більшість людей наводить, полягає в тому, що в процедурних мовах ви можете використовувати цикл for, але у функціональних мовах такого немає - натомість ви використовуєте рекурсивні дзвінки до функцій для виконання того ж завдання. Функціональні мови також створюють функції об'єктів першокласного класу - ви можете передавати їх навколо, як і номер - але ви не можете цього зробити в C (і підтримка PHP для нього порушена).
greyfade

2
@tastro: Коли одна парадигма має більше сенсу, ніж інша. Це справді все. Іноді має сенс моделювати свій код як склад функцій, а іноді має більше сенсу моделювати ваші дані як об’єкти. Існує багато способів виразити алгоритми та структури даних. OOP та функціонал - це дві речі.
greyfade

25

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

Наприклад, якщо ви робите відеоігри, є більше хороших прикладів коду та SDK в C ++, тому вам, мабуть, краще з цим. Для невеликого веб-додатка є кілька чудових фреймворків Python, PHP та Ruby, які дозволять вам швидко працювати. Java є прекрасним вибором для великих проектів через перевірку часу компіляції та корпоративні бібліотеки та платформи.

Бувало так, що стандартні бібліотеки для різних мов були досить малі та легко копіювалися - C, C ++, Assembler, ML, LISP тощо. Поставились з основами, але, як правило, курячі, коли мова зайшла про стандартизацію речей як мережеві комунікації, шифрування, графіка, формати файлів даних (включаючи XML), навіть основні структури даних, такі як збалансовані дерева та хештелі!

Сучасні мови, такі як Python, PHP, Ruby та Java, тепер мають набагато пристойнішу стандартну бібліотеку і мають багато хороших сторонніх бібліотек, якими ви можете легко користуватися, завдяки великій частині завдяки їх прийняттю просторів імен, щоб бібліотеки не стикалися між собою, і збирання сміття для стандартизації схем управління пам’яттю бібліотек.


5
Python, ruby, ... не мають "стандартних" бібліотек, таких як C або LISP, оскільки вони є єдиними мовами реалізації. Python - це, як каже Гуїдо, немає стандарту. Будь-яка конкретна C або LISP (чи будь-яка інша) реалізація сьогодні оснащена великим набором бібліотек, що перевищують стандартні.
Dan Andreatta

8
Питання полягало у відмінностях між об'єктно-орієнтованим, функціональним та процедурним програмуванням. Хоча мови, згадані в цих відповідях, безумовно, піддаються одному з цих підходів, у відповіді не згадується жодне з цих понять ... Незалежно від того, "чи наявні бібліотеки [...] [козир] парадигми" ", це не дає відповіді на відповідне питання, тим самим побіжно переходячи до цілком актуального питання.
rinogo

1
Пов'язані з цим ircmaxell rant: blog.ircmaxell.com/2012/07/oop-vs-procedural-code.html
rinogo

20

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

Що я маю на увазі, що у функціональних мовах (принаймні, в Haskell, єдиній, яку я вивчав) немає тверджень! Функції дозволено лише одне вираження всередині них !! АЛЕ функції є першокласними громадянами, ви можете передавати їх як параметри, а також купу інших здібностей. Вони можуть робити потужні речі з кількома рядками коду.

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

У python функція є першокласним громадянином, але вона може містити довільну кількість тверджень. Таким чином, ви можете мати функцію, яка містить процедурний код, але ви можете передавати її навколо, як і функціональні мови.

Те саме стосується і ООП. Мова, як Java, не дозволяє писати процедури / функції поза класом. Єдиний спосіб передати функцію навколо - це обернути її в об'єкт, який реалізує цю функцію, а потім передавати цей об’єкт навколо.

У Python у вас немає цього обмеження.


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

Так, я вважаю, що взаємовиключний кращий термін для цього! спасибі
hasen

14

Для GUI я б сказав, що об'єктно-орієнтована парадигма дуже добре підходить. Вікно - це об'єкт, текстові поля - це об'єкти, а кнопка «Гаразд» - теж одна. З іншого боку, такі речі, як обробка рядків, можна зробити з набагато меншими накладними витратами і, отже, більш простою за допомогою простої процедурної парадигми.

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


17
Спокусився подати заяву за увічнення помилкового уявлення про те, що "Object = GUI віджет", але я утримаюсь. OOP працює так само добре, що представляє абстрактні поняття, такі як "UserAccount" або "PendingSale", а також для видимих ​​елементів інтерфейсу, таких як "Window" і "Button".
Дейв Шерохман

5
Я писав, що вікно може бути об’єктом. Як ви робите висновок, що кожен Об'єкт - це вікно звідти? Це був лише приклад. Звичайно, OOP може бути використаний так само добре для моделювання абстрактних сутностей та їх взаємозв'язку. У будь-якому випадку, спасибі за те, що не звернули увагу. У мене все одно немає багатьох моментів: D
panschk

6
-1. OOP не має нічого спільного з GUI. В ідеалі найкращим методом проектування guis є використання зовнішнього текстового файлу (наприклад, HTML). Хоча такі речі, як обробка рядків, насправді набагато краще робити з об’єктами. (подумайте про рядки в С) !!
hasen

1
Я не знаю, можливо, я просто звик програмувати з об'єктами, щоб усвідомлювати це. Але як би ви зробили деякі інтерактивні речі, такі як зміна значення в TextBox X, коли значення TextBox Y було змінено без використання об'єктів? Гаразд, ви можете просто використати глобальну різноманітність для всього ...
panschk

1
Обробку рядків дивовижно виконується в perl (на 100 разів краще, ніж у Java, C ++ або C #), але функціональність рядка мови абсолютно НЕ об'єктно орієнтована. Обробка струни C була жахливою, але тоді C не є єдиною процедурною мовою (ні найкращою).
Джо Пінеда

6

Щоб відповісти на ваше запитання, нам потрібні два елементи:

  1. Розуміння характеристик різних архітектурних стилів / моделей.
  2. Розуміння характеристик різних парадигм програмування.

Перелік стилів / візерунка архітектури програмного забезпечення показаний у статті про архітектуру програмного забезпечення про у Wikipeida. І ви можете легко досліджувати їх в Інтернеті.

Коротше кажучи, загалом, процедурний підходить для моделі, яка дотримується процедури, OOP хороша для дизайну, а функціональна - для програмування високого рівня.

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

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


2

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


1

Один з моїх друзів пише графічний додаток, використовуючи NVIDIA CUDA . Застосування дуже добре поєднується з парадигмою OOP, і проблема може бути акуратно розкладена на модулі. Однак для використання CUDA потрібно використовувати C, який не підтримує успадкування . Тому потрібно бути розумним.

а) Ви розробляєте розумну систему, яка певною мірою буде імітувати спадщину. Це можна зробити!

i) Ви можете використовувати a гака , яка очікує, що кожна дитина C батьківського P матиме певний перебір функції F. Ви можете змусити дітей реєструвати їхні скасування, які зберігатимуться та викликатимуться за потреби.

ii) Ви можете використовувати struct вирівнювання пам'яті функцію щоб передати дітей батькам.

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

б) Ви можете використовувати послідовну політику іменування та використовувати підхід розділення та перемоги для створення програми. Він не матиме успадкування, але оскільки ваші функції невеликі, зрозумілі та послідовно відформатовані, вам це не потрібно. Кількість коду, який потрібно написати, збільшується, дуже важко залишатися зосередженим і не піддаватися простим рішенням (хакам). Однак цей спосіб кодування ніндзя є способом кодування C. Залишайтеся балансом між свободою низького рівня та написанням хорошого коду. Хороший спосіб досягти цього - писати прототипи, використовуючи функціональну мову. Наприклад, Haskell надзвичайно хороший для алгоритмів прототипування.

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


Перші c ++ copmpilers були не що інше, як попередні процесори, що генерували код C. Таким чином, ВСІ функції c ++ - включаючи множинне успадкування, можна реалізувати за допомогою C. (для емуляції обробки винятків c ++ в C потрібна буде якась підтримка платформи для винятків, але для цього також потрібна реалізація c ++, тому я не думаю, що це робить основним ідея недійсна).
Кріс Бекк

2
@Chris Becke, ваша відповідь занадто філософська. Для одного, C має декілька стандартів (через роки), ледь будь-який з них повністю прийнятий компіляторами C, не кажучи вже про c ++. Сказати, що C ++ - це супернабір C, оскільки він використовує синтаксис C, не означає багато, тому що ви навіть не можете написати код для одного компілятора C, який збирається в інший компілятор C без значних зусиль. Крім того, існують мовні функції (системи типів, підтримка OOD), які пропонуються іншими мовами, які неможливо реалізувати на C, не використовуючи C для створення нової мови (саме тому існують "нові мови")
Sprague

Ти знаєш. Я більше не бачу, яку релевантність має мій коментар до цієї публікації. : P
Кріс Бекк

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