Чи базуються бази даних та функціональне програмування?


122

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

Одне, що зробило мене набагато більш продуктивним розробником з боку речей OOP, - це відкриття об'єктно-реляційних картографів, таких як MyGeneration d00dads для .Net, Class :: DBI для perl, ActiveRecord для ruby ​​тощо. Це дозволило мені триматися подалі від написання вставляти та вибирати висловлювання протягом усього дня, а також зосереджуватись на легкій роботі з даними як об'єктами. Звичайно, я все-таки могла писати запити SQL, коли потрібна їх потужність, але в іншому випадку це було чудово абстраговано за лаштунками.

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

(Зауважте, я не переглядав Веб-блоки або Посилання надзвичайно уважно, я можу просто нерозуміти, як вони використовуються).

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

  1. Не використовуйте функціональне програмування
  2. Доступ до даних набридливим, не абстрагованим способом, який включає вручну написання багатьох SQL або SQL-подібних кодів ala Посилання
  3. Змусимо нашу функціональну мову перетворити на псевдо-OOP парадигму, тим самим видаляючи частину елегантності та стабільності справжнього функціонального програмування.

Зрозуміло, що жоден із цих варіантів не здається ідеальним. Чи знайшов спосіб обійти ці проблеми? Чи справді тут навіть є проблема?

Примітка: Особисто я найбільше знайомий з LISP на фронті FP, тому, якщо ви хочете навести будь-які приклади та знати кілька мов FP, lisp, ймовірно, буде кращою мовою вибору

PS: Про питання, специфічні для інших аспектів веб-розробки, див. Це питання .


Дивіться також: stackoverflow.com/questions/218190/…
WW.

4
Ознайомтеся з ClojureQL та HaskellDB. Вони є шарами абстракції, що використовують реляційну алгебру.
Масса

10
Ви починаєте з неправильної передумови. Функціональне програмування стосується явного та розумного управління станом. Насправді вони дуже добре працюють з базами даних.
Лукіан

3
SQL - одна з найуспішніших мов, орієнтованих на функціональне програмування, я не думаю, що є якісь властиві труднощі.
Дуглас

3
Ваші №2 та №3 - хибна дихотомія. Запис необробленого SQL - це не те, чого слід обов'язково уникати, а абстракції над базою даних не обов'язково повинні бути OOP-esque.
Ден Бертон

Відповіді:


45

Перш за все, я б не сказав, що CLOS (Common Lisp Object System) є "псевдо-OO". Це першокласний ОО.

По-друге, я вважаю, що ви повинні використовувати парадигму, яка відповідає вашим потребам.

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

Якщо у вас декілька потреб змішані, змішайте свої парадигми. Не обмежуйтеся лише використанням правого нижнього кута вашої панелі інструментів.


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

80

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

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

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

Я б не намагався писати T-SQL або використовувати концепції дизайну бази даних для створення вашого інтерфейсу користувача, чому б ви намагалися використовувати мову свого інтерфейсу та концепції дизайну для доступу до моєї бази даних? Тому що ви думаєте, що SQL недостатньо фантазійний (або новий)? Або вам не комфортно з цим? Просто те, що щось не відповідає моделі, з якою ви відчуваєте себе найбільш комфортно, не означає, що це погано чи неправильно. Це означає, що вона є різною і, ймовірно, різною з законних причин. Ви використовуєте інший інструмент для іншого завдання.


"SQL написаний для управління першими двома міркуваннями більш ефективно, ніж будь-яка мова на передньому кінці." О, справді? Чому ж тоді виходить, що обмеження SQL до сих пір не можуть робити такі речі , як це ?
Робін Грін

Але тригер може, це одна з головних цілей тригерів, щоб мати можливість обробляти складні обмеження.
HLGEM

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

31

Подивіться на статтю Бен Мозелі та Пітера Маркса "З ями дьогтю" , доступну тут: "З ями дьогтю" (6 лютого 2006 р.)

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

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

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


4
Який чудовий папір. Посилання, яке ви надаєте, порушено (тимчасово?), Але я знайшов папір також на shaffner.us/cs/papers/tarpit.pdf
пестофаг

2
@queque Оригінальна посилання все ще мертва. Я поклав нове посилання у відповідь Кевіна.
Девід Тонхофер

25
  1. Функціональні мови не мають мети залишатися без громадянства, вони мають на меті зробити явним управління державою. Наприклад, у Haskell ви можете вважати монаду State як серце "нормальної" держави, а IO монаду - представленням стану, яке повинно існувати поза програмою. Обидва ці монади дозволяють вам: (а) явно представляти впорядковані дії та (б) будувати виважені дії, складаючи їх за допомогою референтно прозорих інструментів.

  2. Ви посилаєтесь на кілька ОРМ, які відповідно до їх імені абстрагують бази даних як набори об'єктів. Правда, це не те, що представляє інформація у реляційній базі даних! За своєю назвою він представляє реляційні дані. SQL - це алгебра (мова) для обробки відносин на реляційному наборі даних і сама по собі є досить "функціональною". Я підводжу це так, щоб вважати, що (a) ORM - це не єдиний спосіб відображення інформації бази даних; (b) що SQL насправді є досить приємною мовою для деяких конструкцій баз даних, і (c) що функціональні мови часто мають реляційну алгебру відображення, які розкривають потужність SQL в ідіоматичному (а у випадку з Haskell, типовим) способом.

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


15

Я не думаю, що безгромадянська мова мов fp не є проблемою підключення до баз даних. Lisp - це не чиста функціональна мова програмування, тому у неї не повинно виникнути проблем з державою. І чисті функціональні мови програмування, такі як Haskell, мають способи поводження з введенням і виведенням, які можна застосувати до використання баз даних.

З вашого запитання здається, що ваша основна проблема полягає в тому, щоб знайти хороший спосіб абстрагувати дані, що базуються на записах, які ви повертаєте зі своєї бази даних на щось, що є lisp-y (lisp-ish?), Не вимагаючи писати багато SQL код. Це здається скоріше проблемою з інструментами / бібліотеками, ніж проблемою з мовною парадигмою. Якщо ви хочете робити чисто FP, можливо, Lisp не є правильною мовою для вас. Звичайний ліс здається більше інтеграцією гарних ідей від oo, fp та інших парадигм, ніж про чистий fp. Можливо, вам слід скористатися Erlang або Haskell, якщо ви хочете пройти чистий FP-маршрут.

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

Відмова: Я не експерт Ліспа. Мене найбільше цікавлять мови програмування та граю з Lisp / CLOS, Scheme, Erlang, Python та трохи Ruby. У щоденному житті програмування я все ще змушений використовувати C #.


3
Ерланг не є чистою ПП за будь-яким визначенням цього слова. Ви пишете erlang, створюючи безліч процесів (усі вони працюють паралельно), які надсилають повідомлення іншим, подібно до об'єктів, скажімо, у малій розмові. Тож з точки зору високого рівня це може здатися дещо OO-результатом, і, безумовно, має стан. Якщо ви збільшуєте масштаб (на код, який працює всередині процесу), він виглядає більш функціональним, але все ще не є виключно функціональним, оскільки ви можете надсилати повідомлення (а отже, робити введення-виведення тощо) з будь-якого місця, де ви хочете, а також зберігати " глобальні змінні "(глобальний до процесу, всередині чогось, що називається" процес диктату ").
Amadiro

@Amadiro "безумовно має стан". Звичайно, так і є. У нас завжди є держава. Проблема не держава, це стан, що змінюється . Добра частина «функціонального програмування» полягає у позбавленні від крихких представлень стану (наприклад, об'єктні екземпляри, які змінюються іншими процесами, в той час як ми посилаємось на них, без транзакційного способу, щоб додати образи до травми). Ерланг має стан, який не змінюється, і тому відповідає цим критеріям функціонального програмування. Отже, бази даних будь-якого виду ніколи не є проблемою. Оновлення баз даних є проблемою (див. Також неприємне твердження в Prolog).
Девід Тонхофер

15

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

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

# Start: Time T
likes(db, "Bob")
=> "Suzie"
# Change who bob likes
...
likes(db "Bob")
=> "Alice"
# Recover the database from T
db = getDb(T)
likes(db, "Bob")
=> "Suzie"

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

Наприклад, це головна ідея Datomic .


Приємно. Я навіть не знав про Datomic. Дивіться також: Обгрунтування Datomic .
Девід Тонхофер

12

Зовсім ні. Існує жанр баз даних, відомий як «Функціональні бази даних», з яких Mnesia є, мабуть, найбільш доступним прикладом. Основний принцип полягає в тому, що функціональне програмування є декларативним, тому його можна оптимізувати. Ви можете здійснити з'єднання за допомогою списку «Поняття» на постійних колекціях, і оптимізатор запитів може автоматично розробити спосіб реалізації доступу до диска.

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


1
Я не думаю, що це багато рішення. Існують і об’єктно-орієнтовані бази даних, але зазвичай потрібно підключитися до звичайної старої реляційної бази даних SQL.
jalf

4
Ви все ще маєте невідповідність імпедансу з мовами OO та базами даних приблизно так само, як і невідповідність функціонального опору SQL.
ЗанепокоєнняOffTunbridgeWells

1
@ConcernedOfTunbridgeWells Я довільно констатую, що ця невідповідність імпедансу є плодом уяви людей з молотками, яким потрібно все, щоб бути цвяхами. Дуже тонкі шари та знання про SQL можуть елегантно пройти довгий шлях, отже, jOOQ та подібні прокладки.
Девід Тонхофер

6

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

Ідея об'єктно-реляційного Mapper, де ви імпортуєте запис бази даних як об'єкт, а потім модифікуєте його, настільки ж застосовна і корисна для функціонального програмування, як і для об'єктно-орієнтованого програмування. Одне застереження полягає в тому, що функціональне програмування не змінює об'єкт на місці, але API бази даних може дозволити вам змінювати запис на місці. Контрольний потік вашого клієнта виглядатиме приблизно так:

  • Імпортуйте запис як об’єкт (API бази даних може заблокувати запис у цей момент),
  • Читайте об’єкт і гілку, базуючись на його вмісті, як вам подобається,
  • Упакуйте новий об'єкт із потрібними модифікаціями,
  • Передайте новий об'єкт у відповідний виклик API, який оновлює запис у базі даних.

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


5

Мені найбільше комфортно з Haskell. Найвизначніша веб-структура Haskell (порівнянна з Rails і Django) називається Yesod. Здається, є досить класний, типовий безпечний, багатозахідний ORM. Погляньте на розділ Персистенс у своїй книзі.


0

Бази даних та функціональне програмування можна сплавити.

наприклад:

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

               Clojure -> DBMS, Super Foxpro
                   STM -> TransactionMVCC
Persistent Collections -> db, table, col
              hash-map -> indexed data
                 Watch -> trigger, log
                  Spec -> constraint
              Core API -> SQL, Built-in function
              function -> Stored Procedure
             Meta Data -> System Table

Примітка. В останньому spec2 spec більше нагадує RMDB. дивіться: spec-alpha2 wiki: схема та вибір

Я виступаю за: побудова моделі реляційних даних на основі хеш-карти для досягнення комбінації переваг NoSQL та RMDB. Це насправді зворотна реалізація posgtresql.

Введення качок: якщо це схоже на качку, і какає, як качка, це повинно бути качка.

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

Clojure - це функціональна мова програмування, заснована на теорії реляційних баз даних

Все є RMDB

Реалізація реляційної моделі даних та програмування на основі хеш-карти (NoSQL)

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