angular组件层次与军事指挥层级职责的联系

时间:2023-12-25 13:59:49

又继续读angular文档,发现自己之前理解还是有误。按官方文档的思路service不是属于component的,是属于module的。module才是负责完整领域逻辑的单位。demo的英雄编辑器给我误导了,好像service是从component里拆出去,属于component一样。

问题提出:svg拆分粒度选择

主要问题就是拆分的粒度问题:

1 1个svg图对应1个ng的component

2 1个svg图对应多个compoent, 如<g>里定义若干元素如node,link各自作为组件node-component,link-component

这个和ng和d3本身无关。要看怎么做最符合领域本身的复杂度。然后才是复用的问题。

总的来说:

越是复杂领域复杂问题,越要用大刀阔斧,切记用小刀,过度切分,过度设计

Visualizing Data with Angular and D3的作者的选择是2。他的demo是有点复杂的力导向图,把node link都单独提出去建模了。

是不是也要这样拆分呢?

辨析过程

前端的战场是页面。核心域是"基于dom元素的交互<->更新数据模型"。

D3的计算与展现也是分开的。

如果用ng负责核心域,那么d3就会退居外围service。

ng大概用module负责不同页面的大区(或者顶部/底部这种):每个module内部:

angular组件层次与军事指挥层级职责的联系

多个component,每1个component负责屏幕上1个特定区域。官方文档摘抄:

每个模块都是一个内聚的代码块专注于某个应用领域、工作流或紧密相关的功能。

组件的任务就是提供用户体验,仅此而已。它介于视图(由模板渲染)和应用逻辑(通常包括模型的某些概念)之间。 设计良好的组件为数据绑定提供属性和方法,把其它琐事都委托给服务。

服务没有什么特别属于 Angular 的特性。 Angular 对于服务也没有什么定义。 

从Domain Driven Design角度:

ng的module是aggregate root,service对应repository factory service,那么component对应的是entry,ts原生class用于value object

从军事领域编制角度看:

module类似本级司令部(战役军团或者高级战术兵团),而component类似下1级的作战编组,承担命令,负责某个地段区域;service是分队,具体实现,更细的class,function类似兵力与兵器。

团以上才称部队,有司政后装,能相对独立地完成任务。

对应ng里module,component都是部队:

module 下辖多个component/service/全套待遇,component也有自己的css/template 负责屏幕上一个地段。

部队负责组织调度分队,分配资源;分队负责执行实现细节。属性方法类似兵力兵器(用值对象表示)

对应 这句话:

组件为数据绑定提供属性和方法,把其它琐事都委托给服务。

我目前理解的系统切分的大的粒度:

每1个作战序列直辖7±2个带HQ的编组比较合适。本级HQ直辖超过10个的没有HQ的分队是明显不合适的,直辖超过10个有HQ的部队,就更离奇了。

这时候,应该像《重构》里说的那样,增加抽象级别。把数量多的部/分队作为自己的下2级,而在下1级建立几个新HQ,把下2级的部/分队分配给新增加的下1级HQ里。

保证自己直接指挥的还是数量有限的下1级HQ,把宝贵的/有限数量的HQ用在这里,不建立过多的HQ,浪费指挥与参谋人员。

这也就是《孙子兵法》里的“分“和”数”了。

我的应用中要有多个svg叠加,更适合用每个component负责一个svg,类似每个作战编组负责一个作战地域,

结论

军队编制 部队(拥有司政后装/承担较完整独立的任务) 分队(函数式的任务)
领域驱动设计 聚合根(拥有相应的service repository 完成较完整的领域逻辑) 实体类,值对象
angular module, component service,class
svg <svg>根节点 <g>下辖的div元素

心得体会:

1表面上是设计问题,技术问题;背后的本质是领域概念切分粒度的分析问题,领域概念理解问题。

2 核心域分析模型的复用:在一个领域和层面想不清楚(D3和angular还没学明白)的时候,从别的自己理解比较清楚的领域,借鉴分析模型(军事指挥中的部队-分队)有奇效。同样之前在军事领域想不清的问题(情报与作训),参考了设计领域的方案(读写分离,CQRS。Command Query Responsibility Segregation)一下就容易理解了。

在复杂度高的领域,长期实践形成的分析模式(行内“条块分割”的通行做法,分工方式/关注点分离的思路),一定是可以借鉴参考的。

前端复杂吧?但是军事更复杂啊。

架构无非就是如何“条块分割”,让系统用起来更顺手,更禁得住各种风险冲击的问题

那么借鉴一下以“条块分割”著称的军队,准没错。(不要借鉴德日这种军阀与地主的l败者组军队,要借鉴鼎盛时期中美苏家的军队架构)

3 不光要有分析模型,设计用的概念模型也要丰富。

"一切皆对象”或者“一切皆函数",“一切皆数据”,抽象粒度太单薄了,语言太贫乏了。

自己脑子也要有军队的部/分队,军团/兵团,基本/高级战术单位,有对应的几级层次才好。

所以增补class上的 namespace,文件级的module之类。不同的语言与框架还提供了 component  blueprint,DDD也增补了聚合根以及配套的(service,repository factory,类似部队的司政后装),确实是有必要的。

比如站在本级的角度,要想着对接上下各2级HQ的方式。对上,要掌握上2级的意图和任务;对下:

命令与事件下1级的HQ部队负责,而兵器兵力数字状态在下2级分队

那么在ng里,本级如果是module:

module->component是命令式指挥,表示目的

component->service是函数式的封装调用,完成实现细节

——在此放一炮:DDD的设计思路如果核心域封装目的,在内;而技术实现在支持域,在外;

那么显然风格应该是  命令式内核,函数式外壳。而不是某些书上说的“函数式内核,命令式外壳”。

内核是领域逻辑的目的,而不是具体实现

军队的级别晋升,不是从基层到高层,而是从实现->意图,从技术->艺术,从控制->指挥,从外围->核心的过程。

基层重视实现过程,用动词抽象,对应函数式

高层重视意图和目的,用名词抽象,对应面向对象与命令式

——函数式用得多的地方,主要也是基础设施,编译器之类。从高层调用的时候,根本不去考虑复杂实现过程。

service作为分队,class作为兵力兵器,不独立承担领域任务,本级没有司令部,所以不判断情况,只负责执行上级明确赋予的战术任务(函数式),本级只负责掌握部队(有错报异常)。分队级的世界观非常符合函数式了:

函数式编程在使用的时候的特点就是,你已经再也不知道数据是从哪里来了,每一个函数都是为了用小函数组织成更大的函数,函数的参数也是函数,函数返回的也是函数,最后得到一个超级牛逼的函数,就等着别人用他来写一个main函数把数据灌进去了。

来自 <https://www.zhihu.com/question/28292740>

恶搞一下:战法(行动)式的分队指挥:

战法式作战在使用的时候的特点就是,你已经再也不知道兵力兵器是从哪里来了,每一个战法都是为了用小战法组织成更大的战法,战法的参数也是战法,战法返回的也是战法,最后得到一个超级牛逼的战法,就等着别人用他来写一个想定把兵力兵器灌进去了。

——其实,用动词建模,不就是活动图么。BPRM

module和component作为部队,拥有自己的司政后装(但不必须):repository,factory,service。承接较独立完整复杂的任务,命令式为主,状态机也会用到。

app->module这个级别,CQRS,领域事件啊该上就上。

——微服务,扁平化,不意味着没有部队,只有分队。高级HQ直接领导数量庞大但琐碎平级的战术分队,那是蒋介石领导的国军(越过自己的战区HQ,总司令指挥到每个战术分队,甚至连)。

所以系统里也不能是app下直接大量的component 大量的class到底。

系统不是多个平级对象互相协作完成任务,而是多个对象在上1级统一指挥下协作,多级HQ形成层次,不要统称class。最终写出来的系统容易变成蒋介石的军队。

不能把负责统一指挥的那个上1级HQ推到设计开发之外,好像“服务编排”之类。那可能才是核心域,写那些脚本才是核心域编码工作。是要精心设计的层次和约束数量的。

必须有要有清晰合理的层级划分。学到的各种设计技巧,因为OO领域抽象语言还是比较贫乏,只能自己强制划分,每级只有某些特性(class分队级没有service,repository这样ER OR的司政后装)