Допустим, вам нужно подключиться к базе данных.
Итак, вы даете DbConnection
в качестве последнего аргумента некоторой гипотетической функции с таким типом: doDbStuff :: Int -> DbConnection -> Int
Возможно, существуют другие функции, которые также зависят от DbConnection
, и все они выполняют операции записи. Таким образом, они могут выполняться отдельно или как часть атомарной операции (то есть транзакция ).
Поскольку можно хотеть управлять DbConnection
, используя пул , а функции могут быть или не быть частью атомарной операции, они не реализуют код для получения и освобождения экземпляров DbConnection
из и в бассейн.
Теперь эти функции являются частью композиции длинных функций, в которой могут приниматься определенные решения, не требующие DbConnection
. То есть существует вероятность того, что DbConnection
может быть взято из пула и использовано другим запросом, что может привести к появлению узких мест.
Существует альтернатива, в которой не вводят DbConnection
, а функцию высокого порядка, такую как withConnection :: (DbConnection -> a) -> a
, поэтому каждая функция может взять DbConnection
, использовать ее, а все withConnection
заботится о получении и освобождая связи. Недостатком здесь является то, что труднее заставить многие функции сотрудничать в рамках атомарной операции.
Итак ...
Сейчас я использую подход №2. Кстати, есть ли альтернатива, на которой можно сохранить лучшее из обоих подходов?
Псевдокод в JavaScript:
Подход № 1
const connectionString = '[whatever]'
const env = { connection: acquire (connectionString) }
const output = composition (arg0) (argN) (env)
// then, release the connection
// f :: a -> b -> { connection: DbConnection }
const f = x => y => ({ connection }) =>
doDbStuff (x + y) (connection)
Подход № 2
const withConnection = f => [stuff to acquire the connection, and aftewards, release it]
const env = { withConnection }
const output = composition (arg0) (argN) (env)
// type FnConnection DbConnection c = c -> a
// f :: a -> a -> { connection: FnConnection }
const f = x => y => ({ withConnection }) =>
withConnection (doDbStuff (x + y))