“员工请假”流程及在线表单开发示范

1. 什么是小圈子(Domain)

咱俩所做的软件系统的目标都是来解决一各个题材,例如做一个电商系统来在线销售自己公司的成品;做一个灰度公布平台来提高服务的质量和稳定。任何一个连串都会属于某个特定的世界,例如:

  • 论坛是一个世界:要做一个论坛,那那么些论坛的大旨业务是规定的:比如用户发帖、回帖等基本基本作用;
  • 电商系统是一个世界:只假如电商领域的种类,那主题业务就是:商品浏览、购物车、下单、减库存、付款交易等基本环节;

同一个世界的种类都有着同等的焦点工作,因为他们要解决的标题标本色是类似的。因而得以测算:一个世界本质上可以知晓为一个 难点域 。只要确定了系统所属的世界,那么这几个系统的中坚工作,即要解决的关键难题就着力确定了。日常大家说,要变为一个领域的大方,必要求在这些小圈子深远探究广大年才行,唯有如此才会遇到尤其多的该领域的题材,积累了拉长的经验。

1. “员工请假”流程及在线表单开发示范

2.界限上下文(Bounded Context)

常常来说,一个领域有且唯有一个宗旨难题,大家称为该领域的『焦点子域』。在宗旨子域、通用子域、支撑子域梳理的还要,会定义出子域中的『限界上下文』及其涉及,用它来 解说子域之间的关联 。界限上下文可以大致了解成一个子系统或机件模块。

譬如说:下图是对饭馆管理的子域和界限上下文的梳理:

图片 1

1.1. 描述

透过本示例达到急忙对F2流程管理平台的在线表单速讯上手及零编码式的费用。落成一个以请假为示范的流水线及在线表单,及请假数据的询问。

3. 领域模型(Domain Model)

世界驱动设计(Domain-Driven Design)分为五个等级:

  1. 以一种领域专家、设计人士、开发人员都能通晓的通用语言作为相互交换的工具,在沟通的长河中发觉世界概念,然后将这几个概念设计成一个领域模型;
  2. 由世界模型驱动软件设计,用代码来促成该领域模型;

有鉴于此,领域驱动设计的主导是树立正确的园地模型。领域模型具有以下特点:

  1. 对富有某个边界的园地的一个虚幻,反映了世界内用户 业务需要的面目 。它属于『解决问题空间』。领域模型是有边界的,只影响了我们在圈子内所关注的有的,包蕴 实体概念(如:货物,书本,应聘记录,地址等),以及 进度概念(如:资金转化等);
  2. 增强软件的 可维护性,业务可驾驭性以及可重用性。领域模型确保了俺们的软件的业务逻辑都在一个模子中,协理开发人士相对平缓地将世界知识转化为软件构造;
  3. 贯通软件 分析、设计、开发 的满贯经过。领域专家、设计人士、开发人士面向同一个模型举行互换,互相共享文化与新闻,所以可以预防需要走样,让软件开发人士做出来的软件真正满足须求;要赤手空拳科学的世界模型并不简单,须求领域专家、设计、开发人士积极沟通共同努力,然后才能使大家对天地的认识不断长远,从而不断细化和健全领域模型;
  4. 为了让世界模型看的见,使用的常用表明领域模型的办法:图、代码或文字;
  5. 重点:领域模型是成套软件的主干,是软件中最有价值和最具竞争力的一对;设计丰裕精彩且符合业务须要的天地模型能够更急忙的响应须要变动;

  6. 天地通用语言


由软件专家和领域专家合作开发一个天地的模子是有必不可少的。开发进程中,
开发人士以类、算法、设计形式、架构等举行思考与调换。但领域专家对此一窍不通,他们对技术上的术语没有太多概念,只询问特有的园地专业技能,例如:在空中交通监控样例中,领域专家知道飞机、路线、海拔、经度、纬度,他们有和好的术语来谈谈这个事情。软件专家和领域专家调换进度中,须要做翻译才能让对方知道这么些概念。

领域驱动设计的一个主导标准是行使一种基于模型的语言。使用模型作为语言的主干骨架,必要组织在进展富有的互换是都施用同样的语言,在代码中也是那般,那种语言被称呼『通用语言』。

1.2. 对象效果

(1) 如何布署一个“请假在线表单”

(2) 怎么着布置请假流程

(3) 怎么着询问本人个人的请假历史数据

(4) 怎样让管理员查询所有请假的数目

5.建模思考的难点:用户必要

『用户须求』不可能一如既往『用户』,捕捉『用户心中的模子』也无法平等『以用户为骨干设计领域模型』。设计领域模型时不可以以用户为出发点去思考问题,不可能老想着用户会对系统做什么;而应当从一个理所当然的角度,根据用户要求挖掘出领域内的相干东西,思考那一个东西的精神关联及其变化规律作为出发点去思考难点。

天地模型是 排除了人之外的客体世界模型 ,包涵了人所扮演的参与者角色。但是一般情况下不要让插足者角色在天地模型中据为己有首要地方,否则各种系统的圈子模型将变得没有异样,因为软件系统就是一个人机交互的连串,都是以人为主的移动记录或跟踪。例如:

  • 论坛中假若以人为中央,那么领域模型就是:人发帖,人回帖,人结贴,等等;
  • 商品托运系统中假若以人为基本,就成为了:托运人托运货物,收货人收货物,付款人付款,等等;

以一个货物运输系统为例子简单说Bellamy(Bellamy)下。在用户必要相对明朗之后,那样描述领域模型:

  • 一个Cargo(货物)涉及八个Customer(客户,如托运人、收货人、付款人),每个Customer承担分裂的角色;
  • Cargo的运输目标已指定,即Cargo有一个运送目的;
  • 由一文山会海知足Specification(规格)的Carrier
    Movement(运输动作)来形成运输目标;

上述描述没有从用户的角度去描述领域模型,而是以世界内的相关东西为着眼点,考虑这么些事物的精神关联及其变化规律的:

  • 以货物为着力,把客户看成是商品在某个场景中可能会涉嫌到的关系角色,如货物会提到到托运人、收货人、付款人;
  • 商品有一个规定的靶子,货物会经过一密密麻麻的运载动作到达目标地。

以用户为主干来揣摩领域模型的合计只是停留在急需的外部,而从不挖掘出真正的须要的面目。领域建模时须求全力以赴挖掘用户要求的本来面目,这样才能真正贯彻用户必要。

1.3. 怎样安插一个“请假在线表单”

6. 经典分层架构

图片 2

 

用户界面/体现层:1)请求应用层获取用户所需的体现数据;2)发送命令给应用层执行用户的指令

应用层:薄薄的一层,定义软件要完毕的职务。对外为显示层提供各类应用效益,对内调用领域层(领域对象或领域服务)完结各类事务逻辑。应用层不分包业务逻辑

领域层:表达业务概念、业务情状音讯及作业规则,是事情软件的骨干

基础设备层:为任何层提供通用的技艺能力,提供了层间通讯;为世界层提供持久化机制。

1.3.1. 数据库表定义

点击在线表单==》数据库表定义==》新增,如下图:

 图片 3

 

点击编辑字段,如下图:

 图片 4

点击编辑字段,新建请假的有所字段

 图片 5

说胆:每个表中必要求有CreatorId和Created提姆e,那多个字段的意思在于存放创立人ID和数量创立时间,后边将用此字段做过过滤条件来做表的数目查询管理。申请人ID在表单元素配置时会配置为隐藏域,当请假人提起请假时会自动绑定申请人的用户ID,常常也会有一个相应的请假人姓名,如上图所示。当然这五个字段也不是相对要的,要是没有那多少个字段那么需要贯彻“目的意义”中的第3和第4点需求在菜单地址中增加多八个参数

参数地址传入指定的字段来顶替那多个字段,增加sortName参数和creatorId参数,详细见

后边的辨证在“如哪一天查询个人的请假历史数据”中有涉嫌。

点击生成物理表

 图片 6

到此数额库表就布局完结了。

7. 接纳的格局

1.3.2. 多少对象定义

点击“新增”,拔取方面定义好的多寡库表

 图片 7

点击编辑子表能够添加子表,由于请假表没有子表,所以可忽略。

 图片 8

至此,数据对象字义已成功。

7.1. 总览图

图片 9

1.3.3. 表单定义

表单定义是很首要的一环节,要求定义字段的控件元素。

增产一个表单定义,选择你刚才配置的数额对象

点击编辑元素字段,如下图:

 图片 10

图片 11

慎选数据对象中的字段后效果如下图所示:

图片 12

编纂每个字段的控件类型,如下图编辑姓名字段,由于申请人的人名是不须求用户自己来输入的,通过配备默许值来机关填写:

 图片 13

所在部门也是和姓名同理,通过布置默许值来达到提起流程时自动填写。

 

 

陈设请假种类,因为请假类型是一个取舍,我们得以从数据库在安顿,通过自定义、数据字典,或Sql来得到选项。下边是由此自定义选项的配备;

 图片 14

 图片 15

 

布局申请日期,由于申请日期用的是Created提姆e创设时间,在意义上是千篇一律的,重假使用来末端列表的默许排序字段,通过默许获取当前岁月来设置申请日期。

图片 16
设置申请人ID,由于申请人ID是不须求被呈现的,同时也是不须求用户自己来输入的之所以大家安插申请人ID为隐藏域,同时安装默许值为当前登录者ID,如下图

图片 17

唤醒:大家在其实支付应用进程中时常要用到各样地点的ID作为来有限支持数据的关系,比如用户ID,部门ID是最常见的,所以那么些ID都经过隐藏域和装置默许值来促成多少自动填写和存储到您自定义的数据库表中。那一个值都能透过默许值或高级控件“自定义选取器”和“自定义选择对话框”来贯彻。

7.2. 提到的宏图

涉及在领域建模的经过中非凡紧要,关联的筹划可以遵守如下的有的规则:

  • 提到 尽量少。对象时期复杂的关系不难形成对象的涉嫌网,对于通晓和掩护单个对象很不利,同时也很难划分对象与目标之间的界限;此外,裁减涉及有助于简化对象时期的遍历;
  • 涉嫌尽量保持 单向 的关联;
  • 在创设关联时,需要开挖是还是不是留存涉嫌的 限制条件 。若是存在,那么最好把范围条件加到关联上,往往那样的限量标准能将关联化繁为简,即将多对多简化为1对多,或将1对多简化为1对1;

1.3.4. 布署表单应用

急需将上边定义的请假在线表单定义应用成一个表单应用供流程引擎调用,如下图所示:

 图片 18

编纂表单Html模板如下图,点击生成表单模板,调整布局格式后如下图所示:

 图片 19

点击保存。

 

 

 

 

 

致此表单定义已毕。

7.3. 实体(Entity)

实体就是圈子中需求 唯一标识 的天地概念。因为我们有时候须要区分是哪个实体:有五个实体,若是唯一标识分歧,那么即便实体的任何具有属性都一样,也觉得他俩是七个区其余实体。

不应有给实体定义太多的特性或作为,而应该寻找关联,将品质或行为转移到其他涉及的实体或值对象上。比如:Customer
实体,有部分地点音信,由于地方音信是一个整机的有事情含义的概念,所以大家得以定义一个
Address 对象,然后把 Customer 的地点相关的信息转换来 Address
对象上。如果没有 Address 对象,而把那一个地址音信直接放在 Customer
对象上,然后对于一些任何的近乎Address的新闻也都直接放在Customer
上,会招致 Customer 对象很糊涂,结构不明晰,最后促成它难以保证和了然。

1.4. 什么安排请假流程

布置流程定义请参见流程定义相关支持,那个不再赘言。

布局表单应用

 图片 20

 

表单表单权限,表单权限分为读和写,可以配备怎样字段在哪些环节或都这厮可知可编制的权力。首先分析请假表业务,所有字段都在开班的时候由提单人填写,并且申请人姓名和申请时间提单人不可以填写只好由系统默许生成。下边大家来落成那作用的安插。

 图片 21

先经过批量设置,再独自设置个其他字段,如下图:

 图片 22

 

据悉作业须要,所有字段只可以在提货单时填写,设置如下:

 图片 23

 

单身设置:申请人姓名和申请日期,因为那八个字段提单人也无法修改。通过增选“空环节”来达成其余环节都无法编辑此字段的职能。

 图片 24

 

此致表单配置已毕

最后发起流程,申请日期是粉藏黄色不可编辑,同时已是当明天子,效果如下:

 图片 25

 

7.4. 值对象(Value Object)

并不是每一个事物都必须有一个唯一标识。就以地点的地方对象 Address
为例,假使多少个 Customer 的地址音讯是如出一辙的,大家就会以为那四个 Customer
的地方是同一个。用程序的办法来表述就是:要是五个对象拥有属性的值都一致,我们会以为它们是同一个对象,那么就可以把那种对象设计为值对象。

值对象的表征:

  • 值对象 没有唯一标识 ,那是它和实体的最大不相同。值对象在认清是或不是是同一个对象时是通过它们的拥有属性是还是不是同样,假设同样则以为是同一个值对象。在界别是不是是同一个实体时,只看实体的绝无仅有标识是不是一致,而任由实体的性质是还是不是相同。
  • 值对象是 不可变 的,即所有属性都是只读的,所以可以被安全的共享。

有道是给值对象设计的尽量不难,不要让它引用很多其余的靶子。值对象只是一个值,类似(int
a =
3)中的『3』,只但是是用对象来表示。值对象即便是只读的,是一个完好无损的不可分割的全体,但是可以被全体替换掉:类似(a
= 4)把a的值由『3』替换为为『4』,当修改 Customer 的 Address
对象引用时,不是由此 Customer.Address.Street
这样的主意来修改属性,可以那样做:Customer.Address = new Address(…)

1.5. 什么询问本人个人的请假历史数据

下面来看看哪些询问本人个人请假的历史表单内的数目,也就是最初始的时候大家定义的请假数据库表中的数码。效果如下:

 图片 26

那么大家仅要求配备一个种类菜单,菜单的地址规则如下:

/SingleQuery/MySearch/?appId=流程应用ID&tableName=数据库表名

延展:如若您的数据库表字段中绝非CreatedId和Created提姆e那么也足以把在地点前边伸张sortName参数和creatorId参数,对应的值就是字段名称,用于指定对应分别表示那八个字段。如下

/SingleQuery/MySearch/?appId=AB&tableName=cust_qjsqb&sortName=默许排序字段名&
creatorId=成立人字段名

请假数据个人查询的地址是:

/SingleQuery/MySearch/?appId=AB&tableName=cust_qjsqb

 图片 27

由此点击配置的菜系突显数据库列表如下,以下是通过安顿好列表表头的效果,一先导出来的列表将会是兼备字段,大家须求配备部分出示哪一部分字段,哪一部分字段隐藏,哪一部分字段做为查询条件。

 图片 28

图片 29

 

是或不是Sql输出:指的是列表展现数据时不查询此字段,由于大文本字段相当庞大而且字段内容可会有一些是Html或Json的数码,假使查询出来会招致列表的数据源分外大,不便民突显突显,强烈性提出把大本的字段去掉Sql输出的勾选,并且Grid列隐藏打上勾。

若是仅是是Grid列隐藏打勾并不影响Json数据的例行输出,只是没有在列表中显示。依旧仍能透过EasyUI的Row能收获得到Grid列隐藏的数据,假如把Sql输出去除勾选则EasyUI的row中也不存在此字段的特性。

结霜列:冻结列的便宜在于浏览器大小变化时不影响列表的来得和查阅,更好的浏览效果,寻常列表要冻结前四列。

 图片 30

 

 

日期字段市里为寻找条件时浏览:需求把是或不是可编制勾选上,如下图

 图片 31

日期查询参数,默许所有查询方式都是like,对于日期使用like无意义,可修改为当先等于,如下图

 

 图片 32

切切实实参考系统请假示例的安插。

致此配置完结。

7.5. 世界服务(Domain Service)

世界中的一些定义不太符合建模为对象(实体对象或值对象),因为它们本质上就是有的操作、动作,而不是事物。这几个操作往往要求 协调四个世界对象。借使强行将那么些操作职务分配给其余一个目的,则被分配的靶子就是背负部分不应该承担的职务,从而会促成对象的天职不分明很糊涂。DDD认为世界服务方式是一个很当然的范式用来对号入座那种跨多个目的的操作。一般的圈子对象都是有动静和行事的,而世界服务没有动静唯有行为。

领域服务还有一个很重点的机能就是足以避免领域逻辑败露到应用层。因为要是没有领域服务,那么应用层会直接调用领域对象完开销该是属于世界服务该做的操作,须求理解各类领域对象的业务职能,以及它或许会与什么其他领域对象交互等一多元世界知识。那样一来,领域层或者会把一部分世界知识走漏到应用层。对于应用层来说,通过调用领域服务提供的简短易懂且意义同理可得的接口肯定也要比一向控制领域对象简单的多。

说到世界服务,还索要提一下软件中一般有两种服务:应用层服务、领域服务、基础服务。从以下的事例中得以清楚的观看每种服务的天职:

应用层服务

  1. 收获输入(如一个XML请求)
  2. 发送新闻给世界层服务,须要其促成转帐的业务逻辑
  3. 天地层服务处理成功,则调用基础层服务发送Email通知

领域层服务

  1. 得到源帐号和目的帐号,分别通报源帐号和目标帐号举行扣除金额和增添金额的操作
  2. 提供再次回到结果给应用层

基础层服务

  1. 依照应用层的乞请,发送Email公告

1.6. 什么让管理员查询所有请假的数额

布署让管理员查询到所有人的请假数据库表数据和方面的配置相同,只是不会过虑当前用户的数目,将体现请假表数据库中的所有数据,不相同仅是菜单地址的不一致。

本节不必要配置表头,由于在上一小节中已经配备过了。

菜单地址格式:

/SingleQuery/ListSearch/?appId=应用ID&tableName=数据库表名

请要是下效果的地方是:/SingleQuery/ListSearch/?appId=AB&tableName=cust_qjsqb

图片 33

 

7.6. 凑合及聚合根(Aggregate,Aggregate Root)

集结定义了一组具有 内聚关系 的相干对象的集结,以及对象时期清晰的所属关系和边际,幸免了复杂的难以有限支撑的对象关联网的形成。大家把聚合看作是一个改动数据的单元。

聚集有以下特征:

  1. 各样聚合有一个根和一个边界:根是相会内的某个实体;边界定义了一个聚集内部有何实体或值对象;
  2. 聚合根是外部可以保险对聚集引用的唯一元素,负责与表面其余对象打交道并有限援救团结内部的业务规则。聚合内部的靶子之间可以互相引用,不过聚合外部若是要访问聚合内部的目的时,必须经过聚合根开首导航,相对不可以绕过聚合根直接访问聚合内的靶子;
  3. 集合内除根以外的其他实体的绝无仅有标识都是地面标识,也就是一旦在会聚内部保持唯一即可,因为它们总是从属于这些聚合的;
  4. 聚拢内部的对象可以维持对任何聚合根的引用;
  5. 去除一个聚合根时必须同时删除该聚合内的兼具有关对象,因为她俩都同属于一个汇集,是一个完好无缺的定义;
  6. 据悉聚合的如上概念,大家可以推论出从数据库查询时的单元也是以聚众为一个单元,无法直接询问聚合内部的某个非根的目的;

何以分辨聚合:

可以从作业的角度分析怎么样对象它们的关系是内聚的,可看做一个一体化来考虑的,然后那一个目的可以置身一个聚合内。关系内聚是指那些目的之间必须保证一个永恒规则,固定规则是指在数额变化时务必维持不变的一致性规则。当修改一个汇集时,必须在 事务级别 确保整个聚合内的所有目的满意这些定位规则。聚合尽量不要太大,否则可能带来一定的特性难题。常常在超过半数世界模型中,有70%的聚众平常唯有一个实体,即聚合根,该实体内部从不包涵其余实体,只含有部分值对象;别的30%的集纳中,基本上也只含有两到两个实体。

怎么着辨别聚合根:

如若一个见面只有一个实体,那么那些实体就是聚合根;假设有三个实体,那么大家得以考虑聚合内哪些目标有单独存在的意义并且可以和外部间接开展交互。

7.7. 工厂(Factory)

DDD中的工厂也是一种呈现 封装思想 的方式。DDD中引入工厂格局的因由是:有时创建一个领域对象是一件相比复杂的事务,不仅仅是大致的new操作。工厂是用来封装创制一个错综复杂对象尤其是聚合时所需的学问,将创立对象的细节(如何实例化对象,然后做什么样伊始化操作)隐藏起来。

客户传递给工厂一些大致的参数,即使参数符合业务规则,则工厂可以在里头创设出一个应和的小圈子对象回来给客户;但是倘诺参数无效,应该抛出格外,以有限襄助不会创建出一个不当的靶子。当然也并不一连须要通过工厂来创立对象,事实上大多数景况下领域对象的开创都不会太复杂,只必要简单的采取构造函数就足以了。隐藏成立对象的利益:可以不让领域层的事务逻辑败露到应用层,同时也减轻了应用层的承担,它只要求简单的调用领域工厂创设出希望的靶子即可。

7.8. 仓储(Repository)

储存被设计出来的原由:领域模型中的对象自从创办后不会直接留在内存活动,当它不活动时会被持久化到DB中,当要求的时候会重建该对象。所以,重建对象是一个和DB打交道的长河,须求提供一种机制,提供类似集合的接口来赞助我们 管理对象。

积存里存放的目标自然是集结,因为事先提到的小圈子模型是以聚众的概念来划分边界的。大家 只对聚集设计仓储 ,把全体聚合看成一个完全,要么一起取出来,要么一起被去除,不会单独对某个聚合内的子对象开展独立查询和更新。仓储还有一个重视的风味就是分为仓储定义部分和存储落成部分,在圈子模型中定义仓储的接口,而在基础设备层落成具体的蕴藏。

8.布署领域模型时一般步骤

  1. 基于需要建立开头的圈子模型,识别分明的圈子概念和之间的涉及(1:1,
    1:n的关联),用文字规范没有歧义的叙说出各种领域概念的意义;
  2. 剖析重点的软件功效,识别关键的应用层的类,那样有助于及早发现什么样是应用层的任务,哪些是天地层的职分;
  3. 尤其分析世界模型,识别出实体、值对象、领域服务;
  4. 浅析关联,通过对事情的长远解析和软件设计原则及品质方面的权衡,明确关系的动向,去掉一部分不需求的关系;
  5. 找出聚合边界及聚合根,在条分缕析进程中会出现麻烦清洗判断的接纳题材,那就凭借平时分析经验的聚积了;
  6. 为聚合根配置仓储,一般情形下为一个会晤分配一个存储,此时设计好仓储的接口即可;
  7. 遍历所有场景,确定陈设的小圈子模型能一蹴而就缓解事情必要;
  8. 设想什么创造实体和值对象,是透过工厂照旧构造函数;
  9. 重构模型,寻找模型中有疑点或不佳的地点,比如思考:聚合的宏图是还是不是科学,模型的性质等等;

领域建模是一个连发重构,持续完善的进度,大家会在议论上校变化的部分显示到模型中,从而模型不断细化并朝正确的倾向走。

9. 参考

本文是阅读学习 汤雪华的博客 后所做的有些疏理,希望能对大家有所帮忙~