序
本文主要赏析一下go-bank-transfer对于Clean Architecture的实践
项目结构
├── adapter
│ ├── api
│ │ ├── action
│ │ ├── logging
│ │ ├── middleware
│ │ └── response
│ ├── logger
│ ├── presenter
│ ├── repository
│ └── validator
├── domain
├── infrastructure
│ ├── database
│ ├── log
│ ├── router
│ └── validation
└── usecase
这里分为adapter、domain、infrastructure、usecase四层
domain
account
type AccountID string
func (a AccountID) String() string {
return string(a)
}
type (
AccountRepository interface {
Create(context.Context, Account) (Account, error)
UpdateBalance(context.Context, AccountID, Money) error
FindAll(context.Context) ([]Account, error)
FindByID(context.Context, AccountID) (Account, error)
FindBalance(context.Context, AccountID) (Account, error)
}
Account struct {
id AccountID
name string
cpf string
balance Money
createdAt time.Time
}
)
func NewAccount(ID AccountID, name, CPF string, balance Money, createdAt time.Time) Account {
return Account{
id: ID,
name: name,
cpf: CPF,
balance: balance,
createdAt: createdAt,
}
}
func (a *Account) Deposit(amount Money) {
a.balance += amount
}
func (a *Account) Withdraw(amount Money) error {
if a.balance < amount {
return ErrInsufficientBalance
}
a.balance -= amount
return nil
}
func (a Account) ID() AccountID {
return a.id
}
func (a Account) Name() string {
return a.name
}
func (a Account) CPF() string {
return a.cpf
}
func (a Account) Balance() Money {
return a.balance
}
func (a Account) CreatedAt() time.Time {
return a.createdAt
}
func NewAccountBalance(balance Money) Account {
return Account{balance: balance}
}
account定义了AccountRepository接口及Account类型,同时还提供了Withdraw、Deposit方法
transfer
type TransferID string
func (t TransferID) String() string {
return string(t)
}
type (
TransferRepository interface {
Create(context.Context, Transfer) (Transfer, error)
FindAll(context.Context) ([]Transfer, error)
WithTransaction(context.Context, func(context.Context) error) error
}
Transfer struct {
id TransferID
accountOriginID AccountID
accountDestinationID AccountID
amount Money
createdAt time.Time
}
)
func NewTransfer(
ID TransferID,
accountOriginID AccountID,
accountDestinationID AccountID,
amount Money,
createdAt time.Time,
) Transfer {
return Transfer{
id: ID,
accountOriginID: accountOriginID,
accountDestinationID: accountDestinationID,
amount: amount,
createdAt: createdAt,
}
}
func (t Transfer) ID() TransferID {
return t.id
}
func (t Transfer) AccountOriginID() AccountID {
return t.accountOriginID
}
func (t Transfer) AccountDestinationID() AccountID {
return t.accountDestinationID
}
func (t Transfer) Amount() Money {
return t.amount
}
func (t Transfer) CreatedAt() time.Time {
return t.createdAt
}
transfer定义了TransferRepository接口及Transfer类型
usecase
➜ usecase git:(master) tree
.
├── create_account.go
├── create_account_test.go
├── create_transfer.go
├── create_transfer_test.go
├── find_account_balance.go
├── find_account_balance_test.go
├── find_all_account.go
├── find_all_account_test.go
├── find_all_transfer.go
└── find_all_transfer_test.go
这一层定义了CreateAccountUseCase与CreateAccountPresenter、CreateTransferUseCase与CreateTransferPresenter、FindAccountBalanceUseCase与FindAccountBalancePresenter、FindAllAccountUseCase与FindAllAccountPresenter、FindAllTransferUseCase与FindAllTransferPresenter接口
adapter
➜ adapter git:(master) tree
.
├── api
│ ├── action
│ │ ├── create_account.go
│ │ ├── create_account_test.go
│ │ ├── create_transfer.go
│ │ ├── create_transfer_test.go
│ │ ├── find_account_balance.go
│ │ ├── find_account_balance_test.go
│ │ ├── find_all_account.go
│ │ ├── find_all_account_test.go
│ │ ├── find_all_transfer.go
│ │ ├── find_all_transfer_test.go
│ │ ├── health_check.go
│ │ └── health_check_test.go
│ ├── logging
│ │ ├── error.go
│ │ └── info.go
│ ├── middleware
│ │ └── logger.go
│ └── response
│ ├── error.go
│ └── success.go
├── logger
│ └── logger.go
├── presenter
│ ├── create_account.go
│ ├── create_account_test.go
│ ├── create_transfer.go
│ ├── create_transfer_test.go
│ ├── find_account_balance.go
│ ├── find_account_balance_test.go
│ ├── find_all_account.go
│ ├── find_all_account_test.go
│ ├── find_all_transfer.go
│ └── find_all_transfer_test.go
├── repository
│ ├── account_mongodb.go
│ ├── account_postgres.go
│ ├── nosql.go
│ ├── sql.go
│ ├── transfer_mongodb.go
│ └── transfer_postgres.go
└── validator
└── validator.go
adapter层实现了domain与usecase层定义的接口
小结
go-bank-transfer工程在domain层定义了model及repository接口,usecase层定义了usecase及presenter接口,同时调用domain层实现业务编排;adapter则实现了上面两层定义的接口。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。