【问题标题】:Logger in Clean Architecture清洁架构中的记录器
【发布时间】:2019-04-24 11:41:32
【问题描述】:
我正在尝试在我的 PHP 应用程序中应用 Clean Architecture。目前我有我的业务逻辑实体User 和服务UsersService。 UsersService 收集与用户实体相关的所有用例。
UsersService->createUser(someData) 获取用户存储库并将其存储在数据库中。
我在控制器和 Cli 任务中调用 createUser 用例。我想在我的项目中集成日志系统。我想在用例和控制器/任务中记录一些东西。
我需要将Loggers factory/Logger 接口放在哪里?
【问题讨论】:
标签:
php
design-patterns
architecture
【解决方案1】:
这里的前提是,您的内部层对外部层一无所知,因此您在域中使用的任何接口都应该位于域中,这使您能够更改以后的登录方式,而无需进行任何更改你的业务逻辑,所以只需在你的域中创建一个 Log 接口,从外部实现它,瞧。
在您的域中,它可能如下所示:
interface ILogger {
log(level: string, message: string): void
}
class MyUseCase {
public constructor(private readonly logger: ILogger){}
public execute(input: Input): void {
// some stuff
this.ILogger.log('level', 'message')
// some other stuff
}
}
在您的框架和驱动程序层中,您可以:
class MyLogger implements ILogger {
log(level: string, message: string): void {
myChosenLoggerTech.log(level, message) // ie winston, console.log, etc
}
}
所以现在当MyUseCase被实例化时可以使用:
new MyUseCase(new MyLogger())
但是等等,没有那么简单,一般来说有两种日志用例:
- 您要记录业务信息
- 您想要记录应用状态信息
好的,如果您的案例是 2 号,请使用此解决方案,但如果您的案例是 1 号,也许您应该通过将其包装到专用实体、异常或真正代表您的业务的任何内容中来使记录操作更加明确.
更详细的解释可以查看here。
【解决方案2】:
在 Clean Architecture 中,不允许内层依赖外层。
例如域层不能依赖于基础设施层。因此,您可以在域层中放置一个接口 ILogger。
但是,如果将 ILogger 放置在 Domain 项目中,则表明日志记录与业务域相关。
对我来说,Logger 本质上是通用实用程序,因此我会将 ILogger 接口放在一个“通用”项目中,该项目在整个解决方案中无处不在。在基础设施层实现 ILogger。