🐥

依存性逆転の原則について

2025/01/28に公開

SOLIDの5原則の1つである依存性逆転の原則(DIP)について、調べた/実装した内容を記載します。

1. 依存性逆転の原則とは

SOLIDの5原則の1つとなります。

※SOLIDの原則については以下となります。
S:単一責任の原則(Single Responsibility)
O:オープン・クローズドの原則(Open-Closed)
L:リスコフの置換原則(Liskov Substitution)
I:インターフェイス分離の原則(Interface Segregation)
D:依存性逆転の原則(Dependency Inversion)←ここ

2. 依存性とは

関数AControllerが関数Busecaseを参照することを、関数AControllerは関数Busecaseに依存すると言います。
コードで記載すると以下の様になります。

package main

import "DIP/controller"

func main() {
	controller.AController()
}

package controller

import (
	"DIP/usecase"
	"fmt"
)

func AController() {

	b := usecase.Busecase()

	fmt.Println(b)
}

package usecase

func Busecase() string {
	return "B usecase"
}

これを図で書くと、こんな感じです。
image.png

3. なぜ依存性があるの問題点について

各関数で依存性があると、以下のような問題が発生します。
・拡張性が悪くなる。
・テスト容易性が悪い。
・各関数が再利用しにくい。

4. 依存性逆転を意識した実装を行うと

依存性逆転を意識した実装を行うと、以下のようになります。
AControllerは、直接BUseCaseに依存しておらず、BUsecaseのインターフェースに依存しています。
こうなることで、AControllerとBUsecaseは、疎結合な状態となります。

image.png

5. コード

これらのコードの内容は以下の通りとなります。

package main

import (
	"GO_DIP/controller"
	"GO_DIP/infrastructure/repositories"
	"GO_DIP/usecase"
	"fmt"
)

func main() {
	// リポジトリの初期化
	repo := repositories.NewReadUsermstRepository()
	// 依存性の初期化
	usercase := usecase.NewSearchUserInteractor(repo)

	// UserControllerの生成
	userController := controller.NewUserController(usercase)
	fmt.Println(userController.GetUserList())
}

package controller

import (
	"GO_DIP/usecase"
)

type UserController struct {
	usermstUsecase usecase.ISearchUserInteractor
}

// Constructor
func NewUserController(searchusermst usecase.ISearchUserInteractor) *UserController {
	return &UserController{
		usermstUsecase: searchusermst,
	}
}

func (controller *UserController) GetUserList() string {
	return controller.usermstUsecase.SearchAllUsers()
}

package usecase

type ISearchUserInteractor interface {
	SearchAllUsers() string
}

// 構造体の定義
type SearchUserInteractor struct{}

// 新しいインスタンスを作成する関数
func NewSearchUserInteractor() ISearchUserInteractor {
	return &SearchUserInteractor{}
}

// 構造体のメソッドとしてSearchAllUsersを実装
func (s *SearchUserInteractor) SearchAllUsers() string {
	//Usermstの全検索
	return "UseCaseだよー"
}

結果

$ go run main.go
$ UseCaseだよー

6. Github

https://github.com/NoriStock1983/Go_DIP

参考

https://qiita.com/k2491p/items/686ee5dd72b4baf9a81a#テスト容易姓

https://qiita.com/baby-degu/items/d058a62f145235a0f007

https://zenn.dev/edash_tech_blog/articles/b4629f9cd73240

Discussion