2007年07月09日

単一責任の原則

単一責任の原則は、英語ではthe Single Responsibility Principleといい、SRPと略されます。

これも、あなたのオブジェクト指向での物事の捉え方が最適かどうかについてのガイドとなるものです。
原則というのは、みんなそうなんですね。

ソフトウェア開発では、この捉え方が最適かどうか(少なくとも、間違っていないこと)というのは、開発の成否を握るほど重大な問題です。
常に意識すると共に、成果物に対してはこれらの原則に照らして妥当性を検証し、随時リファクタリングしていかなければなりません。

コンテンツ

  1. 日常にある例
    1. 役割で分ける
    2. わかりやすくて扱いやすい
  2. ビジネスの場での例
  3. ソフトウェア開発者の方のための追記
  4. オススメ
単一責任の原則は、非常にシンプルですが、同時に、守るのが非常に難しい原則でもあります。
これは、「オブジェクトの役割(責任)は、一つでなければならない」という原則です。
ソフトウェア開発者の方向けに言うと「クラスを変更する理由は一つでなければならない」とも言えます。
例を挙げて、詳しく見ていきましょう。

日常にある例

たとえば、あなたは今日買い物に行かなければならないとします。
買うものは以下の通りです。
  • じゃがいも
  • にんじん
  • たまねぎ
  • 牛肉
  • デジタルカメラ用充電池
  • 容量1Gバイトのメモリーカード
  • 携帯用三脚
  • バインダー
  • 穴あけパンチ

これを買い物リスト風にオブジェクトにしてみると、以上の買うものを属性に持った、「今日の買い物」というオブジェクトになりますね。
この属性全部が「買った」という状態になれば、買い物は終わりです。

あなたのうちの近所に、大型スーパーありますか?
イ○ン(ジャ○コ)とか西○とか、そういうやつです。
食料品とか家電とか文房具とか、いろいろ売ってるところ。

んー、今日これだけ買わなきゃ行けないんだ。
めんどくさいなー。
どれか買い忘れちゃうかもー。

なんて思う前に、ちょっと待ってください。
この「今日の買い物」オブジェクト、ちょっと見直してみましょう。
これ、このままだと非常に融通が利かないオブジェクトです。
なぜか?
単一責任の原則に反しているからです。
役割で分ける
私たちは、いろいろな役割をまとめていっしょくたに考えることに、慣れきってしまっています。
上の買うもののリストを見て、これを「今日の買い物」と言っても違和感ありませんよね。
でもこのリストは、よく見ると少なくとも3つの別々の買い物がいっしょくたになっています。
  • 晩ご飯の材料
    • じゃがいも
    • にんじん
    • たまねぎ
    • 牛肉
  • デジタルカメラの備品
    • 容量1Gバイトのメモリーカード
    • 携帯用三脚
  • 文房具
    • バインダー
    • 穴あけパンチ
という具合です。
さらに言えば、晩ご飯の材料は
  • 野菜
    • じゃがいも
    • にんじん
    • たまねぎ
    • 牛肉
というように野菜と肉に分けることができますね。

こうすると、買わなきゃいけないものは大きく分けて3つです。
  • 晩ご飯の材料
  • デジタルカメラの備品
  • 文房具
これなら、たった3つですから、忘れる可能性は低いですね。
そしてこの3つそれぞれについて、買うものは2つずつあります。
  • 晩ご飯の材料
    • 野菜
シンプルですね。
  • デジタルカメラの備品
    • 容量1Gバイトのメモリーカード
    • 携帯用三脚
これもシンプル。
  • 文房具
    • バインダー
    • 穴あけパンチ
はい、シンプル。
野菜では、じゃがいも、にんじん、たまねぎを買い、肉では牛肉を買います。
わかりやすくて扱いやすい
「晩ご飯の材料」オブジェクトと「デジタルカメラの備品」オブジェクト、そして「文房具」オブジェクトに分けたことで、把握しやすくなりましたね。

晩ご飯の材料は、食料品を売ってるとこなら買えますし、デジタルカメラの備品は電気屋さんで、文房具は文房具屋さんで買えますね。
大型スーパーが近所になくても、これなら大丈夫。

しかも、よく考えてみると、この中で今日買わなければならないのは晩ご飯の材料だけかもしれませんね。
デジタルカメラの備品は、次に撮影する前までに買えればいいでしょうし、文房具も使う前まででOK。

この買い物オブジェクト達は、それぞれ一つの目的のためだけにあります。
これが「オブジェクトの役割は、一つでなければならない」ということなのです。

こうしてちゃんと単一責任の原則が守られていれば、変更にも強くなります。
たとえば「あ、デジタルカメラの充電池、もう少し容量が大きいのが欲しいんだった」ってことになったとします。
元の「今日の買い物」オブジェクトでは、「イ○ンに、デジタルカメラ用の充電池売ってたかなぁ」なんて心配しなければなりません。
「しかたない、ちょっと遠いけど、西○まで行こう」
なんてことになったら、単にデジタルカメラの備品を一つ余分に買うためだけに、晩ご飯の材料も文房具も、買う店を変更することになるのです。
ちゃんと「晩ご飯の材料」と「デジタルカメラの備品」と「文房具」を分けてあれば、そんなことはありませんね。
デジタルカメラの備品を買う電気屋さんを変えればいいのです。
しかも、それは今日考えなくてもいいですしね。

ビジネスの場での例

仕事上でも、単一責任の原則は大きく影響します。
たとえば、ある人が開発リーダーであり、かつマネージャーだったとします。
これは、肩書きの話ではなくて、事実上の話です。
単に開発リーダーとしか呼ばれていなくても、人やお金や時間のマネジメントをしているなら、その人はリーダー兼マネージャーです。
こういう場合、その人は開発リーダーとしての仕事とマネージャーとしての仕事をきちんと分けて考えなければなりません。
そうしないと、リーダーとしての仕事とマネージャーとしての仕事がお互いに影響を与え合い、うまく両立することが難しくなるでしょう。

また、もしその人が異動や退職してしまう場合、その人の代わりを見つけるのは非常に困難になります。
リーダーに求められるスキルや経験と、マネージャーに求められるスキルや経験は別物だからです。
その両方を兼ね備え、かつそれを同時にこなせる人というのは、単なるリーダーや単なるマネージャーを探すのと比べると、非常に少ないでしょう。
兼務する仕事の種類が増えれば増えるほど、代わりを見つけるのは加速度的に困難になっていきます。

兼任というのは、人材不足を補うにはどうしても採用しなければならない人事手法ですね。
実際、よくある話です。
しかし、実はこのように大きなデメリットを抱えていることを意識していなければなりません。

ソフトウェア開発者の方のための追記

ソフトウェア開発者の方向けに言うと、単一責任の原則は、絶対的なものではなく、どちらかというと相対的なものです。
単一責任の原則は、ソフトウェア開発では、主にアプリケーションの変更に対する強度を高めるためのものです。
将来に渡って変更される見込みが全くないところを、責任を分けるためとはいえ、むやみに分割しても、効果はないということになります。
逆に、意味なく複雑さを増すだけです。

でも、将来に渡る変更の可能性なんて、正しく判断できると思いますか?
XP(エクストリームプログラミング)の有名なプラクティスの一つに、YAGNIというのがあります。
"You Aren't Going to Need It"の略です。
(今必要でないのなら)それは必要にはならない。
という意味で、もう少し突っ込んで言えば、
今必要なことだけを行う。
ということになります。
(XPのプラクティスについては、アジャイルソフトウェア開発の奥義を参照してください)

ぶっちゃけ、ありていに言っちゃうと
最初は単一責任の原則なんてあんまり意識しなくていいですよ。
仕様変更とか修正とかが原因でコードを変更するときに「あ、本来影響しなくていいはずのところに影響してる」と感じたら、この原則を思い出して、きちんとリファクタリングしなさい。
というかんじでいいんじゃないかなーと、私は思います。
(リファクタリングについては、リファクタリング―プログラムの体質改善テクニックを参照してください)

オススメ

ソフトウェア開発者の方向けには、以下の本がオススメです。

アジャイルソフトウェア開発の奥義には、オブジェクト指向の多くの原則が、まとめて具体的に解説されています。

原則だけでなく、デザインパターンやアジャイル開発のプラクティスも解説されています。
実践的な解説が欲しい方には、具体的な開発例を使って、流れに沿って説明してくれるケーススタディが非常に親切です。

リファクタリングについてはリファクタリング―プログラムの体質改善テクニックに詳しく解説されています。

EclipseなどのIDEでも、このリファクタリングで解説されている手法を支援してくれるツールがいろんな形で実装されています。
そのようなツールが、実際どのようなことを意図して実装されているかを知ることも、開発効率アップにつながるのではないでしょうか。
posted by craftsman at 12:39 | 東京 ☁ | Comment(0) | TrackBack(0) | 原則
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。