再聊设计

本文探讨软件设计的五大核心原则,包括拥抱变化、在变化中寻求稳健、可复用可抽离、多用正少用奇及做好当下不要想太多。通过对比软件与建筑的区别,阐述如何设计出既灵活又稳健的软件架构。

前言

CSAPP这本书基本看完了,还有一个自己不太想看的章,稍微翻翻就算结束。手上还有不少经典书籍,光放着吃灰就浪费了,还是想按照原来这种一章章的读书方式去读,下一阶段要读的书是:《敏捷软件开发 原则,模式与实践》这本书在豆瓣打分为9.0分,是一本非常优秀的设计书籍,为什么要阅读这些书,因为这些基本都是通用的知识,无论你用什么编程语言,无论是做哪类行业软件,这些知识都可以用到,相当于内功了。

建筑和软件有相似点,也有非常大的区别,软件是不断变化的,而建筑是建好了之后很少变化的,所以这也就造就了软件编写完成后,要容易修改。建筑可以不用考虑好修改的问题。

一 拥抱变化

软件最大的特点是需要不断演化的,如果一个软件开发完成如建筑一样,无法修改,那其生命周期肯定不会长的。什么样的软件是无法变化的那,根上来说软件属于虚拟的东西,都是可以变化的。这里说的不能变化,只变化的代价很大,比如软件是如下的模块组成,之间的关系是由模块间的连线表示:这样情况下,我们修改扔一个模块,其他模块都受到影响了,成本太高,以至于我们把它看作无法变化的。这样的软件设计就是僵化的。

对于这种情况,我们尽量要减少模块之间的关系,减少了模块的耦合性,让变化隔离起来,假如可以按照下面的方式来设计,这样软件之间的联系由12个,减少到4个,降低了耦合,让软件结构更加灵活了。

二 在变化中寻求稳健

正如上面所说,软件和建筑的最大区别,就是建筑建成后基本无需做大的改动,而软件的变化是持续其整个生命周期的。如果建筑也是随时可以改变的,那么改变而不影响建筑的稳定是最重要的考量因素了。这就要求,整个架构上,改动起来关联性一定要小,就是说不能因为改动一点而导致其他地方也受到影响,总不能拿掉一块砖,整个房子就塌了吧。这对应软件来说,就是软件的脆弱性,脆弱的软件好像盖了个危楼,这座楼随时可能因为一个无关紧要的变化而倒掉。

要对付这种脆弱性,那我们将整个建筑划分成不同部分组成,每一个部分和其他部分有尽可能少的联系,这样我们修改一部分的话,其他部分的影响尽可能的小,或者只要我们不改动连接的地方(即软件的接口层),整个软件还可以保持相当的稳健。

所以软件架构是由基础层搭建的一个架子,这个架子是稳定的,中间的填充部分可以随时变化,而对整个软件的影响甚小,抽象出这个架子是最重要的工作,如果这个架子未考虑到未来可能的变化,未来的功能可能会导致整个架子的变化,即架构跟不上需求了,这变化就要大了。当然我们也无法预测所有变化,只能尽可能地让未来的变化在自己的框架之中,并在新功能开发的过程中随时调整。

正如上图所示,我们通过稳定的抽象层构成整体架子,具体的模块都依赖于抽象,这样各个模块可以随意变化,而对整体机构没有大的影响。

三 可复用可抽离

对建筑里面也有复用,比如我们常用的楼板,我们可以在不同的建筑物都可以使用。软件更是这样,每个软件开发都要耗费大量的人力,如果软件中的模块,可以抽出来,用在其他软件上。不仅可以减少开发这个模块的精力,而且由于这个模块是已经经过实践检验的,所以稳定性更好些。

如果一个软件里面的每个模块的联系都很紧密,抽离模块就很困难,这就相当于乐高积木有非常多的接口和周围的积木都有联系,这样的模块就比较难拼了,拿到其他地方,也难以复用了。感觉和上面还是一样,要把软件设计尽量设计简单的模块化的接口,而且是模块之间的调用是通过接口的,少直接用侵入的。

不可复用不可抽离,就是说软件牢固性比较强,或粘连性比较强,导致想复用的组件无法抽离。这让我想到平时自己封装函数或库的时候,尽量不要打印日志,特别这个日志模块是外部引入的,这样就限制了通用性,如果别人想用你的函数或库就必须引入不必要的日志模块,影响了可用性。

软件模块复用的越高,软件的边界成本就越低,整体软件费用降低,而且开发速度会越来越快。

四  多用正少用奇

正如好的法律设计,让正常做事很容易,让做违法的事情很难一样。好的软件设计,让在添加功能的时候,做正确的事情很容易,做影响软件架构或不符合架构的事情比较难。人均有惰性,如果做正确的事情很麻烦,那么在时间紧的情况下,很多人会倾向于走捷径,这就导致架构的腐烂,后续再来应对变化的时候就会越来越吃力。这里面所谓的正就是容易的,顺手的;所谓的奇就是不顺手的,复杂的。在设计软件的时候,让增加功能变成容易的事情,靠正,而不是走那种取巧的方式,不顺手的方式来实现需求。

这还体现在整体设计上,设计尽可能地简单和易于理解,不要做晦涩的设计,这样沟通成本高,后续实现成本也高。

五 做好当下不要想太多

软件设计为了扩展性,都要预留些接口,目的是将现有的功能和未来可能添加的功能结合在一起,抽象出来一个接口。这样的好处是,未来的变化如果是被预测准了,那就皆大欢喜,如果预测不准那,就需要做伤筋动骨的改变,得不偿失。

这里不是说不要为未来留有接口,而是不要过分注重扩展性,这样会加大复杂性。那如果需求来了怎么办,那就在增加功能的同时进行代码的重构,把这个功能恰如其分地放入到软件合适的位置。

这有点像我们向数据库中插入数据,要保障ID的唯一性,如果我们每次插入之前都判断下此ID是否存在,这种方法是可行,但是却很影响性能。怎么办,就当ID不存在地去处理,如果存在了,在ID唯一约束的情况下,肯定会报错,我们再进一步处理这个错误即可。

六诗词欣赏

浣溪沙·从石楼石壁往来邓尉山中

[清代] 郑文焯 

一半黄梅杂雨晴,虚岚浮翠带湖明,闲云高鸟共身轻。
山果打头休论价,野花盈手不知名,烟峦直是画中行。
根据原作 https://pan.quark.cn/s/459657bcfd45 的源码改编 Classic-ML-Methods-Algo 引言 建立这个项目,是为了梳理和总结传统机器学习(Machine Learning)方法(methods)或者算法(algo),和各位同仁相互学习交流. 现在的深度学习本质上来自于传统的神经网络模型,很大程度上是传统机器学习的延续,同时也在不少时候需要结合传统方法来实现. 任何机器学习方法基本的流程结构都是通用的;使用的评价方法也基本通用;使用的一些数学知识也是通用的. 本文在梳理传统机器学习方法算法的同时也会顺便补充这些流程,数学上的知识以供参考. 机器学习 机器学习是人工智能(Artificial Intelligence)的一个分支,也是实现人工智能最重要的手段.区别于传统的基于规则(rule-based)的算法,机器学习可以从数据中获取知识,从而实现规定的任务[Ian Goodfellow and Yoshua Bengio and Aaron Courville的Deep Learning].这些知识可以分为四种: 总结(summarization) 预测(prediction) 估计(estimation) 假想验证(hypothesis testing) 机器学习主要关心的是预测[Varian在Big Data : New Tricks for Econometrics],预测的可以是连续性的输出变量,分类,聚类或者物品之间的有趣关联. 机器学习分类 根据数据配置(setting,是否有标签,可以是连续的也可以是离散的)和任务目标,我们可以将机器学习方法分为四种: 无监督(unsupervised) 训练数据没有给定...
本系统采用微信小程序作为前端交互界面,结合Spring Boot与Vue.js框架实现后端服务及管理后台的构建,形成一套完整的电子商务解决方案。该系统架构支持单一商户独立运营,亦兼容多商户入驻的平台模式,具备高度的灵活性与扩展性。 在技术实现上,后端以Java语言为核心,依托Spring Boot框架提供稳定的业务逻辑处理与数据接口服务;管理后台采用Vue.js进行开发,实现了直观高效的操作界面;前端微信小程序则为用户提供了便捷的移动端购物体验。整套系统各模块间紧密协作,功能链路完整闭环,已通过严格测试与优化,符合商业应用的标准要求。 系统设计注重业务场景的全面覆盖,不仅包含商品展示、交易流程、订单处理等核心电商功能,还集成了会员管理、营销工具、数据统计等辅助模块,能够满足不同规模商户的日常运营需求。其多店铺支持机制允许平台方对入驻商户进行统一管理,同时保障各店铺在品牌展示、商品销售及客户服务方面的独立运作空间。 该解决方案强调代码结构的规范性与可维护性,遵循企业级开发标准,确保了系统的长期稳定运行与后续功能迭代的可行性。整体而言,这是一套技术选型成熟、架构清晰、功能完备且可直接投入商用的电商平台系统。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值