OO 设计过程:开始设计软件
一个教学项目
Allen Holub
撰稿编辑,JavaWorld
2000 年 8 月
内容:
OO 需求搜集
问题说明书
细化您的说明书
问题和解决方案
编码前的细节
结束语
参考资料
关于作者
我们在七月份已经谈了这个系列的有关如何区分设计过程的优先次序. 这个月,我将着手设计一个软件。我希望项目不要太琐碎但很简洁,使我们在较合理的时间里能完成它。我需要一个实实在在的程序,而不只是一个纯教学性的练习。在这篇文章中,我采用一段教学软件。在以后的几个月课程中,我将演示这个程序的完整设计和 (Java) 实现,您将能够看到整个过程,从开始直至结束。同时,我(特意)没有编辑过程中的错误,以便使您能够如实地看到所发生的一切。让我们开始吧。
OO 需求搜集我曾经看到过一份统计,每年有 60% 已编好的程序在完成后几个月内被废弃,这倒不是因为程序没有实现它的任务,而是因为它没有实现任何有用的东西。当然,由此导致的生产力下降大得惊人。此外,生成的大部分代码是非常正式 -- 他们产生了大量的文件,为了完成他们所想的设计。很显然,他们所做的没有起作用(参阅参考资料中 Steve McConnell 的社论, 同样很明显,没有设计而继续也同样不起作用。如果计算高科技创业公司的失败率,我猜想这个百分率现在甚至高于60%。
我坚信失败的主要原因之一是,大多数程序员在软件开发过程中没有一个有关他们将要做什么的清晰的想法。对于一个有用的程序,必须要问那些将要使用该程序的人,该程序所必须要做的。然而,该步骤经常被全部忽略掉。相反,自己只是找一个真正用户的代理(譬如销售人员)来试图虚构他们称之的所谓的需求。事实上程序设计者与真正用户之间需要经常交流,但在这种情况下用户不可能让程序设计者了解他们所需要的。那么,我们的首要任务是解决必须做什么,而不是如何去做。(大多数程序员会立刻将精力集中到如何去做:用什么数据库?象什么样的数据模型?象什么样的 UI? 数据结构怎样?这在目前是多么的不切实际--先抑制一下这种冲动!)
在 OO 说法中,问题定义的第一步称为正规问题说明书,在以后的几个月中构建这些问题说明书是我们的任务。
在系统中,问题说明书经常忽略需求方面的搜集。我更喜欢用问题定义这个术语,因为“需求搜集”通常包含一些关于需求是什么以及您如何去搜集它等方面的不正确的假定(至少从 OO 角度)。在传统的处理过程中,经常根据一些第三方提供的功能来形成功能性需求规范,譬如市场部门。事实上,这种需求是虚假的,您是不能控制的。您会发现在 OO 环境中这种类型的文档 -- 特别是功能列表 -- 几乎是毫无价值的。那些提供算法和指定性能需求的“功能性需求”对于 00 交付是一个有用的附录,而他们不是最中心的。“功能性需求”指定了 UI 行为、工作流等,其原因我们在下几个月讲解。
问题说明书在任何一个设计中,精确地陈述问题总是第一步的。这里,您的目标是要简洁而精确地说明书您所要解决的问题。再次重申,您的注意力应在做什么和为什么做,而不是如何做。在阐述问题之前,您必须首先了解有关该问题领域方面的知识。虽然每个设计组一定会有一名该方面的专家(较理想的是最终用户)但设计组的其他成员也必须了解该领域的知识,尽管不一定作为一名专家。当您用该领域的专业词汇进行交谈时,您应该具有该领域方面的足够知识而无须专家停下来去解释基本的概念。因而,在开始设计项目之前,要有一个研究阶段。如果您正在设计一个会计程序,去参加本地中级院校的 Accounting 101 的课程。再次重申,您不一定非要成为一个专家,因为那是您用户的工作,而您须做的是能与该领域的专家进行如果没有这方面的知识,您甚至不知道去问什么问题或者如何去问他们。细化您的说明书问题的说明书应该是精雕细琢的,这是整个设计成败的关键。不要去做那些细支末节的工作,因为他们几乎不能抓住体现问题的微妙之处。如果您不能用清楚而组织良好的语言去说明书它,那么您所理解的问题就不足以使您设计出任何东西。良好的语法也是至关重要的;它提供了良好的结构和精确的表达方法,否则会使所要表达的想法一团糟。在任何一个设计组中,一个优秀的拷贝编辑也是非常重要的。这里还有一些有关写作过程本身 -- 即需要准确的语言,但是在谈话当中就无需如此 -- 这能够帮助您发现问题的新方面。我发现仅仅在我先写出所有的问题再开始编码的时候,我才不会被一些东西所难倒。如果您在编码之前先写注释的话,编码就会进行很快而且在代码中有较少的错误。所要讨论的问题必须完全用问题领域方面的词汇来表达。如果您要解决会计方面的问题,问题说明书就应该完全用会计方面的词汇。也就是说,任何一位胜任的会计师都应该理解该问题的说明书,而勿须提出一些问题。关于设计完整的一般性原则是,一位有头脑的外行通过浏览熟悉该领域的且胜任的程序员的文档,能够完全理解所要解决的具体问题和该问题的一般性解决方案。如果这种层次理解不能实现,那么设计是不完整的。 我不能太强调问题说明书不是计算机程序方面的讨论. 问题说明书应该涉及问题本身,而不是该问题基于计算机的解决方案。我们要讨论的是现实世界中您的最终用户所要解决的问题。诸如“计算机”、“菜单”、“对话框”、“因特网”和“互联网”等词汇不应该出现在这里。问题说明书从来不应包含诸如:“系统必须……”或“我们写一段计算机程序……”写计算机程序可能是您的事情,但您的最终用户所关心的问题却很少涉及计算机(虽然他们也许涉及该解决方案)。大多数问题可以在没有计算机的情况下很好地描述和解决,虽然计算机可能解决起来更快些或者更容易些。虽然您最终必须编写基于计算机解决方案的描述,但到目前为止,我们关注的焦点是文档有关领域方面的部分。记住这里没有计算机方面的行话,任何一位会计师都应该清楚地理解程序员写的会计领域方面的问题说明书。 尽可能地确认问题和解决方案相反,作为问题自身领域的一部分问题的解决方案理所应当讨论。所有 OO 系统必须进行一些建模。如果已存在的问题有一个好的解决方案,但现实的问题是人们不可能很快地执行已有的解决方案,那么就需要将现有的解决方案建模。即手动过程自动化是全部所必需的,而您的问题说明书应完整地描述那个手动过程。在问题说明书中,要确认的一件重要事情是用户的目标。用户确切地要完成什么?用户的目标完全影响解决方案的方向。(譬如,您的目标是计划一个会议还是维护一个日历?在第一种情形,您在程序中可能看见类似于传统日历的地方是在输出中。Alan Cooper,在他的 About Face这本书中,称这种工作方式为“指导目标的设计”(请参阅参考资料。)
您还必须说明所希望的结果。解决问题的最终成果是什么?最终成果表达了什么信息?(注意在此阶段我们感兴趣的是该信息的内容,而不是物理布局或者是内容表达的方式。)
尽可能地忽略旧系统的存在。用户的目标很少是改进旧系统,相反,用户是要完成工作,并且因为旧系统不能工作就由您来处理。让我们从头开始。
在问题说明书问题中,不要试图太正式。只要描述您想要做的事情就行了,就好象您在和一位伙伴谈话一样。(我经常被问及“我怎么说?" 我的回答总是,“就象那样 -- 您说的那样。”
下一步,和真正的用户和该领域的专家进行几次会谈,来恰到好处地定义问题。然后,用该领域的词汇来说明问题,让您的用户看一下问题说明书,以确保您是正确的。这里我认为可以跳过会谈过程,因为我自己就是该方面的专家(父母),下面我就直接开始了。结果证明采取的这种捷径是错误的,我将在下个月的专栏中讨论这个问题。
所以,让我们开始吧
The Bank of Allen
教孩子如何管理钱财(也是一个很有趣的工作)的最好办法之一就是为他们建立一个银行帐户。然而,说起来,真正的银行不会支付非常多的利息来满足小孩子的兴趣。(毕竟,一般年利率为 3.5%,20美元存一年所获得的利息最多为 $0.72)。我从 NationalPublic Radio 的 "Marketplace," 节目中得到启示,决定开个 Bank of Allen(或 BofA),它的月利率是 5%(每个月的确是5% -- 每年为60%)但每日计算。根据 Bank of Allen 的这个利率 20 美元在一年之后可以赚得 $15.91。尽管有如此高的利率,Bank of Allen 仍然象真正的银行一样运作。孩子们有他们自己的帐户,在这个帐户上,除了利率,他们可以进行任何操作。他们可以在任何时候查看(或打印)存折。他们可以随意的存取。
为了提高孩子们的兴趣,存折必须让孩子们看,以显示他们除了一般帐项(存、取和余额)以外赚得了多少利息。
孩子必须对假设分析游戏感兴趣:如果我整整两个月不取一分钱,那么会有多少钱呢?这一点显示了您不花钱而可以赚钱。
这里还有几个安全性的问题。只有银行(即,父母)可以改变利率或建立新帐户(和初始余额)。象真正的银行一样,孩子们不能够通过篡改他们的存折来存钱或取钱,他们必须让银行来做这件事情;银行处理交易和更新存折。即,孩子把钱交给银行,银行把这笔钱放入其帐户。银行从该帐户提取钱款并将其分与孩子。(实际上也就是,这意味着只有父母可以存钱或取钱,但这是在孩子们提出取钱的请求或认为银行正在使用这笔钱而使他们取不到自己的钱。)
目标(按重要性排列):
教孩子们存钱
显示利息是怎样形成的
"Bank of Allen" 是 Allen I. Holub 的一个商标。本程序及相关设计,是 (c) 2000, Allen I. Holub. 版权所有,保留所有权利。
我不认为这个问题的说明书完整的,它只是一个开始。一般来说,如果一些适当的问题还没有表述出来,那问题的说明书是不完整的。比较典型的是大量的细节问题。对于一个小程序 -- 大概需要 6 个人花 8 个月的时间去完成 -- 在所有的细节都解决后,它的问题说明书很容易达到 80 页左右。所以,很显然到目前为止我所做的是一种非常简略的方法。
编码前的细节练习的要点是在编码开始之前,尽可能多的考虑许多细节。您不要试图把细节问题都留到真正开始编码的时候。不要异想天开您可以事先解决所有的问题。除非您在一个非常安静的夜里工作。事先解决所有的细节问题几乎是不可能的,在任何情况下,当系统转化成成果并开始使用时,最终用户会发现一些他们原先没有考虑过的一些问题。这种事后发现很正常,任何设计方法都不能应付后来发生的变化,从而使设计方法在大多数的编程环境下显得很脆弱。事实上,随后,当设计和执行时,问题的定义会发生变化。这就是为什么在设计队伍中要有一个最终用户的原因:以确保您不会因为改善它们而破坏一些事情。虽然如此,最初的问题定义应尽可能的详尽。将您所想的都写在纸上。不要遗漏任何细节,即便是最简单的。教导成员通过他们的 OO 设计是我赖以生计之一,但往往他们在已经开始设计时,才邀请我。通常,我让我的客户给我一份他们的设计文件,这样我就可以为我们的第一次会谈做准备,而且是多多益善。我被告知我必须去并且发言以使我充分地理解问题是什么。那些答复回给我一些提醒。如果问题没有被详尽的写下来而一个外行人可以通过阅读而理解问题,那么我就知道客户对问题的理解可能不足以开始设计。尽管我相信“分析失败”的存在,但我从来没有看见过;相反,我曾看见过与之相反的:程序员过早地进入编码状态,而没有进行充分地分析。回过头来看一下初始的问题说明书,您会注意到我还没有在任何地方提到计算机。我现在正在描述问题,而不是计算机程序。这里,问题是养育,而不是银行。因此,说明书是写给父母读的,不是银行家。同时也要注意使用相对简单的句子。避免使用被动语态以及深奥晦涩的学术性文体,这对于用户来说简直是灾难。简单句(主语/谓语/直接宾语)确定了行为的主体(主语),执行的动作(谓语)和请求动作的信息接受者(直接宾语)。而被动语态只涉及了这三部分中的后两部分。无论什么时候用“我”、“您”等有意义时,就那么做。 结束语这个月就到这里。我们已经开了个头 -- 确定了基本问题。下个月,我将继续这个讲座,细化问题说明书,使它能有效地使用。 参考资料 请阅读 IEEE Software 2000年3月/4月期刊中的有关“文书工作进展中的困惑”的社论。这篇社论"Cargo Cult Software Engineering",由 Steve McConnell 写。
了解更多有关 UI 设计,请参阅About Face: The Essentials of User Interface Design由 Alan Cooper 写( IDG 出版社)。与此巧合的是这本有关 UI 设计的书作者也是“Visual Basic 之父”--该工具是造成许多最差的用户界面的原因从而引起计算机界的混乱的作者。Cooper 有许多观点,其中一些我赞成,还有一些我不赞成。(特别是我认为作为 UI 的程序不应有智能方面的瑕疵而使程序挂起)。尽管如此,Cooper 仍然有许多好的见解,使人感兴趣。
我发现大多数有关 UI 设计的书籍是由程序员(他们把程序员的便利置于用户需求之上)或者美工(他们把艺术、效果和创意置于用户需求之上)。无论哪一种情况,用户都被抛弃了。所以,让人喜欢读的有关 UI 书是由有见识的程序员著作的,他不但坚持把用户放在第一位,而且有良好的设计意识。
Cooper Design 网站,从 Cooper Design "Manifesto":事实上,今天大多数软件都有类似于这样的界面:
关于作者Allen Holub 自1979年一直在计算机领域工作。他在许多杂志上发表过文章( Dr. Dobb's 月刊, 程序员月刊, Byte, MSJ,以及其它杂志),并且他是在线杂志JavaWorld的撰稿编辑。他有八本自己较赞赏的书,其中最新的一本(Taming Java Threads)讲述了 Java 线程的陷阱和缺陷。他一直从事设计和构建面向对象的软件很长时间了。在当了 8 年 C++ 程序员之后,Allen 在 1996 年初放弃了 C++ 转向 Java 编程。他自从1982年一直在自己和为加利福利亚大学伯克利分校教编程(先是 C,然后是 C++ 和 MFC,现在教 OO 设计和 Java 编程)。Allen 提供 Java 技术和面向对象方面公共课程和专门培训。他还进行面向对象设计咨询和商业性 Java 编程。请访问 Allen 的网站 www.holub.com。