単一責任の原則(SRP)
SRP
単一責任の原則(SRP)は1つのクラスに1つの役割を持たせるというものです。オブジェクト指向三大要素の中で言うとカプセル化に当たります。
この記事では、SwiftでのSRP違反に違反しているコードをもとにSRPとは何なのかを解説していきます。
SRP違反コード
SRPに違反したコードを用意しました。
Languageクラスでは、情報の表示とローカルデータベースへの保存という2つの役割を保持しています。クラスの役割が1つではなくなってしまっているので、洗練されたカプセル化からかけ離れてしまっています。
class Language{
let name: String
let description: String
init(name: String, description: String) {
self.name = name
self.description = description
}
func informationDisplay() {
print("\(name): \(description)")
}
func saveLanguage() {
let userDefaults = UserDefaults.standard
userDefaults.set("\(name): \(description)", forKey: name)
}
}
let language = Language(name: "Swift", description: "由来となったのアマツバメは燕の巣を作るらしい、Swiftを食べよう!")
language.saveLanguage()
let userDefaults = UserDefaults.standard
print(userDefaults.string(forKey: "Swift")!)
Qiitaの記事にカプセル化に置けるわかりやすい説明があったので引用させていただきました。SRP違反のサンプルコードは十得ナイフの状態です
十得ナイフは便利ですが、コンピュータの世界において十得ナイフは必要ありません。もし現実世界においても四次元ポケットが存在したら十得ナイフはいらなくなるでしょう。栓抜きを必要とした時、四次元ポケットから何を取り出すでしょうか?わざわざ十得ナイフを取り出して十得ナイフの栓抜きを使うようなことをするでしょうか?答えはNOです。四次元ポケットからは栓抜きを取り出して使います。
https://qiita.com/tutinoco/items/6952b01e5fc38914ec4e
現状は小さなサンプルで2つしか責任を保持していないので問題がわかりにくいかもしれませんが、2つの責務が3つ4つ…と増えていった時に既存の機能に修正を加える必要が出てきたとします。
そんな時、十得ナイフ(神クラス)状態になってしまっていると修正・変更を行うことがとても困難になります。
SRPに一致させたコード
違反コードを修正しSRPに一致させたものにしました。
新規にLanguageDBというクラスを作成し、ローカルデータベースへの保存を行うという責任を分離しました。
class Language{
let name: String
let description: String
init(name: String, description: String) {
self.name = name
self.description = description
}
func informationDisplay() {
print("\(name): \(description)")
}
}
class LanguageDB {
func saveLanguage(language: Language) {
let userDefaults = UserDefaults.standard
userDefaults.set("\(language.name): \(language.description)", forKey: language.name)
}
}
let language = Language(name: "Swift", description: "由来となったのアマツバメは燕の巣を作るらしい、Swiftを食べよう!")
let db = LanguageDB()
db.saveLanguage(language: language)
let userDefaults = UserDefaults.standard
print(userDefaults.string(forKey: "Swift")!)
責務の分離は行えましたが、上記のコードでも完全に依存関係は取り除けてはいません。
LanguageDBクラスがLanguageクラスに依存しています。Languageクラスが変更された場合LanguageDBクラスにまで変更が及んでしまう可能性があります。Languageクラスだけを独立して修正することはSRPだけでは少々役不足です。依存関係逆転の原則(DIP)を守ることで独立した修正を行うことができます。
DIPに関してはまた別の記事で紹介しようと思います。