🤖

インターフェース分離の原則

2025/02/03に公開

インターフェース分離の原則について

SOLIDの5原則の1つであるインターフェース分離の原則について、調べた/実装した内容を記載します。

1. インターフェース分離の原則とは

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

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

2. インターフェース分離とは

インターフェースは呼び出された先の関数で、利用しない関数が無いように設計するということです。
もし利用しているインターフェースに、その関数では利用しない関数が設定されていたら、バグを作りこむ可能性が出てきます。

3. インターフェースを分離する意味

インターフェースを分離するためのメリットは以下となります。

1) 柔軟性の向上

利用したい関数のみ実装出来るようになり、余計な関数が入り込みません。
 また、拡張したい時は、対象のインターフェースに定義するだけで、利用可能になります。
そのため、利用可能な関数を制御、拡張することが可能になるため、柔軟性が向上します。

2) 保守性の向上

インターフェースがシンプルになり、余計な関数が定義されていません。
 そのため、各インターフェースの責任が明確になり、将来的な拡張や変更が容易にとなります。

3) 再利用性の向上

各関数は、必要な機能のみ実装すればよく、他の機能に影響されることがないため、他の機能でも再利用することが可能となります。

4. 実装

実際にインターフェース分離の原則を元に実装した内容は以下の通りとなります。

package main

import (
	controller "InterfaceSegregation/controller/usermst"
	"InterfaceSegregation/infrastructure/repositories"
	usecase "InterfaceSegregation/usecase/usermst"
	"fmt"
)

func main() {

	// DI(Repositoryコンストラクタの生成)
	repo := repositories.NewSearchUsermstRepository()

	// DI(Usecaseコンストラクタの生成⇨Repositoryを引数に渡す)
	usermstusecase := usecase.NewSearchUsermstUsecase(repo)

	// DI(Controllerコンストラクタの生成⇨Usecaseを引数に渡す)
	c := controller.NewUsermstController(usermstusecase)

	fmt.Println(c.SarchAllUsermst())
	fmt.Println(c.SearchByUsercd())
}

package usermst

import "InterfaceSegregation/usecase/usermst"

type SearchUsermstController struct {
	SearchUsermst usermst.ISearchUsermstInteractor
}

// SearchUsermstControllerのコンストラクタ
func NewUsermstController(s usermst.ISearchUsermstInteractor) SearchUsermstController {
	return SearchUsermstController{
		SearchUsermst: s,
	}
}

// usermstの全件検索処理
func (s *SearchUsermstController) SarchAllUsermst() string {

	return s.SearchUsermst.SarchAllUsermst()
}

// usermstのユーザーコード検索処理
func (s *SearchUsermstController) SearchByUsercd() string {
	return s.SearchUsermst.SearchUsercd("usercd")
}

package usermst

import "InterfaceSegregation/domain/repositories"

type ISearchUsermstInteractor interface {
	SarchAllUsermst() string
	SearchUsercd(usercd string) string
}

type SearchUsermstInteractor struct {
	repositories.ISearchUsermstRepository
}

// SearchUsermstInteractorのコンストラクタ
func NewSearchUsermstUsecase(searchusermst repositories.ISearchUsermstRepository) ISearchUsermstInteractor {
	return &SearchUsermstInteractor{
		searchusermst,
	}
}

// usermstの全件検索処理(ビジネスロジック)
func (s *SearchUsermstInteractor) SarchAllUsermst() string {
	return s.AllSearchUsermst()
}

// usermstのユーザーコード検索処理(ビジネスロジック)
func (s *SearchUsermstInteractor) SearchUsercd(usercd string) string {
	return s.SearchByUsercd(usercd)
}

package repositories

// 検索用のインターフェース
// 検索処理を行う場合にのみ必要な関数を定義する。
// 検索処理を行うためだけのインターフェースのため、登録、更新、削除処理は含まない。
type ISearchUsermstRepository interface {
	AllSearchUsermst() string
	CountByUsercd(usercd string) int
	SearchByUsercd(usercd string) string
}

// Insert用のインターフェース
// Insert処理を行う場合にのみ必要な関数を定義する。
// Insertを行う前に、対象データが存在するかどうか確認するためにCountByUsercd関数を定義する。
type IInsertUsermstRepository interface {
	CountByUsercd(usercd string) int
	InsertUsermst() bool
}

// Update用のインターフェース
// Update処理を行う場合にのみ必要な関数を定義する。
// Updateを行う前に、対象データが存在するかどうか確認するためにCountByUsercd関数を定義する。
// Update処理を実行する前に、対象データが他のユーザに更新されていないかなどを確認するために、SearchByUsercd関数を定義する。
type IUpdateUsermstRepository interface {
	CountByUsercd(usercd string) int
	SearchByUsercd() string
	UpdateUsermst() bool
}

// Delete用のインターフェース
// Delete処理を行う場合にのみ必要な関数を定義する。
// Deleteを行う前に、対象データが存在するかどうか確認するためにCountByUsercd関数を定義する。
// Delete処理を実行する前に、対象データが他のユーザに更新されていないかなどを確認するために、SearchByUsercd関数を定義する。
type IDeleteUsermstRepository interface {
	CountByUsercd(usercd string) int
	SearchByUsercd() string
	DeleteUsermst() bool
}
package repositories

import "InterfaceSegregation/domain/repositories"

type UsermstRepository struct{}

// SearchUsermstRepositoryのコンストラクタ
func NewSearchUsermstRepository() repositories.ISearchUsermstRepository {
	return &UsermstRepository{}
}

// usermstの全件検索処理
func (searchall *UsermstRepository) AllSearchUsermst() string {
	return "AllSearchUsermst"
}

// usermstのユーザーコード検索処理
func (searchbyusercd *UsermstRepository) SearchByUsercd(userced string) string {
	return userced
}

// usermstのユーザーコード件数取得処理
func (countbyusercd *UsermstRepository) CountByUsercd(usercd string) int {
	return 1
}

// usermstのユーザーコード登録処理
func (insertusermst *UsermstRepository) InsertUsermst() bool {
	return true
}

// usermstのユーザーコード更新処理
func (updateusermst *UsermstRepository) UpdateUsermst() bool {
	return true
}

// usermstのユーザーコード削除処理
func (deleteusermst *UsermstRepository) DeleteUsermst() bool {
	return true
}

実行結果

$ go run main.go
$ AllSearchUsermst
$ usercd

以上が、SOLID原則のインターフェース分離の原則についての説明となります。

5. Github

本説明で利用したコードを以下のGithubにあげておきます。

https://github.com/NoriStock1983/Go_InterfaceSegregation

6. 参考にしたサイト

https://baapuro.com/chapter/seventeen/

Discussion