在学习资料满天飞的大环境下,知识变得非常零散,体系化的知识并不多,这就导致很多人每天都努力学习到感动自己,最终却收效甚微,甚至放弃学习。我的使命就是过滤掉大量的无效信息,将知识体系化,以短平快的方式直达问题本质,把大家从大海捞针的痛苦中解脱出来。

文章目录

    • 0 引言
    • 1 软件设计的目的
      • 1.1 目的
      • 1.2 什么是好代码
        • 1.2.1 可读
        • 1.2.2 可测
        • 1.2.3 可复用
    • 2 软件设计的本质
    • 3 设计思想、设计原则、架构模式、设计模式、编程规范、重构几者的关系
    • 4 设计思想
      • 4.1 结构化编程、面向对象、分层思想
        • 4.1.1 从结构化设计到面向对象设计
        • 4.1.2 从随心所欲的设计到结构化设计
        • 4.1.3 从另一个维度去思考
      • 4.2 三个维度
      • 4.3 接口标准化
    • 5 总结

0 引言

软件设计看似浩如烟海的知识背后,设计思想也显得那么朴实无华。虽说朴实无华,但有不失优雅。

1 软件设计的目的

1.1 目的

软件为什么要特意去设计呢?最直白的目的就是为了构建和维护大型工程时更容易。

为了达成这个目的,最朴素的需求就是所有参与工程的工程师都能写出好代码

1.2 什么是好代码

好代码的定义太模糊。

较清晰完备而又不失简洁的表述方式是——可读可测可复用

下面使用反正法说明这三者的重要性。

1.2.1 可读

不可读的代码只有写代码的人能够维护,甚至过一段时间写代码的人也无法维护。

至于怎么样能使代码更可读,想必每个人心里都清楚,就是做不做的问题。

1.2.2 可测

不可测的代码只是自嗨。当自己不能完全保证代码的正确性,而又不方便测试时简直是这段代码或测试人员(白盒往往是开发人员自己)的灾难。

至于如何使代码更可测,了解过TDD,写过单元测试或自动化测试用例之后想必自己就有体会了。最简单的方式就是精细地添加测试接口或者测试Log。和上一条一样,最简单的方式有时候反而更有效,就看做不做了。

1.2.3 可复用

如果所有的代码都不可复用,工程会迅速爆炸,问题频发,变得不可维护。

至于如何做到软件复用,就需要设计思想、设计原则和设计模式的加持了。

2 软件设计的本质

软件工程的特点就是 。软意味着可以变化,但正是因为大量的变化(比如用户需求变更、场景变更、算法改进等)也会导致软件工程固有的复杂不稳定

必然要有 。软代表着变化,硬代表着稳定。

所以,软件设计的本质之一是:拆分稳定部分和变化部分

当然除了变化和稳定的区别,还有其他功能上的区别啊,难道不需要拆分么?

当然需要,那就再前进一步。

软件架构设计最本质就是做 分割和联系 的事情。想要降低耦合就要分割,想要各个模块合作就要联系。

3 设计思想、设计原则、架构模式、设计模式、编程规范、重构几者的关系

设计思想、设计原则、架构模式、设计模式、编程规范、重构。前者更抽象,后者更具体,是一个落地顺序。

设计思想和设计原则的研究对象是整个软件工程;架构模式的研究对象是组件;设计模式的研究对象是类;编程规范的研究对象是包含函数体在内的所有编程细节。

重构的研究对象是整个代码演进过程,走的是时间维度,是各种高大上理论以及繁琐编程规范落地的动态过程。

4 设计思想

4.1 结构化编程、面向对象、分层思想

结构化编程、面向对象设计、分层思想这些都是我们耳熟能详的设计思想。

但他们之间有什么关系呢?

4.1.1 从结构化设计到面向对象设计

面向对象设计的三大特点是封装、继承和多态,大部分高级语言(例如C++语言)天然支持这些特性。

我们来看看仅支持结构化编程的语言在这三个方面的表现。

结构化编程(例如C语言)的最小组成单位是函数,变量可以是零散分布的,但也可以使用源文件和头文件进行封装,甚至封装效果比C++还好(因为private 变量可以完全封装在源文件中,不暴露到头文件中);对于继承来说,使用结构体扩展就可以达到继承效果(C++中的类本身就是从C语言的结构体过度过来的),只是这种方法非常不方便;至于多态,使用函数指针完全可以呈现出多态效果(C++中的多态就是基于虚表实现的)。

基于上述分析,面向对象设计语言不是什么新东西,它和结构化编程语言可以基于同样的设计思路完成程序设计,如果说有区别,最大的区别就是——面向对象设计的高级语言将之前低级语言不好表达的思想变得更好表达了,而且做了一定的语法限制(比如虚表的实现就一定程度上限制了函数指针的使用)。

我们刚刚看了从结构化编程演化到面向对象编程的过程,个人认为最大的突破就是强化(有了好用的语法糖,才有更多的人愿意去用)了 继承 这个思想。

4.1.2 从随心所欲的设计到结构化设计

下面我们再看一下从最初的编程手法(比如基于汇编编程)过度到结构化编程(比如C语言)发生了什么。

这个过程最大的变化就是有了函数的概念,这个概念产生的底层思想就是 分而治之

有些人可能已经发现了,使用汇编难道不可以分而治之么?是可以的,但需要程序员自己约束自己——需要建立合适的label,需要精心设计跳转语句等等。而这些在C语言中已经被 语法糖 包裹起来了,程序员只需要按照语法操作就可以了,省去了一些设计细节的繁琐工作。

从上面的分析,我们能看出结构化设计的精华就是 分而治之 的思想。划分功能模块,降低耦合,可以极大地降低软件的复杂度。

4.1.3 从另一个维度去思考

除了继承、分离(分而治之)的思想之外,我们还会经常接触到 分层 思想。尤其是在操作系统和协议栈中尤为常见,甚至有人说没有什么问题不是加一层解决不了的。那分层与分离和继承有什么关系呢?

一句话讲就是:分离、分层、继承是描述软件的三个不同的维度,是线性无关的。

举个例子。人们有的当老师,有的当医生,就是使用了分离思想;而在人这一类中,又有爷爷、父亲、儿子的继承关系;一个公司乃至一个国家又是基于分层制度进行管理的。

4.2 三个维度

本小节先重申一下描述软件的三个维度:分离、分层和继承
为什么是三个维度?两个维度不行么?四个维度不行么?

继承对应着类的实现关系;分离对应着类的组合(聚合)关系;分层已经跳出了单纯类设计模式的范畴,属于架构模式的范畴了。

所以,只用分离维度设计软件就是结构化设计;使用分离和继承维度设计软件就是面向对象设计了。使用一个或两个维度都是可以的。

下面再分析使用更高维度可不可以。

继承维度作用的对象是类,所以这个维度不方便再进行扩展。但是分离和分层其实是可以交替扩展的——就像切豆腐一样,你可以横着切,也可以纵向切。

接上一节那个例子,除了人之外,还有植物,之所以有人和植物之分,就是在更高的视野使用了分离思想。这就是第四维了。对于整个世界而言,可能真是由无限维度组成的,但对于软件设计来说三个维度可能就够用了,实在不够可以根据需要随时扩展。

4.3 接口标准化

前面重点强调了怎么分割,这里我们强调一下联系

接口标准化就是在联系上做文章。接口标准化是行业兴盛的标志,也是一个软件成熟稳定的标志。

5 总结

抓住软件设计的目的、本质和方法论,其实可以不用拘泥于任何设计模式,就可以做到形散神聚了。

学习设计模式的意义在于和别人沟通起来更方便;以及孰能生巧——对于经常出现的场景可以节约思考时间。

恭喜你又坚持看完了一篇博客,又进步了一点点!如果感觉还不错就点个赞再走吧,你的点赞和关注将是我持续输出的哒哒哒动力~~