从Unix开源开发学习应对大型复杂项目开发
封装与抽象
在 Unix、Linux 系统中,有一句经典的话,“Everything is a file”,翻译成中文就是“一切皆文件”。
这句话的意思就是,在 Unix、Linux 系统中,很多东西都被抽象成“文件”这样一个概念,比如 Socket、驱动、硬盘、系统信息等。它们使用文件系统的路径作为统一的命名空间(namespace),使用统一的 read、write 标准函数来访问。
比如,我们要查看 CPU 的信息,在 Linux 系统中,我们只需要使用 Vim、Gedit 等编辑器或者 cat 命令,像打开其他文件一样,打开 /proc/cpuinfo,就能查看到相应的信息。除此之外,我们还可以通过查看 /proc/uptime文件,了解系统运行了多久,查看 /proc/version 了解系统的内核版本等。
实际上,“一切皆文件”就体现了封装和抽象的设计思想。
封装了不同类型设备的访问细节,抽象为统一的文件访问方式,更高层的代码就能基于统一的访问方式,来访问底层不同类型的设备
。这样做的好处是,隔离底层设备访问的复杂性。统一的访问方式能够简化上层代码的编写,并且代码更容易复用。
除此之外,抽象和封装还能有效控制代码复杂性的蔓延,将复杂性封装在局部代码中,隔离实现的易变性,提供简单、统一的访问接口,让其他模块来使用,其他模块基于抽象的接口而非具体的实现编程,代码会更加稳定。
分层与模块化
前面我们也提到,模块化是构建复杂系统的常用手段
。对于像 Unix 这样的复杂系统,没有人能掌控所有的细节。之所以我们能开发出如此复杂的系统,并且能维护得了,最主要的原因就是将系统划分成各个独立的模块,比如进程调度、进程通信、内存管理、虚拟文件系统、网络接口等模块。不同的模块之间通过接口来进行通信,模块之间耦合很小,每个小的团队聚焦于一个独立的高内聚模块来开发
,最终像搭积木一样,将各个模块组装起来,构建成一个超级复杂的系统。
除此之外,Unix、Linux 等大型系统之所以能做到几百、上千人有条不紊地协作开发,也归功于模块化做得好。不同的团队负责不同的模块开发,这样即便在不了解全部细节的情况下,管理者也能协调各个模块,让整个系统有效运转。
实际上,除了模块化之外,分层也是我们常用来架构复杂系统的方法
。
我们常说,计算机领域的任何问题都可以通过增加一个间接的中间层来解决
,这本身就体现了分层的重要性。比如,Unix 系统也是基于分层开发的,它可以大致上分为三层,分别是内核、系统调用、应用层。每一层都对上层封装实现细节,暴露抽象的接口来调用。而且,任意一层都可以被重新实现,不会影响到其他层的代码。
面对复杂系统的开发,我们要善于应用分层技术,把容易复用、跟具体业务关系不大的代码,尽量下沉到下层,把容易变动、跟具体业务强相关的代码,尽量上移到上层
。
基于接口通信
刚刚我们讲了分层、模块化,那不同的层之间、不同的模块之间,是如何通信的呢?一般来讲都是通过接口调用。在设计模块(module)或者层(layer)要暴露的接口的时候,我们要学会隐藏实现,接口从命名到定义都要抽象一些,尽量少涉及具体的实现细节。
比如,Unix 系统提供的 open() 文件操作函数,底层实现非常复杂,涉及权限控制、并发控制、物理存储,但我们用起来却非常简单。除此之外,因为 open() 函数基于抽象而非具体的实现来定义,所以我们在改动 open() 函数的底层实现的时候,并不需要改动依赖它的上层代码
。
高内聚、松耦合
高内聚、松耦合是一个比较通用的设计思想,内聚性好、耦合少的代码,能让我们在修改或者阅读代码的时候,聚集到在一个小范围的模块或者类中,不需要了解太多其他模块或类的代码
,让我们的焦点不至于太发散,也就降低了阅读和修改代码的难度。而且,因为依赖关系简单,耦合小,修改代码不会牵一发而动全身,代码改动比较集中,引入 bug 的风险也就减少了很多。
实际上,刚刚讲到的很多方法,比如封装、抽象、分层、模块化、基于接口通信,都能有效地实现代码的高内聚、松耦合。反过来,代码的高内聚、松耦合,也就意味着,抽象、封装做到比较到位、代码结构清晰、分层和模块化合理、依赖关系简单,那代码整体的质量就不会太差
。即便某个具体的类或者模块设计得不怎么合理,代码质量不怎么高,影响的范围也是非常有限的。我们可以聚焦于这个模块或者类做相应的小型重构。而相对于代码结构的调整,这种改动范围比较集中的小型重构的难度就小多了。
为扩展而设计
越是复杂项目,越要在前期设计上多花点时间。提前思考项目中未来可能会有哪些功能需要扩展,提前预留好扩展点,以便在未来需求变更的时候,在不改动代码整体结构的情况下,轻松地添加新功能。
做到代码可扩展,需要代码满足开闭原则
。特别是像 Unix 这样的开源项目,有 n 多人参与开发,任何人都可以提交代码到代码库中。代码满足开闭原则,基于扩展而非修改来添加新功能,最小化、集中化代码改动,避免新代码影响到老代码,降低引入 bug 的风险。
最小惊奇原则
《Unix 编程艺术》一书中提到一个 Unix 的经典设计原则,叫“最小惊奇原则”,英文是“The Least Surprise Principle”。实际上,这个原则等同于“遵守开发规范”,意思是,在做设计或者编码的时候要遵守统一的开发规范,避免反直觉的设计。实际上,关于这一点,我们在前面的编码规范部分也讲到过。
遵从统一的编码规范,所有的代码都像一个人写出来的,能有效地减少阅读干扰。
在大型软件开发中,参与开发的人员很多,如果每个人都按照自己的编码习惯来写代码,那整个项目的代码风格就会千奇百怪,这个类是这种编码风格,另一个类又是另外一种风格。在阅读的时候,我们要不停地切换去适应不同的编码风格,可读性就变差了。所以,对于大型项目的开发来说,我们要特别重视遵守统一的开发规范。
总结
封装与抽象
分层与模块化
基于接口通信
高内聚、松耦合
为扩展而设计
最小惊奇原则
参考
78 | 开源实战二(上):从Unix开源开发学习应对大型复杂项目开发
从Unix开源开发学习应对大型复杂项目开发相关推荐
- 2021物联网开发学习——基于小熊派IoT开发板Bear-Pi-IOT、E53_IA1_智慧农业拓展板与小熊派-鸿蒙·季Bear-Pi-HM Nano并接入Hi-Link
2021物联网开发学习--基于小熊派IoT开发板Bear-Pi-IOT.E53_IA1_智慧农业拓展板与小熊派-鸿蒙·季Bear-Pi-HM Nano并接入Hi-Link 目录 作者介绍 目的 用到的 ...
- 恩施软件开发人员每月多少钱_恩施软件开发学习,恩施软件开发学习哪家好,恩施软件开发学习一般能拿多少工资...
恩施软件开发学习,恩施软件开发学习哪家好,恩施软件开发学习一般能拿多少工资 首页 > 软件 > 恩施软件开发学习 作者:镀金池 发布时间:2017-11-22 18:54 因为cent ...
- java项目开发实战入门电子书,java项目开发实战入门全彩版
<JaWeb项目开发实战入门>以企业门户网.51商城.BBS--程序源论坛.YouKnow问卷.OA办公自动化系统.铭成在线考试系统.K12(中小学)综合测评系统和Show--企业个性化展 ...
- 浅谈软件开发工具CASE在软件项目开发中发挥的作用认识
浅谈软件开发工具CASE在软件项目开发中发挥的作用认识 内容摘要:阐述了CASE工具作为 一种开发环境在软件项目开发中所起到的开发及管理作用.CASE工具实际上是把原先由手工完成的开发过程转变为以自动 ...
- 项目启动 ora-00942:_如何解决大型软件项目开发难题?唯快不破!
目前多数信息管理软件可以满足行业内的通用需求,而在特殊流程和场景定制上成本很高.对于大型软件项目需求方来讲,主要面临三方面难题: l 软件行业专业性强,产品业务和技术实现衔接难: l 供应商及其输出品 ...
- 微信开发学习总结(三)——开发微信公众号的最基本功能——普通消息的接收和回复...
2019独角兽企业重金招聘Python工程师标准>>> 一.微信公众平台消息管理接口介绍 要实现微信公众号的普通消息的接收和回复,我们需要先熟悉微信公众平台API中消息接口部分,点此 ...
- 微信开发学习总结(三)——开发微信公众号的最基本功能——普通消息的接收和回复
在上篇<微信开发学习总结(二)--微信开发入门>我们介绍了微信公众平台的基本原理,如何接入微信公众号,如何保持access_token的长期有效性以及进行了简单的文本消息测试,本篇再来具体 ...
- python项目开发实战网盘-python项目开发实战 第2版
python项目开发实战 第2版是一本Python项目开发流程实战手册,由日本BePROUD股份有限公司编著.本书的内容全部基于python开发事实,全部都是BeProud员工实际尝试.实践过的,可以 ...
- 开发vue用什么ide_VUE项目开发前期需要准备和配置些什么环境?
VUE项目开发前期需要准备和配置些什么环境? Node环境 下载:https://nodejs.org/en/,安装在G盘 npm包管理工具(package manager)自动安装完成. 使用npm ...
最新文章
- 遍历list、set、map和array
- 服务器支持热部署吗,热部署
- Linux面试最常见的5个基本问题
- matlab armax 无法识别,求教:Java调用系统辨识工具箱内的armax函数出错
- 1.5 编程基础之循环控制 45 金币 方法二(python3实现)
- linux给目录加裸设备磁盘,Linux添加裸设备空间(Redhat)
- 表单组件中state依赖props
- Retrofit2从入门到放弃
- Win7安装curl工具、解决PowerShell ISE中文乱码问题
- mysql 分组之后统计记录条数
- UNIQUE constraint failedの原因
- 实现自定义背景色、前景色、显示进度的进度条
- linux usb转串口驱动报错,USB转串口驱动编译出错
- Nuvoton M031-时钟树
- 营销科学学会2021年年会揭晓玫琳凯博士论文奖得主
- 6.Java设计模式之设配器模式
- html5网页设计 薛之谦个人网页适用个人博客网页模板
- 详解项目管理中任务、成本、产品三者的关系
- 程序员如何正确的自我提升?
- 未来-区块链-Aliyun:阿里云IoT - 所知不止于感知
热门文章
- mockjs的介绍、基本使用和封装
- google地图网页版_谷歌收录查询方法大全,如何让Google快速收录网页?
- 开源私有云盘python_用Seafile不花钱搭建高安全性局域网私有云盘
- wx.chooseimage 超过了最大请求长度_一次 HTTP 请求到底经历了什么?
- 下载和安装CUDA和Cudnn(图文详解)
- redis分布式锁简单总结
- python 文本框内容变化_当文本框中的文本发生变化时,动态读取文本输入中的文本?...
- dfs dtft dft fft
- 在后台增加一个查询条件
- 数据库mysql的注释怎么加_mysql表如何添加字段注释