首页 > 编程知识 正文

简述代码设计的原则(代码设计的基本原则)

时间:2023-05-05 18:30:30 阅读:83805 作者:3307

无论我一生有多成功,其主要原因不是我知道多少,而是在无知的情况下知道自己该怎么办。 我一生中学到的最重要的事情是基于原则的生活方式,帮助我发现什么是真相,并据此采取行动。

——瑞达里奥(雷达里奥) ) )。

在日常的开发和设计过程中,对于技术设计上的一些问题,大家往往会面临很多选择,每个人有不同的选择。 每次我都试着问问自己。 我做出选择和判断背后的原则是什么?

经过多年的发展,在软件设计的过程中,目前沉淀的原则有很多,但很多原则由于普遍性而抽象归纳,如果抽象过度,对原则的解释和理解就会因人而异。 比如,大家都知道高凝聚低结合的原则,但很难说怎么落地执行完全一致。 因此,有必要对一些实际场景中的问题进行总结和补充,在大原则下具体化,形成大家容易理解的一致的相对明确的原则。

本文总结了我在工作中遇到的一些问题并介绍了使用的一般原则

一 常用原则总结

1分层设计的相关原则

单向依赖原则

原则上只允许低级别的依赖,不允许低级的依赖。

我部门是向b类企业提供金融解决方案的技术部门,对我部门来说,金融平台层系统不能逆依赖业务产品层系统。 同一层的金融平台层的系统之间的依赖不受限制,但对同一层的依赖最小。

另外,我们在解决底层依赖的高层沉淀了几种基本方式:

依赖于从系统依赖到数据依赖的转换接口,在基础上定义SPI,在业务层实现,这种方法实际上是不得已的,同时我们在设计过程中也可以避开这条路。 通过事件机制消除依赖。 没有循环依存的原则

设计系统时尽量减少系统之间的依赖,同时避免系统之间的循环调用。

这是微服务场景中最容易出现的问题之一,特别是由于同层域系统之间的调用,系统容易发生循环调用,循环依赖带来的严重问题之一是影响系统分发和部署的问题。

避免跨层调用策略

在较高级别上,不能在之间调用较低级别。

在软件设计中进行分层的一个重要目的是分层屏蔽下层的实现细节,如果跨越层间的话,相当于直接暴露下层的实现。 例如,第三方服务层绕过域服务层,直接调用DAO层进行数据的读写操作。 一旦需要重新构建和修改原有的DAO层接口,就会发现升级改造成本巨大,不知道多少团队都曾面对过这种痛苦。

单一职责原则

这个原则是ngddh(Robertc.Martin )在《敏捷软件开发:原则、模式和实践》这本书中提出的。 这里的作用是班级变化的原因,在单一的作用原则下,一个班级应该有,引起这种变化的原因只有一个。 否则,类应该被划分。 (thereshouldneverbemorethanonereasonforaclasstochange )。

这个原则是为了解决班级的角色定义问题而提出的,但实际上对模块的划分也有指导意义。 这个原则很简单,但容易被忽视。

在最近的项目中,我充分体会到了这个原则的作用。 我们部门的金融网络系统主要解决的是机构的标准化对接问题,我们把系统分为上下两层,下层通过标准化的接口对接机构,提高机构在产品之间的复用能力。 上层是产品扩展层,通过为上游业务产品层提供标准接口,支持同一产品访问多个机构,屏蔽机构的差异。 判断功能属于组织对接层还是产品扩展层的一个简单原则是:添加组织后,是否可以不更改产品扩展层的代码而只影响组织对接层。 相反,添加一个产品是否可以只修改产品增强层,组织层是否不更改代码。 同时,为了不突破这个原则,我们甚至连机构对接层的代码都去除了与产品相关的所有参数。 这样,为产品定制的逻辑自然就不能放在这一层上。

数据冗余

体系结构设计应该使系统内数据的冗余度最小。

例如,在实践中,我们在设计接口时,在Javadoc上强制指定接口的必需参数,尽量最小化,从而降低上游系统使用接口的成本。 另外,接口安装时,要求事先进行参数检查,使不满足要求的数据不被系统冗余化。

为了提高系统性能,备份节点和子系统/模块必须根据需要缓存数据,并且在发生更改时需要一种保证缓存数据一致性和有效性的机制。

2质量属性原则

数据安全性

在这个金融业务部门中尤为突出。 由于金融的特殊性,经常需要收集大量顾客的真实和隐私数据。 数据安全是设计中需要重点考虑的问题通常我们主要关注以下三个方面的问题

数据存储安全性:加密敏感数据,解除日志输出的机密。 数据传输的安全性:包括加密、传输通道规格、最小现场传输(充分原则),特别是在金融部门,经常需要将数据输出到外部第三方机构,在此基础上管理起来更加严格。 数据输出展示:前端展示需要防止水平越权,另外前端展示可以填补积分,便于数据采集。

row-right">3 资损防控

可核对和可监控:上下游系统的数据模型核对关联关系简单、稳定(具备通用性,和产品无关)。可熔断:对关键资损链路需要做到可熔断。

对金融技术部门而言,资损防控是第一位,而我们在实际过程中发现,由于前期的一些系统在设计之初没有考虑资损的防控,导致核对或者监控的成本很高,因此,在后来的系统数据模型设计时重点会去review是否具备可核对。

4 并发控制

悲观锁:代码编码规范——一锁二查三更新。乐观锁:必须在事务内更新。

5 热点问题

避免流量倾斜,导致单台机器/单个数据表/数据库集中读写。

这个需要在设计时充分提前预判业务的发展规模和系统的容量问题。在实际实施过程中,我们会提前按照3~5年左右的业务规模来设计。

6 数据倾斜

分表分库规则在设计时需要考虑数据分布均匀,避免单库或者单表数据倾斜。

数据倾斜这个在之前踩过比较大的坑,在系统设计之初没有结合业务场景去考虑系统的数据存储层设计,导致数据出现严重倾斜,数据库操作出现瓶颈,现在是我们在设计存储层方案时必须要考虑的一个原则。

7 性能原则

可压测:对性能要求高的链路,需要做到可以压测。

这个主要是由于每到大促就需要重新梳理和改造压测链路,耗时费力,苦不堪言。

8 事务控制相关原则

优先使用编程式事务:为了更好的控制事务,一般要求使用编程式事务,避免潜在的跨事务问题。事务更新需要保证顺序一致性:强一致要求还是最终一致,强一致是否会涉及到跨库,事务操作时需要相同记录的更新顺序保证一致。事务中不进行远程调用。

9 一致性相关原则

区分系统调用错误和业务失败:远程调用失败,不代表下游系统没有接收请求,更不能做为业务失败依据,需要严格区分系统调用错误和业务失败。可重试:任何一行代码执行时都有可能因系统重启而中断,所以需要支持可重试。异步处理必须增加核对:最终一致性离不开恢复重试策略,也需要有系统间数据核对用于及时发现数据不一致,同时在核对时需要增加处理时效的监控,及时发现长时间未处理成功的数据。

二 API设计相关设计原则

1 水平越权控制

API设计时需要考虑防范水平越权。

目前我们的做法是,从前端到后端,每层都需要进行越权校验。通过从接口设计层面防控,避免某层出现疏忽导致越权的事件发生。

2 接口幂等控制

调用方必须提供用于幂等控制的参数,为了控制幂等,同一个请求的幂等参数不变。

在血泪史上,由于接口不幂等导致的问题太多了,这个目前基本上已经成了部门在接口设计上的共识。

3 兼容性原则

API升级和调整,需要兼容老的版本。

为了保证接口可以升级,我们对接口的设计就会存在比较高的要求,譬如接口参数中不能使用枚举,不能使用Java基础类型等,同时也要求接口设计需要具备一定前瞻性和通用性,尤其对于面向业务领域的接口设计,更要求对该领域的业务知识有比较多的了解。

当然还有一些原则在《Java开发手册》中已有叙述,这里就不在赘述。

三 总结

本文介绍了我们在系统设计和开发实际场景中总结出的一些原则,通过这些原则的总结和沉淀,可以在后续出现同类问题时做出相对正确的选择,避免重蹈覆辙。另外,通过在大的原则下进行具体化和明确化,能够让大家容易达成一致,让架构方案更容易落地,不走偏。

另外,无论是在生活上还是工作上,建议多从成功的经验或者失败的教训中去总结,形成自己的原则,丰富自己的决策系统。这是《原则》这本书给我带来的一个比较大的启发。

本文为阿里云原创内容,未经允许不得转载。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。