在分层理念中,一种通用的分层思想,是将应原创内容,盗版必究。【本文受版权保护】用分为“数据层”“逻辑层”“表现层”,在转载请注明出处:www.tangshuang.net【版权所有,侵权必究】每层内,我们又可以细分。你可能会想,“分【本文首发于唐霜的博客】【转载请注明来源】层?有必要吗?”就像我们接触毒药一样,离【本文首发于唐霜的博客】【作者:唐霜】开了剂量谈毒是没有意义的,同样的道理,离【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】开了具体的业务复杂度谈分层,也是没有意义未经授权,禁止复制转载。【版权所有,侵权必究】的。在极为简单的应用中,我们当然要追求快本文作者:唐霜,转载请注明出处。【作者:唐霜】速高效立马上线,但在一些企业应用中,却需未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】要我们慢条斯理,在长达数年的岁月里慢慢推【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】进一套系统的演进。我们谈分层,大多是在这【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】类有比较复杂的业务逻辑的系统中去谈,这类【转载请注明来源】本文作者:唐霜,转载请注明出处。系统可能在具体界面的呈现上实现起来并不复未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】杂,甚至没有什么交互上的难度。但是,这类【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net系统中的前端开发者们,常常还是很抓狂,因【本文受版权保护】【版权所有,侵权必究】为一个逻辑可能被折腾死,最后一定会思考,我们如何才能合理的区分哪些代码是业务的,转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】哪些代码是交互的,应该如何组织代码才能高转载请注明出处:www.tangshuang.net【作者:唐霜】效的解决自己遇到的烦恼?
【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】【访问 www.tangshuang.net 获取更多精彩内容】【原创内容,转载请注明出处】本文将阐述我在工作中的思考与解决的方案。【版权所有,侵权必究】未经授权,禁止复制转载。相信它可以帮助那些与我曾经一样遇到此类烦【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。恼的小伙伴。
原创内容,盗版必究。转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】【原创不易,请尊重版权】烦恼从而而来?【版权所有】唐霜 www.tangshuang.net
原创内容,盗版必究。本文作者:唐霜,转载请注明出处。原创内容,盗版必究。本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】我们前端在开发一个业务的时候,总是先从界【本文首发于唐霜的博客】著作权归作者所有,禁止商业用途转载。面出发,看着界面想我这里要怎么做怎么做,著作权归作者所有,禁止商业用途转载。【本文受版权保护】等把界面交互大致写出来之后,再把产品文档原创内容,盗版必究。【未经授权禁止转载】里面的业务逻辑作为一些判断条件加入到写好【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。的交互代码中,最终交付。我能这么讲出来,原创内容,盗版必究。原创内容,盗版必究。说明这里面有很大的问题。问题在哪里呢?我【作者:唐霜】转载请注明出处:www.tangshuang.net们用一段假代码来看看:
【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】原创内容,盗版必究。【关注微信公众号:wwwtangshuangnet】export default {
template: `
<form @submit="handleSubmit">
<input type="number" v-model="price" placeholder="单价" />
<input type="number" v-model="count" placeholder="数量" />
<input type="number" :value="total" disabled />
<span v-if="save">折扣10%</span>
<span>
<input type="text" v-model="code" @change="handleChangeCode" placeholder="优惠码" />
<button type="button">查询</button>
<span v-if="codeChecked">优惠码有效</span>
</span>
<button>提交</button>
</form>
`,
data() {
return {
price: 0,
count: 0,
code: '',
codeChecked: false,
}
},
computed: {
total() {
return this.price * this.count * (1 - this.save) * (this.codeChecked ? 0.9 : 1)
},
save() {
return this.price * this.count > 100 ? 10 : 0
},
},
methods: {
handleCheckCode() {
ajax.post('...', this.code).then(res => {
this.codeChecked = !!res
})
},
handleChangeCode() {
this.codeChecked = false
},
handleSubmit(e) {
e.preventDefault()
// ....
// 一大堆校验逻辑
const { price, count, code, codeChecked } = this
const data = { price, count }
if (codeChecked) {
data.code = code
}
// 提交数据
// 。。。
},
},
}
你看,也就简简单单几个字段,就让代码开始【转载请注明来源】【本文首发于唐霜的博客】有点点混乱了,要搞清楚每一个字段与其他字【原创内容,转载请注明出处】【本文受版权保护】段之间的关联,你需要通读整个组件的代码,【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net而随着业务的越来越积累,这个看似简单的组【作者:唐霜】本文版权归作者所有,未经授权不得转载。件,会慢慢撑开,字段从这几个慢慢撑到10转载请注明出处:www.tangshuang.net【未经授权禁止转载】多个,甚至20、30多个,字段与字段之间未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net的关联性,以及每一个字段和它的提示语在什【转载请注明来源】本文版权归作者所有,未经授权不得转载。么情况下才展示出来,等等,越来越复杂。当转载请注明出处:www.tangshuang.net【版权所有,侵权必究】这个业务持续增长超过1年后,你发现这个组【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net件已经满目全非,根本不敢改一行代码,因为【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。你怕一改就影响整个业务。
未经授权,禁止复制转载。【转载请注明来源】【本文受版权保护】本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net为什么呢?是什么东西,冥冥中让我们的代码【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】走向不可维护呢?
著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。我认为,一个重要原因在于:【作者:唐霜】我们的代码同时承载了业务的逻辑和界面的交原创内容,盗版必究。【本文首发于唐霜的博客】互逻辑。比如上面的codeChecked对于整个著作权归作者所有,禁止商业用途转载。【本文受版权保护】业务而言,是非必需的,但是对于交互而言是著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】必须的,你必须用一个状态去控制提示语是不【作者:唐霜】【本文受版权保护】是要展示出来。因此,上面这段代码中,用于本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】完成业务目标的price, count,【作者:唐霜】著作权归作者所有,禁止商业用途转载。 code,和用于完成交互任务的code本文版权归作者所有,未经授权不得转载。【本文首发于唐霜的博客】Checked被放在一起管理。而且更糟糕转载请注明出处:www.tangshuang.net【转载请注明来源】的是,其中在handleSubmit中,原创内容,盗版必究。转载请注明出处:www.tangshuang.net用于交互的codeChecked却成为了【原创不易,请尊重版权】【版权所有】唐霜 www.tangshuang.net控制code字段是否提交的开关,这直接让【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net业务逻辑和交互逻辑耦合在一起,在未来的开原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。发中,你不可能把这两部分解耦开,因为这个著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】逻辑写死了。
本文版权归作者所有,未经授权不得转载。【本文受版权保护】【作者:唐霜】【关注微信公众号:wwwtangshuangnet】正因为这种线性的开发思维,让我们写的组件【转载请注明来源】未经授权,禁止复制转载。随着业务的扩展,越来越难以高效的维护,直转载请注明出处:www.tangshuang.net【本文受版权保护】到最后不敢修改一行。我称这种情况为“缠线原创内容,盗版必究。【转载请注明来源】定律”,即一根线在比较短的时候不会打结,未经授权,禁止复制转载。【转载请注明来源】到一定长度后容易打结,当很长的时候一定会未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。打结,所以无论你的耳机线材质多有韧性,只著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net要直接塞在裤兜里,一定会打结。那么怎么避著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】免呢?就像避免耳机线打结一样,我们需要用著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。一个耳机线盒把规整的线圈管理起来,有了盒【关注微信公众号:wwwtangshuangnet】【转载请注明来源】子的约束和隔离,耳机线打结的几率微乎其微【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。。同样的道理,我们需要对我们的代码重新进【未经授权禁止转载】本文作者:唐霜,转载请注明出处。行管理,让原本线性的逻辑表达,按照一定的本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。结构重新梳理,并把这些结构用合理的文件结未经授权,禁止复制转载。【转载请注明来源】构进行框定,从而做到不打结。
【未经授权禁止转载】转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net领域模型未经授权,禁止复制转载。
【作者:唐霜】本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。【转载请注明来源】解决代码逻辑打结的第一个杀手锏是领域建模本文作者:唐霜,转载请注明出处。【关注微信公众号:wwwtangshuangnet】。领域建模是指,我们先抛开软件的界面、实著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】现逻辑、运行环境等应用层面的东西,转换自未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。己的角色,把自己当作一个业务人员,问自己【版权所有】唐霜 www.tangshuang.net未经授权,禁止复制转载。我用这套系统要完成什么业务目的,梳理出业【版权所有,侵权必究】【原创内容,转载请注明出处】务流程,指明不同角色在业务流程中的责任,【本文首发于唐霜的博客】【本文受版权保护】画出业务的示意图,并最终用代码把它表达出【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。来。
著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】【本文受版权保护】转载请注明出处:www.tangshuang.net我们以往的做法是直接写代码,然后去和需求【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net方沟通,边沟通边改。但是我们经常遇到这样著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】的情况,在一个天朗气清的工作日,我们开心转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】的去和业务方沟通下一步业务,结果业务方突【版权所有,侵权必究】著作权归作者所有,禁止商业用途转载。然冒出一句听上去自然而然的但却和你之前写【作者:唐霜】本文版权归作者所有,未经授权不得转载。的代码不一致的地方,这个时候,你一定会大【本文受版权保护】【版权所有】唐霜 www.tangshuang.net喊一声“稍等一下,刚才那个地方……”然后著作权归作者所有,禁止商业用途转载。【作者:唐霜】是两个小时的重新确认和5个小时的重新编码【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net!这样的场景在我有限的工作经历中,也经历【原创内容,转载请注明出处】原创内容,盗版必究。了不少次。
【作者:唐霜】【作者:唐霜】本文版权归作者所有,未经授权不得转载。【本文受版权保护】解决这一问题的有效办法,是DDD提供的沟原创内容,盗版必究。本文作者:唐霜,转载请注明出处。通方法论,在开始编码之前,建立领域模型。本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net实际上,领域模型包含两个部分,一部分叫统【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net一语言,说的直白些,就是图纸,在你的业务本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net部门里任何人都能看的懂,另一部分是与图纸【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。等效的建模代码,在未来的日子里,任何的沟【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。通,大家只会基于图纸来明确某个细节,而不【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。会关心你写的代码,如果你的实现与图纸不一【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net致,那明显是你的问题,而不是图纸。
【转载请注明来源】【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。原创内容,盗版必究。原创内容,盗版必究。好了,接下来我们来聊一聊怎么做出个图纸等本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】价的建模代码。
著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】我们要清楚在这个过程中,其实主要包含3类转载请注明出处:www.tangshuang.net【版权所有,侵权必究】对象,一类是描述业务的实体对象,是业务所著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。围绕的核心概念,你的公司所做的业务,本质本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】上就是在创建和处理这些对象。一类是描述工转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】作流程的服务对象,它们主要是对实体对象的未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。处理过程、逻辑、事件,是使得业务产生实际著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。效果的非实体对象。最后一类是用于辅助完成著作权归作者所有,禁止商业用途转载。【本文受版权保护】编程任务的程序对象,用以解决在特定编程语著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。言下面,怎么让你的业务的部分能够反馈到计未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net算机系统中,用计算机系统的方式运行起来。【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。我们进行领域建模,主要针对第一类和第二类【原创内容,转载请注明出处】【原创内容,转载请注明出处】。
转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。原创内容,盗版必究。转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】面向对象是DDD的核心方法,我们在具体编【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。程时,通过创建和关联各种class完成模【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。型。贫血和充血之争一直是一个问题,我认为【关注微信公众号:wwwtangshuangnet】【版权所有】唐霜 www.tangshuang.net在前端语境下,模型一定是充血的,因为前端【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】建模要为交互留足空间。
未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。原创内容,盗版必究。以前文的例子为例,我们可以建立这样的模型
原创内容,盗版必究。本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.netclas Order {
price = 0
count = 0
code = ''
total = 0
}
这种就是所谓的贫血模型,它只能告诉你有什本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。么,但是具体的业务你需要另外封装出来,这未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net显然不可能在前端领域成为合理的建模方式。【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】怎么做呢?我们要对每一个字段进行业务说明【本文首发于唐霜的博客】【本文受版权保护】,可以这样:
【本文首发于唐霜的博客】【转载请注明来源】本文作者:唐霜,转载请注明出处。import { Model, meta, state, Int, Validator } from 'tyshemo'
class Order extends Model {
@meta({
type: Number,
label: '单价',
required: true,
validators: [
Validator.required('单价必填'),
],
})
price = 0
@meta({
type: Int,
label: '数量',
required: true,
validators: [
Validator.required('数量必填'),
],
})
count = 0
@meta({
type: String,
label: '优惠码',
checked: false,
checking: false
watch() {
const view = this.use('code')
view.checked = false
view.checking = true
ajax.post('...', this.code).then(res => {
view.checked = !!res
}).finally(() => {
view.checking = false
})
},
drop() {
return this.use('code').checked
},
validators: [
determine(code) {
return !!code && !this.use('code').checking = false
},
validate() {
return this.use('code').checked
},
message: '优惠码无效',
],
})
code = ''
@meta({
type: Number,
label: '总额',
compute() {
const { save } = this.use('total')
const { checked } = this.use('code')
return this.price * this.count * (1 - save) * (checked ? 0.9 : 1)
},
save() {
return this.price * this.count > 100 ? 10 : 0
},
saveMessage() {
return this.save ? '折扣10%' : ''
},
disabled: true,
drop: true, // 由后台计算,这个字段仅前端展示,不提交
})
total = 0
}
我们写完上面这个模型,它是充血的,它完整【关注微信公众号:wwwtangshuangnet】未经授权,禁止复制转载。的描述了对应业务实体的所有字段,以及每个著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】字的的具体业务阐释。而且更重要的是,基于本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】这一模型设计,我们可以从meta信息中,【原创内容,转载请注明出处】原创内容,盗版必究。阅读每一个字段关于自己的全部逻辑。这种设【转载请注明来源】【本文受版权保护】计的思路很清晰,就是字段本身的逻辑应该放【版权所有】唐霜 www.tangshuang.net【转载请注明来源】在字段的旁边,集合在一起,阅读关于字段本原创内容,盗版必究。未经授权,禁止复制转载。身的业务逻辑,只需要关注这一处代码,而不未经授权,禁止复制转载。【作者:唐霜】需要跨多个上下文去理解。要了解一个字段的转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net全部逻辑,基本上可以在对应的meta中获【转载请注明来源】本文版权归作者所有,未经授权不得转载。得全部信息(必要的时候,需要阅读整个模型【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。的相关方法,找出多个字段有关联逻辑的业务【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net)。阅读这段代码,你不仅能理解代码本身原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net的意思,而且还能掌握业务的知识。
【本文受版权保护】著作权归作者所有,禁止商业用途转载。【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net你可能会想,我这些字段要怎么用。但是不要本文版权归作者所有,未经授权不得转载。【转载请注明来源】着急,到目前为止,我们只关心业务,不关心本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。界面和交互。
【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】领域服务本文版权归作者所有,未经授权不得转载。
原创内容,盗版必究。本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】转载请注明出处:www.tangshuang.net【作者:唐霜】领域模型帮我们描绘了有关这个业务的核心对原创内容,盗版必究。本文作者:唐霜,转载请注明出处。象的各种逻辑,但是,我们的这个业务实体会【本文首发于唐霜的博客】【本文受版权保护】面对很多场景,每一个场景下,可能存在有些本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。特定的转化逻辑,这就需要我们在领域模型的转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】基础上,提供对应场景的服务。简单讲,你可【本文受版权保护】转载请注明出处:www.tangshuang.net以把领域服务想象成领域模型实例的处理工厂【作者:唐霜】【转载请注明来源】,在这些处理中,我们是为了描述特定场景下原创内容,盗版必究。【作者:唐霜】的业务需求,所以,领域服务仍然是业务描述原创内容,盗版必究。【原创内容,转载请注明出处】,和UI无关。
【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】【作者:唐霜】【版权所有】唐霜 www.tangshuang.net一般而言,我们在不需要的时候,就不需要领未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。域服务。
本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。怎么讲?在领域模型的分类中,除了实体、【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。值,还有一类叫“聚合”的模型,大部分情况【作者:唐霜】【本文首发于唐霜的博客】下,在聚合中我们就可以调动子模型完成各种未经授权,禁止复制转载。【本文受版权保护】处理,因此,如果通过聚合就可以完成不同场【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。景的业务处理需求,我们就不需要领域服务。【本文受版权保护】【版权所有】唐霜 www.tangshuang.net但是,假如实在没有办法,我们就应该考虑用原创内容,盗版必究。【本文受版权保护】领域服务完成业务描述。
本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。以上面的例子为例,同样是订单,我们可能面【版权所有,侵权必究】【作者:唐霜】临创建和编辑两种业务场景。编辑的时候,和本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】新建稍有不同,需要从服务端接口拉取数据,本文作者:唐霜,转载请注明出处。原创内容,盗版必究。并填充,而创建时则不需要。这也就意味着,【转载请注明来源】本文版权归作者所有,未经授权不得转载。相同的领域模型,具有多态性。如何解决呢,本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。我们可在领域模型之上,提供领域服务,用以本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】在不同场景下进行调用。此处的处理方式有两本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。种,一种是直接对类进行扩展,编辑的时候,【未经授权禁止转载】【未经授权禁止转载】使用扩展的类,比如:
【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。class OrderService {
static toEdit(Order) {
return class OrderEdit extends Order {
constructor() {
super()
ajax.get('...').then(data = this.fromJSON(data))
}
}
}
}
// 使用
OrderService.toEdit(Order)
另一种方式是直接在服务内对实例进行数据填【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net塞。例如:
【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net【作者:唐霜】本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】class OrderService {
static recoverOrder(order, order_id) {
ajax.get(`.../${id}`).then(data => order.fromJSON(data))
}
}
总而言之,领域模型是相对比较普遍的业务描【作者:唐霜】未经授权,禁止复制转载。述,而领域服务是相对比较特殊的业务描述。
转载请注明出处:www.tangshuang.net【本文受版权保护】【本文首发于唐霜的博客】另外,一般来讲,服务需要遵循无状态的原则【关注微信公众号:wwwtangshuangnet】【访问 www.tangshuang.net 获取更多精彩内容】,状态一般会放在领域模型中。
【作者:唐霜】转载请注明出处:www.tangshuang.net【作者:唐霜】交互模型转载请注明出处:www.tangshuang.net
【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。至此为止,我们的编码还没有涉及UI或交互【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】。这其实有悖以往的编程经验,“怎么界面都【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】还没有开始写就已经有一大堆代码了?”是的【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。,这是我们实现目标“把业务逻辑从交互代码原创内容,盗版必究。【版权所有,侵权必究】中解救出来“的必经之路。我们要有一层专门【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。去完成业务逻辑,而领域层就是做业务逻辑的著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】。领域层是静态的,描述性质的,因此,可以本文作者:唐霜,转载请注明出处。【原创内容,转载请注明出处】承载业务知识体系。
【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。【转载请注明来源】有了核心的业务逻辑了,接下来,我们就要考本文版权归作者所有,未经授权不得转载。本文版权归作者所有,未经授权不得转载。虑在应用中完成界面和交互,这和后端完全不著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】同,后端实施DDD,没有这一层,业务到D未经授权,禁止复制转载。【作者:唐霜】O就结束了,而前端则还要继续,完成人机交本文版权归作者所有,未经授权不得转载。【未经授权禁止转载】互的真实效果。所以,我在某些场合讲,前端【版权所有,侵权必究】【转载请注明来源】DDD比后端在某些方面更复杂(当然,后端【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】也很复杂,需要考虑很多数据持久化相关的架本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】构问题)。
【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】而且,在我们的产品文档中,经常会这样描述著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。:
本文作者:唐霜,转载请注明出处。【本文受版权保护】著作权归作者所有,禁止商业用途转载。【本文首发于唐霜的博客】未经授权,禁止复制转载。【本文首发于唐霜的博客】当用户点击“提交”按钮的时候,该订单被发本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。送给检验员进行核对。
【原创内容,转载请注明出处】原创内容,盗版必究。转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】【转载请注明来源】
很明显,产品经理在写这句话文档时,是在描本文作者:唐霜,转载请注明出处。【转载请注明来源】述一个业务过程。“点击提交按钮”这个动作【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】是交互层面的,它无法由后端完成,后端只能著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】完成这个动作之后的跟随动作,也就是“订单著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】被发送给检验员”。那么,“点击提交按钮”才能本文作者:唐霜,转载请注明出处。触发“订单被发送给检验员”这个业务逻辑,本文作者:唐霜,转载请注明出处。著作权归作者所有,禁止商业用途转载。你能说不是业务逻辑吗?这种事情往往有屁股【本文受版权保护】【原创不易,请尊重版权】坐哪里哪里就是真理的意味,后端人员不管理【作者:唐霜】原创内容,盗版必究。任何交互行为,因此,他们斩钉截铁的说“这【版权所有】唐霜 www.tangshuang.net【原创内容,转载请注明出处】不是业务逻辑”,其实,他们想要表达的是“本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。这不是我们后端的【本文受版权保护】业务逻辑“。这就有点变味了,产品文档中的【本文首发于唐霜的博客】【转载请注明来源】一句话,只有一半是业务逻辑,你觉得说得通本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】吗?所以,我在很多场景下都讲,交互有两种,一种是界面交互,一种是业务交【本文受版权保护】本文作者:唐霜,转载请注明出处。互。在这个例子中,“点击提交按钮”就是业务本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。交互。
【本文受版权保护】转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。【转载请注明来源】作为前端开发者,需要分清楚“界面”和“交【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。互”存在一定的区别。界面,交互,它们在某原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。些情况下是统一体,不可分割,但是在另外一转载请注明出处:www.tangshuang.net原创内容,盗版必究。些情况下,却是独立的,或者说“业务交互”【作者:唐霜】原创内容,盗版必究。是可以独立于界面存在的。
【转载请注明来源】【未经授权禁止转载】本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】【版权所有,侵权必究】以上面这个“点击提交按钮”为例。你知道这【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net个“点击”动作是一个click事件,但是【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。我想问的是,你现在知道这个按钮是以什么样【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。的界面展示的么?是红色的按钮,还是灰色的【未经授权禁止转载】本文作者:唐霜,转载请注明出处。?是方角的还是圆角的?是短的,还是长条的未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】?是不是都不清楚?或许产品经理在写下这句未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。话时,确实脑海中有一个界面的形状,但是在转载请注明出处:www.tangshuang.net【转载请注明来源】业务本身的过程中,这里是没有界面的,它是【未经授权禁止转载】原创内容,盗版必究。一句抽象描述,对于编码而言,就是一个抽象转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】的表达,因此,我说这里要建立交互模型【原创内容,转载请注明出处】。转载请注明出处:www.tangshuang.net
【本文首发于唐霜的博客】未经授权,禁止复制转载。【转载请注明来源】著作权归作者所有,禁止商业用途转载。什么是交互模型?【原创不易,请尊重版权】
【关注微信公众号:wwwtangshuangnet】【转载请注明来源】原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。就是在没有界面的情况下,对产品文档中的业未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net务交互进行的建模。一般情况下,交互模型会著作权归作者所有,禁止商业用途转载。【访问 www.tangshuang.net 获取更多精彩内容】引用领域模型和领域服务,同时,它还会被用【作者:唐霜】【原创不易,请尊重版权】到视图层中,交给视图层使用。说白了,站在未经授权,禁止复制转载。原创内容,盗版必究。视图层编程的角度讲,你可以把交互模型和我【关注微信公众号:wwwtangshuangnet】【本文首发于唐霜的博客】们平时讲的“状态管理器”划一个约等号,交【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。互模型的实例向视图层提供状态属性和方法,转载请注明出处:www.tangshuang.net【原创内容,转载请注明出处】属性用于视图层进行渲染,而方法用于事件回【本文受版权保护】【原创不易,请尊重版权】调。
本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】在上面的例子中,我们创建这样的交互模型:
【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.netimport { Controller } from 'nautil'
class OrderEditController {
static model = Order
// 需要在视图层赋值
onError = null
recover(order_id) {
OrderService.toEdit(this.model, order_id)
}
async submit() {
const errors = this.model.validate()
if (errors.length) {
this.onError?.(errors.message)
return
}
const data = this.model.toData()
const res = await ajax.post('xxx', data) // 这个接口可能就是我们上面说的发送给检验员
return res
}
}
这样,我们就创建好了一个交互模型。你看它【版权所有,侵权必究】【版权所有】唐霜 www.tangshuang.net的表达是否很清晰呢?而此时,你有没有发现【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】,到现在为止,你还没有写任何的视图层面的原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。代码。到目前为止,我们已经把需求文档中,【原创不易,请尊重版权】原创内容,盗版必究。有关业务的部分完全表达出来了,用领域模型本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。和领域服务表达了业务实体及对应的处理逻辑【原创内容,转载请注明出处】【版权所有,侵权必究】,用交互模型表达了某些业务交互。是不是很【关注微信公众号:wwwtangshuangnet】【原创不易,请尊重版权】神奇,在没有开始写界面的时候,我们就已经原创内容,盗版必究。【转载请注明来源】完成了大部分逻辑的编写。
【本文受版权保护】【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。等一等,在进入下一个部分之前,我还要在补【本文首发于唐霜的博客】【版权所有,侵权必究】充一点。
原创内容,盗版必究。原创内容,盗版必究。【本文首发于唐霜的博客】转载请注明出处:www.tangshuang.net假如你的业务系统有PC端和APP端,其中【本文受版权保护】原创内容,盗版必究。PC端是基于react的,APP端是基于本文作者:唐霜,转载请注明出处。【访问 www.tangshuang.net 获取更多精彩内容】react native的,到目前为止,【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。你有没有发现,由于我们上述代码中没有任何【版权所有,侵权必究】未经授权,禁止复制转载。视图层的编码,所以,我们上述的代码全部都【原创不易,请尊重版权】【作者:唐霜】是可以在两端复用的,但是由于react和转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.netreact native视图层编程方式不【未经授权禁止转载】本文作者:唐霜,转载请注明出处。同,而且,设计稿也会不一样,PC和APP【本文首发于唐霜的博客】【转载请注明来源】的设计稿几乎不可能一样,所以,视图层的代【原创内容,转载请注明出处】【未经授权禁止转载】码,我们必须一定肯定是会有两份的(当然,【原创不易,请尊重版权】【作者:唐霜】还有一种多端同构的方案,你可以了解一下我【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。写的框架 nautil https://github.com/t著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】angshuang/nautil )。现在,业务交互逻辑都已经完成了,两原创内容,盗版必究。【未经授权禁止转载】端虽然需要写自己的视图层代码,但是,这些【本文受版权保护】【版权所有】唐霜 www.tangshuang.net与业务相关的逻辑,却不需要再重新编写了,著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】可以拿过来就用。你可以把两端的代码放在一【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。个git仓库中,这样,就可以直接共用一份著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。业务代码。
本文作者:唐霜,转载请注明出处。【转载请注明来源】【原创不易,请尊重版权】【原创内容,转载请注明出处】【本文受版权保护】另外,前端的单元测试是很难做的,因为UI转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。测试非常麻烦,虽然也能做,但是效率并不高【转载请注明来源】原创内容,盗版必究。。而将业务的领域模型和交互模型独立出来之【版权所有】唐霜 www.tangshuang.net【版权所有】唐霜 www.tangshuang.net后,你可以发现,虽然我做不了UI测试,但【本文首发于唐霜的博客】未经授权,禁止复制转载。是我可以做业务逻辑的测试,这样,我可以保【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。证我的业务逻辑是准确的,在持续的维护中,【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。有测试用例做保障,任何人的改动所带来的破【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】坏,都是不允许的,这就保证我们的业务层面转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net的逻辑是OK的。
本文版权归作者所有,未经授权不得转载。【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。薄薄的视图层【转载请注明来源】
原创内容,盗版必究。未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。有人多次给我评论讲,前端就应该是胖UI。本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】对于这一点我不置可否,不过在我看来,胖U著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.netI的前提是在剖离业务逻辑,纯界面交互的情【作者:唐霜】【未经授权禁止转载】况下讲胖UI才是准确的。以react为例【版权所有】唐霜 www.tangshuang.net原创内容,盗版必究。,我们的一个react应用中有组件,有状转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】态管理,有路由管理,这些都是应该的,但问【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net题在于,是因为基于react的视图层处理【本文首发于唐霜的博客】未经授权,禁止复制转载。导致我们的代码臃肿了,还是因为我们一边写【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。界面交互一边处理业务逻辑把代码撑肥了呢?
【版权所有】唐霜 www.tangshuang.net【转载请注明来源】本文作者:唐霜,转载请注明出处。回到我们文首的例子中,在我们有了建模成果【原创内容,转载请注明出处】未经授权,禁止复制转载。后,我们可以写界面了:
【转载请注明来源】【关注微信公众号:wwwtangshuangnet】【本文受版权保护】本文作者:唐霜,转载请注明出处。import { Component } from 'nautil'
import { Form, FormItem } from 'react-tyshemo-form'
import { Toast } from '...some toast library...'
class OrderForm extends Component {
constructor(props) {
this.controller = new OrderController()
this.controller.onError = Toast.error
}
onInit() {
const { id } = this.props
this.controller.recover(id)
}
async handleSubmit = (e) => {
e.preventDefault()
const res = await this.controller.submit()
const { ... } = res
// ... 做一些跳转之类的
}
render() {
return (
<Form model={this.controller.model} onSubmit={}>
<FormItem name="price" component={['input', { type: 'number' }]} />
<FormItem name="count" component={['input', { type: 'number' }]} />
<FormItem name="code" component="input" />
<FormItem name="total" render={({ value, onChange, saveMessage }) => {
return (
<span>
<input value={value} onChange={onChange} />
{saveMessage ? <span>{svaeMessage}</span> : null}
</span>
)
}} />
<button>提交</button>
</Form>
)
}
}
现在,你可以发现,我们在视图层,主要是对【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net已经写好的controller进行操作和本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net使用,在视图层的所有代码,基本上都是和界【版权所有】唐霜 www.tangshuang.net【转载请注明来源】面与界面交互相关的,而几乎没有看到任何业本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。务的影子。
本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。【未经授权禁止转载】我们基于类似的思路,可以把写好的领域模型【作者:唐霜】【原创内容,转载请注明出处】、交互模型再次用到react nativ本文版权归作者所有,未经授权不得转载。【作者:唐霜】e,甚至跨一个框架,用到vue中去,因为【关注微信公众号:wwwtangshuangnet】【原创内容,转载请注明出处】它们本身和框架无关,所以你在任何框架中都【本文首发于唐霜的博客】【原创内容,转载请注明出处】可以使用它们。
著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。【本文受版权保护】然而,这里会有一个问题,不同的框架要使用本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。这些代码,还存在一个和框架进行结合的东西【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。,比如vue的响应式系统是基于Objec未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】t.defineProperty或Pro【作者:唐霜】【转载请注明来源】xy的,react是基于内部的fiber【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】的,angualr是基于脏检查的,这就导转载请注明出处:www.tangshuang.net【本文受版权保护】致不同的框架里面,你想要使用同一套代码的【版权所有,侵权必究】原创内容,盗版必究。话,你就需要有一个把建模代码和框架的响应【未经授权禁止转载】【版权所有】唐霜 www.tangshuang.net式系统连接起来的东西,比如上面我用到了r原创内容,盗版必究。【转载请注明来源】eact-tyshemo-form,它就转载请注明出处:www.tangshuang.net【作者:唐霜】是一个连接工具。此外,比较优雅的工具有M未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。obx,你可以了解一下这个工具,利用Mo【原创内容,转载请注明出处】【未经授权禁止转载】bx来写controller,将非常有利【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】于在vue或react中使用相同一个cl【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.netass,因为它提供了覆盖全框架的连接工具原创内容,盗版必究。【原创不易,请尊重版权】。
【关注微信公众号:wwwtangshuangnet】著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】结语著作权归作者所有,禁止商业用途转载。
著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】【版权所有,侵权必究】在前端这样去思考和实践,是和我们以往的一本文作者:唐霜,转载请注明出处。本文版权归作者所有,未经授权不得转载。些习惯不符的,这需要我们慢慢体会。现在,著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。我并不需要你立即接受这种开发思维,但是你【版权所有,侵权必究】本文作者:唐霜,转载请注明出处。可以先了解它,直到有一天,你突然发现,你原创内容,盗版必究。转载请注明出处:www.tangshuang.net的业务系统开始在庞大的组件网络中变得难以【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net维护时,可以再找出这篇文章,阅读一下,获著作权归作者所有,禁止商业用途转载。【原创内容,转载请注明出处】得一些思路,然后重新梳理你的代码组织。
【原创不易,请尊重版权】【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。【转载请注明来源】这样的代码组织还面临一个问题,我想你也会【作者:唐霜】【版权所有,侵权必究】思考到这个问题,就是:模型、控制器、视图原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。,应该放在不同的目录中,还是放在同一个目本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。录中?我认为这个问题还是需要根据实际的情本文版权归作者所有,未经授权不得转载。【原创内容,转载请注明出处】况来看。但是,就我个人而言,更倾向于将一【作者:唐霜】本文作者:唐霜,转载请注明出处。个模块的模型、控制器、视图放在一个模块目【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。录中,这个模块从某些意义上,可以从这个项【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】目拖到另外一个需要这个模块的项目中去,你【转载请注明来源】【转载请注明来源】只需要在顶层的应用上,组织和使用这个业务【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。模块。但是,在一些情况下,比如你有多端同【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。时一起开发,那么就要好好考虑,在实践中摸【原创内容,转载请注明出处】【未经授权禁止转载】索,到底应该怎么组织代码目录。
著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。【本文首发于唐霜的博客】
最后,如果你在平日的业务代码开发中,也遇【本文首发于唐霜的博客】本文版权归作者所有,未经授权不得转载。到类似的问题和烦恼,或者你认为本文中的某【转载请注明来源】著作权归作者所有,禁止商业用途转载。些看法,还有改进之处,可以在本文或知乎专著作权归作者所有,禁止商业用途转载。【转载请注明来源】栏“前端数据治理之道”下方留言一起探讨。
本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net


最近在实际业务中遇到了类似的问题,也在思考如何通过将业务和交互分离。看完这篇文章有些感触,总感觉现在自己对于业务交互进行拆分划分时总有些朦胧不清的东西在阻碍着,无从下手的感觉。希望作者可以针对一些简单实际业务场景进行实战演练,这样结合文章中的思想可能感受更深刻。感谢作者的分享!
感谢你的关注。
很多人向我提出过类似的需求,也是希望有实际的代码来聊一聊这个事情。
但是能够公开演示的代码并不多,毕竟任何开源的项目,都不是以某个业务为目标的。
文章的这些想法理念,都需要在工作中去思考、尝试和实践。
如果有任何的朋友看到这条评论,并且愿意拿出自己的业务代码来一起讨论,不妨加我微信,我们可以一起通过代码来展开讨论。
随着工作时间的增加,也有了烦恼对于逻辑与业务耦合的烦恼,对于入行两年的我可以学到很多东西。谢谢大佬。
我把 “指标”划分为model,不同类型的“报表”划分为不同modules,报表中都会使用到指标,这样的话是否就不适合把model放到modules目录下,而要让model目录和modules目录同级,使用会更加灵活
“划分”要整体的看系统的看,单纯从某一点讲,都是有道理的,但是当下一次遇到某些情况的时候,又觉得放在另外一个地方更合适,我建议是先把整个系统的架构分层理清楚,再去斟酌领域代码的管理以及具体业务层面代码的管理
写的很好,看了你之前的一批关于React的DDD架构,理念和我一直以来的思维模式不能说相似,只能说一模一样。前端绝对有必要对业务代码进行充分的抽象建模。而当前的大多数项目都是之间采用的Vue Cli和React cli模板,这些并称不上架构,只不过是实现了一个前端行业的标准化代码结构而以。
关于领域模型的设计,控制器,UI视图的分层理念,简直是知音。最近这一个月都在翻google上的一些文章,没想到在百度上能搜到这么一篇!
对我而言,稳定、支撑了我的理念,帮助很大!
感谢支持,可以加微信一起探讨
在vue中如何具体的实现,如果要写一个CRUD的页面的话
关注我博客或b站,后续会有内容专门以案例来讲
期待ing…
其实,他们想要表单的是“这不是我们后端的业务逻辑“ . 表达写成了表单。
已更新,感谢指出
如果原来的项目大量依赖hooks, 业务逻辑与页面耦合的很死.这时该如何进行分层呢? 难道需要重构所有hooks吗?
使用hooks是属于视图层的处理,所以使用hooks和不使用hooks都是一样的,都是在视图层中写业务逻辑,并没有做到任何分层的设计。
如果确定要重构,应该将这些业务逻辑独立出来,层层抽象,这跟是否使用hooks没有任何关系。
豁然开朗, 要重构的话,也不是重构hooks, 而是把hooks再反向抽象成业务逻辑. 看来重构不太现实了
像 handleSubmit 时的loading状态会存在哪一层呢, 在视图层上吗?
loading在控制器里面可以有,在视图层也可以有,在控制器里面是用于控制某些动作的状态,在视图层用于控制显示界面。当然,你可以直接把控制器的loading暴露出来给视图层用,这样就只有一个loading。而且,就这个场景,可以考虑一下,在控制器里面引入xstate这类状态机工具,解决复杂的状态流转问题。
原来如此,两个地方的loading虽然含义不同但是也能通用.
状态机工具我没了解过,不过涉及到复杂的异步校验的时候,确实会需要借助工具来管理.
文中的例子里页面的跳转是写在视图层里的, 但有些时候, submit后的跳转页面也会跟业务有关. 按这样理解的话, 这时的跳转就会被写在控制器里,在视图层调用跳转方法吧.
是的,你可以把控制器理解为与UI无关的模型