関数に対してDI
from DI
#WIP
https://fsharpforfunandprofit.com/posts/convenience-functions-as-interfaces/
案
カリー化する
Test Stubを使う
これはDIとは言わないと思うけどmrsekut.icon
引数として渡す
https://myuon.github.io/posts/haskell-di/
HaskellでDI
存在型を使う
この辺はmonadが無いと無理
ReaderTパターン
Freeモナド
Tagless final
その他
Velona
定義の仕方が若干キモいけど、わからんではない
Cake Pattern
よく知らん
カリー化する
code:usecases.ts
async function usecase() {
const result = await repository();
return result
}
code:repositoeis.ts
// test時はこれをexport
const getUsersRepository = (DB:DB) => async () => {
const result = await DB.get(SELECT * FROM users WHERE id = ?);
return result;
}
const db:DB = {}
// 通常はこれをexport
const repository = getUsersRepository(db)
Test Stubを使う
ref Jestでmoduleのstubを作る
これで良くない?mrsekut.icon
引数として渡す
『Domain Modeling Made Functional』 9章 Injecting Dependencies
ReaderやFreeを使わない単純なアプローチ
依存を関数の頭から全部入れて、バケツリレーしていく感じ
code:fs
let placeOrder
checkProductExists // dependency
checkAddressExists // dependency
getProductPrice // dependency
createOrderAcknowledgmentLetter // dependency
sendOrderAcknowledgment // dependency
: PlaceOrder = // definition of function
fun unvalidatedOrder -> ..
ちなみに、これらのdependencyは値ではなく関数
main関数で全部のdependencyをinjectionする
main関数が冗長になるが仕方がない
例えば、引数をrecordにするなどして引数の個数を減らす工夫はできるとのこと
まあガチのdependencyならこれでもいいか。
問題はテストしたいだけなのに、ここまでしないといけないのか、という点mrsekut.icon
節の最後の方では、カリー化する例も書いてあった
https://blog.anatoo.jp/2020-05-14
Haskell で Dependency Injection を実現する方法の一つとして Service パターンを紹介している記事👀
DIの対象をレコード型で定義して関数の引数で渡すというシンプルなもの。RIO や Handle パターンなど他の手法との比較も書いてある
Handle Pattern
https://brandonchinn178.github.io/posts/2023/05/03/services-design-pattern
ref