界面原型设计示例

进入详细设计阶段后的一个重要任务是对业务方法进行设计,如果业务逻辑是封装到事务脚本方法中的,那就简单得多了,即根据界面可设计得到事务脚本业务方法。很多事情都是说起来容易,做起来难,下面我结合一个简单的实例,说明业务方法的设计过程。

一、先贴出界面原型设计图,具体操作图中已经标注得非常清楚了,我不再描述。

 

 

二、根据界面原型,建立简单的域模型,如下图:

(注:其中的分页对象,是根据界面原型,在设计模型中加入的)

 


三、业务方法设计过程是我说明的重点
我们最先遇到的问题,应该是业务对象粒度的确定,常见的有两种方法,一种是根据功能模块来划分,另一种是根据用例来划分,如果你仔细想想就会发现,这两种划分方式都是从逻辑上对业务方法进行归类,总的原则是: 有利于实现以及后期的维护 。如果业务类粒度太细,业务类过多,会加大实现及管理上的复杂性;如果粒度过粗,一个业务类中业务方法过多,逻辑相关性不强,也会大了实现和维护难度。
对界面原型分析后,我们基本上可以确定两个业务类(当然是用接口定义的),一个是菜单相关的,一个是与学生相关的(如果再细一点,也可以把班级相关的抽出来)。
1、IMenuService
从上面仅有的需求看,登录成功后我们要展示一个树型结构的菜单,而菜单设计为一对多自关联,所以,我们设计了下面的一个方法:+ getMemnuByLevel(level : int) : List,即根据菜单级别,得到这个级别菜单的集合,在实现的时候,需要取到所有的顶级菜单,通过jstl的循环标记取出子菜单并显示(当然,具体实现时你可能还要动动脑筋)。
2、IStudentService
这是本例中的核心。有人说业务方法命名无非就是一些CRUD的操作,但我认为,业务方法在命名上应该具更有业务含义,而不仅仅是一些简单的CRUD,比如:changePassword,login,register,pay,sendMail等等,这些方法都具有明确的业务含义。 以有明确业务含义来为业务方法命名可以作为业务方法设计的一个标准 ,话又说回来,在实际项目中,还是有70%以上的业务方法命名是具有明显的CRUD含义的,还是来看看具体的设计吧。
a、首先看到的第一个界面是登录界面,界面中有两个输入字段:学号及密码,登录成功后进入主界面,系统应该在作用域中保存用户的状态信息,登录有可能会失败,基于这个需求,设计业务方法如下:
+ login(code : String, password : String) : Student,返回值为Student将作为状态信息保存,这个方法会throws LoginException异常,这个异常是自定义的。
在这个方法的设计中,也有人把code与password封装在一个Studnet对象中传递,看起来就像这样+ login(s: Student) : Student,我个人觉得这种设计就没有第一种方式来得直观。
LoginException也可以不定义,通过返回值Student是否为null,检测登录的执行情况,但我更倾向于业务层抛出统一的异常的做法。
b、学生的分页查询。分页查询功能有两个地方可以触发,一个是:菜单中的“学生信息一览表”,一个是主界面中的“查询”按钮,但主界面中是带查询条件的,那我们是设计一个方法还是设计两个方法呢(我倒是见过不少初学者设计两个方法的哦)?答案是统一成一个,方法签名为+ getStudentsByPage(pageNo : int, pageSize : int, studentExample : Student) : Page。
在上面的方法中,我们在studentExample封装了多个查询条件(我也见过一些初入门的程序员把每个条件都单传的设计,条件多了的话方法参数会非常庞大),后期用QBE实现,我会用一篇文章单独介绍这种多条件的具体实现方法。
c、主界面的查询中会出现班级列表的选择,提供+ getAllClasses() : List就可搞定,但前提是班级不是太多,如果班级非常多,这种设计就有问题了,界面原型设计出得改。
d、新增学生。方法为+ addStudent(studnet : Student) : void,这个方法写出来又有人提出疑问:你的方法返回void,那保存失败怎么办?很显示,提出这样问题的人对异常机制没有理解透,要去好好看书了哦。
新增学生的时候,我们要会对学号(业务主键)的惟一性进行检测(使用ajax或保存时的检测),因此,还要提供一个业务方法+ getStudnetByCode(code : String) : Student来做这件事。
e、修改学生信息。很明显,实现步骤是先查询后修改,因此设计了下面两个方法:+ getStudnetById(id : long) : Student根据id查询学生,+ updateStudent(studnet : Student) : void保存学生信息。
f、删除学生信息。步骤也是先查后删除,查询的方法前面已经设计了+ getStudnetById(id : long) : Student,我们仅设计一个删除方法+ deleteStudentById(student: Student) : void。
也有人设计成这样+ deleteStudentById(id : long) : void,即根据id来删除一个学员,当然底层实现也是先查后删除,这样的设计也是非常不错的,把查询对象的过程都封装到业务类实现中,而不用在 action中进行查询,效率会有一点点的提升,我推荐这种设计。
g、批量删除。可以设计为+ deleteStudentByIds(ids : long[]) : void,也可以在action中通过for循环调用+ deleteStudentById(id : long) : void实现,根据你个人喜好自行设计。或都也可以设计成根据对象集合删除,即传入一个Collection。
h、查看学生信息。+ getStudnetById(id : long) : Student就可以实现,这个方法我们前面已经设计好了。
最终详细设计业务方法如下图:


从以上的分析过程可以发现,我们的业务方法设计完全是依赖于界面原型一点一点“扣”出来的,业务有增删或变化,业务方法进行相应的调整,这种 按用例或模块确定业务方法粒度并依据界面原型确定、分配业务方法的过程 比较直观,也比较简单,业务实现采用事务脚本模式,事务脚本为何在目前的web应用开发中如此流行,与设计过程简单化是息息有关的。掌握了上面这个例子中的业务方法设计,你已经可以胜任软件开发了。
后面的文章中,我会用一个更简单的例子,结合软件开发流程讲,讲解整个实现过程(包括关键部分的伪代码),我努力写成一个对于初级程序员来说最好的基础教程。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值