単一責務の原則って一体何?
良いオブジェクト指向設計を行う上で、SOLID原則を意識することは大切な事である。ただし、この中の一つ、単一責務の原則は非常にわかりにくい。 この原則の意図とする
「クラスを変更する理由が2つ以上存在してはならない」
とは何だろうか?
視点を変えて理解しよう
ここで考え方を変える。インスタンス変数同士が密接に関係して入れば、2つ以上の切り口から変更される理由はないとと考えることができる。なんの事はない、70年代からあるモジュール凝集度の考え方である。
コードでさらに理解を深めよう
例えば以下のクラスを考える
class AB {
int instanceA1;
int instanceA2;
int instanceA3;
int instanceB1;
int instanceB2;
}
以下のようにメソッドによって参照するインスタンス変数が偏っている。
void method A1()
{
instanceA1にアクセス
instanceA2にアクセス
instanceA3にアクセス
}
method A2
{
instanceA1にアクセス
instanceA2にアクセス
instanceA3にアクセス
}
method B1
{
instanceB1にアクセス
instanceB2にアクセス
}
method B2
{
instanceB1にアクセス
instanceB2にアクセス
};
上記の場合は以下のように2つのクラスに分ける事ができる。
class AB {
int instanceA1;
int instanceA2;
int instanceA3;
}
class AB {
int instanceB1;
int instanceB2;
}
[WIP]割り切れない場合はどうするの?
例えば以下のようにA群とB群が混在している場合はどうすればいいのだろうか?
method AB1
{
instanceA1にアクセス
instanceA2にアクセス
instanceA3にアクセス
instanceB1にアクセス
instanceB2にアクセス
};
method AB2
{
instanceA1にアクセス
instanceA2にアクセス
instanceB1にアクセス
instanceB2にアクセス
instanceA3にアクセス
};
正解はないが以下のやり方がある。
- どちらかのクラスのインスタンス変数をメソッドの引数にとる。デメリットはクラス間で結合が発生する。
- いずれかのクラスでない第3クラスに処理を書く。デメリットは同じ処理があらゆるところに散らばる。
- どちらかのクラスで他方のインスタンスを所持する。デメリットは結合度が上がる。ただし、他のクラスからはその状況は見えない。
妥協しなければいけない事もある
設定変数をまとめたクラス等、実際には妥協しなければ行けない場合も存在する。