IT業界で気づいたことをこっそり書くブログ

くすぶってるアプリエンジニアが、日々気づいたことを適当に綴っていきます(受託→ベンチャー→フリー→大企業→ベンチャー→法人化(今年))

プログラムの設計思想には、収束型と発散型があるっていう話(その1)

毎年新しいアーキテクチャーや設計手法が生まれては消えていきます。
毎回新しい案件に入るごとに、モヤモヤする設計を目の当たりにします。

そこでどうにも2つの大きな思想の違いがあることにようやく気づき始めることができました。
おそらく優秀な層の方々は数年前か、もっと前にそこにたどり着いているはずなので、この話は今更かもしれませんが、備忘録的にまとめていきたいと思います。

まだ頭の中でとっちらかってるので、今回は基本事項だけです。

 

 

なぜ気づいたか、きっかけ

リアクティブやRxの思想、あるいはデータバインディングという新しい方法を知る中で、彼らが何をしたいのか考える中で気づきました。
プラスアルファで、そういうったものを導入した時に、却って困る事象が起きた時に、既存コードの優位性を考える中で気づきました。

と言ってもこの考え方自体そもそも古典的な感じがします。

 

なぜ「2種類」なのか

ぶっちゃけ私がリアクティブ周りの思想を全部把握できないから、せいぜい2種類しか観測できないっていうだけです。

リアクティブシステムが注目を集める理由 | Think IT(シンクイット)

 

Reactive Programming(リアクティブプログラミング)
Functional Reactive Programming(ファンクショナルリアクティブプログラミング)
Reactive Extentions(リアクティブエクステンション)
Reactive Streams(リアクティブストリーム)
React.js
 

 

あっあっあっ(脳が壊れる音)
難しすぎる。

 

でもこういうパラダイムを作るときって、色んな複数の思想がゴチャ混ぜで導入されて意味不明になりがちなので、結局どんな差があるの?と限界まで削ぎ落とす分析は重要だと信じています。じゃないと私の矮小な頭では理解できません。

 

発散型と収束型(仮名)

収束型(コールバック型、中央集権)

これまで皆がやってきたプログラミング方法。
メインとなる処理の流れがあり、関数に処理を投げて結果を受け取る。
メインとなる処理の流れが基本的に全てを取り仕切る。

発散型(通知型、分散型、リアクティブ?)

関数に処理を投げるがコールバックは受け取らず、投げっぱなし。
反応的(何かが起きたら、別の何かが起きる)
各モジュールが自分の責任範囲について処理を取り仕切る。

喩えとか

会社に喩えると
収束型は「このタスクやっといて、終わったら報告してね」
発散型は「このタスクやっといて、終わっても報告はいらん」

(思いついたら追記します)

 

オブザーバーパターン、KVO、リアクティブ、マイクロサービスあたりは発散型

例えばマイクロサービスが分かりやすいです。
これは1個のモノリシックなサービスを作るんじゃなく、複数の独立したサービスに分割しようという話です。

 

発散型が流行りつつある

発散型に該当しているキーワードを見ると、スタイリッシュで次世代チックな感じがしないでしょうか?
実際これらは流行りつつあると思います。
理由はおそらく「非常に疎結合に作れる」故に「テストコードが書きやすい」あたりです。悪言い方をすると意識高い界隈で流行ってますね(毒吐き)。クソ真面目界隈でも良いですけど。

 

発散型の欠点

ただこれらには欠点もあるようで、それに気づかず安易に導入して苦しい思いをしている人やその煽りを食らっている人(私)もいるようです。
問題なのは、疎結合という部分です。

WebAPIの例が分かりやすいと思います。
一つのシステム内で完結する場合に比べ、例えば「アプリーWebAPI」のようなシステムが分断している場合では、対応しなければならないことが非常に多くなります。WebAPIはどういうリクエストが来ても内部を正しい状態にしなければなりません。

「処理を投げっぱなしにしていい」という状態を作るには

  • 完全にモジュール化されていて
  • どんなリクエストが来るかのパターンを網羅し
  • どんなリクエストも正しく処理できる

ような状態を作らなければならないのです。

つまり、1個のモジュールとして完璧でなければなりません。
これが非常に困難かつコストが高いのが問題です。
プログラムとしては理想的かもしれませんが、プロジェクト的には理想から程遠くなるかもしれません。

 

対して収束型と言うのは、言ってしまえばモノリシックなコードを見やすく分割しただけに過ぎず、しばしばモジュール化が甘くなります。
ただし代わりに全てのリクエストに対応する必要はなく、仕様上存在する有限個のパターンに対応できていればシステムは動きます。
プログラム的、テストコード的には理想的ではないにしても、プロジェクト的には正解であることもあります。

 

今後の研究課題

最近考えてる内容です。書かないと忘れそう。

  • 発散型、収束型に適したシステムはそれぞれどのようなものか
  • 発散型、収束型に適したプロジェクトはそれぞれどのようなものか
  • それぞれの得意分野はどこにあるか
  • 発散型、収束型は混ぜることは可能か
  • 発散型、収束型が適していない場合どのような自体になるか
  • 発散型、収束型が適していない場合、経験的に修正に非常にコストがかかるがそれは何故か(両立はやはりできないのか?)
  • 発散型、収束型の利点と欠点
  • 発散型、収束型の具体的な処理の流れ
  • 収束型でテストコードは書けないのか
  • それぞれの理想的な設計とは
  • うっかり別の思想を導入してしまいがちなシーン

少なくともモバイルアプリについては、発散型が適していないと感じています。
一部の先進的な会社は確かに発散型を導入しているのですが、元々モバイルアプリに適していないのを理解した上でそれでも余りある理由があるから導入していると思うんですが、どうも他のプロジェクトでその文脈が無視されがちなのでは?と疑っています。

 

本件、中途半端ですが。
来年いっぱいくらい掛けて考えていきたいと思います。