SaaS,RPA,WMS,智能制造,MES
2024-03-09
标杆企业,创业,智能制造,大数据
2024-01-09
开发平台,智能制造,RPA,SaaS
2024-01-04
软件设计,生产力工具,开发平台
2023-07-01
本文是以乘用车制造典型工艺为例,详细阐述汽车行业 MES 的个性化需求。对于乘用车整车厂来说,冲压、焊装、涂装、总装四大整车工艺车间的MES应用各有侧重。 01 冲压车间主要通过对卷料、板料、冲压自制件的出入库信息以及各冲压线体的生产信息和品质信息进行记录,以及时、准确地对车间内各种数据进行汇总和分析,从而提高车间可视化水平,为管理者生产决策提供客观可靠依据。02 焊装车间 MES 功能覆盖从生产计划编制、下发到执行、跟踪与统计分析的全过程。同时,通过 MES与车辆自动识别(AutomatcVehcleIentfcaton,AVI)系统的集成,以及对生产过程中质量、物料数据的记录,使管理人员能时刻洞察车间内的各项业务活动,为生产的持续改善提供强有力保证。03 涂装车间MES 功能覆盖计划管理、品质管理、系统集成、作业指示、统计报表、异常情况处理等,通过与AVI(车辆自动识别)系统集成,可以实时了解从 WBS(白车身缓冲区)到涂装完工的车辆队列,使涂装管理人员能时刻洞察车间内的各项业务活动,帮助提高生产效率和产品质量。04 总装车间MES 功能覆盖计划编制与下达、作业指示、车体跟踪、品质管理、统计报表、异常情况处理等。同时,与AVI系统集成,实时掌握PBS车辆队列信息;与多种类型的自动化设备的系统集成,使总装人员能时刻了解车间内的各项业务活动。 同时,对于各生产线来说,乘用车MES主要包含以下功能。1.作业计划管理(1)按照一定的约束条件进行生产排程和优化形成作业计划,考虑生产均衡化、批次、不同的车间设置不同的生产顺序规则等。(2)跟踪作业计划的执行情况,计划完成后将相关信息反馈给ERP。 2.生产过程管理(1)从生产作业计划单中获取车辆识别号(Vehcle Ientfcaton Number,VIN)码,用于车辆跟踪。(2)生产装配清单,细到工位。(3)通过对 VIN码的扫描,实现从焊装到整车完成全生产过程的跟踪。(4))生产线状态LED显示。(5)工序能力分析。(6)在制品跟踪查询。(7)生产过程中发生的重要事件,以邮件等形式分级自动通告。 3.物料管理(1)针对不同的物料采取不同的调度模式;对于自加工部件,同步生产供应;大件物料,通过现场终端直接通知供货部门供货;小件物料,看板拉动;低值易耗品,达到线边物料上限时,自动发出补货指令。(2)同步化物料补货,支持电子看板、呼叫、序列和KIT(单台套)等物流运作方式。支持缺料报警以及投料原因的分析,并能够对其进行追踪。(3)能够实现关键物料追溯和物料防错,并能进行零部件匹配判断。(4)通过条码扫描建立重要零部件与车辆VIN的关联。(5)实现对物料的个体和批次在生产在线推移、传递、消耗、转化等信息进行采集、记录、跟踪、整理、分析和共享等信息管理功能。(6)与仓库管理系统(Warehouse Management System, WMS)建立数据通信,在发货环节为WMS系统提供信息支持。(7)PBS信息驱动生产车间预装、物料暂存、供应商发货。(8)支持无线呼叫。(9)支持新品切换的控制以及对物料的操控。4.质量管理(1)质量追溯(关键件与VIN 绑定),通过扫描条码,实现关键件数量可增减。(2)装配指导,装配防错。(3)SPC在线信息查询与报表生成,采集数据后,经过系统分析后生成相应的图表,不同权限人员可查看不同图表。(4)建立历史数据库对质号制和设备状态等信息进行分析,并通过数据字典对历史数据进行自动处理。(5)零件试装信息共享,试装信息(质量工艺产品供应商技术援助—Suppler Techncal Assstance,STA)分类后发布给指定的人员。(6)整车生产履历记录,包括订单号、生产线、物料、质量、装配人员和班次等详细信息。(7)装配缺陷次数报警,实现质量领导体系(Qualty Leaershp System,QLS)系统输入的质量问题按触发等级自动报警的功能,同时将报警信息以邮件或短信方式发给相关人员处理。5.其他(1)车辆自动识别系统(AVI),识别车体在车间内的实际位置。(2)物料呼叫安灯系统(Anon),通过在生产工位旁的物料呼叫请求按钮实现物料呼叫,在生产现场和物料存储区设置信息显示板,反馈生产线物料呼叫请求,操作员根据呼叫请求送料。(3)品质异常呼叫安灯系统(Anon),利用声音和视见至现当刖生产线工作状态,实时显示工位异常,以便相关的人员及时做出响应。小结 汽车制造企业的管理重心在于保证生产过程的稳定性与持续性。汽车制造企业多采用JIT生产方式,因此非常注重物料的运输、追踪、管理以及各车间的及时排产。企业在选择 MES方案时应着重考虑如何实现精益化的混流生产管理。 END 声明:本文及素材系转摘自互联网公开文章,著作权归原作者所有,仅为学习参考。千妙导读从我们作为业务开发主要的职责深入到DDD的本质是什么?复杂度应处理?规范设计怎么做?本文将全方位为大家解答。一、作为业务开发,我们的主要的职责是什么的业务开发的职责在文章的开始我想和大家一起思考一个问题:作为一个工程开发,我们最主要的职责是什么? 我极度认可 >文章的观点 - 切实解决业务问题才是每一个工程开发最主要的职责 - 所以每个业务开发都必须要结合业务的视角去思考自己系统的建设和发展,而不是只是做一个“编程的”码农。这里摘录一下文章中要点技术一号位是负责使用技术能力解决业务问题,提供稳定可靠的技术支撑;负责向业务各方提供各种必要的技术支撑,通过合理的数据分析为业务决策提供依据;通过对技术领域的积累和发展,通过业务领域的理解和落地影响业务决策;负责构建梯队完整、能力全面、制度完善的技术团队来支撑业务发展。文中也提到了虽然不是每个人都负责一块完成的业务,也不是每个人都带领团队,但是至少每个人都是自己所负责的那块系统的技术一号位。业务在实际开展中遇到的问题那实际业务开展中,业务到底会遇到有哪些问题呢?我们按业务的生命周期进行切分,然后具体查看每个业务生命周期的诉求:业务启动期:业务能力快速搭建 - 系统提供快速试错的能力业务发展期:业务能力扩展 - 系统需要支持原来越多的业务功能业务平台期:业务能力复制 - 系统需要支持原来越多的业务场景业务衰退期:业务能力创新 - 系统提高生产力延长业务的生命周期我们技术要做的事情是:在业务验证没有问题的情况下,如果尽可能的延长业务的发展和平台期,让业务获取的利益最大化。所以为了支持业务的发展,业务的本身的功能支持诉求以及业务对技术的要求也会越来多,在这种情况下考验软件开发人员的一个非常关键的能力就是: 软件复杂度的控制的能力。软件复杂度软件复杂度其实是一种多维度的概念,其可能来源于多个方面,前阿里资深技术专家李运华在他的《从0开始学架构的》课程中从6个方面阐述了软件复杂度【2】,列举如下:高性能单机性能集群性能高可用计算高可用存储高可用可扩展性低成本安全规模业务规模系统物理规模二、DDD的本质是什么DDD本质上我认为就是一种减低软件复杂度的手段, 其推荐的方法论可以适用于上面包括了业务规模,可扩展性两个维度的复杂度应对。其实业务规模的复杂度的处理包括了对可扩展性的支持。DDD实施给系统之后,我们依然需要关注系统其它的复杂度,这里列举一些示例措施:容量规划架构设计数据库设计缓存设计框架选型发布方案数据迁移、同步方案分库分表方案回滚方案高并发解决方案一致性选型性能压测方案监控报警方案那么我们进一步对业务规模的复杂度进行拆解,又分为下面两类:1、领域复杂度领域模型描述问题域的准确性2、技术实现的复杂性代码没有按照业务绑定的”分析模型”去编码,软件变成一个大泥潭软件的可扩展性较差软件变成面向过程分层不合理没有规范那DDD是如何处理上面提到的软件复杂度的?提供了一个领域划分的方法:让软件系统产生边界。提供一个一系列的战略模式:限界上下文的映射,分层架构等。提供一个一系列的战术模式:如何规划领域层 内部DDD不是什么?不光光只是一种编程方法不光光只是一种架构风格不具体指导如何具体建模三、复杂度处理-领域模型描述问题域的准确性DDD的原名是模型驱动的设计方法:通过领域模型(Doman Moel)捕捉领域知识,使用领域模型构造更易维护的软件。合理性证明DDD的核心思想,大家都清楚,就是分析模型要和代码模型保持一致。 那么如果不保持一致到底会产生什么样的负面影响如果技术实现和业务实现不在用一水平线上,那技术模型的行进路线只会考虑劈开技术障碍并且可能会撞在未来的业务障碍的墙上。这样就很容易出现,业务持续演进等技术想实现的时候,却发现当前的实现依赖于“业务不会这样发展”的假设上。这也是为什么会出现现在众多业务需求,技术无法实现或者是需要花大量时间去实现的原因。但是如果技术和业务通过统一语言打破知识的壁垒保持一致,那么如果后面技术遇到问题即是业务碰到的问题,业务人员需求的变更和迭代会自然而然的帮助技术同学越过一些门槛。也就是说业务方与技术方参与到对方的工作中,就在双方之间带来了更好的协同,形成1+1>2的功效。什么是问题域根据百度百科的解释【3】 在软件工程中,问题域是指待开发系统的应用领域,即在客观世界中由该系统处理的业务范围那么问题域内的组成是什么呢?就是我们的域模型。 这里直接摘抄一段前阿里P10"阿白"在阿里内部发表的域模型的观点:域模型(oman moel)英文又称为问题域模型(problem space moel)。维基百科(Wkpea)对它的定义是” A conceptual moel of all the topcs relate to a specfc problem” 可以翻译成:“域模型是针对某个特定问题的所有相关方面的抽象模型”。这个定义有几个要点:第一是“特定问题”, 也即是说域模型是针对性某个问题域而言的, 脱离的这个特定问题,域模型的构建其实不存在一个最优或者是最合理的构建。第二是抽象, 域模型是一个抽象模型, 不是对某个问题的各个相关方面的一个映射, 也不是解决方案的构建。 如何实现问题域的分析在 DDD 中,Erc Eans 提倡出一种叫做知识消化(Knowlege Crunchng)的方法帮助我们去提炼领域模型。简单来说就是五个步骤:关联模型与软件实现;基于模型提取统一语言;开发富含知识的模型;精炼模型;头脑风暴与试验。开发人员和业务专家在一起通过一个个业务用例仔细讨论应用程序的应用场景,从而使得业务人员深刻理解业务知识,开发人员和业务人员就重要的业务概念建立起统一的语言,开发人员将这些概念根据业务用例的上下文抽象出模型,并且这些模型将会最终成为最终软件实现中的领域模型。随后随着更多的业务用例的输入,开发人员和业务人员会逐渐对已经构建的模型进行精化,并且也会用新的用例去检验之前构建模型的合法性和适用性。DDD在这一步其实没有给出详实标准的如何建模的方法,毕竟建模还是来自于每个人的世界观,其过程还是倾向于经验的。但是还是有不少人总结一些标准的建模方法论例如:1 四色原型法 http:apframework.com20200322-color2 用例分析法 https:bake.bau.comtem%E7%94%A8%E4%BE%8B%E5%88%86%E6%9E%902859078?fr=alan问题域的拆分大家应该发现上面的知识消化的流程是一个非常耗时和复杂耗脑力的过程, 涉及到产品,业务,技术等多方团队, 所以为了让有限的资源投入到最最核心的子域,我们需要对问题域进行这份,把重点的精力放到最核心的领域上。核心领域一定是业务价值最高的,而非技术难度最高或者是基础设施框架部分。 要切分问题域,首先需要了解问题域的种类:1 通用域: 非应用独有的,多个应用都会有的功能。例如发送邮件,触达等2 核心域:和竞争对手区别开来的区域,或者是在市场上被赋予了竞争优势的区域。3 支撑子域:其余的区域如何确定核心域,这里有几个提示:系统哪部分最难用手动处理过程阻止了他们进行了根据创造性, 有附加值的工作哪些修改能提高收益哪些修改能提高运营效率取哪些提示,取决于业务系统的性质。那如何决定支撑子域通用子域,以及支撑子域通用子域的切分呢?目前在我查阅的资料中,还暂时没有人提及到具体的操作方法,感觉主要还是依靠经验主义在做划分。我个人总结了一个方法,主要就是就是关注业务的核心实体和核心流程。以核心实体和核心流程作为切分支撑子域的基础。核心实体:核心实体是存在于核心流程中,对核心流程的决策和扭转可能起到关键的作用。有的时候业务上为了能让核心实体在业务流程中起到更大或者更高效的作用,会添加一些让核心实体更好服务于业务流程一些业务功能,从而使业务实体从整体上看变得相对复杂,这个时候我们应该以核心实体为基础进行切割,把所有和核心实体CRUD相关的操作还有让其变得更高效的业务功能划分为单独的一个领域。核心流程: 当某个业务流程足够复杂也可以当成一个子域。在实现领域驱动设计【4】书中,提到了为在线拍卖网站系统划分问题域的一个例子,我们以此来验证上面等构想划分子域卖家 + 会员身份:这两者都是核心实体,网站可能为了让促进会员能够多参与拍卖可能提供了分层,或者积分等工功能。网站为了能让卖家能够更加提供更加有拍卖价值或者是转化率高的品类可能为卖家提供了数据分析等业务功能。 名册:这也就是核心实体,网站会对名册提供一系列拍卖相关的功能,例如倒计时,一口价等,所以也需要形成一个领域。 拍卖:网站最核心的业务流程,核心域无疑。争议解决:买卖家的售后冲突解决流程向来很复杂,所以会独立成为一个域无疑。四、复杂度处理-进一步降低问题域的复杂度-限界上下文限界上下文的诞生背景一般情况下,一个复杂系统由一系列的模型来表示解答域, 理想状态是一个子域一个模型。但是有些当业务需要且系统复杂的时候,一个模型可能被多个域共享,这个时候这个模型的概念可能变得不清楚。因此为了保护这些模型概念的完整性, 清晰的定义模型的责任边界很重要。实现领域驱动设计【4】书中举了下面这个例子:为了维护模型的概念的完整性,最直观的方法就是为这个模型化一个边界,e.g. 这个商品所表现的意思就是履约的时候用到的"商品",而不是下单的时候的"商品"。只要有一个这样的边界定义,系统就会但是出现多个边界,毕竟"商品"在不同业务上下文中有不同的含义, 例如库存域的货品,物流域的运输品, 价格域的商品等等。这样的一个边界就是DDD的“限界上下文”。 限界上下文给人直观的感受其实和子域很像,我很早以前曾读过一些关于微服务的书籍,也提到过要把DDD中的限界上下文作为微服务划分的重要依据。这里其实就给我很大的疑惑:1 限界上下文到底是怎么划分的?我们划分限界上下文难道真的是用一个基础概念,然后找这个基础概念不同的“上下文”吗?2 限界上下文和子域到底区别是啥?限界上下文的本质DDD理论中提到了DDD的四个边界 所以在DDD中是把限界上下文作为某个子域的内部模块的划分,其实无论是子域的划分,限界上下文的识别,和聚合的划分他们的本质是一样的,他们都是对复杂问题的分解之后,然后归类分组。只不过“聚合”面向的是领域层内部,“领域”划分面向的是业务问题域,而“限界上下文”面向的是解答域,但是我跟倾向于把限界上下文理解为更加深一层次的业务问题域的划分,而不是面向的解答域。 如果这样看的话,那么其实就可以回答上面的疑问, 领域和限界上下文没有本质的区别,就像树的父节点和字节点一样都是树节点。而限界上下文的划分完全可以使用子域划分的理论。(可以回顾下上面问题域拆分的段落)上下文映射上下文的映射是什么, 简单来说就是描述不同上下文之间的关系的描述。举个例子DDD对于限界上下文直接提炼了几种方式,这里这边阿里内部文章《领域驱动设计:软件复杂性应对之道》解释的比较好,描述如下:share kernel共享内核 share kernel :通常是共享核心领域或者是一组通用子领域。customersuppler客户供应商关系 customersuppler:上下游关系。不同客户需要协商来平衡,上游团队需要有自动测试套件。conformst跟随者模式 conformst:单方面跟随模式。上游的设计质量较好,容易兼容,可以采用严格遵循上游团队的模型。antcorrupton layer防腐层 antcorrupton layer:防腐层、隔离层,使用 facae or aapter 等模式。可以减少其它系统变动对本系统的影响。separate way各行其道 separate way:声明一个与其它上下文毫无关联的 boune context,使开发人员能够在这个小范围内找到简单、专用的解决方案。open host serce开放主机服务 open host serce:开放子系统供其他系统访问。其核心思想是开放出一个标准的各个领域都认可的协议,减轻各个领域实施ACL的负担和成本。publshe language共享语言 publshe language:把一个良好文档化、能够表达领域信息的共享语言作为公共的通信媒介,必要时在其它信息与该语言之间进行转换。在当前电商领域的范畴,目前我个人觉得只有ACL,Seperate Way, publsh language 有比较好可行性,其他的关系都不是很靠谱:share kernel:如果使用共享二方库,谁来维护这个二方库,如何防止在不同上下文使用不同kernal版本所带来的问题。 如果一定能保证share kernel的维护在一个团队内,且所有使用share kernel版本一定能保持一致, 那是可以使用的。 customersuppler:我曾经因为汇率包升级而去重构一个应用,因为汇率包变更太大,且应用没有防腐层,所以不论从开发还是测试都是非常痛苦的过程。conformst:和customersuppler类似, 但是在互联网领域没有靠谱的设计, 只有有人维护和没有人维护的设计。conformst从长期来看其实就是customersuppler。Open Host Serce 没有任何一个领域保证自己的接口一定不会变,就算不会,其他领域的同学会相信吗,他们会忍住不用ACL吗?如果他们用ACL,OHS的意义何在?publsh language 目前阿里内部MTOP,TOP等协议正是使用这样的协议。另外限界上下文之间真的能够随便无规则无条件的互相依赖,互相调用吗?在下面的章节将会解释论述。五、复杂度处理 - 分层不合理架构分层主要的作用就是关注点隔离,如果和今天的话题联系起来就是领域模型和技术的关注点隔离(领域和存储,领域和展示)。传统的三层架构这种传统架构的缺点1、业务逻辑层和数据访问层有明显的耦合。 2、没有领域的概念,所有的逻辑沉淀到serce中。所以传统架构只能针对小型的,没有过多的业务逻辑场景。由于这种架构能够保有领域能力的沉淀,所以在现在电商业务场景基本不会被使用。六边形架构Alstar Cockburn在 2005 年时演示了 六边形架构从六边形架构开始,其强调了领域模型。并且确立了领域模型的核心位置,以及其不应该依赖于其他的层次。六边形架构也强化了适配器的概念,其还把适配器分类为nput适配器,和output适配器。所有nput适配器用于对接不用的外部请求形式, 所有output适配器用于对外部的依赖 (e.g. 数据库, 外部服务,内存调用等)这种结构模式树立了以领域模型为核心的先河,但是其忽略了在领域层中跨模型业务逻辑的实现方式-领域服务的沉淀。这也间接导致了其需要强化应用层,并且通过应用层和output适配器的联合去完成一些可以应该在领域层应该完成的事情。 洋葱架构洋葱架构的提出更加进化了一步,推出了域服务层,并且支持域服务层是支持了那些需要多个领域实体联合中作用的领域逻辑. 其层次由外向内依次是领域模型,领域服务,应用服务和外层的基础设施和用户终端。其依赖的关系也只能是由外向内. 在洋葱结构中其把存储层,文件系统和网络服务放到了基础设施层。由于基础设施和用户终端一样在最外层,所以洋葱架构也提倡用依赖倒置来解决应用逻辑和基础设施的耦合问题。洋葱架构的架构图从其依赖顺序上来看,其依赖应用层必须先依赖域服务层,再依赖域模型层, 这样很容易造成领域模型的逻辑外泄到领域服务层,造成领域模型变成贫血模型。DDD 架构DDD的架构大家都非常熟悉了,领域服务和领域模型都归属域领域层。适配层依赖域应用层,应用层依赖域领域层,也可以直接直接调用基础设施层(大多数是查询场景)。领域层理论上不依赖于任何层次,其通过依赖倒置和基础设施层产生关联。在DDD架构中,应用层是可以通过直接访问聚合根(某个实体类),并进行方法的执行和操作的。应用层也可以直接访问基础设施层。可以看出DDD的架构其实更加的贴切实际一些。 上面这张图也很好的阐述了DDD各个架构层次依赖的关系。CQRS很多情况产品构建出来的数据展示,需要横跨几个领域的数据的支撑,也就是我们日常构建的大宽表,在这种情况使用CQRS模式可以完美解决这个问题。其主导视图模型和领域模型分开,让领域模型更加专注业务逻辑,流程和规则而非业务视图。 CQRS的思想很简单,就是把服务中对数据的更新操作(Comman)和读取操作(Query)分离, 一部分逻辑只处理和数据更新有关的业务,另外一部分只处理和数据读取有关的逻辑。这种处理方式,可以让我们辛苦构建的领域模型不被业务中所需要的这类视图需求所干扰。 CQRS 的两种实现方式基于eent- sourcng不基于eent - sourcng以上的图片摘自于文章《CQRS模式及其应用》我们团队里面的架构实践在我们自己的应用中我们构建了基于COLA【5】规范的层次架构,如下图: 我们也对自己的架构定义的一些额外的规范:1、依赖关系(除了依赖倒置)只能是从上当下;2、同层之间永远不能互相依赖;3、如果同层之间需要互相用到对方的服务,那么就需要下沉出一层。例如在上图中,我们的业务层就分为了两层 "Executor"层次和 “Hanler”层此, Hanler层次用来保存业务的一些通用逻辑。六、复杂度 - 软件变成一个大泥潭从这一章节开始介绍DDD的"战术模式",也就是向大家介绍DDD是如何构建和组织自己领域层的。值得一提的是在DDD中,领域的划分, 领域层次的建立, 领域之间关系的建立我们一般叫做DDD的"战略模式",而此章节提到的值对象,实体,域服务,工厂,repostory, 聚合聚合根, 领域事件等都是DDD的战术模式。战略模式的重要性是要远大于DDD的战术模式的,我们如果在领域划分,领域通信协议,分层方面没有大的问题, 那么即使再糟糕系统整体也还是可控的。 在领域层面, DDD通过聚合聚合根的概念来划分单个领域中的类似于类集合的边界,从而降低单个领域层的复杂度。DDD通过实体,值对象,领域服务,repostory, factory 来规划集合内部的类组织, 另外DDD也通过领域事件来处理领域之间的交互,来匹配异步和需要解耦的业务场景。实体当我们需要考虑一个对象的个性特征,获取需要区分对象的时候,就需要引入实体。一般我们发现实体概念,是在和业务产品人员或者领域专家讨论发现的那些需要有唯一标示性或者生命周期连续性很重要的时候。举个例子加入用户需要预定酒店,如果领域专家说了我们定了A酒店了,就不能定B酒店了,哪怕A,B其他的属性完全一样。从领域专家扣中我们可以识别出酒店是有唯一标示性的,且哪怕A,B属性一样,也不能认为A,B 是一样的,这也说明了酒店的唯一性不是从属性来的。这两点我们可以推断酒店是一个实体。唯一标示性可以是现实有意义的,例如工商注册号,也可以无现实意义,例如数据库主键。 实体建模的注意点1、为实体分配唯一标识符现实意义标识符人工生成的标识自增guuu数据库主键自定义sequence2、验证和不变行实体必须自己负责自己保持自己状态的合法性 (alaton) 和不变性(Inarants)。他们的区别是合法性是根据上下文的,而不变性是不用考虑上下文且必须正确的。例如酒店必须有房间这个就是不变性,而酒店的营业时间就是alaton. 一般使用规则和规约模式来实现alaton和narants。规模模式: https:bajahao.bau.coms?=1717403406288752234&wfr=sper&for=pc3、聚焦在行为,而不是属性状态不要暴露属性给外面,如果外面得到属性,很可能就自己实现了一些领域逻辑,那么领域逻辑就外漏了。 4、把一些行为逻辑下方到值对象中需要警惕实体逻辑膨胀,从而混绕了实体所要表达的概念。 例如预定是一个实体, 现在要加上逻辑预定的天数不能小于N天。这个时候我们可以为Bookng 抽象出 Stay 对象,让Stay对象去管理规则逻辑。而不是让预定这个实体去做。让预定只关注预定。 5、不要为世界建模不要过度设计,只要满足需求就好。不要让技术需求污染领域设计,除非真的万不得已。6、分布式的设计不需要让领域概念横跨多个boune context, 如果我们域模型所涉及的概念横跨了,我们就需要用两种设计方法.只是用引用alue objects值对象什么时候需要使用到值对象?概念需要凸显的时候。 e.g. 拍卖系统的能够一口价获取拍卖的价格, 就算是我们用一个nt 就能表示也需要用类来凸显概念publc class WnnngB{...publc nt Prce { get; prate set; }...}表述一个描述性的,但是没有实体编号的概念的时候。 值对象的特征无标识:他们只是标识对象的属性。基于属性的相等性: 所有的属性值相等即值对象相等富含行为:值对象实现业务概念的抽象,其也有自己的行为内聚:将不同的相关属性组成一个概念整体,例如Money, 是由一个long 和一个currency组成的不变性:值对象是不变的对象,如果需要改变属性,那最好是建立一个新的对象并且进行值对象替换。如果一定是需要改变,那就需要考虑设置为值对象是否合理。不变性是值对象非常重要的一个属性,是可以保障值对象不会被"坏味道"代码侵入的一个原则之一。 例如如果一个值对象引入了另外一个类实例, 另外一个值对象也引入了相同的类实例, 如果值对象允许改动,当一个值对象对这个类实例的内容进行修改,势必会影响另外一个值对象。 所以最安全的方式还是通过对象替换的方式。域服务 什么时候用域服务发现和多个实体相关联,但是放入任何一个单独的实体都不适合,这个适合用域服务.域服务应该包含什么内容域服务应该包含业务系统流程和业务规则,不应该包含技术的元素在内,技术的元素都应该在业务服务(Applcaton Serce)中实现。应用服务与领域服务的区别:一些可以在网上搜索到的老生常谈:应用服务里不要处理业务逻辑,只在领域服务里处理业务逻辑。(如何判断某段逻辑是否是业务逻辑?)领域服务掌握领域知识,而应用服务只是对领域服务的编排。应用服务是领域服务的客户方,也就是说应用服务会调用领域服务里的方法。当领域中的某个操作过程不属于实体或者值对象的职责时,需要将个操作放在领域服务中。而且确保领域服务是无状态的(这句话很有意思,也就是说领域服务中不应该有任何记录状态的行为,在任何情况下调用这个服务,它都不会有副作用,也就是说它是个纯内存操作)。领域服务中包含的是业务逻辑,而应用服务关注的应该是安全和事务等非业务逻辑。对事务的管理绝对不能放在领域服务层,事务管理需要放在应用服务层。因为和领域模型相关的操作的粒度都很细,无法用于事务管理。而且领域模型也不应该意识到事务的存在。通常的可以放在应用服务中的逻辑有:参数验证、错误处理、监控日志、事务处理、认证与授权。除了第一条之外,上面的条例只是举出了应用服务与领域服务两者非常易于告之的差别,但是会有一些“业务逻辑”比较难以取舍, 例如例如转账操作:A ->BA.accountDecrease(10);B.accountIncrease(10);我们在现在可以非常肯定的说上面的转账一定在领域服务,因为"转账"就是一个领域概念。但是如果假设世面上所有的银行以前只有存钱和取钱两种功能,"转账"是一个新概念和业务的时候,技术就没有那么容易判别转账是一个临时性的一次性的需求,还是会长久发展。这个时候技术有两个选择:1、构建转账域服务,让应用服务调用域服务2、让应用服务获取A,B的实体,然后在应用层直接调用方法,在应用层做事务保持一致性。如果域能力在其他团队手里,我相信大多数的团队会使用第二种。那遇到这种情况我们到底应该怎么办?我个人的意见和阿里前技术高级专家张建飞在他的文章《一文教会你如何写复杂业务代码》的观点保持一致:我们在新逻辑出现难以判断的时候优先讲能力放入到app层,如果我们发现会有第二个业务场景使用到了相同的能力,就需要考虑是否应该把此能力下发到领域层以增强内聚性和复用性。工厂只负责复杂逻辑对象的构建,让构建逻辑中心化减少外部对象对构建对象内部变量的理解工厂方式不是在任何构建对象的时候使用,一定用在对象构建逻辑复杂,有子依赖或者是有narant规则的场景。 Repostoryreponstory主要用来处理集合根的存储和获取的。提供一个facae接口且是面向oman层的,是oman moel和ata moel的桥梁。其最大的作用就是通过反向依赖的方式充分隔离数据层和领域层。Repostory最常见的用法是被applcaton serce层去使用获取聚合根。在repostory实现中,我们一般会有下面的一些逻辑:unqe ID 的生成数据库的操作数据模型到领域模型的相互横跨多个数据模型构建出一个实体模型。repostory的反模式定义出比较通用化的接口, e.g.Lst fnBy(CusomterQuery query)使用了延迟加载,延迟加载就是设计错误的标志, 有可能说明我们聚合的边界不催。 不要为了报表的诉求使用reponstory, 领域的case和业务报告很不一样,可能需要多个聚合的数据,这种情况可以考虑用一个离线的store去做,和其他的读服务去做,不见得一定需要用领域的Repostory模式。领域事件领域事件所想要解决的问题其实和metaQ消息机制想要解决的问题一致,都是跨领域驱动型业务逻辑实现的最佳方法,让领域和领域之前解耦。领域事件消费教科书的说法是可以在领域层, 也可以在应用服务层, 但是我觉得领域消息如果用metaQ是这样的消息中间件去实现的话,那用领域层和应用服务层去消费就不是很方便,有可能破坏一些分层原则。所以我个人倾向于在aapter层去承接消费,统一化掉。当前可以实现领域事件和消费比较方便的工具有:google guaa - EentBusCOLA框架 - 事件支持聚合聚合根聚合是什么?其实聚合的原理和领域划分,限界上下文划分的原理是一致的,都是为了通过归类分组的方式让整个系统宏观上 N * N 的关系复杂度减低为 T * T 的复杂度。 T远小于N。 聚合前: 聚合后如何划分聚合1、根据业务规则和不变量来决定。例如 customer 聚合是有一套业务规则来维持的,例如信用卡要存在,必须先有一个customer, 有customer 必须有aress, aress必须有coe.2、强关联的对象应该放在一块。什么是强关联,那就是必须生命周期是一样的。例如customer和cretcar在,电商网站中,如果customer被删除了,那么他的信用卡也应该被设置为失效的。而订单和客户不一样,客户下了个订单,然后客户注销,但是订单还是一直存在的。所以customer 和 cretcar 在一个聚合中, 而用户和订单则不在。订单里面可以有客户的ID或者是一个值对象。 3、灵活设置:有些可以根据业务情况,进行可以灵活的设置,下面列举一个论坛系统,帖子和回复聚合思考的例子:大家都知道一个帖子有多个回复,没有帖子,回复就没有意义;所以很多人就会认为帖子应该聚合回复;但实际上不需要这样,如果你这样做了,那对于一个论坛来说,同一个帖子被多个人同时回复的可能性是非常高的,那这样的话,多个人同时回复一个帖子,就会导致多个人同时修改同一个帖子对象,那就导致大家都回复不了,因为会有并发冲突或者数据库事务的等待超时,因为大家都在修改同一个帖子聚合根;实际上如果我们从业务规则的角度去思考一下,那可以发现,其实帖子和回复之间,只有一个简单的规则,那就是回复一旦被创建,那他所对应的帖子不能被修改即可;这样的话,要实现这个规则其实很简单,把回复作为聚合根,然后把帖子传入回复聚合根的构造函数,然后回复保存帖子ID,然后回复将帖子ID设置为不允许外部修改(prate set;即可),这样我们就实现了这个业务规则,同时还做到了多人同时推一个帖子回复时,不会对同一个帖子对象就并发修改,而是每个回复都是并行的往数据库插入一条回复记录即可。-- 摘自阿里内部文档>聚合设计的原则聚合是用来封装真正的不变性,而不是简单的将对象组合在一起;聚合应尽量设计的小;聚合之间的关联通过ID,而不是对象引用;聚合内强一致性,聚合之间最终一致性;什么是聚合根聚合根就是聚合的入口,聚合外部只能通过聚合根和聚合内部通信。由于聚合外部只能通过聚合根和聚合内部通信, 这也就意味着外部不能操作除聚合根以外的任何类进行数据库操作,因为这样有可能会导致破坏业务的规则。举个例子,一个汽车四个轮子,如果我们用 Repo 直接操作轮子,对轮子采取elete,而这个时候汽车对象的状态却可能是 "runnng".如何选出聚合根1、聚合根一定至少有一个对应的atastore 2、聚合根一定更够完全描述一组后者多组业务规则(narant)。绝对不会存在一个业务规则需要多个聚合根联合作用才能做判断的。3、聚合根一定有自己的独立的生命周期。 七、规范设计项目应用的规范设计的长期价值一定是不可忽视的,规范就相当于一个架构内部组件的收纳的容器,架构指定了这些组件在逻辑上的组织形式,但而规范则是则是妥妥的物理组织形式。如果没有合理清晰的规范设计,项目很快就会因为个人开发习惯的不同,导致物理结构混乱,给接下来的应用项目的维护和扩展产生影响。规范设计总共分为两类:放对位置程序架构目录贴好标签类名约定方法名约定错误码约定Doman Eent约定测试约定下面是我们小团队参考了阿里COLA框架建议的命名规范做出的开发规范:程序架构组织层次包名功能Aapter层web处理页面请求的Controllermtop处理mtop的请求hsf处理hsf的请求scheuler处理定时器的请求message处理消息的请求App层executor处理request,包括comman和queryconertor包含转换层类的目录nterceptor包含拦截器目录extpont扩展点目录extenton扩展实现目录hanlerapp 层的一些中间处理逻辑Doman层moel领域模型ablty领域能力,包括DomanSercegateway领域网关,解耦利器extpont扩展点目录extenton扩展实现目录Infra层gatewaympl网关实现mapperbats数据库映射confg配置信息Clent SDKap服务对外透出的APIto服务对外的DTO类命名规范种类对象示例API class增删改服务入参XXXCm. e.g. MetrcsRegstratonCm查询服务入参XXXQry. e.g. LstAllMetrcsQryAPI serceXXXSerceI.jaae.g. MoMetrcsAmnSerceI出参如果是无需返回返回使用Cola框架的Response, 如果是单个概念返回使用Cola框架的SngleResponse, 如果是多个概念返回使用Cola框架的MultResponse. 如果概念是某个明确的对象,例如MultResponse如果是复合对象, 使用XXXResult 例如MultResponse领域层实体XXXE.jaa值对象XXXV.jaa工厂XXXFactory.jaaReponstoryXXXRepostory.jaa域服务XXXDomanSerce.jaa防腐服务XXXGateway.jaa枚举XXXEnum.jaa应用层命令执行器XXXXCmExe.jaa查询执行器XXXXQueryExe.jaa拦截器XXXInterceptor.jaa扩展接口XXXExtPt.jaa扩展实现XXXExt.jaae.g. #{Bz}#{userCase}#{scenaro}Ext.jaa转换器XXXConertor.jaa基础设施层存储的对象XXXPO.jaa仓库实现XXXReponstoryImpl.jaa防腐服务实现XXXGatewayImpl.jaa公共层工具类XXXUtl.jaaThreaLocalXXXThrealocal.jaa其他接口XXXI.jaaSprng配置类XXXConfguraton.jaa配置属性聚合类XXXPropertes.jaa错误码规范 扩展规范使用COLA的扩展框架去实现。COLA的扩展框架的功能不在赘诉,这里讨论的是COLA框架的BzScenaro的划分。 BzScenaroprate Strng bzI = "#efaultBzI#"; prate Strng useCase = "#efaultUseCase#";prate Strng scenaro = "#efaultScenaro#";bzI: 业务,对应某个业务诉求, e.g. 新品孵化。useCase: 业务用例, e.g. 策略定义scenaro:用例下的某个场景。e.g. 定义商家事件任务, 定义小二事件任务全局业务通用实现@Extenton某项业务通用实现@Extenton(bzI=XXX)某项业务,某个用例的通用实现@Extenton(bzI=XXX, userCase=YYY)某个具体实现@Extenton(bzI=XXX, userCase=YYY,scenaro=ZZZ)参考:【1】「技术人生」专题第1篇:什么是技术一号位? :https:www.sohu.comna465299450_612370【2】https:tme.geekbang.orgcolumnartcle6605:https:tme.geekbang.orgcolumnartcle6605【3】https:bake.bau.comtem%E9%97%AE%E9%A2%98%E5%9F%9F7181289?fr=alan【4】实现领域驱动设计. 电子工业出版社:https:book.ouban.comsubject25844633【5】https:gthub.comalbabaCOLA SaaS,RPA,WMS,人工智能
2023-04-03
SaaS,RPA,大数据,人工智能,智能制造
2023-03-27
SaaS,RPA,WMS,人工智能
2023-03-22