.Net Actor 服务端开发框架,Newbe.Claptrap 项目周报 1 - 还没轮影,先用轮跑

Newbe.Claptrap 项目周报 1,第一周代码写了一点。但主要仍是考虑理论可行性。html

第一次接触本框架的读者,能够先点击此处阅读本框架相关的基础理论和工做原理。git

周报是啥?

成功的开源做品,离不开社区贡献者的积极参与。做为一个新启动的轮子项目,项目联合创始人【月落】有交代:github

“我知道你代码能力也不怎么样,你就把你的想法每周的交代清楚。让他人看到项目的价值。等待愈来愈多的人发现项目价值所在的时候,天然就会给予更多的关注,甚至于参与的项目的开发当中。因此你要每周都写一下周报。周报最好侧重于讲解项目的概念,以及经过项目如何解决实际问题。固然也能够包含一些关于项目如何设计的内容,但要注意适度,一般你们不会太注意项目怎么实现。而更关注项目带来的价值。记住:只有产生了价值,项目才会成功。”数据库

因而笔者就只能每周写一下周报,勉强维持生活这样子。编程

轮有轮样

新轮要有新轮的样子,“项目开张篇” 中介绍了本框架相关的基础理论和工做原理。鉴于相关的理论内容对于刚刚接触的读者较为生疏,所以本节将前文最为关键的内容罗列以下以激发读者的回忆。并发

Actor 特性一:Actor 的状态是经过外部调用 Actor 而改变的。框架

更新Actor状态

Actor 特性一补 1:Actor 的状态不与外部进行共享。post

共享Actor状态

Actor 特性一补 2:外部能够读取 Actor 状态。spa

读取Actor状态

Actor 特性二:Actor 是 “单线程” 工做的,每次只能处理一个请求。线程

并发调用Actor

Actor 特性二补 1:并发读取状态能够不是 “单线程”。

并发读取Actor

框架定义的 Actor 类型——Claptrap:经过事件模式,产生事件并经过事件改变自身状态的 Actor。

Claptrap

框架定义的 Actor 类型——Minion:与 Claptrap 对比,Minion 不产生事件而是读取对应 Claptrap 的事件来改变自身的状态。容许存在多个 Minion 对应一个 Claptrap。

Minion

经过 Claptrap 和 Minion 配合完成 “转帐” 业务。

Claptrap & Minion

月落大佬名言警句 1:世界上本也不存在 “银弹”。一套框架解决不了全部问题。
月落大佬名言警句 2:业务复杂度是不会由于系统设计变化而减小的,它只是从一个地方转移到了另外的地方。

还没轮影,先用轮跑

如今咱们拥有了 Claptrap 和 Minion 的概念。接下来,结合一些业务场景,实验一下框架可否应对各类各样的业务需求。

再美的技术手段没法应对现实的需求与变化,那也只能技术花瓶。——刚刚学完赛博坦 XII 量子计算机指令集的月落

业务场景

这是一个简单的电商系统:

  1. 只卖一种绿色的水晶,为了方便描述,将这个商品命名为 “原谅水晶”。
  2. 用户可使用本身帐号中的余额购买原谅水晶。余额是经过外部支付系统充值进来的。充值部分,暂时不是业务场景须要考虑的。
  3. 每一个用户还有一个积分,很巧,这个积分的图标也是绿色的,所以,将这个积分命名为 “原谅积分”。
  4. 原谅积分的获取方式有不少,例如:用户注册;邀请其余用户注册;被邀请用户进行了消费,邀请者也能够得到;原谅即挖矿;现实中得到了原谅;等等其余的一些方式,这部分可能须要配合后续的活动持续增长得到方式。
  5. 原谅积分能够在进行购买原谅水晶时,抵扣一部分须要支付的金额。
  6. 原谅积分在将来极可能有其余的用途。
  7. 购买原谅水晶的支付方式将来极可能不止余额和原谅积分两种。

以上就是对于这个电商系统的一部分需求描述。需求将来确定是会变化的。

要素察觉

电商系统,最为主要的业务场景天然是和商品的交易有关的业务场景。不论其余的需求场景多么的复杂,交易相关的业务场景必然是首当其冲须要分析解决的。

那么首先,咱们将 “用户确认购买原谅水晶” 这个场景用简单的语言描述一下程序须要执行的业务内容:

  1. 须要检查用户的余额是否足够
  2. 假如用户选择了积分抵扣,须要检查用户的积分是否足够
  3. 须要检查库存是否足够
  4. 须要扣减用户的余额
  5. 须要扣减库存
  6. 假如用户选择了积分抵扣,须要扣减用户的积分

若是采用直接操做数据表的方式实现以上六个要点,对于绝大部分开发者来讲应该是十分简单的。开启一个数据库事务,至少具有行级锁,将数据进行检查和更新,即可以完成这个业务。那么如今使用本框架进行实现,根据 “业务复杂度不减小” 的基本事实,也一样须要实现以上六个要点。

未卜先知

首先,在不太讨论依据的前提下,笔者围绕上文提到的一些主体概念,设计了如下这些 Claptrap:

概念 英文命名 缩写 表明颜色
原谅水晶 SKU S ■■■■■
原谅积分 UserPoint P ■■■■■
用户余额 UserBalance B ■■■■■

依轱辘画轮

按照前篇的 “转帐” 业务场景的流程设计,此处采用相同的方式设计一下购买的逻辑。以下图所示:

链形设计

分析一下这个设计方案:

依照业务逻辑的顺序,完成了库存检查、库存扣减、余额检查、余额扣减、积分检查、积分扣减的业务步骤。

注意 Client 和 Claptrap S 之间的调用线的存在时间,只有在一开始的时候,也就是说,客户端仅须要稍做等待,即可以获得响应。

Claptrap S 将事件推送给 Minion S 以后即可以继续响应新的请求。确保了多个用户进行并发购买商品即确保了商品不会超卖,也确保了响应事件足够短。

整个业务逻辑的入口是 S、这样能够确保用户在锁定库存的前提下进行支付,避免了用户付了钱没有办法买到商品的状况。

基于形状上的缘由,这种设计方案被命名为 “链形设计(Chain-Like Design)”

同样的材料,不同的轮子

也存在另一种设计方案。以下图所示:

树形设计

分析一下这个设计方案:

引入了一个新的 Claptrap W(What a amazing that I get a forgiven-crystal)做为业务的入口,这个 Claptrap W 经过调用其余的 Claptrap 实现这个业务过程。

相比与上节的设计方案,Minion S、P、B 都再也不参与业务的流转控制,由于这些业务的流转控制已经由 Claptrap W 进行控制。

而且因为 Minion W 的存在,这个设计方案也能够将部分的调用交由 Minion 来进行,因此这个方案也能够是如下两种形式。

树形设计

树形设计

基于形状上的缘由,这种设计方案被命名为 “树形设计(Tree-Like Design)”

那么此处就出现了选择,既然有出现了选择,那么此处就使用《月老板的软件开发小妙招三十二则》中记载的 “WhyNot 对比分析法” 来决定使用哪一种设计方案:

选项 为何不? 为何!不!
链形设计   业务流转过程的控制经过 Minion 相链接,这是一种紧耦合的设计。这至关于 Minion 和 Claptrap 此次操做业务的上下文。一个明显的问题:客户是否选择了积分支付,这个逻辑,要么在 Minion B 中判断,要么在 Claptrap P 中判断,但不论哪一种方式其实都不合理。
这样的设计在应对流程失败的时候,会特别难以处理。例如在最后一步客户若是积分不足,那么可能就须要逐步回滚,这可能会很是困难。
树形设计 这种设计,把业务的核心流程控制内容集中的一对相关的 Claptrap W 和 Minion W 中。这是一种高内聚的表现。
基于这种设计方案,很容易基于 Claptrap S、P、B 构建出更加复杂的过程。

其实读者很容易发现,对于这个选择的 WhyNot 对比分析表,实际上是一边倒的。这里明显就是要选择树形设计。

《月老板软件开发小妙招三十二则》,是月落大佬在平常开发过程中对软件开发过程用到的一些小方法的收集和概括。这些方法大多不是新发明的内容。月落大佬只是将这些方法收集在一块儿,为了启示后来者,在分析判断一些问题的时候,用一些小方法有时就能让事情变得有条理一些。除了 “WhyNot 对比分析法” 以外,还有较为知名的 “5W1H 需求描述法”;很是简单的“CheckList 备忘录”;被普遍说起的“艾森豪威尔法则” 等。

WhyNot 对比分析法,简单来讲就是要讲选择多个主体进行并排对比,分别列举 “应该选择它” 和“不该该选择它”的理由,而后进行综合判断进而作出决定的方法。它特别适用于多人对某一选择争执不休时采用的方法,经过表格的形式分别记录陈述的理由,确保了不缺不漏有理有据。在方法上的基础,还衍生出了 “理由权重计量”、“人员话语权计量” 等其余的一些变种。此方法与 “优劣对比法”、“异同对比法” 等对比法,以及 “几率选择法”、“经验选择法” 等选择法有必定的联系与区别。此方法的命名听说是月落大佬独创,是一个语法梗。在中文当中,能够采用 “为何不?” 这样的反问句来表示选择一个对象的理由,能够用 “为何!不!” 这个的祈使句来表示不选择一个对象的理由。 WhyNot 其实就是对 “为何不” 四个字的直译。

好轮子外观也好看

初见 WhyNot 对比分析法的读者可能会有疑问:难道就没有选择链形设计的理由?

须要解释的是, WhyNot 对比分析法是对固定场景的分析法,所以若是场景变了,分析的结果也会变。也就是说,在某些特定的场景下,链形设计有其必要性

那么在解释以前,咱们采用另外的方法来解读链形设计与树形设计:

  • 将 Claptrap 和对应的 Minion 合并
  • 用 “由于… 因此…” 的句式来代替图形中的实线调用

链形设计

那么结合上图的链形设计就能够表述为:

  • 由于 S,因此 B
  • 由于 B,因此 P

展开的语义能够是:

  • 由于购买而扣除了库存,因此进一步扣减余额
  • 由于购买而扣减了余额,因此要进一步扣减积分

树形设计

上图树形设计就能够表述为:

  • 由于 W,因此 S
  • 由于 W,因此 B
  • 由于 W,因此 P

展开的语义能够是:

  • 由于购买,因此扣减了库存
  • 由于购买,因此扣减了余额
  • 由于购买,因此扣减了积分

即便笔者这里解释的不太清楚,可是读者仍然能够观察 “由于购买而扣减了余额,因此要进一步扣减积分” 这句其实不太合理,这二者在业务上其实不该该有明显的来龙去脉。

这其实也是链形设计在这个场景下不能适用的缘由:若是二者的调用关系没有明显的来龙去脉,而将二者设计为先后调用的链形关系。那么极可能获得的是不合理的设计。

那么反过来讲:若是要应用链形设计。二者之间必须存在合理的来龙去脉。

不过,在需求分析过程当中,当前可能必然存在的来龙去脉,事后可能就已经不太合理。业务场景的多变和需求的不彻底稳定,致使了事实上,采用树形设计可以应对更多的问题。

读者能够尝试对上文业务场景中剩余的几点需求进行一下设计。

另外,读者能够从新思考一下开张篇中所采用的 “转帐” 场景的设计,采用树形设计是否更为稳当。

其实就是新轮子

在开张篇中,咱们将 Actor 模式与 CRUD 模式进行了简单异同点比较。而如今还存在另一类比较常提到的设计方案,就是 “领域驱动设计”。

领域驱动设计的概念此处很少作介绍,对此内容比较陌生的读者能够参看微软 MVP 汤雪华老师的文章《领域驱动设计之领域模型》

那么,当读者理解了领域驱动设计以后,再结合本篇前面提到的 Claptrap W、S、P、B。或许 Claptrap S、P、B 就是聚合根?或许 Claptrap W 就是应用服务?笔者认为 Actor 模式实际上是对领域驱动设计的一种进一步发挥:

  • 领域驱动设计没有在设计模型内考虑业务并发,而 Actor 模式做为一套并发编程模型其实就弥补了这部分的缺失。
  • 绝大多数(笔者所知到的)领域驱动框架仍然采用了 “从仓储还原聚合根,操做完毕后保存” 的通常过程。而以 Orleans 为例的 Actor 框架会将已经激活的 Actor 在内存中保留一段时间,也就是说,聚合根能够在内存中不断的修改,而不须要重复的从仓储中还原。

总的来讲,读者能够沿用领域驱动设计的思路建模,而后尝试将原有的聚合根和应用服务设计为 Actor ,从理论上尝试一下本身所熟悉的领域,可否采用 Actor 进行实现。或许读者能够从中发现一些不同的体验。

不过,本框架因为采用了 Actor 模式和事件溯源模式,所以设计方法与领域驱动模型相比有所继承又不彻底相同,还有一些其余须要注意的内容,会在后续整理出相应的文章。

结篇

本篇但愿经过一个业务场景的设计,让读者了解到如何采用本框架的理论概念来实现业务。其中包含有一些做者的臆造词,所以可能须要花费读者更多的时间进行理解。

因为做者的工做经验有限,缺少丰富的行业领域知识,所以对于框架的设计理念是否符合特定行业特性的问题没法给出准确的判断,还须要读者多加思考。如有任何须要协助的问题,欢迎联系本项目组。

欢迎对此感兴趣的朋友关注项目,参与项目。

如下是一些与项目有关的连接,欢迎读者查看:

相关文章
相关标签/搜索