一个软件架构师的实践回顾

在接受Real的软件架构师offer之前,我在S社干了6年软件开发,涉及的工作大致分为两类,其一是开发一个相对独立的小功能模块,如MPEG解码驱动、或电视智能卡支持库等;其二是解bug,如FFMPEG在探测某个传输流时消耗时间过长,重复发起对某个HLS源的连接引发内存泄露,或者H.264解码器没有正确地辨识一个场格式输入等。
S社的架构设计和产品开发属于两个极度独立的部门,前者对产品需求理解始终不够清晰,而后者对前者的设计初衷几乎一无所知,这极易导致产品开发阶段因紧迫的量产日程而致使最初的软件结构遭受破坏性的修改,以致Bug驱动的开发模式主导整个产品周期,浪费了大量的人力物力。只是,以当年S社的雄厚实力和充足的盈利空间,足以承受这样的浪费,甚至还形成了一种先于竞争对手推出可用产品的特别模式。

所以,接受新职位时的心情相当激动,利用睡前的点滴时间,把毕业那年就背的滚瓜乱熟的《设计模式》又仔仔细细地翻了一遍。
略出乎我意料的是,我所面对的是一个构架于DOS时代的古老而成熟的多媒体框架(Helix DNA),以COM思想为核心,从WIN95、OSX、Symbia一路走来,正在努力地适应新兴的Android系统,以期补充该系统当时尚未完全发展成熟的多媒体能力集。
从代码中可以看得到前辈们不倦的努力,许多精巧的重构使得一个以单任务调度为基础的系统得以从容地运行于多线程乃至多核的环境之中,但大量古老的代码并没有被删除,许多模块从来都不会被跑到,但它们活在那里,为代码的更改和调试过程引入了诸多的迷惑。
通常,程序员会这样想:“也许它们总会被用到的。”或者:“功能多总比功能少好些。”
删除不要的代码对于程序员来说在感情上不那么容易接受——我指作者本身,接班人则总是迫不及待地删除他不想看到的部分。
我当时就是这种心态,可是,等我发现其结构之精巧慎密之后,断然放弃。兴许,只有当年的作者做得到——或者说当年可以做得到。

因此,我觉得软件的某个模块应当易于删除——任何模块都有自己的生命周期,但众多模块组成的软件系统需要有相当的演进能力。Android系统在2009年的时候使用使用一个叫做的PvPlayer的多媒体模块来支持视频播放,2010年的时候它就被彻底删掉了。
这又引入了一个更大的话题,即模块化。一个软件可以不分模块,它整体就可以作为一个模块,只要有一组稳定的人员维护着它,大家相互了解,打成一片,人在代码在,人去代码亡。显然,这是一种极度理想的场景,现实中,软件系统规模可能会间于两三人至上千人之间,开发者可能属于不同的利益相关者,有供应商、有授权商、也有外包,开发地域可能很跨亚美欧,此时的软件模块划分则成为相当棘手的问题。解决问题的核心是“调和”,如何在效率和成本之间取舍,甚至还要兼顾政治方面的考量。譬如,让中国和美国的团队各自开发相对独立的模块会相较于二者开发同一个模块风险低,尽管模块内部的复杂度会提高,以及接口的定义和协商带来额外的开销。

我起初并没有认识到这一点,还以为软件架构必须分出模块来,定义各自的接口和相互的协作,以尽可能地保持灵活性。当时,对于我来说最要紧的任务是让古老的Real Video解码器在能够充分利用多核平台的并发计算能力。FFMPEG在两年前就做到了,它使用了一个线程池来运行帧的主解码函数,然后在解码过程的特定点插入依赖检测点,在依赖关系成真的时候触发锁操作,以保证正确性。其实是一个很简单的流水线概念,我计划将其用之于Real Video系列解码器中。第一步,我先翻了一遍《设计模式》,看看有多少模式可用,然后设计了一个线程池的接口,一个任务接口,一个线程工厂,一个依赖性接口……两个月后,通过加班加点,还是成功地将解码器在双核平台上加速了30%(FFMPEG是40%以上)。然后,我的Pipeline中接到了其它任务,其后的改进和优化都移交给另一个同事——自然,面对一堆接口和工厂,该同事一头雾水。

其实一言以蔽之,架构师须是一个实用主义者,而非理想主义者
邓是个好的架构师,毛不是。

一年以后,我们要做一个视频播放及转码的软件,基于GStreamer的思想,我想出了一个简化的结构。组里开会讨论,我吐着唾沫星子讲了两个多小时,反响平平,看得出大家并不热心,只是有些同事人好,不好意思讲出来,但也有同事性子直,直言道:“乱起八糟地像一坨屎!”
我不喜争论,但也异常沮丧。当时的处理手法就是脱离群众——“大不了老子自己写。”
加班加点两个月,出来个东西,把FFMpeg的format、decoder和encoder串到了我的框架里面,来把MPEG2的avi转成AVC的mp4。其实,所做的就是:ffmpeg -i sample.avi out.mp4。
现在回想起来,还真是一坨屎。

我的经验是,程序员可以炫技,架构师不可以,架构师的特质是务实,竭力将事情简化。如果有可以重用的,尽量重用,架构师可以写出很棒的代码,但这不是他的主要职责,他要保证的是系统稳定、易于维护、能够演进。此外,无法获得团队的支持是其最大的失败

那以后,我将《设计模式》扔了。

目前,我主要专注于一个操作系统抽象、一个跨设备的系统状态同步框架以及一个基于嵌入式系统的设备管理器。这是三个相对独立却又可以相互利用的模块,它们可以为一个缺乏图形界面的嵌入式设备提供最基本的用户交互行为支持、系统状态同步以及通讯连接管理。

实践尚在进行中,且待时间来检验其成败。

Leave a Reply

Your email address will not be published. Required fields are marked *