お久しぶりです。せしまるです。
今回はSOLID原則の一つ「単一責任の原則」について書いていきます。
いつも通り(?)私のための備忘録('ω')
単一責任の原則 is なに
1つのクラス・メソッド(関数)等に、変更する理由が2つ以上あってはダメ!ということ。
例えば、2つの役割を持ったクラスがあるとする。(役割A、役割B)
役割Aに何かしらの変更があった場合、クラスに変更が発生する。
役割Bに何かしらの変更があった場合も、クラスに変更が発生する。
この場合、クラスを変更する理由は
・役割Aに変更があった時
・役割Bに変更があった時
つまり変更する理由が2つになってしまう。
→🙅🙅🙅🙅🙅🙅🙅🙅
以下のような店員クラスがあるとする。
public class Clerk
{
// 店員の名前
public string Name()
{
return "せしまる";
}
// 店員がいるお店の名前
public string StoreName()
{
return "せしまるラーメン";
}
// 料理する
public string Cook()
{
return "葱ラーメンおまち!";
}
}
名前を聞いたら答えてくれる、どこのお店の人なのかも答えてくれる、そしてラーメンを作ってくれる!
これくらい規模が小さいと特に気にすることはないかもですが・・・
え?葱ラーメンじゃなくて味噌ラーメンになった?
Cook()メソッドに変更が入りますね。
え?お店の名前が変わった?
StoreName()メソッドに変更が入りますね。
この時点で変更する理由が二つですね~
なんでだめ?
もし役割が複数ある場合に変更すると…
変更点の差分とか見たときに「なんでここ変更したんだ?」ってなるし、もしかしたら「なんかほかの処理がおかしくなった!」ということになって、変更したことによる変更が起きてしまうかも…(´・ω・`)
役割を1つに…
では店員クラスを役割で分割してみましょう
// 店員クラス
public class Clerk
{
// 店員の名前
public string Name()
{
return "せしまる";
}
// 店員がいるお店の名前
public string StoreName(IStore store)
{
return store.GetName();
}
// 料理する
public string Cook(ICuisine cuisine)
{
return $"{cuisine.GetName()}おまち!";
}
}
public interface IStore
{
string GetName();
}
public interface ICuisine
{
string GetName();
}
public class SeshimaruRamen: IStore
{
public string GetName()
{
return "せしまるラーメン";
}
}
public class SeshikoRamen: IStore
{
public string GetName()
{
return "せし子ラーメン";
}
}
public class GreenOnionRamen: ICuisine
{
public string GetName()
{
return "葱ラーメン";
}
}
public class MisoRamen: ICuisine
{
public string GetName()
{
return "味噌ラーメン";
}
}
この状態なら、お店の名前が変わってもお店を増やせば店員クラスには変更が入りませんね。
以上!
余談
題材にした店員とかが悪すぎた