疎結合っていいよね

今までの経験でいろんなレイヤーで依存性べったりで密結合なシステムを見てきてそれをちょっとだけ改善してきて思うところを書いてみる。

小さなシステムであれば多少は密結合でも何とかなるかもしれない、というか扱うファイル数、Gitプロジェクト数が1つでむしろやりやすいかもしれないけどシステムが大きくなるにだんだん拡張しにくくなる。かといって最初からあまりにも小さなシステムに分割するとそれはそれでやりづらい。完璧な答えは無いけれど僕が見てきたシステムの話をしよう。

その前にまず依存性といってもいろんなレイヤーがあると思うので、ここでは以下の3つの話をしよう。

  • アプリケーション内のコンポーネント間の依存性
  • システム間の依存性
  • バッチ内の各ジョブ間の依存性


1番目のアプリケーション内のコンポーネント間の依存性の例をあげるとMVCである。

SpringでWebアプリケーションを組んだ場合にModelがあってViewがあってControllerがあってとかあるよね。
さらにいうとControllerはServiceを呼び出してServiveはDaoを呼び出すなんてよくあるパターン。
Serviceはビジネスロジックを書くところで、DaoはRDBMSなどにアクセスしてデータを取得するところ。

ControllerでDBアクセスやビジネスロジックを書かないで分離してユニットテストしやすくしましょう、DIコンテナもあるしねっていうアレである。
まあわかりやすいですな。


2番目のシステム間の依存性というのは複数のシステムがあってそれぞれREST APIで連携するようなやつである。

1番目のシステムなんかでも例えばRDBMSからデータを取得する部分を切り出してREST APIとして公開すれば別のシステムからも使えるようになる。

昔僕が関わったプロジェクトで3社が共同開発していてそれぞれのモジュールがべったり密結合していてコンパイルがほとんど通らないことがあってちょっと心が折れたけど、あれも無理して1システムに3社のソースを突っ込むなんてことしなくて3システムでREST APIで連携すればお互い平和になれた気がする。。。

やはり一つの台所には一人のシェフであるべきなのだ。

開発者は他の人が何をしているかなんて気にしないで開発したい。自分が修正したコードが思わぬところに影響を及ぼすのを恐れている。だから疎結合、独立性は大事なのだ。

OSSのプロジェクトは各開発者が貢献しやすく思わぬ副作用を避ける仕組み、プラグインシステムを採用しているケースが多い。Eclipse, Jenkins, Trac, Redmine, Fluentdなどなど。これは開発者が好きなように開発したい、そして思わぬ副作用を避けたい、というトレードオフのもと良い落としどころだと思う。もちろんあるプラグインが別にプラグインに依存していていわゆるプラグイン地獄なるものもあるがそれはまた別ステージの話。

ところでHBaseのcoprocessorはまあプラグインみたいなもんだけどそのプラグインのせいでHBase全体が不安定になることがあるのであまり独立性が高いとは言えないと思う。難しいものである。

ログ収集システムのせいで本番アプリケーションがおかしくなってはまずいし、独立性は大事である。
なのでアプリケーション側はひたすらログを出力して、ログ収集システム側はそのログをtailするっていうのは独立性を保っていると思う。


さて3番目のバッチ内の各ジョブ間の依存性の話をしよう。

データ量が増えたり処理するバッチの本数が増えたりして夜間バッチの時間がのびるというはよくある話。
僕の場合はazkabanでジョブ管理していてそれぞれのジョブは複数のHiveジョブを含んでいる。

例えばこんなジョブフローがあったとしよう。

ここでJob4-2で2時間かかっていてボトルネックになっているとしよう。

Job4-2のなかには4つのタスク(例えば4つのHiveジョブ)があって、でもそのなかでJob4に依存しているのは1つだけでそいつは30分かかっていたとする。

その場合その1つのジョブを切り出してJob4-2-1として残りをJob-4-2-2としてJob4との依存性を無くせば下記のようになり並列に実行できるジョブが増えて全体の実行時間を短縮することができる。最近は僕は似たようなことをやってバッチの実行時間を約1時間短縮しました。

ぼっち、、、もとい独立性大事です。同調圧力に負けずぼっちでやっていくことも時としては大事です。


さてではなぜ密結合のシステムが出来るのでしょうか。

もともと小さなシステムが規模が大きくなって密結合になるのはよくある話。
そしてリグレッションが怖いので大きな変更はしたくないというのもあります。

なんちゃらadminとかなんちゃらmanageとかそんな汎用的なシステム名のもと機能いっぱいの密結合システムもよくある話。

まあ理由はいろいろあると思うんですが、最近指摘されてなるほどと思った点を書いておきます。

独立性を高めることはファイルなりシステムなりを増やすことにつながります。

でもファイルなりシステムを増やすことにハードルがあるとしたらどうなるでしょうか。

  • Javaのクラスを増やすのにExcelの申請書が必要だったら?
  • Gitのプロジェクトを増やすのにワークフロー申請が必要だったら?
  • マシンを増設するのになんらかの承認が必要だったら? まあこれは普通必要ですよね。。。

事務的な面で何かしら心理的なハードルがあると、ありもののシステムに機能を追加する方を選択する可能性が高くなります。
そして密結合なシステムが出来上がる。

まあそんなわけで事務的な面を減らしてカジュアルにやれるようにすると密結合なシステムを減らせるかも。