OO 需求搜集
我曾经看到过一份统计,每年有 60% 已编好的程序在完成后几个月内被废弃,这倒不是因为程序没有实现它的任务,而是因为它没有实现任何有用的东西。当然,由此导致的生产力下降大得惊人。此外,生成的大部分代码是非常正式 -- 他们产生了大量的文件,为了完成他们所想的设计。很显然,他们所做的没有起作用(参阅参考资料中 Steve McConnell 的社论, 同样很明显,没有设计而继续也同样不起作用。如果计算高科技创业公司的失败率,我猜想这个百分率现在甚至高于60%。
我坚信失败的主要原因之一是,大多数程序员在软件开发过程中没有一个有关他们将要做什么的清晰的想法。对于一个有用的程序,必须要问那些将要使用该程序的人,该程序所必须要做的。然而,该步骤经常被全部忽略掉。相反,自己只是找一个真正用户的代理(譬如销售人员)来试图虚构他们称之的所谓的需求。事实上程序设计者与真正用户之间需要经常交流,但在这种情况下用户不可能让程序设计者了解他们所需要的。那么,我们的首要任务是解决必须做什么,而不是如何去做。(大多数程序员会立刻将精力集中到如何去做:用什么数据库?象什么样的数据模型?象什么样的 UI? 数据结构怎样?这在目前是多么的不切实际--先抑制一下这种冲动!)
在 OO 说法中,问题定义的第一步称为正规问题说明书,在以后的几个月中构建这些问题说明书是我们的任务。
在系统中,问题说明书经常忽略需求方面的搜集。我更喜欢用问题定义这个术语,因为“需求搜集”通常包含一些关于需求是什么以及您如何去搜集它等方面的不正确的假定(至少从 OO 角度)。在传统的处理过程中,经常根据一些第三方提供的功能来形成功能性需求规范,譬如市场部门。事实上,这种需求是虚假的,您是不能控制的。您会发现在 OO 环境中这种类型的文档 -- 特别是功能列表 -- 几乎是毫无价值的。那些提供算法和指定性能需求的“功能性需求”对于 00 交付是一个有用的附录,而他们不是最中心的。“功能性需求”指定了 UI 行为、工作流等,其原因我们在下几个月讲解。
细化您的说明书
问题的说明书应该是精雕细琢的,这是整个设计成败的关键。不要去做那些细支末节的工作,因为他们几乎不能抓住体现问题的微妙之处。如果您不能用清楚而组织良好的语言去说明书它,那么您所理解的问题就不足以使您设计出任何东西。良好的语法也是至关重要的;它提供了良好的结构和精确的表达方法,否则会使所要表达的想法一团糟。在任何一个设计组中,一个优秀的拷贝编辑也是非常重要的。
这里还有一些有关写作过程本身 -- 即需要准确的语言,但是在谈话当中就无需如此 -- 这能够帮助您发现问题的新方面。我发现仅仅在我先写出所有的问题再开始编码的时候,我才不会被一些东西所难倒。如果您在编码之前先写注释的话,编码就会进行很快而且在代码中有较少的错误。
所要讨论的问题必须完全用问题领域方面的词汇来表达。如果您要解决会计方面的问题,问题说明书就应该完全用会计方面的词汇。也就是说,任何一位胜任的会计师都应该理解该问题的说明书,而勿须提出一些问题。关于设计完整的一般性原则是,一位有头脑的外行通过浏览熟悉该领域的且胜任的程序员的文档,能够完全理解所要解决的具体问题和该问题的一般性解决方案。如果这种层次理解不能实现,那么设计是不完整的。
我不能太强调问题说明书不是计算机程序方面的讨论. 问题说明书应该涉及问题本身,而不是该问题基于计算机的解决方案。我们要讨论的是现实世界中您的最终用户所要解决的问题。诸如“计算机”、“菜单”、“对话框”、“因特网”和“互联网”等词汇不应该出现在这里。问题说明书从来不应包含诸如:“系统必须……”或“我们写一段计算机程序……”写计算机程序可能是您的事情,但您的最终用户所关心的问题却很少涉及计算机(虽然他们也许涉及该解决方案)。大多数问题可以在没有计算机的情况下很好地描述和解决,虽然计算机可能解决起来更快些或者更容易些。
虽然您最终必须编写基于计算机解决方案的描述,但到目前为止,我们关注的焦点是文档有关领域方面的部分。记住这里没有计算机方面的行话,任何一位会计师都应该清楚地理解程序员写的会计领域方面的问题说明书。
尽可能地确认问题和解决方案
相反,作为问题自身领域的一部分问题的解决方案理所应当讨论。所有 OO 系统必须进行一些建模。如果已存在的问题有一个好的解决方案,但现实的问题是人们不可能很快地执行已有的解决方案,那么就需要将现有的解决方案建模。即手动过程自动化是全部所必需的,而您的问题说明书应完整地描述那个手动过程。
在问题说明书中,要确认的一件重要事情是用户的目标。用户确切地要完成什么?用户的目标完全影响解决方案的方向。(譬如,您的目标是计划一个会议还是维护一个日历?在第一种情形,您在程序中可能看见类似于传统日历的地方是在输出中。Alan Cooper,在他的 About Face这本书中,称这种工作方式为“指导目标的设计”(请参阅参考资料。)
您还必须说明所希望的结果。解决问题的最终成果是什么?最终成果表达了什么信息?(注意在此阶段我们感兴趣的是该信息的内容,而不是物理布局或者是内容表达的方式。)
尽可能地忽略旧系统的存在。用户的目标很少是改进旧系统,相反,用户是要完成工作,并且因为旧系统不能工作就由您来处理。让我们从头开始。
在问题说明书问题中,不要试图太正式。只要描述您想要做的事情就行了,就好象您在和一位伙伴谈话一样。(我经常被问及“我怎么说?" 我的回答总是,“就象那样 -- 您说的那样。”
下一步,和真正的用户和该领域的专家进行几次会谈,来恰到好处地定义问题。然后,用该领域的词汇来说明问题,让您的用户看一下问题说明书,以确保您是正确的。这里我认为可以跳过会谈过程,因为我自己就是该方面的专家(父母),下面我就直接开始了。结果证明采取的这种捷径是错误的,我将在下个月的专栏中讨论这个问题。
所以,让我们开始吧
我不认为这个问题的说明书完整的,它只是一个开始。一般来说,如果一些适当的问题还没有表述出来,那问题的说明书是不完整的。比较典型的是大量的细节问题。对于一个小程序 -- 大概需要 6 个人花 8 个月的时间去完成 -- 在所有的细节都解决后,它的问题说明书很容易达到 80 页左右。所以,很显然到目前为止我所做的是一种非常简略的方法。
编码前的细节
练习的要点是在编码开始之前,尽可能多的考虑许多细节。您不要试图把细节问题都留到真正开始编码的时候。不要异想天开您可以事先解决所有的问题。除非您在一个非常安静的夜里工作。事先解决所有的细节问题几乎是不可能的,在任何情况下,当系统转化成成果并开始使用时,最终用户会发现一些他们原先没有考虑过的一些问题。这种事后发现很正常,任何设计方法都不能应付后来发生的变化,从而使设计方法在大多数的编程环境下显得很脆弱。事实上,随后,当设计和执行时,问题的定义会发生变化。这就是为什么在设计队伍中要有一个最终用户的原因:以确保您不会因为改善它们而破坏一些事情。
虽然如此,最初的问题定义应尽可能的详尽。将您所想的都写在纸上。不要遗漏任何细节,即便是最简单的。教导成员通过他们的 OO 设计是我赖以生计之一,但往往他们在已经开始设计时,才邀请我。通常,我让我的客户给我一份他们的设计文件,这样我就可以为我们的第一次会谈做准备,而且是多多益善。我被告知我必须去并且发言以使我充分地理解问题是什么。那些答复回给我一些提醒。如果问题没有被详尽的写下来而一个外行人可以通过阅读而理解问题,那么我就知道客户对问题的理解可能不足以开始设计。尽管我相信“分析失败”的存在,但我从来没有看见过;相反,我曾看见过与之相反的:程序员过早地进入编码状态,而没有进行充分地分析。
回过头来看一下初始的问题说明书,您会注意到我还没有在任何地方提到计算机。我现在正在描述问题,而不是计算机程序。这里,问题是养育,而不是银行。因此,说明书是写给父母读的,不是银行家。
同时也要注意使用相对简单的句子。避免使用被动语态以及深奥晦涩的学术性文体,这对于用户来说简直是灾难。简单句(主语/谓语/直接宾语)确定了行为的主体(主语),执行的动作(谓语)和请求动作的信息接受者(直接宾语)。而被动语态只涉及了这三部分中的后两部分。无论什么时候用“我”、“您”等有意义时,就那么做。