[阅读: 508] 2010-09-26 05:57:32
要有一个软件
程序员和客户在星巴克第一次见面。客户很忙,在他们见面的一个小时里,客户有无数个电话进出,包括下单指令。
程序员则比较闲,没有一个电话。他是自由职业者,因为厌倦了加班赶领导制定的最后期限,他选择了辞职。在家里接一些小项目,时间和费用自己说了算。另外还译些技术书籍,偶尔出去讲点课,教别人怎么写程序。
客户拿出他的笔记本,程序员首先注意到了他的3G上网卡。程序员也想过拥有一张,但觉得资费太贵,不值。再说在家的时间居多。客户说他主要是做投资的,股票、外汇、期货全做,但最主要是做期货。程序员努力搜索自己在这方面的经验,可惜的是,没有。这些东西对他来说,只是听过的名词,仿佛是另一个世界的东西。工作十多年来,程序员一直醉心于技术,没有开过股票账户。对于期货,他只知道那个东西比股票厉害,可以让人输光。
客户先讲了一通期货的好处,以提起程序员的兴趣,然后说现在圈子里开始兴起程序化交易,用计算机下单,一个朋友已经通过这种方式赚了不少钱。
程序员终于想到了一点相关的经验,2年前一个在华尔街的台湾老板要在上海找一个研发团队,做的也是程序化交易系统。看来这是一个趋势,值得去试试。毕竟,除了时间,他不会损失什么。
要有一个软件,根据某种指标下单,然后根据行情变化止赢或止损。这就是第一次谈话的结论,双方初步达成合作意向。几乎所有的软件项目都是从这样一个模糊的想法开始的,刚开始的时候只有方向,没有细节。
一无所知
程序员真正感受到了苏格拉底的名言:我只知道,我一无所知。好在程序员的学习能力比较强,了解期货的基本知识应该不难。但麻烦的是,客户对交易策略也是一无所知!客户对程序化交易的了解也非常有限,不知道怎样的程序能够帮他赚钱。他那个赚了钱的朋友,没有透露细节。
更要命的是,双方对对方的能力水平也都是一无所知。实际上,双方的承诺仅仅是,我们愿意花一点时间和精力来了解彼此,尝试合作的可能性。
接下来最重要的事情就是迅速建立一定的信任。客户把程序员带到他开户的期货公司,让程序员体验交易现场的氛围,并努力让程序员相信,只要这个软件写得好,前景无限光明。程序员担心的开发费用根本不是问题。
然后程序员也必须向客户证明他的开发能力。根据程序员这些年对敏捷软件开发的研究,他知道项目成功最重要的事情,就是以小得多的成本,快速地、持续地实现客户价值。具体的手段就是“早交付、常交付”。
早交付、常交付
客户以前曾经尝试过程序化交易。投入了10多万元,最后连一个可以跑的程序都没得到。这是软件取得初步成功后客户告诉程序员的。同时客户也从新闻中了解到,在刚刚过去一年的全球金融危机中,当巴菲特也输钱的时候,有人狂赚了25亿美元,而此人全仗计算机交易策略。未来已经到来,只是分配不均。所以客户在和程序员合作初期时的心情,是既认准了程序化交易值得继续尝试,又怀疑程序员的能力和水平。
由于软件行业有大量的失败项目,导致了大家对项目成功的期望值不高。对于一件成功可能性只有50%的事,有兴趣做的人不是太多。然而客户的看法与一般人略有不同。因为做的是期货,他知道未来有两个方向:涨或跌。而且如果操作得好,跌势中同样能够获得收益。程序员平时喜欢下点围棋。他知道每盘棋有两种结果:赢或输。在赢棋或输棋的时候,都能够学到东西。失败不代表没有收获。
客户从前一次尝试失败得到的经验就是,在程序员证明其能力之前,不付开发费。客户换了一种让程序员比较能够接受的说法:赚了钱我们分成。
对程序员来说,在十多年开发经验中学到的最重要的一点,就是要以最快的速度帮客户用程序实现盈利,让项目避免被取消的命运。但在客户想明白程序化交易策略之前,他需要做一些工作来证明能力。做些什么呢?
快速熟悉编程接口,用程序获取即时行情信息。程序员花了2周的时间就做到了。再尝试一种简单的策略,让程序实现自动交易,即实现挂单、撤单和成交判断。程序员在2个月内做到了这一步。这种简单的策略虽然赚钱的效率不高(按资金的时间成本来看,基本上就是不赚钱),但它证实了程序化交易的可行性和程序员的能力。
接下来要解决的问题,就是程序员已经2个月没有入账了。程序员没有太多的积蓄支持他这样无收入地工作下去。对于一般的项目,他可以免费干一个月;对于有特殊兴趣的项目,他可以免费干两个月。现在已经到了他能承担的极限。
从另一个方面来看,如果客户不付开发费,程序员担心风险增大。项目开发不是单方面的工作,如果客户投入不够,项目失败的可能性很大。
经过商量,程序员和客户达成协议:从现在开始,每个月支付5千块开发费用,年底从盈利分成中扣除。程序员对客户怎样实现盈利仍然没有把握,但至少已经取得了不错的进展,一些未知的东西变成了已知,事情可以继续做下去。
项目的制度安排,是项目成功的重要保证。制度决定行为,它让开发双方成为一个利益共同体。交付制度和支付制度是关键。谁给我们安排下幸福的生活?是制度。制度是协商的结果,是契约。
放大人类的智能
接下来的工作重点就是要实现盈利。让程序赚钱并不难,人怎么赚钱,计算机程序就怎么赚钱。程序只是做得更快、更准确。
鼠标发明人恩格尔巴特说,计算机的作用是放大人类的智能。但是同时,它也能放大人类的愚蠢。计算机只是一个工具。A fool with a tool is still a fool, but maybe a powerful fool.
客户在没有使用程序化交易时如何盈利?有两种方法:投机和套利。程序化交易就是要实现这两种方法,并比人做得更好。
人类的优点是有智能,计算机目前还没有。人类的缺点是有恐惧和贪婪,计算机目前也没有。计算机的优点是速度快、准确,而且不知疲倦,人类不具备这些优点。
项目成功的要点在于,为聪明人提供合适的工具。
设计有3个阶段
Dorothy Sayers(英国作家和戏剧家)说,设计有3个阶段:概念结构的形成、在真实媒质上的实现、与真正用户的交互。程序员非常了解这一点,因为Martin Fowler等研究敏捷方法学的前辈已经指出,设计只有一种形式,就是演进式设计。
程序上线后客户建议,交易成功时程序应该提供报警,最好是播放一段音乐:“赚钱了,赚钱了,我都不知该怎么花……”因为在程序运行时,客户往往同时在做别的事情。放一段音乐有一点夸张了,这会为程序带来不必要的复杂性和依赖关系。但是让计算机喇叭叫几声还是容易的,客户接受了这种方案。
程序是一个控制台程序,每次执行一个策略。同时执行的策略一多,就难以搞清楚是哪个策略完成了。程序员想到了最简单的解决办法,在策略完成时将策略再输出一遍。
程序开始时没有图形界面,因为程序员预计编写图形界面会花掉额外的开发时间,特别是在业务逻辑还不清楚时,会有大量的返工。对这个项目来说,前期的工作重点不在于界面。客户通过文本编辑器来设置策略,那是一个友好的JSON文件。在程序取得初步成功后,客户感到了设置策略的不方便,费时多而且容易出错,提出最好有一个图形界面。此时,因为业务逻辑已相当清楚,界面工作量就小了很多。几乎没有返工,程序员花了一天的时间,写了一个界面来生成那个策略文件。
程序员与客户并肩工作,观察什么事情让客户痛苦或迷茫,然后再设计出解决方案。没有实践检验的设计永远是未完成的设计。所有成功的软件,要么开发者自己就是用户(这样他就能直接体会到用户的痛苦和不满),要么开发者真正关心用户的体验,愿意去改进这种体验。
唯一不变的是变化
这是一个成功的项目,客户和开发者都很开心。年底收回了所有研发成本,还略有盈余。当年实现了赢利,剩下来的事就是扩大规模。然而在某一天,客户告诉程序员,原来的交易网关要停掉了,新的交易网关不再提供协议接口,改为提供dll库。另外,程序应该能支持外盘的交易,外盘有不同的接口。
程序员受打击了。现有的程序是Java写的,包括图形界面。但面对新的网关接口,显然用C++写更合适。程序员上一次写C++已经是10多年前的事了,那时候还在用Borland C++ 3.1。这些年来,程序员一直在玩Java。虽然有人在项目开始时就建议程序员使用C++,因为Java可能有性能问题,但是程序员知道自己最熟悉的是Java,而且解决这点问题用不着复杂的框架,性能完全可以把握。
程序员一度想利用JNI,只重写网关接口的部分。程序员尝试用JNI技术取得行情信息,发现部署的Jar包明显大了一个数量级。而且接口是回调式的,用JNI的复杂程度甚至可能超过了用C++重写整个程序。
想起Kent Beck前辈的话,要拥抱变化,程序员终于下决心用C++重写。
在变化面前,哪些东西可以复用?需求没有变化,测试用例没有变化,基本类设计没有变化,甚至那个Java写的界面部分也不用变化,可以直接拿来用。虽然很重视开发进度,但程序员还是保留了一份特征列表,即最简单的需求文档。测试用例就是测试套件,逻辑不变,只是需要用C++重写。
程序员从他的朋友那里寻求所有可能的帮助,包括如何使用集成开发环境。用了10多年Java之后再来写C++,程序员发现自己的视角发生了很大的变化。
拖式进度
老网关将在某月某日停止运行,因此那就是一个最后期限,而最后期限没有道理可讲,不可讨价还价。对此,程序员采用了拖式进度,即从最后期限开始倒推。同时,程序员根据自己的经验,确定各项工作可能的工作量。找出那些必须完成的工作,只做必须做的事。
同样,程序员仍采用“早交付、常交付”的方法。在取得行情、实现交易、实现策略的时候,交付小的里程碑版本,并在真实环境中部署。这样大大降低了项目风险,使进度变得可控。
程序员的特点
现实生活中,程序员厌恶排队。哪里有排队,哪里就有浪费。时间是唯一的资源。在工作上,程序员厌恶让工作排成很长的队。看不到头的工作排队让人心情沮丧。因此,程序员不是把所有的需求都收集清楚后再开始设计,而是致力于快速解决用户的每一个请求,无论是功能增强,还是缺陷修复,尽量缩短从客户请求到价值实现之间的时间,降低开发的成本。程序员对客户说:“美好远景我知道了,现在你告诉我,下个月对你最重要的工作是什么?”程序员知道,帮助客户实现价值,是自己实现价值的唯一方式。
程序员对重复很敏感。重复在很多时候都是一种浪费。当类似的代码片断反复出现时,程序员会提取出新的方法或类,即新的概念抽象。消除重复带来的直接好处就是软件更容易适应变化,当变化到来时,程序员只需要做最少的改动。
程序员注重软件的内在品质,整天思考的就是怎样才能做得更好。为此,他愿意付出更多的努力。程序员喜欢把写程序比喻成写诗歌,不必长,但一定要生动和深刻。程序员对测试代码和产品代码一视同仁。程序员享受创作的快乐。
软件每天都在变化,程序员也每天都在变化。项目还没有结束,程序员感到自己在进步。