はじめに
最近巷で、熱い『クリーンアーキテクチャ』を社内案件でも導入しています。
まだまだ不完全な部分も多いので、今一度整理してみました。
今回はDomain層を中心に纏めてみました。
やること
- UI層
- View
- ViewController
- Presenter
- Domain層
- Usecase ← ここ説明します
- Repository ← ここ説明します
- Entity ← ここ説明します
- Data層
- Repository ← ここ説明します
- Entity
- DataStore
やらないこと
・クリーンアーキテクチャーの概念について
・UI層について
・Data層について(Repositoryを除く)
ご説明する例
Usecaseからユーザ情報にアクセスする際の事例
レイヤ | カテゴリ | クラス名 | 説明 |
---|---|---|---|
Domain層 | Entity | User | ユーザ情報を管理するクラス(メールアドレス、誕生日) |
Repository | UserRepository | ユーザ情報とのインターフェース | |
Usecase | UserUsecase | 業務ロジッククラス | |
Data層 | Repository | UserRepositoryImpl | ユーザ情報へアクセスする実体のクラス |
1. Domain層のEntityについて
ユーザ情報として、メールアドレスと誕生日を保持するクラス
import Foundation
class User: NSObject {
var mailAddress = ""
var birthDay = ""
}
2. Domain層のRepositoryについて
ユーザ情報へアクセスする手段を纏めたインターフェース(プロトコル)
DAOに近いイメージ???
利用する側は、どこに保存されているかは意識しない。
import Foundation
protocol UserRepository: class {
func store(user: User)
func user(userID: NSInteger) -> User
func users() -> [User]
func delete(userID: NSInteger)
}
3. Data層のRepositoryについて
UserRepositoryプロトコルを実装したクラス
ユーザ情報の保存先は、仕様に合わせて、アプリ内でも、サーバーサイドでも良い。
class UserRepositoryImpl: UserRepository {
func store(user: User) {
//TODO: ユーザ情報をどこかに保存する
}
func user(userID: NSInteger) -> User {
//TODO: ユーザ情報をどこかから取得する
return User()
}
func users() -> [User] {
//TODO: ユーザ情報をどこかから取得する
return []
}
func delete(userID: NSInteger) {
//TODO: どこかに保存しているユーザ情報を削除する
}
}
4. Domain層のUsecaseについて
import Foundation
class UserUsecase: NSObject {
let repository: UserRepository
init(repository: UserRepository) {
self.repository = repository
super.init()
}
//メールアドレスを保存する
func storeMailAddressByID(userID: NSInteger, mailAddress: String) {
let user = repository.user(userID)
user.mailAddress = mailAddress
repository.store(user)
}
//メールアドレスを取得する
func findMailAddressByID(userID: NSInteger) -> String {
return repository.user(userID).mailAddress
}
//誕生日を保存する
func storeBirthDayByID(userID: NSInteger, birthDaty: String) {
let user = repository.user(userID)
user.birthDay = birthDaty
repository.store(user)
}
//誕生日を取得する
func findBirthDayByID(userID: NSInteger) -> String {
return repository.user(userID).birthDay
}
}
まとめ
ポイントは、Domain層のRepositoryだと思います。
-
データにアクセスするためには、Domain層のRepositoryを通してアクセスする。
-
データにアクセスするクライアントは、保存先がサーバー(API経由)なのかアプリ内(CoreData、UserDefaultsなど)か意識しない。
誤りやもっとこうしたほうが良いとというアドバイスがございましたら、ご指摘頂けますと幸いです。
こちらも合わせて読んで頂ければ幸いです。
[Swift版]クリーンアーキテクチャ実践編②(Data層)
謝辞
@KentaKudoさん、ご指摘ありがとうございます。
依存性の注入(Dependency Injection)の観点で、
柔軟性がない、テストしにくいため、
UserUsecaseを修正しました。