架构的本质是管理复杂性,抽象分层分治演化 思维是我们工程师/架构师应对和管理复杂性的四种最基本武器。原文地址

抽象思维

对某种事物进行简化描述或表示的过程,只关注要素而忽略具体的细节
在系统架构和设计中,抽象帮助我们从大处着眼(get our mind about big picture),隐藏细节(temporarily hide details)。抽象能力的强弱,直接决定我们所能解决问题的复杂性和规模大小。
关于抽象层次的跳跃性,开发过程应该保证代码的抽象层次一致性,保证代码清晰明了。如在电商处理订单过程中,需要的流程如下:

  • 更新库存信息;
  • 打折计算;
  • 支付卡校验;
  • 支付;
  • 送货。
    上述流程处于同一个抽象层次上,在编写代码的时候,不应该出现一些细节性的问题,如在支付卡校验过程中,出现调用某一银行卡的支付api,这是不正确的,应该调用一个抽象的支付api,而不是细节。

分层思维

分层抽象,系统分为若干层次化的模块,每一个层次负责解决一个问题,下层向上层提供服务,一些层次贯穿所有层,被称为共享层。常见的分层模式有TCP/IP协议,操作系统等。

分治思维

分而治之也是一种应对和管理复杂性的一般性方法,一次无法解决的大问题,划分成多个子问题,然后将子问题划分为更小的子问题,直到分解成可解的小问题集合,将这些解组合拼接成子问题的解,在以次拼成原问题的解。
面试时为了考察候选人的分治思维,我经常会面一个分治题:给你一台8G内存/500G磁盘空间的普通电脑,如何对一个100G的大文件进行排序?假定文件中都是字符串记录,一行约100个字符。
这是一个典型的分治问题,100G的大文件肯定无法一次加载到内存直接排序,所以需要先切分成若干小问题来解决。那么8G内存的计算机一次大概能排多大的数据量,可以在有限的时间内排完呢?也就是100G的大文件要怎么切法,切成多少份比较合适?这个是考察候选人的时间空间复杂度估算能力,需要一定的计算机组织和算法功底,也需要一定实战经验和sense。实际上8G内存的话,操作系统要用掉一部分,如果用Java开发排序程序,大致JVM可用2~4G内存,基于一般的经验值,一次排1G左右的数据应该没有问题(我实际在计算机上干过1G数据的排序,是OK的)。所以100G的文件需要先切分成100份,每份1G,这样每个子文件可以直接加载到内存进行排序。对于1G数据量的字符串排序,采用Java里头提供的快速排序算法是比较合适的。
好,经过有限时间的排序(取决于计算机性能,快的一天内能排完),假定100个1G的文件都已经排好了,相当于现在硬盘上有100个已经排好序的文件,但是我们最终需要的是一个排好序的文件,下面该怎么做?这个时候我们需要把已经解决的子问题组合起来,合并成我们需要的最终结果文件。这个时候该采用什么算法呢?这里考察候选人对外排序和归并排序算法的掌握程度,我们可以将100个排好序的文件进行两两归并排序,这样不断重复,我们就会得到50个排好序的文件,每个大小是2G。然后再两两归并,不断重复,直到最后两个文件归并成目标文件,这个文件就是100G并且是排好序的。因为是外排序+归并排序,每次只需要读取当前索引指向的文件记录到内存,进行比较,小的那个输出到目标文件,内存占用极少。另外,上面的算法是两路归并,也可以采用多路归并,甚至是采用堆排序进行优化,但是总体分治思路没有变化。
总体上这是一个非常好的面试题,除了考察候选人的分治思维之外,还考察对各种排序算法(快排,外排序,归并排序,堆排序)的理解,计算的时间空间复杂度估算,计算机的内外存特性和组织,文件操作等等。实际上能完全回答清楚这个问题的候选人极少,如果有幸被我面到一个,我会如获至宝,因为这个人有成长为优秀架构师的潜质。
另外,递归也是一种特殊的分治技术,掌握递归技术的开发人员,相当于掌握了一种强大的编程武器,可以解决一些一般开发人员无法解决的问题。比方说最近我的团队在研发一款新的服务框架,其中包括契约解析器(parser),代码生产器(code generator),序列化器(serializer)等组件,里头大量需要用到递归的思维和技术,没有这个思维的开发人员就干不了这个事情。所以我在面试候选人的时候,一般都会出递归相关的编程题,考察候选人的递归思维。

演化思维

设计开发之初,无法对全局业务进行掌握,并且随着业务量的增加和业务的变更,设计架构需要根据业务需求不断演化。