您的当前位置:首页正文

软件架构设计文档

2021-06-23 来源:步旅网
.

密 级:内部公开 文档编号:1002 版 本 号:V3.0

测测(基于安卓平台的测评软件)

软件架构设计文档

文件状态: [ ] 草稿 [ ] 正在修改 [√] 正式发布 文件标识: 当前版本: 作 者: 完成日期: 开发组 V 3.0 张放、张钰若、陈国忠 2014-5-26

中国石油大学(华东)

计算机与通信工程学院 天师团开发团队

.

.

项目名称:测测—基于安卓平台测评软件 软件架构设计文档

版本: 日期: <2014/5/26> 修订历史记录

日期 2014.5.13 2014.5.23 版本 说明 作者 陈国忠,张放 陈国忠,张放 对软件架构进行初始设计 对软件架构进行初始设计进行修正 2014.5.26

确定软件架构 陈国忠,张放 .

.

目录

1.文档介绍 ................................................................................................................................ 4

1.1文档目的 ........................................................................................................................ 4 1.2文档范围 ........................................................................................................................ 4 1.3读者对象 ........................................................................................................................ 5 1.4参考文献 ........................................................................................................................ 5 2.架构设计思想 ....................................................................................................................... 5 3.架构体系描述 ....................................................................................................................... 6 4. views ...................................................................................................................................... 6

4.1 Module structs .......................................................................................................... 6 4.2 Component & Connector(组件-连接器视图) .............................................. 8 4.3 Allocation ....................................................................................................................... 9 5. Mappping between views .............................................................................................. 9

5.1 Class map to Package ................................................................................................ 9 5.2 Package map to Allocation .................................................................................... 10 6. Utility tree ........................................................................................................................ 10

6.1 Quality attribute scenario (质量属性场景) ................................................. 10 6.2 Utility tree .................................................................................................................... 14 6.3 Tactics ........................................................................................................................... 16 7. Architecture ........................................................................................................................ 17

7.1 WebService .............................................................................................................. 17

.

.

7.2 MVC (Model View Controller)..................................................................... 20 7.3 Publish/Subscrib ..................................................................................................... 22

1.文档介绍

1.1文档目的

本文档是对于测测软件系统进行详细设计和编码的重要依据。对该软件的整个系统的结构关系进行了详细描述,阐述了系统的总体框架,包括物理、逻辑结构,说明了体系结构所采取的设计策略和所有技术,并对相关内容做出了统一的规定。为今后的设计、编码、测试都提供了可以参考的模版并且提高效率,使整个开发过程做到资源利用最大化,减少由于需求变更而修改的时间,大大的降低了成本,节约了时间,也使得客户更加的满意。

1.2文档范围

本文档包含以下几个部分:

1、

.

架构设计思想

.

2、 3、 4、 5、

架构体系描述 系统模块化分 系统模块描述 模块接口设计

1.3读者对象

本文档主要读者包括:

1、本系统的设计人员:包括模块设计人员(理解用户需求,在设计时把握用户需求)。

2、本系统的系统开发人员:编码人员(了解用户需求,为编码提供模版)。 3、本系统的测试人员(了解用户需求,为测试提供参考)。 4、 客户(检查是否满足要求)。

1.4参考文献

《软件工程讲义》 《测测需求规格说明书》

2.架构设计思想

为了降低系统耦合度,增加系统内聚性,在需求发生更改时能在较短的时间内对系统做出修改,并重新投入使用,我们决定以分层体系架构风格作为整个系统的体系风格,严格按照一定的规则来进行接口设计,并以之为根据进行详细设

.

.

计。分为数据层、业务逻辑层、表示层。

3.架构体系描述

整个系统顶层架构采用分层的风格,整个系统的体系结构非常清晰,使得后期易于详细设计、编码、维护以及适应需求变更。通过分层,定义出层与层之间的接口,使得在更加规范的同时拥有更为多台花的接口描述,使得层与层之间的耦合度降低,增强了模块的服用型和可扩展性以及可维护性。同时,分层也有益于项目模块的划分以及任务的分配,通过明确清晰的接口,降低集成的难度,提高效率。

4. views

4.1 Module structs

(1)具有三层结构的测测软件包图:

图4.1.1领域模型图

.

.

(2)测测软件领域模型图:

图4.1.2领域模型图

(3)测测软件类图:

图4.1.3类图

.

.

(4)测测系统用例图:

图4.1.4系统用例图

4.2 Component & Connector(组件-连接器视图)

(1)性格测试顺序图:

.

.

图4.2.1性格测试顺序图

4.3 Allocation

(1)测测软件部署图:

图4.3.1部署图

5. Mappping between views

5.1 Class map to Package

(1)类图中的TTestController类、UserContainer类、TendencyContainer类对

.

.

应于包图中表示层的UI包。

(2)类图中的TTest类、User类、Test类、InteligentTest类、CharactTest类、Tendency类、Daily Trend类、ServiceController类对应于包图中业务逻辑层的测试模块包和评价模块包。

(3)类图中的DataHelp类、I/OEventStream类、QuestionBase类、UserInfo类对应于包图中数据层的题库管理包和用户管理包。

5.2 Package map to Allocation

(1)包图中的UI包、测试模块包、评价模块包位于部署图中的C/S客户端。 (2)包图中的题库管理包和用户管理包位于部署图中的客户端数据库和数据库服务器。

6. Utility tree

6.1 Quality attribute scenario (质量属性场景)

(1)可用性: 情节描述: 用户在进行性格测试时,点击无反应。 相关质量属性: 可用性 刺激源: 刺激: 环境: 制品: 反应: .

进行性格测试的用户 用户点击性格测试 正常运行状态 性格测试功能模块 提示程序无响应,需重启软件 .

反应度量: 策略: 异常检测 异常处理

在2s内给出提示 (2)互操作性: 情节描述: 用户完成测试,进行提交,数据库返回测试结 果。 相关质量属性: 互 操作性 刺激源: 刺激: 环境: 制品: 反应: 反应度量: 策略: 发现服务

(3)可修改性: 情节描述: 开发人员更新数据库 进行测试的用户 用户完成测试,进行提交 正常运行状态 数据库、测试模块 显示测试结果 在1s内显示测试结果。 相关质量属性: 可修改性 刺激源: .

开发人员 .

刺激: 开发人员更新数据库数据 环境: 制品: 反应: 反应度量: 策略: 减少耦合 提高内聚 封装

(4)性能: 情节描述: 用户完成测试,提交,数据库返回测试结果。 正常运行状态 数据库, 显示测试结果 在1s内显示测试结果。 相关质量属性: 性能 刺激源: 进行测试的用户 刺激: 开发人员更新数据库数据 环境: 制品: 反应: 反应度量: 策略: 同时计算

.

用户完成测试,提交。 正常运行状态 显示测试结果 在1s内显示测试结果。 .

(5)安全性: 情节描述: 黑客侵入数据库盗取用户密码。 相关质量属性: 安全性 刺激源: 黑客 刺激: 黑客非法侵入数据库 环境: 制品: 反应: 反应度量: 策略: 拒绝攻击 反应攻击 确定用户

(6)可测试性

情节描述: 在开发阶段开发者对自己的模块进行单元测试。 正常运行状态 数据库安全保护模块 阻止黑客获取数据库内容 在1s内进行拦截 相关质量属性: 可测试性 刺激源: 开发人员 刺激: 对已完成的子系统进行测试 .

.

环境: 制品: 反应: 反应度量: 策略: 限制复杂性

(7)易用性 情节描述: 系统开发中 被测代码段 显示代码出错情况 执行测试的时间不能超过2s 用户在完成某一测试后重新进行测试 相关质量属性: 易用性 刺激源: 欲进行重新测试的用户 刺激: 用户点击重新测试 环境: 制品: 反应: 反应度量:

软件正常运行环境 相应测试功能模块 进入该测试,显示测试题 重新跳转到相应测试界面的时间不超过2s。 6.2 Utility tree

质量属性 属性细化 场景 ASR 在系统处于正常运行时,为对题库更新做性能 题库更新响应时间 出响应,用户更新题库要在3分钟内完成.

.

(H,M) 软件产商发布了一个新版本,必须尽快安装该版本。(H,L) 可维护性 软件更新 维护人员发现了软件的缺陷,修复该bug。(H,M) 机密性 安全性 完整性 非维护人员侵入数据库,需在1S内完成拦截。(H,M) 系统拒绝未经登录的访问。(H,M) 软件产商发布了一个新软件,该软件是热插拔的。(H,L) 发布新版本 可用性 网络环境不佳 软件产商发布了一个新软件,支持用户随时进行更新。(M,L) 用户进行每日运势测评无响应,终端在1S内提示用户网络环境不佳,请打开网络连接。(M,L) 用户提交测评后,系统在0.5s内显示测评响应时间 结果。(M,H) 性能 100名用户同时在线时,系统每秒能处理吞吐量 150个正常请求。(M,H) 优化测评结果分析算法,两名开发人员在可修改性 优化算话的复杂性 一个工作日内完成。(H,L)

.

.

6.3 Tactics

一,安全性策略: 1、反应攻击 2、确定用户 二,可用性策略: 1、异常检测 2、异常处理 3、实时监听 三,安全性策略 1、加密数据 2、拒绝攻击 3、反应攻击 4、确定用户 四,可修改性策略 1、降低依赖 2、减少耦合 3、提高内聚 4、封装 五,性能策略 1、同时计算

.

.

7. Architecture

根据软件的重要需求,确定了本软件所采用的设计模式:

7.1 WebService

决定运用该模式的需求:

(1)客户端数据库与服务器同步,采用双数据库实现效率提高。 (2)需调用API,进行每日运势分析。

WebService 调用每日星座运势API核心代码如下:

private void updateEverydayFortune() { if(isNetworkAvailable()){//有网络就更新 //启动更新数据线程 new Thread(new updateEverydayFortuneRunnable()).start(); } } private class updateEverydayFortuneRunnable implements Runnable{ SimpleDateFormat simpleDateFormat = new SimpleDateFormat(\"yyyy-MM-dd\"); String now = simpleDateFormat.format(new Date()); SharedPreferences sharedPreferences = MainActivity.this.getSharedPreferences(\"xzlm\",Context.MODE_WORLD_READABLE); Override public void run() { //将值取获,然后保存 for(int i=1;i<=12;i++){ //判断是否要更新 String date = sharedPreferences.getString(i+\"_date\", \"NoDate\"); if(date.equals(\"NoDate\")||!date.equals(now)){//需要更新的星座就去更新。 sendInfo(i); } } } }

.

.

private StringBuffer json; private void sendInfo(int constellationid) { // 发送http请求 URL url = null; HttpURLConnection conn = null; DataOutputStream outputStream = null; BufferedInputStream bufferedInputStream = null; String requestUrl = \"api.uihoo./astro/astro.http.php\"; String param = \"fun=day&id=\" + EverydayFortune.httpConstellationNumber[constellationid - 1] + \"&format=json\"; byte[] entity = param.getBytes(); try { url = new URL(requestUrl); conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setDoOutput(true); conn.setUseCaches(false); conn.setRequestMethod(\"POST\"); conn.setRequestProperty(\"Charset\", \"UTF-8\"); conn.setRequestProperty(\"Content-Length\", String.valueOf(entity.length)); outputStream = new DataOutputStream(conn.getOutputStream()); outputStream.write(entity); outputStream.flush(); if (conn.getResponseCode() == 200) { bufferedInputStream = new BufferedInputStream(conn.getInputStream()); byte[] bf = new byte[1024]; int i = 0; json = new StringBuffer(); while ((i = bufferedInputStream.read(bf)) != -1) { String str = new String(bf, 0, i); json.append(str); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } if (json != null) { // 有数据返回,下面解析这些数据,并保存 resolveJSONAndSave(constellationid); } } //解析回传的json

.

.

private void resolveJSONAndSave(int constellationid) { JSONArray array; try { array = new JSONArray(json.toString()); String zhys = array.getJSONObject(0).getString(\"rank\"); String aqys = array.getJSONObject(1).getString(\"rank\"); String gzzk = array.getJSONObject(2).getString(\"rank\"); String lctz = array.getJSONObject(3).getString(\"rank\"); String jkzs = array.getJSONObject(4).getString(\"value\"); String stzs = array.getJSONObject(5).getString(\"value\"); String xyys = array.getJSONObject(6).getString(\"value\"); String xysz = array.getJSONObject(7).getString(\"value\"); String spxz = array.getJSONObject(8).getString(\"value\"); String zhgs = array.getJSONObject(9).getString(\"value\"); String date = array.getString(11); //保存到sharedPreferences SharedPreferences sharedPreferences

MainActivity.this.getSharedPreferences(\"xzlm\", Context.MODE_WORLD_WRITEABLE); Editor editor = sharedPreferences.edit(); editor.putString(constellationid+\"_zhys\", zhys); editor.putString(constellationid+\"_aqys\", aqys); editor.putString(constellationid+\"_gzzk\", gzzk); editor.putString(constellationid+\"_lctz\", lctz); editor.putString(constellationid+\"_jkzs\", jkzs); editor.putString(constellationid+\"_stzs\", stzs); editor.putString(constellationid+\"_xyys\", xyys); editor.putString(constellationid+\"_xysz\", xysz); editor.putString(constellationid+\"_spxz\", spxz); editor.putString(constellationid+\"_zhgs\", zhgs); editor.putString(constellationid+\"_date\", date); editor.commit(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 判断有没有网络 * * return是否有网络 */ private boolean isNetworkAvailable() {

.

=

.

Context context = getApplicationContext(); ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivity != null) { NetworkInfo[] info = connectivity.getAllNetworkInfo(); if (info != null) { for (int i = 0; i < info.length; i++) { if (info[i].getState() == NetworkInfo.State.CONNECTED) { return true; } } } } return false; }

7.2 MVC (Model View Controller)

决定运用MVC模式的需求:

(1)实现测试题目选项统计,进行测试结果分析。 MVC核心代码如下:

//Model:///////////////////////////////////////// package .example.service; import java.util.ArrayList; import java.util.List;

import java.util.Observable;

public class Model extends Observable { private List mList ; public int get(int idx) { return mList.get(idx); public void set(int idx) { mList.set(idx,1); setChanged(); notifyObservers(); } public void back(int idx) { mList.set(idx,0); setChanged(); notifyObservers(); }

.

.

public Model(){ mList = new ArrayList(4); mList.add(0); mList.add(0); mList.add(0); mList.add(0); } }

///Controller://///////////////////////////////////////////// answerGroup.setOnCheckedChangeListener(new OnCheckedChangeListener(){ Override public void onCheckedChanged(RadioGroup group, int checkedId) { // TODO Auto-generated method stub nextBtn.setEnabled(true); switch (group.getCheckedRadioButtonId()) { case R.id.answerA: model.set(0); model.back(1); model.back(2); model.back(3); break; case R.id.answerB: model.set(1); model.back(0); model.back(2); model.back(3); break; case R.id.answerC: model.set(2); model.back(0); model.back(1); model.back(3); break; case R.id.answerD: model.set(3); model.back(0); model.back(1); model.back(2); break; } } }

.

.

7.3 Publish/Subscrib

决定运用“发布—订阅”模式的需求:

(1)测试题库需定期更新,并自动提示用户。 Publish/Subscrib核心代码如下:

//Publish/Subscribe接口://///////////////// public interface ISubscribe { void getNewPaper(); }

//个人订阅者:///////////////////////////////////////

public class PersonalSubscriber implements ISubscribe { private String strName; public void setNewsPaperName(String strName){ this.strName = strName; } public String getNewsPaperName(){ return strName; } Override public void getNewPaper() { // TODO Auto-generated method stub System.out.println(\"尊敬的用户,\"+getNewsPaperName()题库已更新,欢迎测试!); } }

//发布者://///////////////////////////////////////// public abstract class Publish { public List list; public Publish(){ list = new ArrayList(); }

public void registered(ISubscribe iSubscribe){ list.add(iSubscribe); }

public void unregistered(ISubscribe iSubscribe){ list.remove(iSubscribe);

.

.

}

public abstract void sendNewsPaper(); }

//下面是实现:

public class PostOffice extends Publish{ Override public void sendNewsPaper() { // TODO Auto-generated method stub Iterator iterator = list.iterator(); while(iterator.hasNext()){ ((ISubscribe) iterator.next()).getNewPaper(); } } }

//测试:////////////////////////////////////////////////////////////// public static void main(String[] args) { // TODO Auto-generated method stub PostOffice postOffice = new PostOffice(); //得到个人用户 PersonalSubscriber person = new PersonalSubscriber(); person.setNewsPaperName(\"智力测试\"); //注册观察者 postOffice.registered(person); postOffice.registered(enterprise); //发布订阅消息 postOffice.sendNewsPaper(); }

.

因篇幅问题不能全部显示,请点此查看更多更全内容