程序设计实例(1)
这一章我们要设计一个叫CurrencyConvertorDemo的程序。
1. 功能简介:
显示常用货币汇率。
2. 程序设计
(1)理解需求:要进行程序设计要做的第一件事就是理解需求。毫无疑问,显示汇率包含2个方面的问题
(a) 获取汇率
(b) 怎样显示汇率
按正常的软件开发流程,程序设计时应该有很明确的需求分析。但进行程序设计前,正确,完整理解需求并不是件容易的事。比如该例,需求很简单:显示常用货币汇率,但常用货币汇率有哪些,汇率是什么?程序设计人员不了解,就做出程序设计,是一件很可怕的事。
由于这是一个演示项目,下面的理解有可能不能真正满足客户需求。
常用货币汇率:这里指的是银行公告牌,金融网站经常公布汇率的货币,有: 美元 - 人民币,欧元 - 人民币,港币 - 人民币,英镑 - 人民币,日元 - 人民币,澳元 - 人民币,加拿大元 - 人民币,欧元 - 美元,美元 - 日元,,英镑 - 美元 ,加拿大元 - 美元,澳元 - 美元。正常的做法是,定义一个表格,由客户自己指定。出于演示目的,这里不把程序设计搞得复杂了。
汇率:现汇买入价,现钞买入价,卖出价,基准价,中行折算价.区分这几种价格很重要,如果程序设计人员不了解几种价格的关系,在这里很可能犯程序设计的大忌,就是把一般化和特殊化没搞清楚。其实这里面一般化的就是基准价,获取汇率时只需获取基准价就可以了。其他价格根据不同的银行自己的价格规则可以计算出来。
怎样显示汇率:关于显示汇率,不同的客户可能会有不同的要求,包括显示的风格,显示的内容都可能不一样。基于这一点,程序设计时显示方式是应该可以扩展,定制的。另外,汇率是一个变化的东西,更新频率也应该考虑。
不难看出,理解需求对程序设计有多么重要,这么简单的例子,要理解的东西也不少啊。
(2)模块设计:
设计的原则之一就是业务和视图分离,这句话许多人挂在嘴边,但真正做好并不有容易,尤其涉及复杂业务和多重视图时。对于本例,一个视图,一个业务逻辑,够简单了吧?下面我们来看看几种可能的模块分类方式:
(a) 2个模块,一个窗口主程序(主视图+汇率视图),一个汇率业务模块(为视图提供业务逻辑)。
(b) 2个模块,一个窗口主程序(主视图),一个汇率业务模块(汇率视图+业务逻辑)。
(c) 3个模块,一个窗口主程序(主视图),一个汇率视图模块,一个汇率业务模块。
(d) 4个模块,一个窗口主程序(主视图),一个汇率视图模块,一个汇率业务模块,一个视图接口模块(提供主视图可以装载不同的汇率视图)
你会选择哪一种呢?是不是还有更好的模块分类方式呢?我看过很多(a)或(b)的程序,在这里,(a)和(b)都有一个很大的问题,汇率视图的变更会影响到其他功能。汇率视图是不停变化的,你别指望客户会同意使用同一个汇率视图,而汇率业务是相对确定的,不会因为换家银行基准价就不同了(有的客户只显示基准价,有的客户要显示所有价格,均不会影响汇率业务模块)。
我选择了(c),不用(d)的原因是:对同一个客户,汇率视图是不变的,没必要在这方面增加灵活性。程序设计不是越灵活就越好,因为越灵活,就要付出性能,开发难度的代价,在灵活和难度之间找到均衡。
模块设计视图:
(3)代码设计:
汇率业务(CurrencyConvertorBusiness)只公开了一个接口,获取汇率列表,返回值为Dictionary<string, double>,TKey为汇率货币,TValue为汇率
public Dictionary<string, double> GetCurrencyConvertorTable(){
//实现略
}
汇率视图(CurrencyConvertorPanel)做成用户控件,使用CurrencyConvertorBusiness
//业务逻辑对象创建private CurrencyConvertorBusiness rateBusiness = new CurrencyConvertorBusiness();
private void CurrencyConvertorPanel_Load(object sender, EventArgs e){
UpdateView();
}//更新视图
private void UpdateView()
{Dictionary<string, double> ratePair = rateBusiness.GetCurrencyConvertorTable();
if (ratePair != null && ratePair.Count > 0){
//显示汇率
}
}
CurrencyConvertorDemo只包含主一个主视图(FormMain),把CurrencyConvertorPanel从工具栏拖到FormMain中就可以显示汇率了,结果如下:
CurrencyConvertorPanel还公开了2个属性:
为什么要公开这2个属性呢?这和获取汇率的实现有关系。
获取汇率有2种常用的方法,一种是直接从网页获取,首先获取网页的内容,然后使用正则表达式把汇率找s出来,另一种是使用提供汇率服务的WebService,这里作为演示使用了第一种。对于第一种方法,变化在于提供汇率的网页URL和检索的正则表达式。如果把网页URL和检索的正则表达式放在配置文件里,就会把Class Library和主程序配置文件关联起来,这不是一种好的方法。作为控件属性公开避开了这种关联,同样达到了可变化的效果。使用属性的默认值达到了控件透明化,一般情况下,使用者不需知道这2个属性干什么的,也照样使用。
公开这2个属性改变的是模块间的接口,这显然是程序设计者来决定的事,而不是程序员。所以程序设计者在设计时还必须知道功能怎么实现的,才能设计好程序。
示例源代码下载
https://files.cnblogs.com/zhongxg/CurrencyConvertorDemo.rar