🛠️

cleanarchitecture

に公開

まず

こちらの記事は私が足りていないと思う所を重点的に勉強する。
onion7日間チャレンジのDay3になります。
詳しくはここの冒頭で書いてあるので気になる人は見てみてください。

Day3

Day3ではクリーンアーキテクチャーを解説することにしました。

クリーンアーキテクチャーとは

クリーンアーキテクチャーはソフトウェアの保守性、テスト性、拡張性を高めることを目的とした設計手法です。

クリーンアーキテクチャーのメリットデメリット

メリット

  1. 再利用性
    機能を独立したモジュールとして分けているため、それぞれを別の開発に再利用ができる
  2. 保守性の向上
    ビジネスロジック、インターフェース、データアクセスなどの責務の分離をすることで変更に強くなった
  3. テストのしやすさ
    ドメインやユースケースは外部から独立しているため単体テストができる

デメリット

  1. 初期構築コストが高い
    レイヤーやインターフェースを複数用意するため、小規模のプロジェクトでは過剰設計になる
  2. 実装の冗長化
    単純な処理でも多くのファイルや抽象化(インターフェースなど)を書くため、記述量が多くなる
  3. 学習コストが高い

他のアーキテクチャー

クリーンアーキテクチャーの他にもMVCレイヤードアーキテクチャーというものなどもあります。

  1. MVC
    単純で学習用やプロトタイプに向いています。
  2. レイヤードアーキテクチャー
    クリーンアーキテクチャーの原型に近いもので、構造が明確でチーム開発に向いています。また、単純なアプリから複雑なアプリまでに対応できます。

このように様々なアーキテクチャーがあります。保守性などを目指さない場合は他のアーキテクチャーを検討してみてもいいかもしれません。

メリットをコードを用いて解説

今まででクリーンアーキテクチャーについて紹介してきました。
しかし、保守性やテストという部分は分かりずらいと思います。そこで今回は開発で実際にコードを用いて紹介していきたいと思います。

保守性の向上

変更に対する強さを向上させるためには、レイヤー間の依存を減らす必要があります。しかし、依存をなくすことはできないのでより抽象的なものに依存させます。SOLID原則のD、依存性逆転の原則にも抽象に依存するべきとあります。これに則ってインターフェースを定義します。

依存関係

私は外部とつながるpresentation-usecase間とDB-domain,usecase間の間に抽象を差し込むことで抽象に依存するようにしています。

実際のコード

まずDB操作(repository)のインターフェースを定義します。

type UserRepository interface {
    Save(ctx context.Context, user *User)
}

次にそれをユースケースで使用します。
ユースケースでは先ほど定義したインターフェースをもつ構造体を作成して
その構造体を返す関数を作成します。
presentation層からはrepositoryの具象を入れることで使用します。

type SaveUseCase struct {
	userRepo userDomain.UserRepository
}

func NewSaveUserUseCase(
	userRepo userDomain.UserRepository,
) *SaveUseCase {
	return &SaveUseCase{
		userRepo: userRepo,
	}
}

そして、構造体のメソッドでは抽象化されたrepositoryを使用します。
実際に使用されるときは具象化されたrepositoryが与えられるため、それを使用します。

func (uc *SaveUseCase) Run(user User) {
 uc.userRepo.Save(user)
}

最後にrepositoryの実装です。

func Save(user User) {
    query := db.GetQuery()
    query.UpsertUser(user)
}

かなり簡略化しましたが、このようにして作成しています。

テストのしやすさ

ここでも先ほど紹介したようにモジュール化や依存関係がかかわってきます。

外部のモジュールを使用しないテスト

モジュール化をすることで外部モジュールやDBを使用しないレイヤーdomainがあります。ここでは書かれている関数に対してのみテストを行うだけで良いです。

外部のモジュールを使用するテスト

usecaseではdb処理の関数を実行しています。そのため、今回は具象を入れないと動かせません。しかし、単体テストをしたいのでモックというものを使用します。モックとはこういう処理を返すという機能を組み込んだダミーです。今回はrepositoryのダミーとしてモックをusecaseに注入しています。

感想

今回は以前作成したものを紹介するだけになってしまいましたが、クリーンアーキテクチャーの理解を深めることができました。

Day2↓

Day4↓

参考資料

Go ⾔語で構築するクリーンアーキテクチャ設計

GitHubで編集を提案

Discussion