当前位置: 首页 > news >正文

龙游建设局网站如何设计制作一般的企业网站

龙游建设局网站,如何设计制作一般的企业网站,网站建设与管理 宋一兵,网络营销推广方案策划概述本文将介绍领域驱动设计#xff08;DDD#xff09;战术模式中另一个常见且非常重要的概念 - 实体。相对战术模式中其他的一些概念#xff08;例如 值对象、领域服务等#xff09;来说#xff0c;实体应该比较容易让人理解和运用。但是我们如何去发现所在领域中的实体呢… 概述本文将介绍领域驱动设计DDD战术模式中另一个常见且非常重要的概念 - 实体。相对战术模式中其他的一些概念例如 值对象、领域服务等来说实体应该比较容易让人理解和运用。但是我们如何去发现所在领域中的实体呢如何保证建立的实体是富含行为的实体运用时又有那些注意的细节呢本文将从不同的角度来带大家重新认识一下“实体”这个概念并且给出相应的代码片段本教程的代码片段都使用的是C#,后期的实战项目也是基于 DotNet Core 平台。何为实体按照国际惯例呢我们先吹牛。直接来看看原著《领域驱动设计:软件核心复杂性应对之道》 中对实体的解释实体(Entity又称为Reference Object) 很多对象不是通过他们的属性定义的而是通过一连串的连续事件和标识定义的。主要由标识定义的对象被称为ENTITY。上面的两句话多读了几遍好像这个定义还是能够理解嘛。不像上一篇文章 如何运用DDD - 值对象 中的概念那么深奥。说白了上面就是说明了一个问题只要你所发现的事物/对象有一个唯一的标识那么它可能就是实体了。而唯一的标识就是我们代码中快写烂了的那个ID。似曾相识来想一下我们在以传统的设计思路和开发过程中我们会在什么情况下为一个对象赋予一个ID呢给它赋予这个ID的作用呢一般来说我们的目的无非就是 1、为了区分本对象如果是在数据库中那就是为了区分本条数据和另外一条数据而这个ID也往往作为主键而存在 2、加个索引吧来提升关联查找速度。所以我们如果将数据库中的表映射到我们的代码中以类的形式呈现的时候它可能就是这个样子//旅行的行程public class Itinerary{ public int ID { get; set; } //参加本次旅行的人员 public ListPerson Participants { get; set; } //旅行的地点 public Liststring Places { get; set; } //关于该行程的备注笔记信息 public string Note { get; set; } //旅行开始时间 public DateTime StartTime { get; set; } //旅行开始时间 public DateTime? EndTime { get; set; } //旅行的状态(进行中 or 已完成) public int Status { get; set; }}上面的代码对我们来说应该丝毫都不陌生我们建立了一个旅行行程的类至于为什么我们会选取旅行行程而不是各个博客都出现的以订单啊电商平台作为案例。那是因为在后期我们会一起动手来实现一个旅行记账的微信小程序并且借助于我们慢慢所学习到的DDD理论作为基础开发属于我们自己的领域驱动框架当然项目也是基于 DotNet Core版本应该是3.x。好了还是回到我们这个例子来思考一下ID出现的目的。你可能会说“这还不简单吗老夫纵横代码界多年你现在还来问我这个问题ID肯定是用来区分的呀行程千千万万我要找出这一条行程肯定需要这个ID了呀。” 是的这是一个毫无争议的问题。我们需要一个唯一的身份标识来区别对象之间的差异。DDD中实体的这一点与我们平时所接触的类的ID有异曲同工之妙所以本文开头也说了实体可能是相对其他战术概念最为让人理解的。你确定它真的需要ID吗还记得我们在上一篇文章 如何运用DDD - 值对象 中所提到过的一个问题吗“当前上下文的值对象可能是另一个上下文的实体”。所以说当前你所判定的实体一定是基于领域当前环境上下文的。脱离了该环境之后一切都将存在变数。同样的事物对象在当前环境需要一个唯一标识来识别它而在另一个环境中可能这个唯一标识对它来说是没有意义的则实体就有可能成为了值对象。请考虑下面的这个例子在一个银行业应用程序中一位顾客可能会在她的银行账户中放入100美元。当她未来某一天提取她这100美元时相较于她存进银行的钱她可能会收到不同的钞票或硬币。不过这一差异是无关紧要的因为资金的身份不重要顾客只关心资金的价值。所以在这个领域中资金无疑是一个值对象。但在另一个领域中比如涉及钞票印刷制作或钞票可追溯性的行业个体钞票或硬币的身份实际上可能就是一个重要的领域概念了。所以每一张钞票都会是一个具有唯一标识符的实体运用实体结合值对象千万不要忘记了我们上一章所学习到了的值对象在实体的内部除了它自己的唯一标识ID之外也许还有许许多多表明它属性的东西而这些东西往往可以通过使用值对象来标识。接下来让我们来改写一下上面的Itinerary类public class Itinerary{ public int ID { get; set; } public ListPerson Participants { get; set; } public ListAddress Places { get; set; } public ItineraryNote Note { get; set; } public ItineraryTime TripTime { get; set; } public ItineraryStatus Status { get; set; }}public class ItineraryNote{ public string Content { get; set; } public DateTime NoteTime { get; set; } public ItineraryNote(string content) { Content content; NoteTime DateTime.Now; }}为实体赋予它的行为当对象建立好了之后为了实现我们的业务逻辑处理我们需要对实例化的对象进行操作。现在我们为该系统提出第一个需求用户可以修改行程中的备注信息。回到我们的第一版代码中如果我们需要处理这个操作我们会怎么做呢itineraryInstance.Note this is my new note info;是不是会像上面这样将需要添加的值赋予实例化的对象呢。这种操作对我们现在正在进行的编程习惯来说是再正常不过了。那么我们来思考如果我们的项目有多处需要对“备注信息”处理呢。则对该属性的变更将被散落在代码各处。而当我们对该需求进行了一个增强验证时比如此时我们需要增加用户修改行程中的备注信息时只允许用户录入200个字以内的文本。OMG此时我们需要去查找所有散落的片段并且为他加上验证。从另外个角度来看第一个版本我们所建立的类我们无法通过仅仅查看它本身就能读懂有关旅行行程有关的业务我们仅仅知道它具有起始时间备注信息等而对他们应该如何相互作用无从所知。所以这种仅仅具有类的属性或者说以POCO呈现的类型我们称之为**“贫血模型”**。接下来我们回到第二版代码中我们为它赋予属于它的行为。从需求中我们得知了行程的备注信息是可以修改的而备注信息是属于行程的因此修改备注信息改行为理应属于行程本身。我们稍微改动代码public class Itinerary{ public int ID { get; set; } public ListPerson Participants { get; set; } public ListAddress Places { get; set; } public ItineraryNote Note { get; set; } public ItineraryTime TripTime { get; set; } public ItineraryStatus Status { get; set; } //ctor public void ChangeNote(string content) { if(content.Length 200 ) throw new NoteIsOverlengthException(); Note new ItineraryNote(content); }}此时我们为Itinerary赋予了一个ChangeNote的行为当外界需要更改备注时则只需通过调用改方法既可以实现而且当展开其他开发人员阅读此类时也会清楚的明白业务上允许用户更改200字以内的备注。但是我们依然有一个地方美中不足我想你可能也发现了属性还是对外暴露的对也就是说我们除了通过类公开的行为修改类自身的属性外我们还可以在外界随意更改。这显然不符合我们设计的初衷。因此我们可以将所有属性的set私有化。所以一定要注意我们在考虑实体的时候一定要知道“实体是高度内聚和自治的”敲重点。当然有的开发者还会尝试另外的写法让实体完全自治将上面的代码中的属性全部转变为私有的字段外界只能通过公开的行为来对实体进行处理。public class Itinerary{ public int ID { get; set; } private ListPerson participants; private ListAddress places; private ItineraryNote note; private ItineraryTime tripTime; private ItineraryStatus status; //ctor public void ChangeNote(string content) { if(content.Length 200 ) throw new NoteIsOverlengthException(); note new ItineraryNote(content); }}但是当外界需要获取该实体的值或者需要ORM映射的时候可能就不是很友好了不过你可以使用类似于像 备忘录模式 的快照方法来处理。后期我们也会采用这种模式来实现部分案例。通过将实体赋予它应用的行为所建立出来的实体我们称为“充血模型”。那么贫血模型好还是充血模型好呢很多同学肯定会说这还用问吗肯定是充血模型啦。其实这个答案并没有一个真正的答案实体自身的行为是通过我们对领域的慢慢分析可能是通过与领域专家沟通得来的如果因为为了使用充血模型而盲目的将一些不属于实体的行为赋予给它只会让实体变的更加混乱从而得不偿失。所以此时的贫血模型并不意味着一直是贫血模型后期随着领域的深入它可能会不断丰富属于自身的行为。尝试转移一部分行为给值对象保持实体专注于身份这一职责很重要因为这样会避免它们变得臃肿————这是它们将许多相关行为拉到一起时容易掉入的陷阱。实现这一专注需要将相关行为委托给值对象和领域服务领域服务也将在后期的文章中进行介绍。来考虑一下最近一版的代码我们已经将行为划分给了Itinerary了但是仔细看一看我们在后期增加需求时增加了一条验证的规则那么这个规则我们可以转移给值对象吗答案是可以的。而且转移是有必要的因为对备注的效验这一行为往往应该属于它自身。就好比机器启动时的自我效验这一行为是属于操作者还是机器自己呢所以我们来将部分行为转移给值对象优化后的代码可能是这样的public class Itinerary{ public int ID { get; set; } public ListPerson Participants { get; set; } public ListAddress Places { get; set; } public ItineraryNote Note { get; set; } public ItineraryTime TripTime { get; set; } public ItineraryStatus Status { get; set; } //ctor public void ChangeNote(string content) { Note new ItineraryNote(content); }}public class ItineraryNote{ public string Content { get; set; } public DateTime NoteTime { get; set; } public ItineraryNote(string content) { if(content.Length 200 ) throw new NoteIsOverlengthException(); Content content; NoteTime DateTime.Now; }}愿景是美好的 现实是残酷的到这里我们仿佛真的一帆风顺建立了属于自己的实体并且融合了该有的值对象实体的行为也被高度内聚在了其中。那是不是我们直接就可以将DDD落地了呢不好意思就如同这个小标题一样现实真的是非常残酷的。如果单单从代码阅读和业务处理上来说我们可能确实已经成功了但是我们需要保存我们的数据也就是持久化。因为实体中包含了大量的值对象所有值对象持久化所面临的问题它都会遇到甚至是让难度翻倍有关值对象持久化的难点可以参考上一篇文章 如何运用DDD - 值对象 。回看我们最后一版代码我们有两个集合的属性Participants、Places。单一的值对象的持久化已经让我们头痛了现在我们不得不面对持久化值对象集合的问题。假如你通过使用EF Core这类的ORM框架来进行持久化操作你会发现我们不得不为List中的值对象加上一个ID此时拥有了唯一标示的值对象显然已经成为了实体这是非常可怕的一件事。我们辛辛苦苦建立的领域模型在最后一步落地时居然成为改变了这往往也是DDD落地困难的一个重要原因被ORM框架或者关系型数据库所限制导致领域模型不断被打乱重构领域模型变得越来越四不像最终又写回了传统的三层架构或者面向数据库建模。但是至少在现在请相信自己的所见认真考虑和发现你项目领域所拥有的值对象和实体不要因为知道持久化的问题而放弃和妥协这也是我们开发者应有的勇气。在后面的文章中我们会关于值对象和实体的一些问题提出解决办法当然包括持久化的问题。总结本文我们介绍了实体的概念以及怎么去运用实体到实际代码中请牢记前人为我们提供的有关实体的经验比如**“实体一定是基于领域当前环境上下文的”、“实体是高度内聚和自治的”、“应该专注于实体的行为而非数据”**等等。后面的文章会为大家带来实体和值对象的一些注意事项以及领域服务的内容。
http://www.zqtcl.cn/news/877252/

相关文章:

  • 网页制作模板的网站免费合肥网站建设5k5
  • 公司信息化网站建设实施方案永久免费国外vps无需信用卡
  • 域名备案企业网站内容好网站建设公司开发
  • 合肥公司做网站网站代码需要注意什么
  • 梧州网站制作公司高端网站开发公司有哪些
  • seo网站设计北京做app的公司有哪些
  • 佛山淘宝设计网站设计价格软件商城免费下载 app
  • 物联网型网站开发cms系统源码
  • 淘宝价格网站建设wordpress 点餐
  • 晋中网站建设公司汉滨区城乡建设规划局 网站
  • 2018年的网站制作湖北省随州市建设厅网站
  • 做网络销售保温材料用什么网站好企业网站的建设企业
  • 2008发布asp网站海外如何 淘宝网站建设
  • 小米云网站开发食品包装
  • 销售网站怎么做的帝国cms网站搬家教程
  • 甘肃省城市建设档案馆网站wordpress推广自己淘宝店
  • 专业做曝光引流网站国家反诈中心app下载流程
  • 深圳校园网站建设响应式手机网站制作
  • 景县住房和城乡规划建设局网站我想买个空间自己做网站
  • 网站建设申请计划宣传片拍摄方案模板
  • 网站开发项目经验描述html网站开发事例教程
  • 998元网站建设优化网站建设实训报告心得体会
  • 网站经营性备案流程搜索引擎优化的简写是
  • 长春制作网站南昌建站系统外包
  • 在火炉做网站公园坐什么车hexo wordpress 比较
  • 好的免费博客网站设计图软件
  • 网站建设合同电子版金融网站建设运营方案
  • 网站域名备案在哪里贵阳经济技术开发区网站
  • 戴尔公司网站建设成功的关键是什么网站商城建设公司
  • 用python做 网站论坛南宁网站建设 南宁联达亿