Goで学ぶSOLID原則:開発工程から理解する単一責任の原則
ソフトウェア設計を学ぶ上で必ず登場するのが SOLID原則。
その中でも特に誤解されやすいのが 単一責任の原則(SRP: Single Responsibility Principle) です。
本記事では、Go言語での具体例を交えながら、開発工程の観点でSRPを解説します。
単一責任の原則とは?
多くの人は「モジュールは1つのことだけをするべき」と解釈しがちです。
しかし、SRPの本質はそこではありません。
SRPの正しい定義は、
モジュールはただ1人のアクターに対して責任を持つべきである
です。
ここでいう アクター(Actor) とは、システムに変更を要求する人や組織のこと。
要するに「誰の都合でそのコードが変更されるのか?」を基準に責務を分けるのがSRPです。
アクターの例え:エンジニア・デザイナー・PM
現場をイメージするために、役者(アクター)を「エンジニア・デザイナー・PM」に置き換えて考えてみます。
SRP違反の例
type Member struct{}
func (m Member) Code() {
fmt.Println("エンジニア: コードを書く")
}
func (m Member) Design() {
fmt.Println("デザイナー: デザインを作る")
}
func (m Member) ManageProject() {
fmt.Println("PM: プロジェクトを管理する")
}
このMemberは「エンジニア・デザイナー・PM」の3つのアクターの責任を同時に持ってしまっています。
その結果、デザイン仕様の変更がコードやプロジェクト管理にまで影響する危険があります。
SRPを守った例
type Engineer struct{}
func (e Engineer) Code() {
fmt.Println("エンジニア: コードを書く")
}
type Designer struct{}
func (d Designer) Design() {
fmt.Println("デザイナー: デザインを作る")
}
type ProjectManager struct{}
func (pm ProjectManager) ManageProject() {
fmt.Println("PM: プロジェクトを管理する")
}
それぞれのアクターが責任を1つだけ持っているため、
「エンジニアの変更がデザイナーに影響する」といった偶発的な問題を防げます。
Facadeパターンでまとめる
アクターを分離した後でも、外部からは「バラバラに呼び出すのが面倒」という問題があります。
そこで役立つのが Facadeパターン です。
Facadeは「チームの窓口」として振る舞い、オーケストレーション的に複数の役者をまとめます。
type Team struct {
Engineer Engineer
Designer Designer
ProjectManager ProjectManager
}
func (t Team) DeliverProduct() {
fmt.Println("=== チームが製品を納品します ===")
t.ProjectManager.ManageProject()
t.Engineer.Code()
t.Designer.Design()
fmt.Println("=== 納品完了 ===")
}
利用者は Team.DeliverProduct() を呼ぶだけで、内部の役者の動きを意識せずに成果を得られます。
SRPで役者ごとに分ける → Facadeでまとめる
これが「責務の分離」と「使いやすさ」の両立です。
開発工程での学び
実際の開発でも同じです。
エンジニアは開発、デザイナーはUI/UX、PMは進行管理。
これらを一人の人間が全部やると破綻します。
しかし「チーム」というFacadeを作れば、依頼者は「チームに頼めばいい」というシンプルな窓口を得られます。
つまり、単一責任の原則は「役者を正しく分け、混ぜない」こと。
そして Facadeパターンは、それを現実の業務フローに耐えうる形でまとめる手法です。
まとめ
- 単一責任の原則とは「モジュールは1人のアクターに責任を持つべき」
- エンジニア・デザイナー・PMを例にすると直感的に理解できる
- Goのコードで実装すると、役者を分けた後に Facade がオーケストレーションを担う
- 現実の開発工程でも、役割を分けた上で「チーム」という窓口を作ると混乱を避けられる
Discussion