学习软件系统分析与设计这门课的过程,是把系统的、有序的、可量的方法应用到软件的开发、运营和维护上的过程。软件系统设计与分析,顾名思义,是一门用工程化的思想去开发软件的学科,强调软件开发的工程性。分析是对软件进行需求分析(明确所要做的内容:对图书进行增删查改),技术可行性分析(实现软件的可行性:要用几个文件,要用二进制存储),风险评估分析(可能面临的问题:输入合法性,内存溢出等),强调对软件的认识与研究。设计是设计软件系统的整体结构、划分功能模块、确定每个模块的实现算法以及编写具体的代码,形成软件的具体设计方案,强调的是软件的具体实现。曾经以为程序就是软件,软件就是程序。学习这门课程第一个收获是,知道了二者的不同之处。软件实际上是一个工程,并不是写写语言代码这么简单。我们在掌握计算机科学与技术方面知识和技能的基础上熟练掌握从事软件需求分析、软件设计、软件测试、软件维护等工作所必需的基础知识、基本方法和基本技能。 在听了老师的课后,我明白了不管我们从事任何工作,我们都必须要兼备两种条件:热情和能力。热情,是不能够在小组合作中“打酱油”,在组内各司其职,稍微加个班来完成一个程序也是正常现象;能力,是你要在自己的岗位上做好本职工作,如果我擅长代码,那我就负责一些模块代码的编写,如果我代码能力较弱而组织动员能力强,那我就负责规划程序的逻辑和督促进度。的确想要过得到真正的提升,是要比别人多吃一些苦,多承担一些责任,多付出。我对这门课的期待就是自己能从这门课程中学到更多的知识,最好能学了这门课以后知道自己以后想干嘛,知道怎么去实现自己的目标,毕竟本门课程算是我正式参与的一个项目工程。 首先对于项目内容我做了一个简单了解。图书馆在正常运营中总是面对大量的读者信息、书籍信息以及两者相互作用产生的借书信息、还书信息。因此需要对读者资源、书籍资源、借书信息、还书信息进行管理,及时了解各个环节中信息的变更,有利于提高管理效率。对于我们团队人员一个开发人员需要首先考虑的稳定性,首先将软件系统的质量保证了,才能做其他更多的。其次,需要提升系统的性能,在保证了系统质量之后,提升了性能就给用户更好的体验,让用户用得爽;以一个系统设计者的视角来看软件系统,要求会有别于软件开发人员,首先要将系统的实用性放在首位。试想,一个系统哪怕质量再好,运行得再快,给人看到再炫酷的效果,结果没什么实际用处,也不会有人去用。其次,是如何实现系统。 软件的复杂性是一个基本特征,这种固有的复杂性有四个原因:问题域的复杂性、管理开发过程的困难性、能实现的灵活性,以及刻画离散系统行为的问题。首先是问题域的复杂性。软件工程写软件的目的就是为了解决用户的需求,当然在开发的不同时期,需要解决不同的问题。在需求分析阶段我们要弄清楚有哪些实体,或者说要有哪些对象实例,这些实体都有哪些属性,以及各实体之间的关系,最后还有在这个基础上弄清楚用户的需求是什么。管理开发过程的困难性具体体现在算法和技术上,在任务开始,我们的开发小组的基本任务就是让用户操作尽量简洁,与内部的复杂性隔绝,程序分了各个层次,各部分不是完全独立的,组件中的高频动作(组件的内部结构)与低频动作(组件间相互作用)分离;小组内部进行需求分析,决定软件功能,规定代码规范(例如命名,参数)维持设计的一致性和完整性,规范录入各种图书信息和各种数据,对用户的账号信息进行规范保存。软件中随处可能出现的灵活性和离散性使得开发者几乎有可能表达任何形式的抽象,我们设置的抽象类可以存在功能、结构等上的重复,为了达到分层的效果我们需要在底层类中封装尽量多的抽象类来完成后续函数功能的调用,该系统的设计分成几个相对独立的模块,便于在前端进行分别调用。运用面向对象的编程思维, 可以完成具体对用户和书籍的管理,在面向对象模型的总体特征中我会具体讲述。 在设计与实现阶段,我们要知道软件是如何解决这些需求的,以及显示世界中实体和属性在软件系统中是如何交换信息的。在测试和发布阶段,我们要知道软件是否真正解决了这些需求,软件解决需求的效率如何。
在设计过程中,我们使用了最为重要的面向对象的设计思想。面向对象是相对于面向的过程而言的。对于具体的功能来说,就是把软件的功能封装进对象,强调具备了功能的对象。好处就是:在完成指定的需求时,先去找具有所需功能的对象来用;如果该对象不存在,那么创建一个具有所需功能的对象;这样简化了开发并且提高了复用性。面向对象有一个非常重要的设计思维:合适的方法应该出现在合适的类里面。在图书管理系统或程序设计中应用了对象模型。在面向对象分析中,主要由对象模型、动态模型和功能模型组成。对象模型是最基本、最重要、最核心的。在本软件中,我们设置的对象具有一定的特征和行为,比如图书特征有ISBN,编号,数量,可以被增加减少;用户有id,姓名,电话号码,可以借书还书。 面向对象模型的总体特征如下。 ① 抽象: 是指核心问题。结合面向对象的概念来看,所有的对象都是通过类来描绘的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。 在本程序中抽象类的使用如下:在本实验中存在的是BOOK、USER等抽象类,例如把图书表抽象成一个线性表,每本图书(包括图书书名、图书作者、图书存放位置、图书出版社、图书出版时间、图书入库数量、剩余数量)作为线性表中的一个元素。在图书信息管理信息系统中要求实现查找,插入,删除,修改和计数等功能。再例如数据抽象的使用:在本次程序设计中,使用C++数据抽象方法可以实现面向对象的简单操作,例如你可以调用changeTelephone()函数,来修改用户的电话信息,而不需要知道函数中排序数据所用到的算法。函数排序的底层实现会因库的版本不同而有所差异,只要接口不变,函数调用就可以照常工作。 C++中,由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。继承在下一个模块细说。 ② 继承: 在设计一个程序之前,我们需要明白代码是必须可修改的并且易于修改的,这样才能有利于团体合作,所以我们也要注重代码的可维护性。如果后期需要修改很多的代码,则容易出错。如果不使用继承,那么相似功能的类中会出现大量的代码的重复,造成代码量大且臃肿,不易于维护,所以我们使用了c++中的继承,可以将几段有相似功能的代码中相同的部分提取出来组成一个父类,子类会继承父类的所有 public 的字段和方法。例如"Student.h"中"class Student :public User"就是一种继承,子student类得到了父user类的int getId();char* getPassword()等函数,然后把从父类得到的函数应用在自己新构造的函数中,例如student里的函数changeMyPass()中就调用了User里的getPassword()函数。继承还有一个特点是,父类的private 的字段和方法, 子类中是无法访问的。由于在本程序中我们使用了分层,所以处于基层的base类并没有private字段,在borrow、student等类中则出现了private字段,分别用来储存不同对象(书籍,用户)的各自的属性(id,ISBN等),防止在调用子类的时候被篡改原有属性。 ③ 封装: 是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。?主要体现在父类的private,在刚刚的继承中也提到过。封装的特点如下:不是每个属性都需要对外公开(borrow类的userid,number)、有一些类的属性是对外公开的(getUserId()、writeBorrow(n)等)、必须在类的表示法中定义属性和行为的公开级别。c++类的封装机制使得使用方式和内部细节分开,在此不多赘述。 ④ 模块化: 该系统的设计分成几个相对独立的模块,便于在前端进行分别调用。各个模块之间的关系是相互联系的。首先,主函数包含了所有的子函数。主函数是整个程序的核心。子函数之间也是有联系的,对前端管理员功能、学生功能,必须是调用中层的调用user、history、student类实现而user、history、student类的子函数之间是没有多大联系的。我们先把程序功能模块分解开,不同的功能模块使用不同的函数来实现,用C++提供的多个.cpp源文件(Base.cpp、Book.cpp、Borrow.cpp、User.cpp、History.cpp等)和.h头文件(Base.h、Book.h、Borrow.h、User.h、History.h等)来规划存放代码,让程序的功能模块之间耦合度降低,扩展性增强。当我们想增加或者删减某个功能的时候,只需要对程序做一点改动就可以,提高工作效率,这也是软件工程中必不可缺的合作原则。 ⑤ 层次: 类似于模块化,分层的模块化程序设计思想,整个系统采用模块化结构设计作为应用程序,有较强的可操作性和扩展性。该程序由底层文件Base.cpp支撑,user、history、student类调用base类中函数,前端的book、borrow、administer则调用user、history、student类实现功能。 ⑥ 对象标识: 标识符有若干:void、abstract、static、final等等,对象标识具有唯一性,对象将始终记住它的类标识;当我们用不同类型的引用变量来指向对象时,这会帮助编译器判断对象是否可以回应特定的消息。例如本实验中的:student属于user类,user属于base类,它们各有自己的对象标识,在编译的时候只有通过base的句柄指向对象,编译器才允许我们访问base独有的特征。 ⑦ 分类: 对数据类型进行了分类:类(分了7个类:Administrator、Base、Book、Borrow、History、Student、User类) 、接口(每个.h之间相互调用) 、字符串(char name[BOOKNAMESIZE], char author[AUTHORSIZE]等)。 ⑧ 持久性: 对本实验来说,在应用程序(控制台)终止之前,实体对象的最新映射(例如修改后的用户资料)会持久保存在数据库(也就是我们把数据存在文件里)中。在对图书管理程序进行检查的过程中,检查到连续修改并没有对原有信息进行完全修改,这就是持久性较差。好的程序都应该需要具备数据持久性,即使在服务器崩溃(或者简单来说,程序出现断点)的情况下仍能存在数据存储。对于一个成熟的软件,必须具备稳定性,而持久性也是稳定性的一个体现。 ⑨ 并发性: 软件正式投入运营前需要进行一系列测试,并发性则是是一个负载测试和压力测试的过程,即逐渐增加负载,直到系统的瓶颈或者不能接收的性能点,通过综合分析交易执行指标和资源监控指标来确定系统并发性能的过程。在本实验中我们设计了测试报告,测试项例如已被删除学生是否可借书、删除在借图书的学生、错误输出等等,来决定系统的性能。 ⑩ 实用性: 简单点说,如果一个系统不能给用户带来使用价值,做再多的工作也是徒劳。在设计需求分析时我们小组讨论了很多情况,例如:需不需要加公告栏?每次返回时要返回首界面还是上一界面?有没有必要在每一次操作后进行确认与否?实用性可以说是所有软件的基石,是基础的基础。
在本课程设计的设计过程中,我们刚开始感觉到有点头痛,毕竟涉及到了一个程序的分割分组完成,要通过两年来C++的学习后将所学知识运用起来有点困难,但回过头来再去看教课书,对于分层的一步一步熟悉运用,概念和解决方案更进一步的理解,感觉也不是很难。外我还体会了从事C++课程设计工作需要特别谨慎认真地态度和作风,一点都不能马虎。每个细微的细节都必须十分注意,如果不认真思考,就会出现或大或小的错误。如果把早期的错误隐藏下来,对后面的工作影响就会很大,甚至有时会推倒很多前面做的工作。有时候,我们自己觉得我写的程序非常正确,但是就是编译通不过,在查找错误的过程中,面临着否认自己的过程,非常的痛苦,而且由于自己的经验及各方面的能力的不足,所以进展的速度非常的缓慢,往往几天的时间没有一点进展。下次一定会吸取本次的经验,记得写注释。
|