您的位置:首页 > 其它

关于实现B/S与C/S平台之间功能通用性的设计思路

2010-03-01 01:40 671 查看
设计场景

1. 有A,B两组开发人员进行某个系统的开发,其中A组开发人员负责B/S平台的功能设计与开发,B组开发人员负责C/S平台的功能设计与开发。

2. 在当时的项目背景下,B/S端的项目是先启动的,而A组的开发人员还没有意识到将来需要配合C/S端来做功能协作,因此产生的问题就是,前期的系统架构设计没有过多地考虑以适应多个平台下的功能适应性。当然,从B/S端的设计角度上看,系统架构还算比较清晰。接着A组的开发人员就在这样的情况下,完成了系统功能的实现。

3. 接着高层领导告诉项目经理需要做一套C/S架构的软件来配合B/S端平台的使用,而这时候B/S端的功能实现已经基本完成,B组开发人员成立。

4. 在B组架构人员开始设计架构的时候,并没有衍用B/S端的开发架构,很多基础架构(如分层模式、数据库结构、数据实体类等等)都存在很大的差异(C/S端项目在初期的要求没有那么高,有的功能能削减掉就削减掉),后来B组架构人员发现需求文档上的有个功能和B/S平台上的某个功能是一样的,于是他和A组架构人员进行交流,希望负责B/S平台上这个功能的开发人员能够帮助C/S平台帮助完成这一功能。于是A组的Leepy就匆匆忙忙地上阵了。

5. 最初Leepy同学因为在B/S平台上也有大量的任务需要完成,任务赶得狠,又收到这样一个“功能复制”的任务,心想:“那么就先把功能复制一份上去,然后如果B/S平台上的功能有更新,就同步修改C/S平台就好”。于是打开C/S平台的项目,发现和B/S平台项目的差异性比较大,包括数据库结构和数据实体类等等,更头疼的是这里采用的是.net framework 2.0进行开发,而B/S端采用的是.net framework 3.5进行开发,而且从功能上,Leepy使用大量的3.5的属性。要直接复用是不可能的,还需要调整相应的代码。

6. 于是C/S平台该功能出来了,运行得还行。现在才是郁闷的开始,因为该功能属于平台的核心模块,于是B/S平台上要时刻调整得比较大,所以同步的C/S端的功能也要相应的调整,然后又运行完好。于是问题出来了,这样反复地修改导致系统(C/S和B/S)维护成本很高,架构间的设计耦合度太大。刚开始Leepy抱怨为什么C/S端没有和B/S端统一架构,至少底层基础平台能够设计得具有可扩展性,光光抱怨无法解决问题,因为这是项目的人员配置的问题。于是,Leepy想到了必须对该功能进重构,使用一个通用的组件进行抽象,而实际实现的,如C/S、B/S端具体应用,只要维护相应的业务代码。

设计思路

1. 说完场景,现在说说动手的部分。以一个中学生教育平台591up的网站为例,以及教育平台客户端的辅助软件。

这一功能实现一份Word文档试卷的导入保存并分解文档中的试题,将试题逐个保存入库(解析出来的试题部分还包括很多属性,如答案、知识点、解题关键点等很多属性)。现在B/S平台和C/S平台都需要这个功能,但是B/S平台和C/S平台下的相关数据库实体类,设计不很统一,导致维护系统的成本很高。于是,考虑是否能将解析器的设计与业务功能分开,将试卷解析器设计成通用的组件,而与B/S端和C/S端的业务代码彻底分开,对于解析的逻辑代码(基础代码)在两端都可以引用到,而B/S端和C/S端所需要做得就是调整业务代码,并不需要关解析的基础代码是什么,组件与业务代码解耦。如下图所示:

代码

/// <summary>
/// Web端试题解析器
/// </summary>
public class WebQuestionConvertor : OfficeWordQuestionConvertor<WordInfo, QuestionInfo>
{
/// <summary>
/// 根据条件初始化试题
/// </summary>
protected override QuestionInfo Initialize(WordInfo wordInfo)
{
QuestionInfo questionInfo = new QuestionInfo();
questionInfo.IsSystem = wordInfo.IsSystem;
return questionInfo;
}

/// <summary>
/// 完成解析后触发
/// </summary>
protected override void Finished()
{
}

/// <summary>
/// 设置试题题干
/// </summary>
protected override void SetQuestionContent(string text)
{
Question.QuestionContent = text;
}

/// <summary>
/// 设置试题难度
/// </summary>
protected override void SetDifficultyCode(string difficulty)
{
switch (difficulty)
{
case "A":
Question.DifficultyCode = 1;
break;
case "B":
Question.DifficultyCode = 2;
break;
case "C":
Question.DifficultyCode = 3;
break;
}
}

//其他业务扩展...
}

从类中可以看出,它们分别继承于OfficeWordPaperConvertor和OfficeWordQuestionConvertor类,这里实现的只是和平台相关的业务逻辑,至于如何对一份Word文档解析,交给解析器组件去做,平台上无需知道。

同理,C/S平台也用了类似的方法,不同的只是个别类型通过泛型抽象类得到实现。并且能够使B/S平台和C/S平台拥有各自的业务逻辑。

这样,维护两个平台的这个功能成本降低了,如果解析器组件需要改动,只要更动基础组件的设计,而不会影响业务上的逻辑。

这是Leepy同学在开发项目的时候遇到的问题,可以说是提供了一种思路吧,也可以算是经验之谈吧:)

591up以及客户端的功能效果如下图所示:





591up 客户端软件

最后附上该范例的Demo
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐