让设计适应变化

让设计适应变化

最好的高频交易策略专家都知道,任何策略有效性的半衰期都不是很长,所以用于交易的策略必须不断改进和更新。类似的想法在高频交易系统的设计中也是有效的。所有的软件工程师都明白,有些软件在设计中为将来的拓展预留了空间,而有些在设计时则没有这么做。大多数工程师会在设计中为两个目标而努力一一模块化和低耦合。模块化的含义很简单,它是指在建设一个庞大的系统的过程中,首先设计并建造许多相互之间相对独立的小模块(虽然在设计时仍然不可避免地会考虑到它们之间的关联),之后将这些小模块关联在一起构成整个的庞大系统。而耦合性是指系统模块之间的交互,或者说通信的方式。如果这些通信接口简洁且开销很小,那么这些模块就被称为低耦合的。在这个概念的另一个极端, 高耦合的模块之间需要相对来说很复杂的通信机制,所以它们之间相互依赖的程度很高。为了让系统能适应变化,设计的目标应该是一组独立性很高的组件( 或者说对象) ,它们通过一些很简单的接口将各种复杂的内部操作或实现隐藏起来。使用低耦合的组件构造的系统相对来说更容易修改,因为要在这样的系统中添加新功能,你只需要创建并引入新的对象就行了。在系统改造时,这样的架构也能更好地抵御对系统结构的破坏而显得更加优越。

最理想的系统设计目标是一一或许它显得有些乌托邦了,在你改造、修复系统中的某一个组件,或是向系统中添加一个全新的组件时,对系统的其他部分不会造成或者只会造成很有限的负面影响。这个目标的反面则是一个非常脆弱的系统,它的内部相互依赖关系太过复杂以至于事实上没人能把它弄清楚,即使一些几乎完全无害的漏洞补丁也有可能使整个系统瘫痪。你决不会想要一套这样的系统,就像你也绝不会想要一辆只是换个前灯就会让刹车失灵的汽车。

模块化和低耦合本身是来源于软件系统设计的概念,但是当你在管理一个构建面向适应未来变化的系统的工程时,这些概念也派得上用场。在这里,方法论是一门艺术,不过大多数人谈起方法论的时候,因为这个词太深,往往都会失去兴趣。人们在使用这些概念时很容易越界,用空谈和大话取代了真实开发中的常识和经验, 要是有几年实战经验的软件开发者都会明白我所说的意思。

尽管如此,还是有一些方法和实践能够得到绝大多数人的认可。它们中的绝大多数都与演进式的,或者说递进式的、迭代式的开发方式相关,而与之相对的则是"大爆炸"式的开发方式( 这是指一种在庞大的系统开发之前就将与它相关的所有细节规划好的方式)。在一个演进式的系统开发中,你需要做的第一步是勾勒出一个整体的系统框架。在整个工程开始前,你需要得到整张图画的大致蓝图和终极目标。使用一支可擦写的白板笔来勾画这张蓝图,绝对要比用擦不掉的墨水笔明智得多。一旦完成了一个试验性的设计方案,你就可以开始建造你的系统了,最好是从那些最困难、风险最高的组件开始。你可以先构造出一小部分的组件,将它们放在测试环境中,并诚实而谦虚地评估一下哪些部分能行,哪些部分行不通。然后再回过头去修改它们,当你得到了一个能够运行得比较顺利的系统核心时,就可以向其中添加新的功能和组件了。这种构建系统的哲学是从人们反复从自然母亲身上借鉴而来的:一个真正能够运行良好的复杂系统一般都是在更简单且可行的系统的基础之上演进而来的。

当你努力尝试去设计由低耦合的对象组成的系统架构和能够为伟大软件的演进提供基础的开发流程时, 也可能会因为过于执著于这样的目标而走得太远。当然,模块化和渐进式开发这些概念的正确性实在是太显然了,几乎是不证自明的,但是真正的挑战在于,你需要想起那句古老的谚语:"不要让追求完美成为达到优秀的敌人。"回到现实中来,我们还是需要削减支出、支付账单, 需要取悦投资者和股东, 一个总是停留在白板上的系统设计方案是没有多大意义的。你永远也不可能确定地知道什么时候能够得到一个足够好的架构和开发流程。这些都来自于经验,但即使是经验也无法为你提供确定的答案。当我还在美国银行工作时,虽然我们拥有很多天赋异禀的交易员和程序员,但当我们在构建一个固定收益衍生品的定价系统时,还是会互相提醒,我们的任务只是在基于常规的基础上"把事情搞定" 。同样,我们需要在系统开发的过程中不断说出或者写下"GSD " 这几个大写字母。来提醒彼此:我们的任务是做出好的软件,而不只是构造伟大的想法。