大泥球——世界上最常用的软件体系结构,一个经久不衰的传奇。

大泥球是一件很神奇的事情,阅读文章里列举了大泥球出现的一系列原因,但是我们貌似很少在其他的领域看到这么不专业的专业行为,从这个角度看看,不妨稍稍刨根问底一下。

我觉得首先有个成本问题——软件开发可以说是没有物质成本的。可以看到大泥球能够工作,而且,造成一个大泥球并不比有道理的开发架构需要更多的物质成本,多调几个大泥球经费也不会被马上耗光——一个失败的设计在量产时需多焊很多的电路板可能会马上被产品经理批评——相反,软件工程中的大泥球还能提高时间效率,它能减少了架构设计的思考占用的时间——这一点我还是很有体会的,之后我会提到之前的课程学习经历来简述我的体验。

另外文章说到的能见度也是一个有趣的原因,闭源的软件产业使得产品和设计的分离,设计对于用户乃至其他开发人员来说常常是不可见的,软件开发者并不在意软件的内部架构在用户看起来是什么样,反正你也看不到,软件就像是一个神奇的魔法盒子,不管它怎么工作的,反正有用。

对于软件开发,效率是至关重要的,代码重用是提高效率的一个重要思想,但是正如文章所说也是风险,一个仅需要适应当前需求的架构可以快速完工并且投入工作,但当需求变更来临的时候怎么办?架构扩充还是一件小事,有时候新的需求甚至可能会扰动架构的根基,在这英雄的悲剧时刻通常有两种选择:

1.推翻架构的一部分或者全部以适应新的需求,再开始新的编码——无论是一部份还是全部,架构的改变都可能影响架构之上的其他代码,你都不得不考虑兼容性,一旦兼容无法实现又是另一出悲剧,就算侥幸地架构师是一个天才,几天几夜的设计之后,更新的架构能够承担新的需求并且完美兼容之前上层建筑,那么——用户说他还想要来一个新需求呢?

2.或者为了开始一段架构之外的罗曼,作为一个补充,有时候可以在架构之外补充一段代码,横跨底层至用户界面,就像一栋精致的别墅从地板到天花板被开了一个洞,露出了一根电线杆。同样地,再来几根,一颗裹着别墅的大泥球诞生了。

为了避免这些悲剧的发生,一个勇敢的架构师说,我们应当预先考虑大部分可能来临的需求,我们的架构需要在实现当前需求的时候,同时拥有良好的可扩展性,新需求来临的时候只要扩充就可以了。为了提供预留的这些需求以扩充实现的,便不再有眼前需要设计的小屋,而是一座城市。这个架构本身就需要足够多时间去设计和建造,相比架构本身,需要实现的功能才成了真正的小部分。结果延长了工程周期,很多人认为这不值得,而且也没人相信有一个牛逼的架构能够轻易地扩展实现不讲理的一切用户需求,即便有这样牛逼的架构,也没有这样牛逼的人……

回过头来谈谈实际,我作为一个不偏向于大泥球的程序员,一定是对良好架构有这特殊坚持和憧憬的。因为我的理论是没有架构的工程就像是不写函数的程序……增加项的工作量是平方的甚至是指数,那是要死……那不科学……我理解中架构的一个有点就是层次地整理可以重用的代码来减少代码量,提供可维护性,缺点在于不灵活,然后对于经验不足的初学者来说,开发周期有时候是更长的。还有一点,当一个人做的不完全是真正的产品,而是一个试验品、或者说是简历填充物的时候,能见度原因就不起作用了,因为要是说代码给别人一看,让别人觉得,这TM写的一坨大……肯定没有前途。所以我必须坚信写软件要有架构。

我大二上的Java大作业和大二下面向对象大作业,基本都是一个人写的Java小游戏,是个泥球vs设计的正面例子。

Java大作业就像一个大泥球,我只求每个单位只管自己的所有逻辑,能够运行,有点像用FlashAS写小游戏的感觉,最后我做出了一个可以玩的版本,只有三个游戏单位,三种子弹,三种效果,一个不太完善不容易制定的固定规则和友好度较差的界面。开发时间之有大约两周,也算有始有终了。

当我在大二下应对面向对象大作业的时候,我觉得有了上次的经验,这回我应该能不太费力地写出一个游戏内容更丰富一些的游戏,增加了一些目标的游戏内容量和网络联机功能,等于是对原来的Java大作业作一个扩充。这个时候,我发现逐个单位去考虑各自的逻辑是个噩梦,工作量太大了,而且不便维护,从而开始考虑一个架构。举个架构主要功能来说:希望用一套逻辑抽象来所有类型的单位,然后以数据文件来定义不同单位的逻辑,这样就需要一个能够用动作跳转的数据结构来控制单位运动逻辑架构,而且这个动作结构又万能。仿照我之前接触过的游戏数据形式,我进行着这方面的尝试,结果大约从开始集中注意力写作业到一个月过去之后,基本以失败告终,因为剩下的时间已不多了,剩余工程已经非常巨大,光游戏逻辑还有几十个类没有实现,类之间的工作互相依赖,逐个单元测试工作量也极其大。眼看快要到死期了,果断放弃了新架构的设计,转而使用简化的代码状态机(而非数据状态机)编写。最后的情况是一个简略得多的架构完成了整个场景只有四种游戏物体的游戏,然后有网络联机功能,一坨翔。

不服,果然在之后的大二暑假我还是用C++和DX完成了之前未完成的架构。花了我一暑假。而且在架构实现和游戏实现的过程中,遇到了一些架构设计时未考虑的问题导致游戏实现过程也在反复修改架构,这经验太宝贵我会出去随便乱说?

有了这次失败之后我认识到架构设计有难度的……首先设计就是有难度的。然后实现是更有难度的。而且我坚信了,一定没有人会愿意用一套动作游戏的动作引擎来编写动作相对简单的射击类游戏的!动作游戏需要动作引擎是因为的具体单位的动作编写复杂性太高需要的代码太多了!而我做的游戏是动作射击游戏!

我一瞬间懂了,所以架构的设计是目标驱动的,如果没有一个合适的目标,大泥球还是更合适一点。没有足够经验的开发人员希望借助一个nb的架构减少自己的工作量是愿景很美好。而且你不能说要做成什么样我马上就设计成什么样,首先我要试一下。

这些经验我带到了软件工程大作业中,鉴于经验还不足够多到能马上给出一个足够优秀的架构,而且游戏内容必须不能太少以至于不能改变世界,我很谨慎地先制定好了游戏设计的需求,坚决不要考虑基本不需要的功能,首先使用一个“架构非常简单+只有少量基本单位+部分地方由小泥球组成”的原型工程,来看看架构设计的需要。然后才和安然开始正式的架构设计,并且和团队开始完整的开发。如此慢步前进,虽然工程开始的时间相对其他小组较晚,但是……大作业能够追求一体成型(希望)……

学生团队有一个好,就是架构设计搓了,也还不要紧,不至于流落街头要饭,回头还能滚泥球一下。这使得我们有机会积累更多的软件工程经验,避免今后真正进入职业了,也只能天天往工程里塞泥巴。我也以为大泥球依然在正牌软件架构中有极高市场占有率的原因,是太多软件工程不敢有足够宏伟的目标、承担不起时间和尝试的成本(也就是没有足够NB的架构设计师嘛)。不经历风雨,怎见得彩虹?一个PM既得要堆过泥巴,也有过足够多的失败设计,才能有一天能够站出来,给出一个顶级的设计,力挽狂澜。