您的位置:首页>软件开发>软件工程>软件方法学>

OO 设计过程:细化问题定义

[ 来源:IBM DW站点 | 更新日期:2007-7-15 20:17:03 | 评论 0 条 | 我要投稿 ]
这个月我将继续细化上个月开始的关于 Bank of Allen 的教育软件的问题说明书。

当开始问题定义时,我通常是做下一步,建立一个词汇表。一般来说,对于熟悉该领域的人会马上明白术语的含义,因而不需要去定义它,但对于具有模糊含义的术语,或者在目前的问题中用在有限的范围内,这就需要专门来定义它。

在问题说明书中如 gotcha 是不妥当的。一个词不能指两个不同的事物,同时两个不同的词不能指同一件事物。要做到这一点,首先要建立词汇表。不需要定义该问题领域的术语。譬如,如果是会计方面的问题,您勿须定义信用或者利率。然而,目前的问题是关于养育,所以象信用之类的术语需要精确定义。

词汇表对我们的主要目标也有帮助,它能确定关键问题层次的抽象。避免词汇表中的词和概念经常出现在问题说明书的正文中。譬如,存折引入了术语交易。(交易的概念是重要的,虽然我没有立即认识到这一点。)

在词汇表中加入实现细节部分也是很有帮助的,它提供了记录这些细节的地方,就其本身而言,尽管它不是问题说明书的都具有的。那些通常归入功能性需求规范的东西常被放入实现细节。
字串6


以下是我的第一遍词汇表和实现细节。


词汇表 余额 当前在帐户中的货币金额。
银行 父母
贷方 由银行存入您的帐户,而不是您自己。
存款 将钱放入银行;增加您的余额。
利息 作为您一直把钱放入银行的报酬而给您的信用。利息是每天计算的,通过把信用按当前帐户余额的固定比例放入该帐户(“本金”)。如果利率是 10%/月,余额乘以 (.10/30) 就得到每天的利息。
存折 发生在某个帐户上的交易的作业记录和摘要信息。孩子们必须从银行得到存折。
取款 从银行取钱;降低您的余额。



实现细节

就其本身而言,这部分不是问题说明书的一部分。它只不过是我想起的清单,我把它与问题说明书放在一起。

当程序第一次运行时,父母可以为他们自己设置口令。从那以后,以父母亲登录必须要知道口令。父母亲在任何时候可以更改口令。

字串6


更改利息率可以立即生效,但根本不影响以前的余额。(存折不一定(但可以)反映新的利率,该利率用于利率更改之日的存款,甚至是那天以前的。)
小孩必须向银行申请存折。
每次在给孩子们之前,存折要更新。
父母必须要有备份或银行的措施。这可以是简单文件拷贝或更加详细描述的说明。


验证和细化问题说明书

如果满意自己准备的合理的问题说明书,那么下一步做设计审查。我感激我的妻子 DJ,她是程序员并且是该方面的专家--母亲。她发现了各种各样小的语法性问题(我必须承认,你刚才所读的最初的陈述是我修订的),而且她发现了一个我没有意识到的严重缺陷。“你不能象那样计算利息”她指出。如果你仅仅根据一个月的天数来计算每月的利息,但是每天计算利息过于复杂,到月底你会得到一个很大的数目这要比你到月底再结算一次利息多的多。你在此所需要的是名义的每月低于5%的利率,它将向你提供每月5%的有效利率。好吧。回到正文。

在当前问题中,出现了两个领域:养育,当然,从较小范围的角度讲的融资。我原以为我对费用了解的很多,但是很显然我错了。所以,我停下了设计,拣起了书本直到我完全了解了这方面的知识再继续设计下去。

字串2



这个问题本该出现得更早一些,如果我没有省略掉设计所必须的第二个步骤:在你对问题所属领域非常熟悉之后(第一阶段)和在开始建模之前(第三阶段),你必须与客户进行交谈以发现他们所需要的。我认为我不需要这样做,因为我已经是这方面的专家了-作为一个父亲。我错了。如果我与这方面的专家会谈过,一些并没有象我一样进入到设计的实质的人(例如我的妻子),在第一部分的利息问题上,我就可能做对。

不要忽略明显的错误
这儿有很多其他的例子,但最重要的是我称之为“浴室效应。”这一词干来源于几年以前我写给“ Dr. Dobb’s Journal”一篇(未发表)文章开头的部分。“假设我们建造房子象我们做软件一样。” (我们都居住在如Winchester Mystery House一样的破房子里)。总之,到了文章的结尾,最后购房者第一次来看房子(在房子已经完全造好之后)。购房者带着迷惑的表情四处看了一圈,问“浴室在哪里?”


“浴室?”分包商说,“在说明当中没有浴室。现在把他们加上去会花很多钱;我们得浇注水泥,敲开墙。我们为什么不在房屋的后院盖一个呢?”

字串2




"这是什么意思‘它不在说明当中是什么意思’?”购房者结结巴巴的说,“谁会傻到设计房子而没有浴室?”

但是在软件设计中却是经常发生的问题。用户倒是不经常提及他需要的东西,而这些东西对问题来说都是很基本的。不是用户“对我隐瞒”正如许多程序员所说。这是因为设计者对问题所涉及的领域不够了解而提不出正确的问题。

不要仅仅点头 -- 倾听
当进行会谈的时候,倾听!不要打断。记住会谈中出现的每一件事情(那种会速记的人获益非浅),准确的记录下此领域专家的每一句话都是非常重要的。我曾经参加过许多会议,用户们说了几个小时,没有谁记录。随后,当用户离开后,没有谁能精确地记住讨论了些什么。在一部分程序员当中有一个不好的倾向,对用户所说的不加理会。都知道程序员们将用户对于问题是什么的描述扭曲为程序员认为问题该象什么的描述。他们将重新描述一些事情,将那些组成的问题涉及的领域翻译成更熟悉的语句,否则,他们所听到的就会产生扭曲和变化。经常,记住的是程序员们对问题的错误理解,而不是此领域的专家对问题的实际描述。 字串6

最后,记住大多数的用户都有过与那种自以为是的计算机人员相处很长的历史,那些人认为对于任何问题,他们比用户懂得更多。 (由于认不清方向,城里人对农夫说,“你不是很聪明,是吗?”农夫回答道,“也许,但我没有迷路。”)问题是许多用户过了一会儿就放弃了。如果程序员不认真倾听,为什么在交谈中就会有障碍?你将不得不打破这一系列的障碍。

一般而言,对于问题说明书的主要问题根本在于细节的级别是否属于它。通常,在问题实际上所涉及的领域当中,问题说明书的本身不会是科技术语。你得为了这个目标去参考教科书或字典。但在这,答案是“是的”因为固定利率和有效利率的区别在于他们不是实际问题领域的一部分(这是养育)。我们领域的专家是父母或会计师们。我们并不是发展一个运用于银行或建立一个试图运用于真正银行的模块的系统。这仅仅是为孩子们写的软件,不是关键的银行系统,所以我们不能采取我们部分专家关于如何计算利息的建议。利息的计算是问题定义的一个重要的部分,所以事实上它属于问题说明书。

问题说明书重点放在手边的问题是十分重要的。我们并不想在一段孩子的软件中解决“银行”的通病。在另一方面,我们也不想遗漏任何重要的细节。如果一般的读者(假设他们都是此领域的专家)需要一些信息以了解问题的陈述,然后就属于他们。如果这些资料是这个领域当中重要的一部分,我们不会加上去。在现在的情况下,如果我真正在写一个银行系统,我当然也就不会为定义“有效利率”犯愁了。因为我可以向这方面领域的专家请教这些知识。(由于同样的原因,设计者必须对问题所涉及的领域和此领域的基本术语有足够的了解。你不能设计一个会计应用程序除非你懂会计的一些知识-至少是一个聪明的外行。) 字串3

所以我找出一本傻瓜金融书,查出名义利息,并修改利息的定义为:

利息 作为您一直在银行存钱的报酬而给您的信用。利息被加入每天的余额中。
Bank of Allen 的运作如真正的银行一样,利息按照月份来计算。尽管如此,每天挣得的利息必须登记在存折上。这里的问题是根据每天计算的利息与每月计算的利息会产生不同的结果。

譬如,如果您开始在银行有 $100,利率是 10%,按照每 10 天计算的复利,在 10 天后,您帐户上将有 $110。

而另一方面,如果根据每天的复利计算,也就是将 10% 的利率平摊到每一天(1%/天)来计算,得到的结果会大于按每 10 天计算的结果。 第零天 本金 $100.00
利息 $1.00
第一天 本金+利息 $101.00
利息 $1.01
第二天 本金+利息 $102.01
利息 $1.02
第三天 本金+利息 $103.03
利息 $1.03
第四天 本金+利息 $104.06
利息 $1.04 字串2
第五天 本金+利息 $105.10
利息 $1.05
第六天 本金+利息 $106.15
利息 $1.06
第七天 本金+利息 $107.21
利息 $1.07
第八天 本金+利息 $108.28
利息 $1.08
第九天 本金+利息 $109.36
利息 $1.09
第十天 本金+利息 $110.45


需要用两种利率解决这个问题:一种是孩子们知道的,另一种是银行内部用的。

有效利率
实际的利率,包含按复利计算的结果。假定月名义利率为5%,当按每日复利计算时,有效利率为5.12%。
名义利率
规定的利率,除去按复利计算的结果。
什么是有效利率,按每日复利计算,它是如何得到5%名义月利率? N = 以小数表示的名义利率 (.05)
P = 周期的天数(30天)
E = 以小数表示的有效利率

公式:

字串5


E = (1 + N/P)P -1 = .0512

利率 5%,按每日复利计算,与按每月复利 5.12% 计算,30 天后帐户上的余额数目是相同的。


当按每日复利计算时,名义利率为多少,可以得到有效利率为5%/月? N = 以小数表示的名义利率
P = 周期的天数(30天)
E = 以小数表示的有效利率 (.05)

公式:
N = P * (E + 1)1/P -1 = .0488

利率 4.88% 按每日复利计算,与按每月复利 5% 计算,30天后帐户上的余额数目是相同的。



在一个周期内,如果只计一次复利,那么有效利率与名义利率是相同的。即,如果一个月计算一次利息,那么月有效利率与月名义利率是相同的。

简单地讲,银行公布的是有效利率:“您的月利率为 10%。这意味着如果您在银行存 $10 一个月,银行付给您 $1 的利息。”

由于利息是按每日复利计算的,每天计算利息必须要用名义利率(这样到了月底,由有效利率技计算的利息才能与之相一致)。譬如,假定一个月有 30 天,公布(有效)月利率为 5%,计算使用的(名义)日利率为 4.88%。如果您的帐户上初始有 $10,运用以下算法,您帐户上的将有 $10.50: double balance = 10.00;

字串8


int days_in_month = 30;
double
effective_rate = ->05;
double nominal_rate = days_in_month *

( Math.pow(effective_rate+1,

1.0/days_in_month)
-1);
for
( int i = 0; i balance =
balance + balance *

(nominal_rate/days_in_month));




现在看上去更合理,下面我们该做还没有完成的事情。这正是下个月专栏的主题。

参考资料

参阅上个月的 “OO 设计过程”专栏,开始设计软件."
访问Winchester Mystery House 参阅任意设计的结果。
Tags:
责任编辑:
您的评论
用户名: 新注册) 密码: 匿名评论 [所有评论]

·用户发表意见仅代表其个人意见,并且承担一切因发表内容引起的纠纷和责任
·本站管理人员有权在不通知用户的情况下删除不符合规定的评论信息或留做证据
·请客观的评价您所看到的资讯,提倡就事论事,杜绝漫骂和人身攻击等不文明行为