仓库源文

.. Kenneth Lee 版权所有 2021

:Authors: Kenneth Lee :Version: 1.0 :Date: 2021-16-15 :Status: Release

细节的丢失


本文尝试从一个更容易理解的角度探讨一下架构设计是什么。

我们建立一个数据结构:

.. code-block:: cpp

class Student { private: string Name; bool IsBoy; int Age; static class Student gAllStudents[MAX_STUDENT_NUM];

    public:
            Student(string Name, bool IsBoy, int Age);
            class Student *FindByName(string Name);

};

这是代码,但不是全部的代码,但我们看了这个数据结构,我们就能拼出这个代码一部分 的图样来:它把每个学生封装成一个Student对象,保存在一个数组里面,用name作为 index进行查找。

至于怎么查找,是顺序比较,还是基于Hash来抽取,这里没有说。如果我们用这个数据结 构作为抽象,那么如何查找这件事情,就是被抽象的部分。所谓“不知”。我们既不关心它 是这样,也不关心它不是这样。我们关心的是:我不用那个做我其他逻辑的根。

这就是架构设计的核心。架构设计是其他设计“架子”,是其他设计可以依赖的“根”。所有 坚挺的逻辑,都需要其他逻辑为基础,架构设计自身也不例外。架构设计是建立一个逻辑 ,这个逻辑有自己的根,一路搭建上去,每个下级逻辑都有其他的根去支撑。但它不碰其 他“不知”的部分,把这些部分留给下一级设计作为自由度 (如\ :numref:图%s<图:架构设计的知和不知>\ ):

.. _图:架构设计的知和不知:

.. figure:: _static/架构设计和不知.svg

架构设计的知和不知

所以,架构是精确和不完整的。它的作用是让我们看看在这么粗疏的逻辑链构建中,是否 都有不可逾越的逻辑障碍,导致这件事情做不成。这种被单独拉出来的逻辑链,就是我在 其他地方描述的“逻辑闭包”,也是很多架构设计资料中说的“视图”。只是强调点不同。逻 辑闭包更强调逻辑的自恰性,而视图更关注逻辑抽象的分类。

我们可以有无限的抽象的可能性,可以有无数的“视图”,那种视图最有利于我们发现未来 细节中的破绽,这取决于我们如何抽取属性。所以人们常常认为这是一种“艺术”,因为它 和其他“艺术”,比如舞蹈,绘画,写作一样,关键在于你抽取哪个属性。如果追究它的本 源,是因为抽象是个“机器学习”的结果,是人脑在大量的细节训练后,单独在大脑中留下 的一组参数,每个人的训练集不同,造就了不同的训练结果。所以,同一个抽象,在不同 的人脑子中复现为不同的样子,而做架构设计,是希望这这个模糊的范围内,取得一定程 度的共识,并把它复现现实中(最终实现出产品)。

所以,我们进行抽象,成本都在逻辑的关联上,关联少的逻辑,我们就不作为我们视图的 一部分。比如,在实际操作中,上面这个数据结构有很多东西我们其实是不关心的。比如 这个IsBoy,或者也许以后我们会需要一个IsTallerThan180mm的属性,但这些属性,和它 关联的逻辑仅仅就是“如何显示”,其他逻辑和它一点关系没有。这种属性,我们就希望忽 略。

所以你看到更多的构架描述会是这样的:

.. figure:: _static/学生数据结构建模.svg

学生数据结构建模

我们放弃掉了更多不影响其他逻辑的条件,把它们填到“不知”中。这样那个条件就是可以 变化的,这样,我们在可以在另一个上下文中决定要不要它。比如我们这里讨论要不要 IsBoy这个属性,你有什么条件来做判断呢?这个属性的判断条件是:“用户是否想知道这 个学生的性别”,这个和“我们需要通过名字查找一个学生”这个逻辑,一点关系没有。你要 正确地,详细地描述这个学生的所有属性,强行把“性别”这个属性放上来,为了判断这个 属性是否正确被使用,你就需要进入另一个逻辑空间,去问:“到底要不要显示学生的性别 ?”这就把很多的信息放到同一个逻辑空间内,你脑子就处理不了了。

所以,抽象的过程,其实是一个重要性和关联性不断进行判断的过程,而重要性和关联性 这两个属性,在每个具体场景中都不是一样的,所以架构设计没有固定的方法,只有针对 具体问题的反复判断。