在谈论完书中提的组织 domain 的三种模式 :
接下来我们要来提书中将他放在 domain 章节的『 Service 』。
先提一下,我前面有几个范例里有写到 service,但严格来说这不是书中所提 service 层意思,之前范例是指商业逻辑用的地方,我范例都写 service,应该不少人的定义也是相同,但书中不同。
从书中抓出的一张图应该就可以知道, service 在书中实际上的位置如下,从下图可以简单的定义 :
Service Layer 会在 domain model 的前,但他还是属於 domain 层,它负责处理业务的工作流处理。
我当初在读 domain model 那章节我事实上一直有地方卡到,那就是 domain model 可以当做以每个业务为单位,然後内包属性与行为,那假设有个业务为『 这个月当用户注册後,要送 Coupon 卷 』,这个业务要如何处理呢 ?
以 domain model 应该是会分 :
但问题是,同时呼叫这两个方法的地方是那 ? 对 ~ 这个地方就是 『 Service Layer 』。
图片来源: 《 企业应用架构模式 》
书中事实上还有提到几个 Service Layer 的使用重点 :
我事实上在思考 ~ 有时後我们 Web 开发时,有分所谓的 controller、service 会不会严格来说,以书中定义 controller ⇒ service 而 service ⇒ domain model 呢 ? 因为我相信不少人 controller 里面,是写这个 api 要处理的事情 ~ 对吧 ?
不过我这里不太建议,以我自已的标准这三个实际上该做的事情为 :
这里给个简单的范例,业务需求为 :
当用户注册时,会给一张 Coupon ( 折扣卷 ),且寄出欢迎信
简单来说该业务可以分为三个部份 :
其中有几点要注意 :
class ApplicationService {
getEmailGateWay(): IEmailGateway{
return new EmailGatewayService()
}
}
interface IEmailGateway{
sendEmailMessage(toEmail: string, subject: string, body: any): void
}
class EmailGatewayService implements IEmailGateway{
sendEmailMessage(toEmail: string, subject: string, body: any): void{
console.log('取得该 application 的寄信服务的 config,然後在寄信')
}
}
class UserService extends ApplicationService{
register(username: string, email: string): void{
const userDomainModel = new UserDomainModel({})
const couponDomainModel = new CouponDomainModel({})
// 建立使用者
const user = new User(username, email)
userDomainModel.create(user)
// 建立第一次注册 Coupon
const firstCoupon = new Coupon('First Coupon', 100)
couponDomainModel.setCoupon(firstCoupon)
couponDomainModel.sendToUser(user.id)
// 寄欢迎信
this.getEmailGateWay().sendEmailMessage('[email protected]', 'First Register', {})
}
}
class User{
username: string
email: string
constructor(username: string, email: string){
this.username = username
this.email= email
}
}
class Coupon{
title: string
discount: number
constructor(title: string, discount: number){
this.title = title
this.discount = discount
}
}
class UserDomainModel{
userDao: any
constructor(userDao: any){
this.userDao = userDao
}
create(user: User){
this.userDao.create(user)
}
}
class CouponDomainModel{
couponDao: any
coupon: Coupon
constructor(couponDao: any){
this.couponDao = couponDao
}
setCoupon(coupon){
this.coupon = coupon
}
sendToUser(userId){
console.log('Save to user coupon table')
this.couponDao.save(this.coupon, userId)
}
}
有时後在写业务需求时,我发现真的很难每一个 domain 都定义清楚,像我刚刚提到的范例 :
当用户注册时,会给一张 Coupon ( 折扣卷 ),且寄出欢迎信
如果我们将『 用户注册时,会给一张 Coupon 』,写在 User Domain Model 中,但如果其它 application 不需要给一张 coupon 时,要怎麽办呢 ? 这时有了 service 专门处理工作流的地方真的方便不少。
事实上我写到现在,单纯的使用 domain model 来写,我还真想不到如果写,但多了一个 service layer 就真的方便多了…
然後在看《 搞笑谈软工-PoEEA之Server Layer 这篇文章 』》有提到一句话 :
传统阶层式架构所说的 Service Layer,就是Clean Architecture里面的 Use Case Layer。Teddy现在觉得Use Case Layer比较具体,因为Service这个字有很多种含意,因此用Service Layer来代表应用程序所提供功能或服务的边界,好像有点那麽不是很直觉
这句话我觉得有理,给其它人参考看看。
>>: 29.移转 Aras PLM大小事-额外编码取号(3)
今日目标 继续完成批次渲染 结果... 今天抓到一堆bug,但是还是没debug完,被我弄丢的小方块...
在进入机器学习之前,想先大家深入了解一些 python 的进阶操作。接下来的操作会有点抽象,请好好品...
在上一篇,我们学会如何用HTML写出'Hello World!',而这一篇,我将会教大家怎麽帮HTM...
立案後的费用产生 很多人会产生一个疑问,立案後如果没有营业跟有营业的费用产生的差别。 这里必须要先说...
如同前面介绍的,Flutter 定义了三种不同型别的Platform Channel 在platfo...