関数型プログラミングと Purescript を試してみることにしました。コードを読ん"Learn you a Haskell for great good"
で"PureScript by Example"
少し遊んだ後、基本を理解していると言えると思いますが、コードが非常に結合しているように見えることが 1 つあります。ライブラリを頻繁に変更するのが普通で、OOP ではオニオン アーキテクチャを使用して、独自のコードをライブラリ固有のコードから切り離すことができますが、Purescript でこれを行う方法がわかりません。
私は人々が Haskell でこれをどのように行っているかを見つけようとしましたが、「Haskell で複雑なアプリケーションを作成したことがないので、誰もその方法を知りません」または「入力があり、出力がある」などの回答しか見つかりませんでした。 、その間にあるものはすべて純粋な関数です。」しかし、現時点では、仮想ドメイン、シグナル、Web ストレージ、ルーター ライブラリを使用するおもちゃのアプリがあり、それぞれに独自の効果とデータ構造があるため、1 つの入力と 1 つの出力のようには聞こえません。
私の質問は、アプリの半分を書き直さずにライブラリを変更できるように、コードをどのように構成するか、またはどのようなテクニックを使用する必要があるかです。
アップデート:
複数のレイヤーを使用し、エフェクトをメイン モジュールに保持するという提案も非常に一般的であり、そうする必要がある理由も理解しています。
これは、私が話している問題をうまく説明する簡単な例です。
btnHandler :: forall ev eff. (MouseEvent ev) => ev -> Eff (dom :: DOM, webStorage :: WebStorage, trace :: Trace | eff) Unit
btnHandler e = do
btn <- getTarget e
Just btnId <- getAttribute "id" btn
Right clicks <- (getItem localStorage btnId) >>= readNumber
let newClicks = clicks + 1
trace $ "Button #" ++ btnId ++ " has been clicked " ++ (show newClicks) ++ " times"
setText (show newClicks) btn
setItem localStorage btnId $ show newClicks
-- ... maybe some other actions
return unit
-- ... other handlers for different controllers
btnController :: forall e. Node -> _ -> Eff (dom :: DOM, webStorage :: WebStorage, trace :: Trace | e) Unit
btnController mainEl _ = do
delegateEventListener mainEl "click" "#btn1" btnHandler
delegateEventListener mainEl "click" "#btn2" btnHandler
delegateEventListener mainEl "click" "#btn3" btnHandler
-- ... render buttons
return unit
-- ... other controllers
main :: forall e. Eff (dom :: DOM, webStorage :: WebStorage, trace :: Trace, router :: Router | e) Unit
main = do
Just mainEl <- body >>= querySelector "#wrapper"
handleRoute "/" $ btnController mainEl
-- ... other routes each with it's own controller
return unit
ここには、ルーティング、Web ストレージ、dom 操作、およびコンソール ロギングを備えた単純なカウンター アプリがあります。ご覧のとおり、単一の入力と単一の出力はありません。ルーターまたはイベントリスナーから入力を取得し、コンソールまたは dom を出力として使用できるため、少し複雑になります。
この効果的なコードをすべてメイン モジュールに置くと、次の 2 つの理由から、私には違和感を覚えます。
- ルートとコントローラーを追加し続けると、このモジュールはすぐに数千行の混乱に変わります。
- ルーティング、dom 操作、およびデータ保存を同じモジュールに保持することは、単一責任の原則に違反します (FP でも重要であると思います)。
このモジュールをいくつかのモジュールに分割できます。たとえば、コントローラーごとに 1 つのモジュールを作成し、ある種の効果的なレイヤーを作成できます。しかし、10 個のコントローラー モジュールがあり、DOM 固有のライブラリを変更したい場合は、それらをすべて編集する必要があります。
このアプローチは両方とも理想からかけ離れているため、問題はどちらを選択するかです。それとも他に行く方法があるのでしょうか?