高质量软件模块开发总结

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

当开始进行模块开发时,系统负责人会给模块开发负责人描述模块功能与要求,但是此时模块功能与需求一般是比较粗线条和不完备的,例如很多细粒度异常情况处理需求一般系统负责人可能会考虑不到。模块负责人通过详细设计完成:细化和确定模块的功能(包括异常处理需求)、识别关键问题和实现策略与流程、以及主要静态类和线程结构设计等。详细设计完成并通过评审之后,模块负责人根据详细设计指导,进行编码并实现模块。需要指出的是即使详细设计,但一般只是初步设计了主要的类和线程结构,以及一些比较大方面的异常情况处理。虽然可能不同的人完成的详细设计的细致粒度存在差别,即使是设计比较细致的详细设计一般不能到达可以直接根据详细设计自动生成代码的粒度,当然个人认为类和线程结构等实现方面的设计也没有必要太过细致,要把握好度,不要太过也不要不够。因此即使在编码和实现阶段其实也存在大量的设计工作,此时设计的粒度较为细致,一般是类级别的详细设计和编码实现(包括详细划分和确认类的功能规格说明书,并实现类的功能)。虽然个人认为在详细设计阶段类和线程结构等实现方面的设计不必要太过细致,但是对模块功能规格(包括异常处理需求)的确认和细化一定要尽可能细致和想全。对关键问题和实现策略也一定要尽可能的细致和想全。对实现方面的类和线程结构设计能够想细还是细的为好,即尽量想细一点为好。所谓“谋定而后动”,只有先设计好了,想好了后面才能少出错。根据上面论述,我们可以得出不管是详细设计还是编码实现都包括两个阶段工作:首先确认和细化功能规格,然后是实现功能规格。对详细设计而言是确认和细化模块的功能规格,并初步设计如何实现模块功能。对编码实现而言是确认和细化各个类的功能规格,然后实现各个类功能,最终实现模块功能。而导致模块质量不高的主要原因是整个开发过程,没有明确地区分“确认和细化功能规格”和“实现功能规格”两个阶段,很多开发者的开发过程是两个过程混在一起,整个过程属于没有明确方向和不断变化的状态,恶果是导致很多例外情况没有考虑到并进行妥当处理,最终导致大量BUG的出现。具体表现如下:详细设计时,模块功能需求确认不够细致,甚至是一直到编码实现阶段都是处于模糊状态,导致很多情况没有想到。例如各个对外提供接口的功能细节,特别是在一些异常情况下的返回值细节或者响应细节都不是很明确。详细设计时,不仔细考虑会存在哪些异常情况,以及设计相应异常处理措施,导致在设计阶段很多异常根本没有考虑。详细设计时,不识别模块实现中关键问题,导致很多关键实现策略要到编码时才确定,但是由于编码时一般思维焦点是当前类,导致确定实现策略时缺乏全局考虑,同时加上还要考虑如何实现,因此会导致采用不是最优的或者是错误的实现策略。详细设计时,类、类状态变化、线程结构设计等考虑太粗。由于详细设计时能不考虑具体实现,会忽略一些细节,这样更能集中精力从整体和全局来考虑一些关键的实现策略和以及类和线程结构设计。而实现阶段一般更加关注细节,但只关注当前类细节和局部细节,因此详细设计时类、类状态变化、线程结构设计等考虑太粗会导致这些问题遗留到开发阶段,使得整个编码过程混乱,最终很多例外情况想不到。至少要保证详细设计完成后,模块开发者能在自己大脑里面把模块跑起来。编码实现阶段,还没有制定清楚每个类、类方法的详细功能规格说明(即要处理哪些情况,异常情况下如何处理等)的情况下,就开始编码实现。明确区分两个阶段的好处是每次大脑只需要集中精力考虑一个方面问题,这样大脑考虑问题会比较轻松,使得问题能够容易想全,出现纰漏的概率要小一些。1详细设计过程明确划分为两个阶段第一个阶段是明确模块的需求,能够以详细的功能规格说明书的方式,明确模块的功能需求,重点考虑模块要处理哪些例外和异常情况,尽自己最大努力把情况想全。例如对本模块对外提供的接口要详细写清楚,各种输入参数情况下的行为是什么,以及返回什么值。对本模块要调用的外部接口,要写明白本模块要求的响应是什么,以及调用失败情况下的处理策略等。此阶段同时要描述清楚本模块运行环境包括:与周围模块交互描述、对内存以及磁盘的要求等对外围环境的需求、模块部署方式(多机并发部署、还是单节点运行)等。注意此时只集中精力考虑需求,不要考虑如何实现。第二阶段是设计中的实现阶段。此阶段要求必须包括有:关键问题与实现策略、主要静态类图设计和说明(主要类、主要方法说明)、线程结构说明(包含哪几类线程、每类线程个数、每类线程职责、每类线程会访问到的类和对象等,如果比较复杂则要说清楚为什么这些设计,设计目标是解决什么问题)、在线程结构基础上描述互斥策略以及线程间关系等、主要的处理活动图(个人推荐更多使用泳道图,能更直观看到对象之间的职责划分和交互过程)。如果类对象的状态比较多,则建议采用状态机图的方式描述清楚,并通过审查状态机变化来检查是否有情况没有处理。2编码阶段建议采用三个步骤先想清楚,并写出类和每个方法详细功能规格说明(可以先把类名和方法名写好,然后以注释的方式把类的职责、关键实现策略、以及每个方法的功能规格说明重点是例外和异常情况的处理与返回值)。根据规格说明中列举情况,写出相应测试代码。编写实现代码,并通过测试。编写模块功能规格说明书,重构代码经过编码阶段之后,模块功能已经非常明确了,此时应该细致、清楚地编写模块功能规格说明书。原因如下:1)模块功能规格说明中描述的功能会比详细设计中更为细致和清楚。另外经过编码阶段,此时模块实现的功能可能与详细设计时考虑的模块功能在细节方面可能会有些变化。项目描述本模块的功能说明,可以方便自己和其他人日后进行系统维护工作。2)通过编写该功能规格说明可以弥补详细设计万一考虑不细情况下,一些例外和异常情况是否处没有处理或者处理不周到。由于在详细设计阶段,设计出模块的类和对象构成以及运行机制还是有一些模糊,因此很可能存在某些例外、特别分布式情况下某些状态组合没有考虑到的情况发生。但是在编码阶段,由于一般只会关注当前类和当前的方法的实现,因此考虑问题一般比较局部。为此在完成整个模块编码后,所有细节都已经明确(特别是在写代码过程中会发现存在一些新的异常情况需要处理详细设计时没考虑到),此时必须再一次从整体来考虑模块运行起来后在处理逻辑是否有缺陷,这样能更早发现以前设计中缺陷,避免上线后才发现缺陷。此时重点考虑是否还有情况没有考虑到或者某些处理不到位。很多BUG难以发现和定位原因是在不同类和对象之间的发生交互和联系后,组合排列后的情况非常多,从而想不到某些组合。这种BUG只有从整体考虑、考虑不同类和对象之间交互关联后才可能想到。3模块详细设计指南与规范模块详细设计要完成两个方面工作:一是明确模块的功能需求和非功能需求、二是设计如何完成和实现模块的功能需求,包括类结构、线程结构设计等。本节根据后台模块特点,描述了两部分工作需要考虑和设计的关键点。3.1确定模块的功能规格1)本模块概述概述主要描述了本模块所属子系统,以及在子系统中所承当职责的简单描述。2)本模块在系统中与周围模块关系和交互情况很多模块一般要依赖周围的模块或者数据库,为此建议以图形方式描述本模块与本模块依赖的其他模块或者数据库之间交互情况。交互方式主要包括:基于接口调用的交互、基于数据流的交互,直接访问数据库。基于接口交互要描述:接口实现方式(ICE、WCF等)、接口调用目的、以及什么时候调用等。基于数据流交互要描述:传输数据类型,传输方式等。对数据库或者存储要描述:需要访问的数据库名称、表格名称以及表格存储数据含义、访问数据库中表格的目的等。3)本模块部署角色以及对基础软硬件要求描述本模块将要部署的角色、部署模式、对操作系统要求、对基础软件要求、对硬盘要求、对内存要求等。部署模式主要考虑是分布式多机部署、还是只会单实例部署。操作主要考虑需要对操作系统版本的要求。基础软件主要包括:jdk版本要求、需要安装其他基础软件以及版本等。对硬盘要求:是否需要临时存储、大概需要多大(尽量能不用存储就不用)。对内存要求:大概需要多大内存等。4)本模块所处理数据的数据格式描述对数据预处理模块,描述本模块对待处理数据的格式的假定和要求。5)本模块调用接口描述详细描述清楚需要调用接口:接口名字、参数类型、参数单位、接口功能、接口执行时间要求(超时处理)、分片传输(消息大小限制导致分片传输需求)。接口功能部分重点要描述清楚异常情况下接口返回值和应该执行操作,例如调用的接口是否会返回NULL等。6)本模块功能性需求描述以功能点方式详细描述本模块功能。如果是涉及对外提供接口的,明确描述:接口名字、参数类型、参数单位、各种输入参数下预期行为和返回值、接口应该满足执行时间要求。7)例外与异常情况下描述与处理要求详细考虑本模块第2)、3)、4)、5)中所描述本模块依赖的外部环境不满足本模块要求情况下的处理方式。3.2设计与实现部分1)关键问题与策略只要有一点复杂或者难度模块的设计工作都会存在几个有难度或者关键问题去解决,这些关键问题的解决方案好坏决定了整个模块实现质量。一般而言这些关键问题解决方案会有多种,并且有好有坏,且会存在较大争议。相反一般非关键点设计就比较没有异议。关键问题与策略是开展设计评审的重点。模块设计评审就是审查两点:是否存在有些关键问题没考虑到、二是每个关键问题的解决方案是否是最优的。因此要求模块设计人员,在确认了功能规格后,第一件事就是要考虑本模块设计中存在哪些关键问题,然后再思考对应解决方案。在确定了所有影响比较大的关键问题的解决方案之后,剩余的类结构设计和线程设计等就会比较顺利。此部分要求设计人员要反复问自己:一是否所有值得斟酌的问题都想到了、二目前设计的策略是否是最好的(好的策略一般是简单策略),要敢于否定自己已经设计好的策略。衡量优秀实现策略的标准是:“用最简单方式满足最重要需求”。后台设计过程中要避免的事情是:不要为了某个不常用、但是听起来很美好的功能点导致设计很复杂。有时候为了模块运行简单和稳定,宁肯不要太完美。特别是很多时候很多需求是矛盾和有冲突的,作为设计人员一定要能识别哪些是主要需求,哪些是次要需求。例如某全文检索检索模块,第一版本为提高检索性能,设计了检索结果缓存功能。但是实际使用过程中发现缓存命中概率很低,而这个功能导致整个模块设计复杂很多。2)静态类结构设计类结构设计,主要设计出本模块主要类以及类之间的关系,并利用类图的方式表达出来。在静态类结构设计中,除类图外,还需要对各个类的职责分工,以及类中主要的方法要进行描述。另外要仔细考虑哪些类是主动类。在静态类结构设计好坏,主要取决与设计人员面向对象设计的能力。要求设计人员考虑以下几个方面:是否可以采用现成的设计模式。是否违反了面向对象的几个原则:单一职责原则、开放封闭原则、替换原则、依赖倒置原则、接口隔离原则。为了提高自己此方面设计能力,希望大家多看一些面向对象设计方面的书,以及一些经典优秀开源软件的结构,能真正领会设计模式和面向对象的几个原则的精髓,并能指导自己模块类结构设计。另外如果感觉自己负责多个模块存在重复部分,例如感觉可能几个模块大的处理步骤基本相同,只是在处理细节上不同,则可以考虑将其中相同部分抽出来设计成一个具备一定通用性的框架或者共用代码,并贡献出来。3)线程结构与同步互斥策略设计后台模块一般会涉及多线程的处理,因此线程结构设计是后台组模块设计经常会遇到的问题。线程结构设计必须描述以下几个部分:包括那几类线程以及每类线程的职责每类线程的个数每类线程的启动和停止时间线程间的协作关系:消费者-生成者关系、同步互斥、共享变量等。为了清楚描述和思考同步互斥问题,建议采用图的方式划出每类线程与每类线程会访问到公共对象,这样就能很直观识别出需要保护的对象,然后在详细设计和描述同步互斥策略。线程结构设计基本经验是:尽量减少线程间的交互。例如有三类线程,本来可能需要每类之间都要交互,则可以考虑以以某类线程作为枢纽,其他两类线程都和该线程交互,而其他两类线程之间不交互。同步互斥在后台性能不是很重要情况下,可

1 / 9
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功