5

関数型プログラミングと 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 つの理由から、私には違和感を覚えます。

  1. ルートとコントローラーを追加し続けると、このモジュールはすぐに数千行の混乱に変わります。
  2. ルーティング、dom 操作、およびデータ保存を同じモジュールに保持することは、単一責任の原則に違反します (FP でも重要であると思います)。

このモジュールをいくつかのモジュールに分割できます。たとえば、コントローラーごとに 1 つのモジュールを作成し、ある種の効果的なレイヤーを作成できます。しかし、10 個のコントローラー モジュールがあり、DOM 固有のライブラリを変更したい場合は、それらをすべて編集する必要があります。

このアプローチは両方とも理想からかけ離れているため、問題はどちらを選択するかです。それとも他に行く方法があるのでしょうか?

4

2 に答える 2