无论我毕生中获得了多大的获得成功,其主要其原因都不是我晓得啥事,而要我晓得在幼稚的情况下他们如果怎么做。我毕生小学到的最重要的小东西是一种以准则为依据的生活形式,是它协助我发现事实真相是甚么,并依此怎样暴力行动。
——瑞·达Tessy(Ray Dalio)
在日常生活的合作开发和结构设计操作过程中,我们对控制技术结构设计上的许多难题常常会遭遇许多的优先选择,相同的人能有相同的优先选择,每每如此,我单厢试著着问他们:我作出优先选择和推论另一面的准则是甚么?
经过那么十多年的发展,在软件结构设计操作过程,目前结晶留下来的准则有许多,但许多情况下,许多准则为了如上所述,归纳得会较为抽象化,除非太过抽象化,对准则的说明和认知就会一般来说,例如:高contained低谐振准则,我们都懂,但是怎样破冰和继续执行看似无论如何全然达成一致全然一致。因此,需要特别针对许多前述的情景中的难题去归纳和补足,在大的准则下Haon形成我们难认知全然一致的相较明晰准则。
责任编辑如是说的就是我沃苏什卡碰到的许多难题而归纳和使用到的许多常见原则。
一 常见准则归纳
1 多层结构设计有关准则
双向倚赖准则
准则上只容许较多层面倚赖较多层面,不容许逆向倚赖。
我们部门是为B类企业提供金融解决方案的控制技术部门,特别针对我们部门,在金融平台层系统不能逆向倚赖业务产品层系统。同一层的金融平台层系统之间的倚赖不进行限制,但会尽量减少同层倚赖。
另外,我们在解决底层倚赖的高层中结晶了几种基本形式:
系统倚赖转换为数据倚赖;接口倚赖,通过底层定义SPI,业务层实现,这种做法其实是不得已为之,同时,我们在结构设计操作过程中还是尽可能避免走这条路;通过事件机制解耦倚赖。无循环倚赖准则
系统结构设计时,尽量减少系统之间的倚赖,同时需要避免系统之间出现循环调用。
这是微服务情景下最难出现的一个难题,尤其是同层的领域系统之间的调用,导致系统难出现循环调用,循环倚赖带来的一个严重的难题是影响系统的发布和部署难题。
避免跨层调用准则
较多层面不容许之间跨层调用底层。
软件结构设计中进行多层的一个重要目的是通过多层屏蔽底层的实现细节,如果出现跨层相当于把底层的实现直接暴露了。例如门面服务层,绕过领域服务层,直接调用DAO层进行数据读写操作,除非需要重构修改原有的DAO层接口,就发现升级改造成本巨大,我不晓得有啥个团队也遭遇过这种痛苦。
单一职责准则
该准则由罗伯特·C·马丁(Robert C. Martin)于《敏捷软件合作开发:准则、模式和实践》一书中提出的。这里的职责是指类变化的其原因,单一职责准则规定一个类如果有且仅有一个引起它变化的其原因,否则类如果被拆分(There should never be more than one reason for a class to change)。
这个原则虽然提出时是解决类的职责定义难题,但前述上在对模块的划分上也有指导意义。该准则虽然很简单,但是常常也难被忽视。
在最近的项目中,我充分体会到这个准则的作用,我们部门的金融网络系统主要解决机构标准化对接难题,我们将系统分为了上下两层,下层通过标准化的接口对接机构,提升机构跨产品的复用能力;上层是产品扩展层,通过提供标准接口给到上游的业务产品层,支持同一个产品接入多家机构,屏蔽机构差异。我们推论一个功能到底属于机构对接层,还是产品扩展层的一个简单的准则是:如果新增一家机构,能否做到只影响机构对接层,而保持产品扩展层标识符不改;反过来,如果新增一个产品,是否能做到只修改产品扩展层,机构层能否不改标识符。同时,为了避免这个准则被突破,我们甚至在机构对接层的标识符中,去除了所有和产品有关的参数,这样,根据产品定制的逻辑天然无法放到这一层。
数据冗余
架构结构设计如果使得系统中数据的冗余最小。
例如我们在实践操作过程中,接口结构设计时,在Javadoc上强制指定接口的必传参数,尽量做到最小集,减少上游系统使用接口的成本。另外要求在接口实现时,提前进行参数校验,不让不满足要求的数据冗余到系统中。
为了提高系统性能,备份节点和子系统/模块必要时需要对数据进行缓存,当发生变化时,必须有相应的机制保证缓存数据的全然一致性和有效性。
2 质量属性有关准则
数据安全
这块在我们金融业务部门中尤其突出,金融由于其特殊性,常常需要收集大量的客
数据存储安全:敏感数据加密、日志输出脱敏。数据传输安全:包括加密、传输通道规范,最少字段传输(够用准则),尤其是我们金融部门,需要将数据输出给到外部第三方机构情况较为多,这块上面会控制较为严格。数据输出展示:前端展示需要防止水平越权,另外,前端的展示可以埋点和方便数据采集。3 资损防控
可核对和可监控:上下游系统的数据模型核对关联关系简单、稳定(具备通用性,和产品无关)。可熔断:对关键资损链路需要做到可熔断。对金融控制技术部门而言,资损防控是第一位,而我们在前述操作过程中发现,由于前期的许多系统在结构设计之初没有考虑资损的防控,导致核对或者监控的成本很高,因此,在后来的系统数据模型结构设计时重点会去review是否具备可核对。
4 并发控制
悲观锁:标识符编码规范——一锁二查三更新。乐观锁:必须在事务内更新。5 热点难题
避免流量倾斜,导致单台机器/单个数据表/数据库集中读写。
这个需要在结构设计时充分提前预判业务的发展规模和系统的容量难题。在前述实施操作过程中,我们会提前按照3~5年左右的业务规模来结构设计。
6 数据倾斜
分表分库规则在结构设计时需要考虑数据分布均匀,避免单库或者单表数据倾斜。
数据倾斜这个在之前踩过较为大的坑,在系统结构设计之初没有结合业务情景去考虑系统的数据存储层结构设计,导致数据出现严重倾斜,数据库操作出现瓶颈,现在是我们在结构设计存储层方案时必须要考虑的一个准则。
7 性能准则
可压测:对性能要求高的链路,需要做到可以压测。
这个主要是由于每到大促就需要重新梳理和改造压测链路,耗时费力,苦不堪言。
8 事务控制有关准则
优先使用编程式事务:为了更好的控制事务,一般要求使用编程式事务,避免潜在的跨事务难题。事务更新需要保证顺序全然一致性:强全然一致要求还是最终全然一致,强全然一致是否会涉及到跨库,事务操作时需要相同记录的更新顺序保证全然一致。事务中不进行远程调用。9 全然一致性有关准则
区分系统调用错误和业务失败:远程调用失败,不代表下游系统没有接收请求,更不能做为业务失败依据,需要严格区分系统调用错误和业务失败。可重试:任何一行标识符继续执行时都有可能因系统重启而中断,所以需要支持可重试。异步处理必须增加核对:最终全然一致性离不开恢复重试策略,也需要有系统间数据核对用于及时发现数据不全然一致,同时在核对时需要增加处理时效的监控,及时发现长时间未处理获得成功的数据。二 API结构设计有关结构设计准则
1 水平越权控制
API结构设计时需要考虑防范水平越权。
目前我们的做法是,从前端到后端,每层都需要进行越权校验。通过从接口结构设计层面防控,避免某层出现疏忽导致越权的事件发生。
2 接口幂等控制
调用方必须提供用于幂等控制的参数,为了控制幂等,同一个请求的幂等参数不变。
在血泪史上,由于接口不幂等导致的难题太多了,这个目前基本上已经成了部门在接口结构设计上的共识。
3 兼容性准则
API升级和调整,需要兼容老的版本。
为了保证接口可以升级,我们对接口的结构设计就会存在较为高的要求,例如接口参数中不能使用枚举,不能使用Java基础类型等,同时也要求接口结构设计需要具备一定前瞻性和通用性,尤其对于面向业务领域的接口结构设计,更要求对该领域的业务知识有较为多的了解。
当然还有许多准则在《Java合作开发手册》中已有叙述,这里就不在赘述。
三 归纳
责任编辑如是说了我们在系统结构设计和合作开发前述情景中归纳出的许多准则,通过这些原则的归纳和结晶,可以在后续出现同类难题时作出相较正确的优先选择,避免重蹈覆辙。另外,通过在大的准则下进行具体化和明晰化,能够让我们难达成一致全然一致,让架构方案更难破冰,不走偏。
另外,无论是在生活上还是工作上,建议多从获得成功的经验或者失败的教训中去归纳,形成他们的准则,丰富他们的决策系统。这是《准则》这本书给我带来的一个较为大的启发。
责任编辑为阿里云原创内容,未经容许不得转载。