3.271. 一些架构设计引导的例子
因为我总在公开的地方写架构设计的总结,所以常常有同事私下找我引导一下他们的架构设计,我平时都根据具体的案例提取一些总结写在不同的文档中了。但现在我发现,有一些特征不那么明显的案例,可能对一些人来说,也是很有帮助的。我们不能把难的东西提炼出来,因为在实际中很多人反而是被一些我们觉得不难的问题给拖住了。我希望通过这个文档,收集各种架构设计中有疑问的案例,供在架构设计上遇到困难的读者参考。
和其他案例一样,为了避免和实际的产品拉上关系。这里的案例我都故意转换了设计主题,但基本上和问题是可以在很精细的范围上贴合的。比如明明是一个NoSQL数据库的存储问题,我会变换成一个Json文件的存储问题,问题会是一样的问题,但对应不到任何产品上去,而且如果那个设计涉及高级的,有专利的算法,我也会把它替换掉。我们把重点放在构架设计思考问题的模式上,不讨论每个具体技术本身。
3.271.1. 一个测试脚本的案例
有一位做测试的同事找我,他说他手上有一个python脚本,用来做各种电气化测试,大概的意思是在PC上运行一个脚本,设置一组信号/电源发生器,经过一段时间的测试后,就从各个传感器里面读数据,生成报告,然后评估这个被测系统的电气特性是否正常。
他说,他支持了很多很多的DUT(被测试设备),信号源和传感器,现在这个脚本已经很大了,但不知道怎么优化这个脚本的架构。
上面其实只是我的一个总结,实际上这位同时尝试了几次,都没有能够说明这个脚本到底是什么样的,最后只能把代码拿出来给我看。
首先,我认为,如果描述不清楚,那就不可能有架构。架构就是你对这个实现的总结,你没法总结,就意味这逻辑是发散的,没法用一个可以描述清楚的方法来抽象它。所以,架构设计最基本的方法就是用人话来总结你到底做了个或者将要做个啥。
但如果实在抽象不出来怎么办呢?那我们就承认我们没有架构,没有架构就直接线性写程序,你不是有很多测试吗?每个测试一个目录,分别写脚本,这总可以吧。
你写了两个,有重复代码吗?有,就另外拉一个目录出来,但凡重复的,都写成一个公共函数,这样至少就没有重复代码吧?等你这些函数之间共享的数据多了,我们就知道怎么建一个class,建一个公共接口(比如用json描述你的测试报告)了,那时就有架构了。
架构最怕是你没有发现规律的时候强行制造一个规律,比如你非要认为你的测试过程一定是:init->setup->start->collect_sensor->report这样一个过程,等到用于某个设备的时候,每个发现都和这个规律不一致,你就只好在每个过程中对那个具象写特殊逻辑。这样的结果是这个抽象本身就成了具象。这个架构设施就从简化系统,变成复杂化系统了。所以架构设计我们强调不敢为主而为客,强调不为天下先。我们不是为了做架构而做架构,我们是为了做目标系统而做架构了。这一点很多初学者都看不上,但这一点恰恰是成败的关键。
3.271.2. 一个中断控制器设计的案例
有一位同事做了一个中断控制器的方案让我评审,他的目的是把CPU主动发出的中断发到同构或者异构的其他处理单元上。所以他做了复杂的路由表,描述了从各种不同的中断源到目标的转换过程。我对此听得云里雾里,我认为这是一个失败的构架设计。
它的失败在于,它尝试描述一个算法,却不能把这个算法放在一个独立的闭包中。也就是说,他没有抽象他解决问题的所有条件,就开始写他的算法了。你可以看懂一个函数,但不告诉你输入参数是什么吗?
同样的,你看一个中断的路由算法,可以在没有任何Topo的定义的情况下,看懂这个算法吗?
实际上,他也不是没有写Topo,他的问题在于,他的Topo是建立在一个具象上的。是某种实现的Topo上,如何实现这个算法。但你的中断控制器只用于这个具象吗?如果你说是,我就有这个约束,那没有问题,我们就用这个Topo来分析你的算法了。但你又不是,然后你给我讲这个精巧的算法,说这先发给谁,又发给谁,然后从谁那里查了个什么参数,我都听不进去,这好比你解一个三元方程每个元x, y, z的值域,你给我讲如果x=0的时候如何如何,我一点兴趣没有,因为定了x=0的时候求出来的y和z的值域有啥用呢?除非你能用这个为基础可以求x不是零的范围,然后把两者合并起来,但显然这里又不是这种情况。