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

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

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

### 1. インターフェース分離の原則とは
SOLIDの５原則の１つとなります。

※SOLIDの原則については以下となります。
[S：単一責任の原則(Single Responsibility)](https://qiita.com/Nori1983/items/221e32f40f3b512d7b60)
O：オープン・クローズドの原則(Open-Closed)
L：リスコフの置換原則(Liskov Substitution)
I：インターフェイス分離の原則(Interface Segregation)<font color="Red"> ←ここ</font>
[D：依存性逆転の原則(Dependency Inversion)](https://qiita.com/Nori1983/items/601f99ad5b2fbd8443af)

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


### 3. インターフェースを分離する意味
インターフェースを分離するためのメリットは以下となります。
##### 1) 柔軟性の向上
　利用したい関数のみ実装出来るようになり、余計な関数が入り込みません。
　また、拡張したい時は、対象のインターフェースに定義するだけで、利用可能になります。
  そのため、利用可能な関数を制御、拡張することが可能になるため、柔軟性が向上します。
 
##### 2) 保守性の向上
　インターフェースがシンプルになり、余計な関数が定義されていません。
　そのため、各インターフェースの責任が明確になり、将来的な拡張や変更が容易にとなります。

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

 
### 4. 実装
実際にインターフェース分離の原則を元に実装した内容は以下の通りとなります。
``` main.go
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())
}

```

```SearchUsermstController.go
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")
}

```

```SearchUsermstUsecase.go
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)
}

```

```IUsermstRepository.go
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
}
```

```SearchUsermstRepository.go
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/