Pinto公開に向けて #16 ― 責務駆動設計で仕切り直すことに決めた
あらすじ
Pintoというソーシャルブックマークサービスを、Rubyで開発中です(GitHubリポジトリ)。開発中に気づいたことや工夫した点などを、備忘録も兼ねて書いています。その16回目です。
ActiveSupportのDependenciesを使って、やめた
autoloadを山ほど書くのが面倒なのでactivesupportのDependenciesを使ってみたのですが、ライブラリの読み込みに時間がかかり、Webサーバ起動時やユニットテスト時にイライラさせられたので、採用を見合わせました。
軽いautoloaderを自分で書けば解決できる問題なので、そのうち書くかもしれません。Zend_Loaderが恋しいとかなんとか。
ラップを外した
前回、String等をラップしたわけですが、なんでもかんでもラップしてしまったため、クラス数がふくれあがり、収拾がつかなくなってしまいました。なので、元に戻しました。
とはいえ、単なるStringやIntegerを使うべきでないオブジェクトも、やはり存在するだろうと思われます。なんとなく、バリデーションが必要ならラップすべきなんじゃないかと思っていますが、まだ方針は固まっていません。
ここから本題:責務駆動設計に出会った
そんなこんなでオブジェクト設計について、すがるための藁を探していたら、責務駆動設計という考え方があることを知りました。
責務駆動設計(Responsibility-Driven Design、RDD)の詳細は、提唱者であるRebecca Wirfs-Brock女史のサイトにあるPDF群をご参照ください。私は、下記の2つを読み、感銘を受けました。
日本語で読みたい方は、同女史とAlan McKean氏の共著『オブジェクトデザイン』をどうぞ。
責務駆動設計で、私が重要だと思ったのは:
- オブジェクトには役割があるとみなそう
- 各オブジェクトの役割を6つのステレオタイプで考えてみよう
という考え方です。
6つのステレオタイプ
6つのステレオタイプについて、前掲書から引用します。
- 情報保持役(Information Holder)
- 情報を知り、情報を提供する
- 構造化役(Structurer)
- オブジェクト間の関係と、それらの関係についての情報を維持する
- サービス提供役(Service Provider)
- 仕事を行うが、一般に演算サービスを提供する
- 調整役(Coordinator)
- 他のオブジェクトにタスクを委譲することでイベントに対応する
- 制御役(Controller)
- 判断を行い、他のオブジェクトのアクションをしっかりと指示する
- インターフェース役(Interfacer)
- システム内の異なる部分間で情報やリクエストを変換する
各オブジェクトの役割を、これらのいずれかとみなすと、すっきりした設計になるのではないか。あるいは役割を2つ以上もつオブジェクトもあるかもしれないが、その場合でもメインの役割は1つと考えられるのではないか。――これが責務駆動設計のエッセンスだと私は理解しています。
たとえば、Webアプリケーションならば、インターフェース役がHTTPリクエストを内部で扱いやすいリクエストオブジェクト(情報保持役)に変換し、ルータ(調整役)がリクエストを見て適切なコントローラ(制御役)にタスクを委譲し……という流れになるのではないでしょうか。
というわけで
いろいろ迷走した感はありますが、そのおかげで責務駆動設計に出会えたので、良しとしましょう。これからは手が進む予感がしています(ほんとか)。