所谓“读书破万卷,下笔如有神”,放到DDD上面确是个难题,仅这章的破题部分就难住了我,想要做到言简意赅但还不能口若悬河。虽自信本人面对指责应可作到宠辱不惊,但也不能依仗此而无赖的误导别人,所以本单的内容“我妄言之,您姑且听之”。
我有过这样的经验,读书的越多后面能攫取的有用的知识越少,也许从一本书中只能获取到一条有用的内容,可正是因为这一条内容会让自己瞬间悟道。2015年前我曾经读遍了市场上所有的DDD国内外相关书籍,也几乎读遍了能从网络上找到的各类问题。大方面都了解,可在日常工作中经常会因为一个小的细节让自己不得要领。因为这一小的瓶颈,无法上升到另外的一层台阶。所以我期望个人的一些经验能在您悟道的途中起到启发作用。
本章我会着重解释一下DDD的本质,也就是其到底在说些什么。这里面有个人的理解也有书上的理论,结合在一起,说一些白话,最重要的是掀起她那神秘的盖头。
DDD分为两个部分:战略与战术。本质一点,这两点可指导您在业务与技术两方面应如何做来最小化需求变更导致的系统调整;再本质一点,DDD所达到的最终结果就是我们常常在面向对象中所说的:高内聚、低耦合。实际上,想要做到这两并不拘泥于是否使用了DDD,DDD之前也有许多上佳的实践可供使用。我们把目标进行反推:高内聚、低耦合的系统必然会让您的系统易维护、易扩展。易维护与扩展的系统必然是在设计之初就在业务方面与技术方面进行了思考与设计,这是起点,而DDD正好服务于这个起点。下图概括了DDD包含的内容,其实没您想像的复杂。

DDD的战略模型主要关注于“子域”与“限界上下文”,这两个都是DDD中的特有名词。用白话去说:“子域”是一种概念模型。再直白一点,假如您对比子域说明和实际的系统部署说明,会发现两者并不能一一对应。再比如,您以微服务架构落地一个OA系统,子服务可能包含“用户管理”、“签到管理”、“会议室管理”,这些是您可见的一个个的服务,也许还使用了不同的开发语言。而子域是虚的,是对一个大系统在业务上划小后人为的赋予每一个小业务的名称。仍然以OA系统为例,在系统未构建前将OA这个领域分成几个“中心”,比如“审批中心”、“员工中心”、“公文中心”,叫什么名是您自己定义的,是为了后面大家讨论的时候能明白彼此在说什么,这里的中心即为子域;放到落地阶段,“员工中心”搞不好会分成多个子系统比如“签到管理”、“绩效管理”,这些才是物理上可见的服务。
针对“子域”,此处您需要记住的是:1)子域是一种对领域的概念上的划分,是人为的主观行为,灵活性较高;2)子域的目的是把大的领域划小,使用分而治之的方法来简化业务设计时的复杂度;3)子域的划分是变化的,随着您对系统认识度的加深,会删除某些子域并增加新的进来,这不是您早期的划分有错,而是很自然的现象。子域的划分方式及相关细节会在下一章进行阐述。
“限界上下文(Bounded Context,为方便,后续文章中都将其简称为BC)”又是一个容易产生疑惑的名称。其重点是关注于系统的物理划分,在这里我给出的不严格定义是:限界上下文泛指系统中的模块、微服务架构中的子服务、单体中的“包(Java)”或“名称空间(C#)”。请拿出小本本记录下来:BC是对系统的一个物理划分,这里存在着可见的边界。实践中,建议明确子域后再进行BC设计,这种方式会让您的工作具备理论指导。
您可能会问:为什么叫限界上下文?这东西得分成两个词:限界,您的领域模型的活动范围是有界限的,不能像脱了缰的野马一样乱窜。那这个界限是什么或者说要将领域模型限制在哪里呢?答:“上下文”中!换成人话就是某个系统或某个业务场景。因此,系统设计之初“您需要画一个圈,将领域模型限制在这个圈内保证其不可串场,这个‘圈’即为限界上下文,实现时可以是一个单独的服务或‘包’或‘名称空间’”。引入BC的目的是为了达到“高内聚、低耦合”这个目标。想像一下:领域模型都在自身的圈子活动,互不干扰,后续有任何变更都不会超圈,这样的程序是否会更好维护?限界上下文的定义可以说是相当严谨的,但同时也比较晦涩。所以在非严格的场景下只需从朴素的角度理解即可。
另外,DDD还有一个词叫“通用语言”,简单来说就是大家在说一个东西的时候都能明白彼此所指的是什么。比如有个流行词叫“打卡”,如果您在和朋友聊工作考勤,这里的打卡代表的是员工到公司时的签到;如果您和朋友在聊某个比较火的景点或美食,这里的打卡代表着某人曾至此一游。因场景不同,同一个词就会有着不同的含义。这个场景有专业人士称其为“语境”,其实也就是“限界上下文”,所以BC又多了一层其它的作用:他给予了某个东西一个唯一的含义。实际上,“通用语言”是面向BC的,只有在BC内讨论才有意义。书上常说做DDD要有事件风暴,事件风暴的主要作用除了确认子域、BC、领域模型外,设定通用语言也是其主要的目的之一。
总结一下BC的概念:1)是系统的物理划分;2)应根据子域进行推导;3)限定了领域模型的边界;4)BC内,领域术语都有一个明确的含义(即通用语言)。
战术模式对于技术人员来说就比较熟悉了,比如系统架构、领域模型、分层这类纯技术的内容,是DDD书籍中大讲特讲的部分。战术模式更多的聚焦于BC内,这方面的内容后续我们会进行细化说明。
复杂业务场景落地时,DDD尤其推荐使用面向对象或称之为对象驱动(ODD)的编程方式。实际上,DDD并不局限于面向对象,面向过程(经典三层模式)也会被经常用到。以个人的经验来看,两种方式使用的比例至多五五开,ODD使用率并不高,一般都在核心域内使用。Martin Fowler认为面向过程是一种“反模式”,我倒是觉得不存在正或反的概念,适合的最好。我们知道,一个研发团队应该以枣核形状为最佳,即存在着一大批的中等水平的工程师。ODD落地难度较大,开发缓慢,工作量也相对较多,应只在非常复杂的、多变的业务场景下使用。从管理角度来说,让整个团队无差别的使用面向对象编程也不太适合一般企业中的一般团队。
有人会反驳说:DDD如果就是这点内容,为什么我看了半天看不懂,看懂了落地又如此之难。其实原因很简单:要构建优秀的系统,DDD指导仅仅是一方面。正常来说,系统分成内外两面,用户能看到的只有外面。虽然外面的工作量相对少也无法直接反映出架构的优秀度,但其是用户直接可见的,界面不好用、不好看,给人的印象就不好。再举个例子,做内容检索时一般会使用Elastic Search。在这个场景下面,DDD最多能在战略上给出指导,好不好用、快不快还在您的技术实现,这里面已经不是怎么建模能搞定的事情了。您要考虑的是有多少台服务器、如何配置等内容。
好的系统是由各类知识和各类人员汇聚而成,要包括优秀的UI设计师、项目经理、运维、测试;作为研发的您也需要对数据库、缓存、队列、所用框架和语言等有深入的了解,当然了,还要有一个端正的态度。这些都需要您在日常工作和学习中积累和反思。再实际一点,您简历上写精通DDD其实也说明不了什么,面试官一般都会从多个角度不同的技术上考核您,差一点就直接枪毙。所以,请您客观看待DDD,切莫神化,它就像您学习的如数据库、缓存、分布式系统等知识一样,是系统建设中的一个方面而非全部。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道rubyonrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
我在我的项目中有一个用户和一个管理员角色。我使用Devise创建了身份验证。在我的管理员角色中,我没有任何确认。在我的用户模型中,我有以下内容:devise:database_authenticatable,:confirmable,:recoverable,:rememberable,:trackable,:validatable,:timeoutable,:registerable#Setupaccessible(orprotected)attributesforyourmodelattr_accessible:email,:username,:prename,:surname,:
我正在尝试创建密码规则来设计可恢复的密码更改。我通过passwords_controller.rb做了一个父类(superclass),但我需要在应用规则之前检查用户角色,但我所拥有的只是reset_password_token。 最佳答案 假设您的模型是用户:User.with_reset_password_token(your_token_here)Source 关于ruby-on-rails-设计通过reset_password_token获取用户,我们在StackOverflow
我已经使用Apartment设置了一个Rails5应用程序(1.2.0)和Devise(4.2.0)。由于某些DDNS问题,应用只能在app.myapp.com下访问(请注意子域app)。myapp.com重定向到app.myapp.com。我的用例是每个注册该应用的用户(租户)都应该通过他们的子域(例如tenant.myapp.com)访问他们的特定数据。用户不应限定在其子域内。基本上应该可以从任何子域登录。重定向到租户的正确子域由ApplicationController处理。根据Devise标准,登录页面位于app.myapp.com/users/sign_in。这就是问题开始的
我在关注RyanbatesRailsCast的devise和omniauth(第235集-devise-and-omniauth-revised)。当我尝试使用Twitter登录时,标题中不断出现错误。defself.new_with_session(params,session)ifsession["devise.user_attributes"]new(session["devise.user_attributes"],without_protection:true)do|user|user.attributes=paramsuser.valid?end完整跟踪:C:/Ruby20