高质量代码三要素

高质量代码三要素
高质量代码三要素

高质量代码的三要素

我们评价高质量代码有三要素:可读性、可维护性、可变更性。我们的代码要一个都不能少地达到了这三要素的要求才能算高质量的代码。

1.可读性强

一提到可读性似乎有一些老生常谈的味道,但令人沮丧的是,虽然大家一而再,再而三地强调可读性,但我们的代码在可读性方面依然做得比较糟糕。每当我看到大段大段、密密麻麻的代码,而且还没有任何的注释时常常感慨不已,深深体会到了这项工作的重要。由于分工的需要,我们写的代码难免需要别人去阅读和维护的。而对于许多程序员来说,他们很少去阅读和维护别人的代码。正因为如此,他们很少关注代码的可读性,也对如何提高代码的可读性缺乏切身体会。有时即使为代码编写了注释,也常常是注释语言晦涩难懂形同天书,令阅读者反复斟酌依然不明其意。针对以上问题,我给大家以下建议:

1)不要编写大段的代码

如果你有阅读他人代码的经验,当你看到别人写的大段大段的代码,而且还不怎么带注释,你是怎样的感觉,是不是“嗡”地一声头大。各种各样的功能纠缠在一个方法中,各种变量来回调用,相信任何人都不会认为它是高质量的代码,但却频繁地出现在我们编写的程序了。如果现在你再回顾自己写过的代码,你会发现,稍微编写一个复杂的功能,几百行的代码就出去了。一些比较好的办法就是分段。将大段的代码经过整理,分为功能相对独立的一段又一段,并且在每段的前端编写一段注释。这样的编写,比前面那些杂乱无章的大段代码确实进步了不少,但它们在功能独立性、可复用性、可维护性方面依然不尽人意。从另一个比较专业的评价标准来说,它没有实现低耦合、高内聚。我给大家的建议是,将这些相对独立的段落另外封装成一个又一个的函数。

许多大师在自己的经典书籍中,都鼓励我们在编写代码的过程中应当养成不断重构的习惯。我们在编写代码的过程中常常要编写一些复杂的功能,起初是写在一个类的一个函数中。随着功能的逐渐展开,我们开始对复杂功能进行归纳整理,整理出了一个又一个的独立功能。这些独立功能有它与其它功能相互交流的输入输出数据。当我们分析到此处时,我们会非常自然地要将这些功能从原函数中分离出来,形成一个又一个独立的函数,供原函数调用。在编写这些函数时,我们应当仔细思考一下,为它们取一个释义名称,并为它们编写注释(后面还将详细讨论这个问题)。另一个需要思考的问题是,这些函数应当放到什么地方。这些函数可能放在原类中,也可能放到其它相应职责的类中,其遵循的原则应当是“职责驱动设计”(后面也将详细描述)。

在编写代码的过程中,通常有两种不同的方式。一种是从下往上编写,也就是按照顺序,每分出去一个函数,都要将这个函数编写完,才回到主程序,继

续往下编写。而一些更有经验的程序员会采用另外一种从上往下的编写方式。当他们在编写程序的时候,每个被分出去的程序,可以暂时只写一个空程序而不去具体实现功能。当主程序完成以后,再一个个实现它的所有子程序。采用这样的编写方式,可以使复杂程序有更好的规划,避免只见树木不见森林的弊病。

有多少代码就算大段代码,每个人有自己的理解。我编写代码,每当达到15~20行的时候,我就开始考虑是否需要重构代码。同理,一个类也不应当有太多的函数,当函数达到一定程度的时候就应该考虑分为多个类了;一个包也不应当有太多的类

在aside的源码中,对包的组织是比较规范的,但很多action中存在大量大段代码的函数并且缺少注释,比较典型的有ModuleInfoAction、FileInfoUploadAction,QueryModelAction。里面都有好几百行的函数,甚至一个700行的类一个函数就占了一大半。

2)释义名称与注释

我们在命名变量、函数、属性、类以及包的时候,应当仔细想想,使名称更加符合相应的功能。我们常常在说,设计一个系统时应当有一个或多个系统分析师对整个系统的包、类以及相关的函数和属性进行规划,但在通常的项目中这都非常难于做到。对它们的命名更多的还是程序员来完成。但是,在一个项目开始的时候,应当对项目的命名出台一个规范。譬如,新增记录用new或add 开头,更新记录用edit或mod开头,删除用del开头,查询用find或query开头。使用最乱的就是get,get开头的函数应该仅仅用于获取类属性。

在aside中,ModuleInfoAction这个类的命名就非常奇怪,这是一个用来做走查的类,却起了这样一个名字,看的我非常迷惑。MissionAction,MissionManager中的命名也非常古怪,getMissionTargets02,getMissionTargets这样的函数命名很难理解

注释是每个项目组都在不断强调的,可是依然有许多的代码没有任何的注释。为什么呢?因为每个项目在开发过程中往往时间都是非常紧的。在紧张的代码开发过程中,注释往往就渐渐地被忽略了。利用开发工具的代码编写模板也许可以解决这个问题。

用我们常用的Eclipse为例,在菜单“window>>Preferences>>Java>>Code Style>>Code Templates>>Comments”中,可以简单的修改一下。

“Files”代表的是我们每新建一个文件(可能是类也可能是接口)时编写的注释,我通常设定为:

Java代码

1./*

2. * created on ${date}

3. */

“Types”代表的是我们新建的接口或类前的注释,我通常设定为:

Java代码

1./**

2. *

3. * @author ${user}

4. */

第一行为一个空行,是用于你写该类的注释。如果你采用“职责驱动设计”,这里首先应当描述的是该类的职责。如果需要,你可以写该类一些重要的方法及其用法、该类的属性及其中文含义等。

${user}代表的是你在windows中登陆的用户名。如果这个用户名不是你的名称,你可以直接写死为你自己的名称。

其它我通常都保持为默认值。通过以上设定,你在创建类或接口的时候,

系统将自动为你编写好注释,然后你可以在这个基础上进行修改,大大提高注释编写的效率。

同时,如果你在代码中新增了一个函数时,通过Alt+Shift+J快捷键,可以按照模板快速添加注释。

2.可维护性

软件的可维护性有几层意思,首先的意思就是能够适应软件在部署和使用

中的各种情况。从这个角度上来说,它对我们的软件提出的要求就是不能将代码写死。

1)代码不能写死

应该通过定义一些常量或者通过一个属性文件可以修改,也不要把所有变

量都定义在一个地方,对于一些有限制的属性,定义成int或string是非常难维护的并且不容易在编译期检查到错误,java5开始提供了枚举这种数据类型,我们要善于利用。

据一个例子,baseLine.setStatus("3"); 不可读,一旦状态发生变化,

需要各处去改,用IDE无法重构,维护性很差,而且容易错。在hibernate中有@Enumerated可以直接用来映射,可读性,可维护性会好很多,而且可以避免用户输入了乱七八糟的字符。同样的例子还有phase这个属性。后面在Constants 中定义了一些变量提高了可读性,但是同样要求调用者对用哪个Constants的变量很清楚,并且不能约束调用者必须要用,不能提供约束。

2)预测可能发生的变化

除此之外,在设计的时候,如果将一些关键参数放到配置文件中,可以为软件部署和使用带来更多的灵活性。要做到这一点,要求我们在软件设计时,应当更多地有更多的意识,考虑到软件应用中可能发生的变化。

软件的可维护性的另一层意思就是软件的设计便于日后的变更。这一层意思与软件的可变更性是重合的。所有的软件设计理论的发展,都是从软件的可变更性这一要求逐渐展开的,它成为了软件设计理论的核心。

但是在这里还要提醒的一点就是过度设计带来的问题,如果我们在设计任何功能时都考虑以后会不会有变化,然后去设计一个框架去适应这些变化,那么可能把一些简单的问题给复杂化了,因为实现一个功能和实现一个框架,然后基于这个框架实现这个功能在工作量上是有天壤之别的。这个就需要对需求要有充分的了解,并且根据经验取得平衡。大多数情况下直接实现功能,在必要的时候进行重构是比较好的方法。但如果没有持续重构的保证,走一步看一步会把代码写得乱七八糟。

3.可变更性

前面我提到了,软件的变更性是所有软件理论的核心,那么什么是软件的可变更性呢?按照现在的软件理论,客户对软件的需求时时刻刻在发生着变化。当软件设计好以后,为应对客户需求的变更而进行的代码修改,其所需要付出的代价,就是软件设计的可变更性。由于软件合理地设计,修改所付出的代价越小,则软件的可变更性越好,即代码设计的质量越高。一种非常理想的状态是,无论客户需求怎样变化,软件只需进行适当地修改就能够适应。但这之所以称之为理想状态,因为客户需求变化是有大有小的。如果客户需求变化非常大,即使再好的设计也无法应付,甚至重新开发。然而,客户需求的适当变化,一个合理地设计可以使得变更代价最小化,延续我们设计的软件的生命力。

1)通过提高代码复用提高可变更性

我们对于各数据项的操作在各个模块的代码中都可以看到,甚至有些还写入到了那些复杂的SQL语句中。在这样一种情况下,如果对数据项的命名、分类等逻辑进行修改无异于需要遍历这个项目代码。代码复用的道理十分简单,但要具体运作起来非常复杂,它除了需要很好的代码规划,还需要持续地代码重构。

对整个系统的整体分析与合理规划可以根本地保证代码复用。系统分析师通过用例模型、领域模型、分析模型的一步一步分析,最后通过正向工程,生成系统需要设计的各种类及其各自的属性和方法。采用这种方法,功能被合理地划分到这个类中,可以很好地保证代码复用。

采用以上方法虽然好,但技术难度较高,需要有高深的系统分析师,并不是所有项目都能普遍采用的,特别是时间比较紧张的项目。通过开发人员在设计过程中的重构,也许更加实用。当某个开发人员在开发一段代码时,发现该功能与前面已经开发功能相同,或者部分相同。这时,这个开发人员可以对前面已经

开发的功能进行重构,将可以通用的代码提取出来,进行相应地改造,使其具有一定的通用性,便于各个地方可以使用。

一些比较成功的项目组会指定一个专门管理通用代码的人,负责收集和整理项目组中各个成员编写的,可以通用的代码。这个负责人同时也应当具有一定的代码编写功力,因为将专用代码提升为通用代码,或者以前使用该通用代码的某个功能,由于业务变更,而对这个通用代码的变更要求,都对这个负责人提出了很高的能力要求。

虽然后一种方式非常实用,但是它有些亡羊补牢的味道,不能从整体上对项目代码进行有效规划。正因为两种方法各有利弊,因此在项目中应当配合使用。

2)职责驱动设计

前面我提到,当我们尝试写一些复杂功能的时候,我们把功能分解成一个个相对独立的函数。但是,应当将这些函数分配到哪个类中呢?也就是系统中的所有类都应当拥有哪些函数呢?或者说应当表现出哪些行为呢?答案就在这里:以职责为中心,根据职责分配行为。我们在分析系统时,首先是根据客户需求进行用例分析,然后根据用例绘制领域模式和分析模型,整个系统最主要的类就形成了。通过以上分析形成的类,往往和现实世界的对象是对应的。正因为如此,软件世界的这些类也具有了与现实世界的对象相对应的职责,以及在这些职责范围内的行为。

职责驱动设计的核心思想,就是我们在对一个系统进行分析设计的时候,应当以职责为中心,根据职责分配行为。这种思想首先要求我们设计的所有软件世界的对象,应当与现实世界尽量保持一致,称为“低表示差异”。有了低表示差异,一方面提高了代码的可读性,另一方面,当业务发生变更的时候,也可以根据实际情况快速应对变更。

a.代码设计的目标:低耦合,高内聚

耦合就是对某元素与其它元素之间的连接、感知和依赖的量度。耦合包括:1.元素B是元素A的属性,或者元素A引用了元素B的实例(这包括元素A调用的某个方法,其参数中包含元素B)。

2.元素A调用了元素B的方法。

3.元素A直接或间接成为元素B的子类。

4.元素A是接口B的实现。

如果一个元素过于依赖其它元素,一旦它所依赖的元素不存在,或者发生变更,则该元素将不能再正常运行,或者不得不相应地进行变更。因此,耦合将大大影响代码的通用性和可变更性。

内聚,更为专业的说法叫功能内聚,是对软件系统中元素职责相关性和集中度的度量。如果元素具有高度相关的职责,除了这些职责内的任务,没有其它过多的工作,那么该元素就具有高内聚性,反之则为低内聚性。内聚就像一个

管理者,它只做自己职责范围内的事,而将其它与它相关的事情,分配给别人去做。

高质量的代码要求我们的代码保持低耦合、高内聚。但是,这个要求是如此的抽象与模糊,如何才能做到这些呢?软件大师们告诉我们了许多方法,其中之一就是职责驱动设计。要理解职责驱动设计,我们首先要理解“低表示差异”。

b.低表示差异

我们开发的应用软件实际上是对现实世界的模拟,因此,软件世界与现实世界存在着必然的联系。如果我们在软件分析和设计的过程中,将软件世界与现实世界紧密地联系到一起,我们的软件将更加本色地还原事物最本质的规律。这样的设计,就称之为“低表示差异”。

采用“低表示差异”进行软件设计,现实世界有什么事物,就映射为软件世界的各种对象(类);现实世界的事物拥有什么样的职责,在软件世界里的对象就拥有什么样的职责;在现实世界中的事物,因为它的职责而产生的行为,在软件世界中就反映为对象所拥有的函数。

低表示差异,使分析设计者对软件的分析和设计更加简单,思路更加清晰;使代码更加可读,阅读者更加易于理解;更重要的是,当需求发生变更,或者业

务产生扩展时,设计者只需要遵循事物本来的面貌去思考和修改软件,使软件更加易于变更和扩展。

c.角色、职责、协作

理解了“低表示差异”,现在我们来看看我们应当如何运用职责驱动设计进行分析和设计。首先,我们通过与客户的沟通和对业务需求的了解,从中提取出现实世界中的关键事物以及相互之间的关系。这个过程我们通常通过建立领域模型来完成。领域模型建立起来以后,通过诸如Rational Rose这样的设计软件的正向工程,生成了我们在软件系统中最初始的软件类。这些软件类,由于每个都扮演着现实世界中的一个具体的角色,因而赋予了各自的职责。前面我已经提到,如果你的系统采用职责驱动设计的思想进行设计开发,作为一个好的习惯,你应当在每一个软件类的注释首行,清楚地描述该软件类的职责。

当我们完成了系统中软件类的制订,分配好了各自的职责,我们就应该开始根据软件需求,编写各个软件类的功能。在前面我给大家提出了一个建议,就是不要在一个函数中编写大段的代码。编写大段的代码,通常会降低代码的内聚度,因为这些代码中将包含不是该软件类应当完成的工作。作为一个有经验的开发人员,在编写一个功能时,首先应当对功能进行分解。一段稍微复杂的功能,通常都可以被分解成一个个相对独立的步骤。步骤与步骤之间存在着交互,那就是数据的输入输出。通过以上的分解,每一个步骤将形成一个独立的函数,并且使用一个可以表明这个步骤意图的释义函数名。接下来,我们应当考虑的,就是应当将这些函数交给谁。它们有可能交给原软件类,也有可能交给其它软件类,其分配的原则是什么呢?答案是否清楚,那就是职责。每个软件类代表现实世界的一个事物,或者说一个角色。在现实世界中这个任务应当由谁来完成,那么在软件世界中,这个函数就应当分配给相应的那个软件类。

通过以上步骤的分解,一个功能就分配给了多个软件类,相互协作地完成这个功能。这样的分析和设计,其代码一定是高内聚的和高可读性的。同时,当需求发生变更的时候,设计者通过对现实世界的理解,可以非常轻松地找到那个需要修改的软件类,而不会影响其它类,因而也就变得易维护、易变更和低耦合了。

举一个实例也许更能帮助理解。拿一个员工工资系统来说吧。当人力资源发放一个月工资的时候,以及离职的员工肯定不能再发放工资了。在系统设计的期初,开发人员商量好,在员工信息中设定一个“离职标志”字段。编写工资发放的开发人员通过查询,将“离职标志”为false的员工查询出来,并为他们计算和发放工资。但是,随着这个系统的不断使用,编写员工管理的开发人员发现,“离职标志”字段已经不能满足客户的需求,因而将“离职标志”字段废弃,并增加了一个“离职时间”字段来管理离职的员工。然而,编写工资发放的开发人员并不知道这样的变更,依然使用着“离职标志”字段。显然,这样的结果就是,软件系统开始对离职员工发放工资了。仔细分析这个问题的原因,我们不难发现,确认员工是否离职,并不是“发放工资”软件类应当完成的工作,而

应当是“员工管理”软件类应当完成的。如果将“获取非离职员工”的任务交给“员工管理”类,而“发放工资”软件类仅仅只是去调用,那么离职功能由“离职标志”字段改为了“离职时间”字段,其实就与“发放工资”软件类毫无关系。而作为“员工管理”的开发人员,一旦发生这样的变更,他当然知道去修改自己相应的“获取非离职员工”函数,这样就不会发生以上问题。

在aside中,同样存在很多类似的问题,我们每个模块对外暴露的接口基本上就是对数据库的操作接口,而没有按照业务逻辑进行封装隐藏,一个模块的数据模型的变化往往导致很多模块的变更。比如任务模块、基线模块、走查模块这些通用模块,应该从较高层次上总结出对其他模块的服务接口,其他模块要避免直接操作这些模块的数据。我们系统中更多的情况是大家害怕这种变更,不改变以前的逻辑,通过一些奇怪的方法加上新的逻辑,导致代码的可读性和可维护性越来越差。

d.职责分配与信息专家

通过以上对职责驱动设计的讲述,我们不难发现,职责驱动设计的精要就

是职责分配。但是,在纷繁复杂的软件设计中,如何进行职责分配常常令我们迷惑。

信息专家模式(又称为专家模式)告诉我们,在分析设计中,应当将职责

分配给软件系统中的这样一个软件类,它拥有实现这个职责所必须的信息。我们称这个软件类,叫“信息专家”。用更加简短的话说,就是将职责分配给信息专家。

为什么我们要将职责分配给信息专家呢?我们用上面的例子来说明吧。当“发放工资”软件类需要获取非离职员工时,“员工管理”软件类就是“获取非离职员工”任务的信息专家,因为它掌握着所有员工的信息。假设我们不将“获取非离职员工”的任务交给“员工管理”软件类,而是另一个软件类X,那么,为了获取员工信息,软件类X不得不访问“员工管理”软件类,从而使“发放

工资”与X耦合,X又与“员工管理”耦合。这样的设计,不如直接将“获取

非离职员工”的任务交给“员工管理”软件类,使得“发放工资”仅仅与“员工管理”耦合,从而有效地降低了系统的整体耦合度。

不应该把大量的逻辑充斥在Action中,应该把逻辑集中在service层,action只应该充当接收页面请求,请求服务,准备下个页面的显示数据,然后返回结果。比如SystemRequirementAction. baseline()函数完全应该是baseline模块提供的服务,提供接口给各模块使用,而不应该放在SystemRequirementAction中做,在baseline模块,应该提供一个统一的manager,而不是三个分开的其实只是封装了数据操作的manager,BaseLineManager、BaseLineSourceManager、BaseLineTargetManager,这三个manager本质上不能称之为service。

总之,采用“职责驱动设计”的思路,为我们提高软件开发质量、可读性、可维护性,以及保持软件的持续发展,提供了一个广阔的空间。

3)利用设计模式提高可变更性

一个快速提高软件质量的捷径就是利用设计模式。这里说的设计模式,不仅仅指经典的模式,是一切前人总结的,我们可以利用的、更加广泛的设计模式。

a.警惕if...else...

我忘了是从哪里学到的这个原则,但这个简单的原则一直非常有用地指导我的编码,它是这样描述的:当你发现你必须要设计这样的代码:“if...elseif...elseif...else...”时,你应当想到你的代码应当重构一下了。我们先看看这样的代码有怎样的特点。

Java代码

if(var.equals("A")){

doA();

}else if(var.equals("B")){

doB();

}else if(var.equals("C")){

doC();

}else{

doD();

}

这样的代码很常见,也非常平常,我们大家都写过。但正是这样平常才隐藏着我们永远没有注意的问题。问题就在于,如果某一天这个选项不再仅仅是A、B、C,而是增加了新的选项,会怎样呢?你也许会说,那没有关系,我把代码改改就行。然而事实上并非如此,在大型软件研发与维护中有一个原则,每次的变更尽量不要去修改原有的代码。如果我们重构一下,能保证不修改原有代码,仅仅增加新的代码就能应付选项的增加,这就增加了这段代码的可维护性和可变更性,提高了代码质量。那么,我们应当如何去做呢?

经过深入分析你会发现,这里存在一个对应关系,即A对应doA(),B对应doB()...如果将doA()、doB()、doC()...与原有代码解耦,问题就解决了。如何解耦呢?设计一个接口X以及它的实现A、B、C...每个类都包含一个方法doX(),并且将doA()的代码放到A.doX()中,将doB()的代码放到B.doX()中...经过以上的重构,代码还是这些代码,效果却完全不一样了。我们只需要这样写:

Java代码

X x = factory.getBean(var);

x.doX();

这样就可以实现以上的功能了。我们看到这里有一个工厂,放着所有的A、B、C...并且与它们的key对应起来,并且写在配置文件中。如果出现新的选项时,通过修改配置文件就可以无限制的增加下去。

这个模式虽然有效提高了代码质量,但是不能滥用,并非只要出现if...else...就需要使用。由于它使用了工厂,一定程度上增加了代码复杂度,因此仅仅在选项较多,并且增加选项的可能性比较大的情况下才需要使用。一般来说,原则是第一次就这样写,当发生了两次需要增加选项的时候再去重构它。

在aside中,有很多这种if else的情况,前面我举的几个大函数的例子就是因为里面有大量的if else,可以用这种方法重构一下

b.策略模式

也许你看过策略模式的相关资料但没有留下太多的印象。一个简单的例子可以让你快速理解它。如果一个员工系统中,员工被分为临时工和正式工并且在不同的地方相应的行为不一样。在设计它们的时候,你肯定设计一个抽象的员工类,并且设计两个继承类:临时工和正式工。这样,通过下塑类型,可以在不同的地方表现出临时工和正式工的各自行为。在另一个系统中,员工被分为了销售人员、技术人员、管理人员并且也在不同的地方相应的行为不一样。同样,我们在设计时也是设计一个抽象的员工类,并且设计数个继承类:销售人员、技术人员、管理人员。现在,我们要把这两个系统合并起来,也就是说,在新的系统中,员工既被分为临时工和正式工,又被分为了销售人员、技术人员、管理人员,这时候如何设计。如果我们还是使用以往的设计,我们将不得不设计很多继承类:销售临时工、销售正式工、技术临时工、技术正式工...如此的设计,在随着划分的类型,以及每种类型的选项的增多。通过以上一个系统的设计,我们不得不发现,我们以往学习的关于继承的设计遇到了挑战。

解决继承出现的问题,有一个最好的办法,就是采用策略模式。在这个应用中,员工之所以要分为临时工和正式工,无非是因为它们的一些行为不一样,比如,发工资时的计算方式不同。如果我们在设计时不将员工类分为临时工类和正式工类,而仅仅只有员工类,只是在类中增加“工资发放策略”。当我们创建员工对象时,根据员工的类型,将“工资发放策略”设定为“临时工策略”或“正式工策略”,在计算工资时,只需要调用策略类中的“计算工资”方法,其行为的表现,也设计临时工类和正式工类是一样的。同样的设计可以放到销售人员策略、技术人员策略、管理人员策略中。一个通常的设计是,我们将某一个影响更大的、或者选项更少的属性设计成继承类,而将其它属性设计成策略类,就可以很好的解决以上问题。

使用策略模式,你同样把代码写活了,因为你可以无限制地增加策略。但是,使用策略模式你同样需要设计一个工厂——策略工厂。以上实例中,你需要设计一个发放工资策略工厂,并且在工厂中将“临时工”与“临时工策略”对应起来,将“正式工”与“正式工策略”对应起来。

c.适配器模式

水货手机充电器的插头与我们常用的插座不一样,必须带一个适配器,才能使用不同地方的插座。这是一个对适配器模式最经典的描述。当我们设计的系统要与其它系统交互,或者我们设计的模块要与其它模块交互时,这种交互可能是调用一个接口,或者交换一段数据,接受方常常因发送方对协议的变更而频繁变更。这种变更,可能是接受方来源的变更,比如原来是A系统,现在变成B系统了;也可能是接受方自身的代码变更,如原来的接口现在增加了一个参数。由于发送方的变更常常导致接受方代码的不稳定,即频繁跟着修改,为接受方的维护带来困难。

遇到这样的问题,一个有经验的程序员马上想到的就是采用适配器模式。在设计时,我方的接口按照某个协议编写,并且保持固定不变。然后,在与真正对方接口时,在前段设计一个适配器类,一旦对方协议发生变更,我可以换个适配器,将新协议转换成原协议,问题就解决了。适配器模式应当包含一个接口和它的实现类。接口应当包含一个本系统要调用的方法,而它的实现类分别是与A系统接口的适配器、与B系统接口的适配器...

我曾经在一个项目中需要与另一个系统接口,起初那个系统通过一个数据集的方式为我提供数据,我写了一个接收数据集的适配器;后来改为用一个XML 数据流的形式,我又写了一个接收XML的适配器。虽然为我提供数据的方式不同,但是经过适配器转换后,输出的数据是一样的。通过在spring中的配置,我可以灵活地切换到底是使用哪个适配器。

d.模板模式

经典模式中的模板模式,对开发者的代码规划能力提出了更高的要求,它要求开发者对自己开发的所有代码有一个相互联系和从中抽象的能力,从各个不同的模块和各个不同的功能中,抽象出其过程比较一致的通用流程,最终形成模板。譬如说,在aside中,高层需求、底层需求、编写测试用例等流程,虽然涉及的数据项不同,但是都要经过分配编写任务、走查、提交问题、评审等流程。正因为有这样的特征,它们可以使用共同的模板,那么,什么是模板模式呢?

模板模式(Template Model)通常有一个抽象类。在这个抽象类中,通常有一个主函数,按照一定地顺序去调用其它函数。而其它函数往往是某这个连续过程中的各个步骤。由于这是一个抽象类,这些步骤函数可以是抽象函数。抽象类仅仅定义了整个过程的执行顺序,以及一些可以通用的步骤(如读取XML文件和解析XML数据流),而另一些比较个性的步骤,则由它的继承类自己去完成。

各个继承类可以根据自己的需要,通过重载重新定义各个步骤函数。但是,模板模式要求不能重载主函数,因此正规的模板模式其主函数应当是final(虽然我们常常不这么写)。另外,模板模式还允许你定义的这个步骤中,有些步骤是可选步骤。对与可选步骤,我们通常称为“钩子(hook)”。它在编写时,在

抽象类中并不是一个抽象函数,但却是一个什么都不写的空函数。继承类在编写时,如果需要这个步骤则重载这个函数,否则就什么也不写,进而在执行的时候也如同什么都没有执行。

通过以上对模板模式的描述可以发现,模板模式可以大大地提高我们的代码复用程度。

以上一些常用设计模式,都能使我们快速提高代码质量。还是那句话,设计模式不是什么高深的东西,恰恰相反,它是初学者快速提高的捷径。

编写高质量代码--Web前端开发修炼之道笔记

第一章从网站重构说起 打造高质量的前端代码,提高代码的可维护性——精简、重用、有序。 第二章团队合作 精一行,通十行。 增加代码可读性——注释。 重用性需提高,分为公共组件与私有组件,代码模块化。公共组件不能轻易修改,因为影响大,所以一般只提供“读”的权限。 磨刀不误砍柴工——前期的构思很重要。构思的主要内容包括规范的制定、公共组件的设计和复杂功能的技术方案等。一般来说,前期构思占整个项目30%~60%的时间都算是正常的。 第三章高质量的HTML

CSS只是web标准的一部分,在HTML、CSS、JS三大元素中,HTML才是最重要的,结构才是重点,样式是用来修饰结构的。正确的做法是,先确定HTML,确定语义的标签,再来选用合适的CSS。 判断标签语义是否良好的简单方法:去掉样式,看网页结构是否组织良好有序,是否仍然有很好的可读性。语义良好的网页去掉样式后结构依然很清晰。 “CSS裸体日”,2006.04.05第一届,从第三届开始改为4月9日。(设立目的就是为了提醒大家用合适的HTML标签的重要性) 一个语义良好的页面,h标签应该是完整有序没有断层的,也就是说要按照h1、h2、h3、h4这样的次序排下来,不要出现类似h1、h3、h4,漏掉h2的情况。 当页面内标签无法满足设计需要时,才会适当添加div和span等五语义标签来辅助实现。 第四章高质量的CSS 组织CSS的方法:base.css+common.css+page.css,在一般情况下任何一个网页的最终表现都是由这三者共同完成的,这三者不是并列结构,而是层叠结构。

base.css一般包括cssreset和通用原子类,比如设置一些常用的清除浮动、宽度、高度等class。可以参考一些前端框架,例如YUI、bootstrap等等。 拆分模块技巧:模块与模块之间尽量不要包含相同的部分,如果有相同部分,应将它们提取出来,拆分成一个独立的模块。模块应在保证数量尽可能少的原则下,做到尽可能简单,以提高重用性。 团队开发人员多,可在classname前加前缀。 如果不确定模块的上下margin特别稳定,最好不要将它们写到模块的类里,而是使用类的组合,单独为上下margin挂用于边距的原子类(例如mt10、mb20)。模块最好不用混用margin-top和margin-bottom,统一使用margin-top或margin-bottom。 低权重原则——避免滥用子选择器 普通标签权重1,class权重10,id权重100 为了保证样式容易被覆盖,提高可维护性,CSS选择符需保证权重尽可能低。 CSS sprite的最大好处是减少HTTP请求数,减轻服务器的压力,但它却需要付出“降低开发效率”和“增大维护难度”的代价。对于流量并不大的网站来说,CSS sprite带来的好处并不明显,而它付出的代价却很大,其实并不划算。所以是否使用CSS sprite主要取决于网站流量。 编码风格:推荐一行书写,能减少文件大小。(因为调试工具多,所以忽略易读性)Hack: A标签问题:

质量的三要素

质量的三要素

质量的三要素 ISO9000:2000对“质量”的定义是,一组固有特性满足要求的程度。从定义可见,质量具有三个要素:固有特性、要求、该特性满足该要求的程度。 每当我们讨论质量的时候,总是指某一个具体、特定事物的质量。譬如某产品的质量、某过程的质量、某体系的质量。一定要同时注意这三个要素,忽视其中任何一个,质量好坏就不好确定了。 1、第一个要素“固有特性”。ISO9000:2000标准第3.5.1条对特性有一个定义是可区分的特征。它可以定性的,也可以定量的。有物理的(机、电、化学、生物)、感官的(味、嗅、触、视、听)、行为的(礼貌、诚实、正直)、时间的(如准时性、可靠性、可用性)、人体工效(生理特性或有关人身安全的)、功能的(如飞机速度)等好多种类。所谓固有特性,是指某特定事物内在的,不是外加的特性。固有特性是具体、特定事物“质量”中“质”的表征,也叫性质。以此从质方面来区别其他事物,所以叫“特”性。特性都可以用某种指标来表述和测量的。 2、第二个要素是“要求”。ISO9000:2000标准第3.1.2条

对要求的定义是,明示的、通常隐含的或必须履行的需求或期望。 针对产品,可以分顾客的使用要求和组织自己根据顾客要求转化的各种规定的要求。如果转化正确,这些规定要求也就成为内部的顾客要求。正是因为我们所提供的产品、服务具有这些符合规定要求的特性才能满足顾客的使用要求。因此,也只能由顾客感知他们的要求是否都得到满足。 3、第三个要素是“满足的程度”。它是具体、特定事物“质量”中“量”的确定。具体、特定事物所具有的固有特性是“质”,满足顾客要求程度是“量”。把前面这两个要素联系起来,就叫质量。相对于把quality翻译成“品质”来说,更加确切一些。 衡量质量的好坏,只能用这些要求是否达到满足来衡量。同样的产品,具有同样的特性,由于顾客要求不同,满足程度就不同。得出质量好坏的结论也就不同。这就是我们常说“质量是由顾客说了算”的道理。 对任何一个事物我们可以从很方面、角度去认识。关键是认识的目的是为什么人服务的,是为了解决什么问题,如何去解决问题。因此,以上的定义和名称根据不同情况都是相对的。

双代号时标网络计划典型例题

双代号时标网络计划典型例题 2012-07-04 11:47 来源:打印| 收藏| 字号 分享到: 例题1:下图所示的双代号网络图中,存在绘图错误的有()。 A.循环回路 B.多个起点节点 C.多个终点节点 D.一对节点编号代表多项工作 E.节点编号顺序错误 【正确答案】CDE 【答案解析】选项C,有8、9两个终点节点,故错误;选项D,错在一对节点(1和3)表示了两项工作(B.C工作);选项E,节点3、4编号顺序错误。参见教材P117、119 例题2:下列关于双代号网络计划绘图规则的说法,正确的有()。 A.网络图必须正确表达各工作间的逻辑关系 B.网络图中可以出现循环回路 C.网络图中一个节点只有一条箭线引出 D.网络图中严禁出现没有箭头节点或没有箭尾节点的箭线 E.单目标网络计划只有一个起点节点和一个终点节点 【正确答案】ADE

【答案解析】双代号网络计划的绘图规则包括:①双代号网络图必须正确表达已定的逻辑关系;②双代号网络图中,严禁出现循环回路;③双代号网络图中,在节点之间严禁出现带双向箭头或无箭头的连线;④双代号网络图中,严禁出现没有箭头节点或没有箭尾节点的箭线;⑤当双代号网络图的某些节点有多条外向箭线或多条内向箭线时,为使图形简洁,可使用母线法绘制(但应满足一项工作用一条箭线和相应的一对节点表示);⑥绘制网络图时,箭线不宜交叉。当交叉不可避免时,可用过桥法或指向法;⑦双代号网络图中应只有一个起点节点和一个终点节点(多目标网络计划除外),而其他所有节点均应是中间节点;⑧双代号网络图应条理清楚,布局合理。参见教材P117、119 例题3:某分部工程各工作之间的逻辑关系如下表所示。根据该逻辑关系表绘出的正确网络图是()。 A.A图 B.B图 C.C图 D.D图

竞价关键词质量度的三要素及优化方法

竞价关键词质量度的三要素及优化方法 一、关键词质量度定义 广告质量是竞价系统中对关键词、创意、落地页等多个维度的评判,而关键词质量度是对关键词近期一段时间的广告质量总结。 关键词质量度反映了搜索用户对的关键词广告的认可程度,质量较高的广告能够以较低的价格获得较为理想的广告排名。 二、关键词质量度三要素及优化方法 关键词质量度由“预估点击率”、“创意相关性”、“落地页体验”三要素组成。每个要素会有“低于平均”、“平均水平”、“高于平均”三种得分。每个关键词会根据三要素的得分汇总得到一个1-10之间的关键质量度总分。 1、预估点击率 即用户看到关键词广告后,点击广告的可能性。 关键词的预估点击率如果显示低于平均,说明搜索用户在看到的广告时,点击广告的可能性低于行业平均水平,也就是用户会更倾向于点击同时展现的其它广告主的广告。 这种情况下,可以考虑采取以下方式进行优化: (1)添加与业务相关性高的新关键词,可以使用搜索推广操作后台的关键词规划师工具,或者前往账户的优化中心查看“添加新关键词”建议,选择添加高相关性的关键词。 (2)删除效果欠佳或相关性低的广告物料和关键词。

(3)如果关键词和的投放业务确实符合,建议针对这个关键词来丰富的广告创意、创意组件和落地页内容。 (4)为每个单元添加更多高相关性的创意、图片,使用行业内热门的样式,合理的使用创意中的关键词通配符,也有助于提升的预估点击率。 2、创意相关性 即关键词与创意(标题、描述)的相关性。 关键词的创意相关度若低于平均,说明的搜索广告和关键词的相关度低于行业平均水平,这意味着搜索用户看到的广告时,认为的广告内容和他/她的搜索意图不太相关,对比其它广告,的广告创意无法非常好地满足用户在百度搜索中所寻求的答案。 这种情况下,可以考虑采取以下方式进行优化: (1)调整创意标题,合理的使用关键词通配符,但请注意保持创意被关键词替换后的通顺性。 (2)修改创意内容,使标题和描述非常符合用户搜索需求,可以使用创意中心工具,不断提高创意的质量。 (3)将关键词移动到与创意更相关的单元中。 (4)查阅搜索词报告,对匹配方式较为宽泛的关键词,合理添加否定词,保障用户看到广告时,和他/她当下搜索需求是相关的。 3、落地页体验 即关键词和落地页内容的相关性,及用户访问落地页的体验。 关键词的落地页体验若低于平均,意味着搜索用户在访问的广告落地页时,用户体验低于访问其它广告主的推广落地页。

敏捷开发中高质量Java代码开发实践

本文将介绍在敏捷开发过程中如何通过采取一系列的步骤来保证和提高整个项目的代码质量,阐述了每一步可以利用的工具和最佳实践,从而使开发过程更加规范化,成就高质量的代码。 概述 Java项目开发过程中,由于开发人员的经验、代码风格各不相同,以及缺乏统一的标准和管理流程,往往导致整个项目的代码质量较差,难于维护,需要较大的测试投入和周期等问题。这些问题在一个项目组初建、需求和设计均具有不完全可预期性和完备性的全新项目中将尤为突出。本文将结合敏捷开发周期短,变化快等特点,介绍如何通过在开发过程中采取一系列步骤来保证和提高整个开发团队的代码质量,并阐述了每一步可以利用的工具和最佳实践,从而使开发过程更加规范化,成就高质量的代码,减少测试的投入,并促进整个团队的技能提高,最终提高开发效率和质量。 如图1所示,敏捷开发过程经历需求调研,用例分析和用例分解,进入开发迭代阶段。在每个迭代过程中,可以采用以下五个步骤来保证和提高整个项目的代码质量:统一编码规范、代码样式;静态代码分析(static code review);单元测试;持续集成;代码评审和重构(Review&Refactor)。下文将针对每个步骤和其所使用的工具、方法进行详细描述。 图 1.敏捷开发中的Java代码质量保证步骤 步骤一:统一编码规范、代码样式 规范统一的编码会增加项目代码的可读性和可维护性,但实际情况往往是项目组内的Java代码开发

人员的编码风格常常各不相同,这可能是由于不同的经验习惯或者缺乏编码规范方面的学习造成的。这样一来,其他项目成员或者维护人员在阅读项目代码时就需要花费更多的时间来理解代码作者的意图,所以制定并采取统一的编码规范就显得很重要。编码规范主要应包含以下几个方面: ?一般规则和格式规范。例如代码缩进、程序块规范、每行最大代码长度等。 ?命名规则。例如包名、类名、变量、方法、接口、参数等命名规范 ?文档规范。例如类文件头声明、类注释、成员变量和方法注释等规范。 ?编程规范。例如异常、并发、多线程等方面的处理方式。 ?其他规范。例如日志格式、属性文件格式,返回值和消息格式。 项目的编码规范可以参考已有的一些Java编程规范书籍和其他相关资料并结合项目的本身来制定,可供参考的书籍有《Java编程风格》(英文书名为:The Elements of Java Style)。编码规范要形成文档,而且要简洁明了,并组织项目成员一起学习,确保所有成员正确理解所有条目。 一旦编码规范确定,就可以利用Eclipse自身提供的功能来控制代码样式和格式。具体做法是,点击Eclipse的Windows->Preference菜单项,在打开的Preferences对话框的左侧栏中找到Java节点下的子项Code Style(如图2),该项和它的子项允许您对Java代码的样式进行控制。 图 2.Eclipse代码样式设置窗口

简单好用的双代号网络图绘制软件

简单好用的双代号网络图绘制软件 导语: 双代号网络图是一种十分普遍的网络计划形式,主要是以箭线及两端节点的编号来表示某一项工作的一种网络图。但对于新手而言,理解起来似乎有点困难。不过没关系,借助专业绘制软件,就可以帮助新手绘制双代号网络图。 免费获取网络拓扑图软件:https://www.360docs.net/doc/6f11510881.html,/network/ 一款好用的双代号网络图绘制软件 亿图网络图绘制作软件是由亿图软件公司推出的一款专门用来绘制电脑双代号网络图的软件。软件功能强大,容易上手,几乎包含所有网络图的绘制,例如基本网络图、双代号网络图、Cisco网络图、机架图、网络通信图、3D网络图、AWS图等等,可以完美替代Visio。软件采用拖拽的绘图方式,界面简单明了,操作方便,用户即看机即会,无需花费多少时间学习。

软件不仅提供各种专业图库,还提供海量模板,这点是其他软件无法比拟的。强大的定制功能使得用户不仅可以自定义图形的填充和线条颜色,也可以自行绘制图库里的形状。一键导出到PDF,Word, Visio, Png 等17种文件格式,无障碍与他人分享。新版本不仅实现了跨平台,而且还支持云存储,使得团队协作更加容易。亿图网络图绘制软件是您绘制双代号网络图的不二选择。

双代号网络图的三要素: 1、工作:即箭线。是用来表示一项工作需要消耗的人力、物力以及时间的具体活动过程。也称之为工序或者作业。 2、节点:网络图中,箭线出发点和交汇处会使用圆圈,来表示该圆圈前面一项或者多项工作的结束以及允许后面一项或者多项工作的开始的时间,即为节点。 3、线路:在网络图中,从起点节点开始,沿箭头方向连续通过一系列箭线与节点,最后到达终点节点的通路称为线路。 双代号网络图的绘制规则: 1、不能出现从一个节点出发,又顺着箭头方向又回到原出发点的循环回路。 2、不能有两个或者两个以上的箭线从同一节点出发又同时指向同一节点。 3、网络图中的箭线(包括虚箭线,以下同)应保持自左向右的方向,不应出现箭头指向左方的水平箭线和箭头偏向左方的斜向箭线。 4、网络图中的节点编号应该自左向右,由小到大,确保工作的起点节点的编号小于工作终点节点的编号,而且不能出现重复编号的节点,但是可以是非连续的编号。 5、网络图中不能出现双向箭头和无箭头的连线。 6、网络图中不允许出现没有箭尾节点的箭线和没有箭头节点的箭线。 7、禁止在箭线上引入或者引出其他箭线,除非网络图的起点节点有多条箭线引

客户关系管理三要素

客户关系管理三要素 在大多数市场中,都有一两家公司因为同客户保持着更紧密的关系,而在业绩上远远胜出竞争对手。然而,这些企业的优势与客户关系管理(CRM)的工具和技术并无太大关系。事实上,IT技术仅仅是获得这一优势的一个必要但不充分的条件。 越来越多的证据表明,单靠IT本身,对于创造更好的客户关系并无多大助益。更大程度上,优异的客户关系能力取决于企业如何构建和管理它的组织,具体地说,它源自公司对三个组织要素的清晰聚焦和灵活安排。 第一个要素是组织定位,组织应将“留住客户”列为企业须优先考虑的事项,并且给予员工更大的自由度去满足客户的要求。 第二个要素是组织架构,包括组织的结构、为客户提供个性化产品和服务的流程,以及为督促员工致力于建立客户关系而采取的激励机制。 信息是最后一个要素,指的是深入的、相关性强的客户信息,而且是可以通过IT系统在全公司范围实现共享的。 所有公司都可以通过专注于这些关键要素,更清晰地感知它们之间的关联方式,从而改善自身的客户关系,并最终提高企业的经营业绩。要做到这一点,企业的管理者必须对每一个要素都要有更深的理解。 定位:“留住客户”优先 表明组织对客户关注程度的一个最重要的指标就是,全公司都拥有一个共同的信念:“留住客户”是企业每个人都优先关注的工作,而不仅是市场营销人员的事。另外一个指标是,有关客户的信息要在组织内开放共享。 如果某一职能部门(如销售部)认为它应独自拥有客户,那么企业的以上定位就达不到预期目的。有用的信息会被那些认识客户的人牢牢抓住,其他团队和部门都不大可能从他们那里分享到这些宝贵的客户资料。同样地,如果企业的思维定式和历史传统都鼓励员工依靠个人努力去赢取客户,那么就不会有人把更多的精力用在捕捉和集中共享客户信息上面。 以客户关系为中心的公司定位也会根据“区别对待不同客户”的理念而做出相应的调整。大部分公司都把这个提法挂在嘴上,但很少能做到像郭士纳(LouGertsner)领导下的IBM 那样,把服务于最好的客户并竭尽所能满足他们的需求列为公司的价值观。这种务实的方法使得IBM避免了遭遇惠普、思科和康柏都曾遇到的问题,它们都曾因追逐每一个互联网热点而忽略了自己的长期支付能力。通过在整个组织范围内强调客户保留的重要性,IBM脱颖

双代号网络习题1

第三章 网络计划技术习题 .选择题 )。 B. 紧前工作、紧后工作、关键线路 D.工期、关键线路、非关键线路 )。 B. 不会影响紧后工作,但会影响工期 D.会影响紧后工作和工期 B.由关键工作组成的线路是关键线路 D.自由时差是局部时差,总时差是线路性时差 A. 任何工程都有规定工期、计划工期和计算工期 B. 计划工期可以小于规定工期 C. 计划工期可以等于规定工期 D. 计划工期有时可等于计算工期 5.( ),会出现虚箭线。 A. 当只有相同的紧后工作时 B.当只有不相同的紧后工作时 C. 既有相同,又有不相同的紧后工作时 D.不受约束的任何情况 6.网络计划的缺点是( )。 A. 不能反映工作问题的逻辑 B .不能反映出关键工作 C.计算资源消耗量不便 D.不能实现电算化 7.在建设工程进度计划的表示方法中,与横道计划相比,网络计划的优点是能够( )。 A.明确表达各项工作之间的逻辑关系 B. 直观表达工程进度计划的计算工期 C.明确表达各项工作之间的搭接时间 D. 直观表示各项工作的持续时间 8.建设工程组织流水施工时,用来表达流水施工在施工工艺方面进展状态的参数之一是( )。 A.流水段 B. 流水强度 C.流水节拍 D.流水步距 9.双代号网络图中的虚工作( A. 即消耗时间,又消耗资源 C.即不消耗时间,又不消资源 1.双代号网络图的三要素是指( A. 节点、箭杆、工作作业时间 A.不会影响紧后工作,也不会影响工期 C.会影响紧后工作,但不会影响工期 3.下列( )说法是错误的。 A.总时差为零的工作是关键工作 C.总时差为零,自由时差一定为零 4.下列( )说法是错误的。 )。 B.只消耗时间,不消耗资源 D.不消髦时间,又消耗资源

论时间、质量、成本三要素的关系

论时间、质量、成本三要素的关系 姓名:杨坤 引言 在经济全球化的市场环境下,对于任何一个行业来说,科学地运用项目管理是降低成本与提高提高生产率的有效途径。时间、质量、成本是管理的三要素,如何处理 、 1. 3.项目成本管理的原则 (1)全生命周期成本最低原则 (2)全面成本管理原则 (3)成本责任制原则

(4)成本管理有效化原则 (5)成本管理科学化原则 在实际的成本管理中我们可以将项目成本管理过程总结如下: 一:资源计划编制。确定完成项目活动需要物质资源的种类,以及每种资源的需要 量 1. 2. 1. 2. 3.WBS 项目成本预算案例 四.项目成本控制。控制项目预算的变更,以保证预算目标的实现,项目成本控制的方法有项目成本分析表法、项目成本分析法、成本累计曲线、挣得值法。 五.成本决算。确定项目从开始到项目结束交付使用为止的全部实际费用。

一个项目的成功不仅仅要以最低的成本还要有尽可能短的时间,项目的时间控制的 目的为: 1.保证按时获利以补偿已经发生的费用支出 2.协调资源 3.使资源在需要时可以利用 4. 2. 1. 2. 3.工作描述。为了更明确的描述项目包括的各项工作的具体内容和要求。工作描 述的依据是项目描述和项目工作分解结构。其结果是工作描述表及项目工作列 表。 4.工作责任的分配。为了明确各单位或个人的责任,便于项目管理部门在项目实

施过程中的管理协调,需要对项目的每一项工作分配责任者和落实责任。 5.工作先后关系的确定。 (1)逻辑关系的确定。这是工作相互关系确定的基础,工作逻辑关系的确定 相对比较容易。 (2)组织关系的确定。对于无逻辑关系的那些工作,由于其工作先后关系具 6. 8. 那么 因此, 遵循八项基本原则:以顾客为关注焦点、领导作用、全员参与、过程方法、管理的系统方法、持续改进、基于事实的决策方法、与供方互利的关系。 项目质量计划就是确定与项目相关的质量标准并决定达到标准的方法,质量计划的工具和技术有收益/成本分析、基准计划、流程图、试验设计、质量

编写高质量Java代码

敏捷开发中编写高质量Java代码 敏捷开发的理念已经流行了很长的时间,在敏捷开发中的开发迭代阶段中,我们可以通过五个步骤,来有效的提高整个项目的代码质量。 Java项目开发过程中,由于开发人员的经验、Java代码编写习惯,以及缺乏统一的标准和管理流程,往往导致整个项目的代码质量较差,难于维护,需要较大的测试投入和周期等问题。这些问题在一个项目组初建、需求和设计均具有不完全可预期性和完备性的全新项目中将尤为突出。 如图1所示,敏捷开发过程经历需求调研,用例分析和用例分解,进入开发迭代阶段。在每个迭代过程中,可以采用以下步骤来保证和提高整个项目的代码质量:统一编码规范、代码样式;静态代码分析(staticcodereview);单元测试;持续集成;代码评审和重构 (Revi ew&Refactor)。下文将针对每个步骤和其所使用的工具、方法进行详细描述。 图1.敏捷开发中的Java代码质量保证步骤 步骤一:统一编码规范、代码样式 规范统一的编码会增加项目代码的可读性和可维护性,但实际情况往往是项目组内的Java代码开发人员的编码风格常常各不相同,这可能是由于不同的经验习惯或者缺乏编码规范方面的学习造成的。这样一来,其他项目成员或者维护人员在阅读项目代码时就需要花费更多的时间来理解代码作者的意图,所以制定并采取统一的编码规范就显得很重要。编码规范主要应包含以下几个方面: ◆一般规则和格式规范。例如代码缩进、程序块规范、每行最大代码长度等。 ◆命名规则。例如包名、类名、变量、方法、接口、参数等命名规范 ◆文档规范。例如类文件头声明、类注释、成员变量和方法注释等规范。 ◆编程规范。例如异常、并发、多线程等方面的处理方式。 ◆其他规范。例如日志格式、属性文件格式,返回值和消息格式。

网络图基本概念

一、基本概念 1.网络图 完成一项计划(或工程),需进行许多工作(或施工过程)。 用一个箭杆表示一项工作,工作的名称写在箭杆上方,工作的持续时间写在箭杆下方,箭尾表示工作开始,箭头表示工作结束。箭头、箭尾衔接处画圆圈并编号,用箭尾、箭头的号码作为这项工作的代号,这种表示方法称为双代号法。 将所有工作(或施工过程)按顺序及相互关系从左向右画成网络状图形,称为网络图。 2.工作 工作(或施工过程)的划分根据需要可粗可细。 根据资源及时间的消耗,工作可分为: 工作——消耗时间,消耗资源。如扎筋、立模、浇混凝土等; 间歇——只消耗时间,不消耗资源,包括工艺间歇及组织间歇,如混凝土养护、油漆干燥、测量放样等。 虚工作——不消耗时间,也不消耗资源,仅为了表示工作间的逻辑关系而引入,用虚箭杆表示。 箭杆的长度一般可不按比例绘制(除时间坐标网络图外),方向也可任意,但为了整齐箭头通常向右向下。

3.事件(节点) 表示(计划)工作开始、结束或连接关系,用圆圈表示,节点又分: 原始节点——表示一项计划开始; 结束节点——表示一项计划结束; 起点节点——表示一项工作开始; 终点节点——表示一项工作结束; 中间节点——一项计划中除原始、结束节点外都是中间节点,它既是紧前工作的终点节点,又是紧后工作的起点节点。 4.线路 从原始节点至结束节点经过的通道称为线路,一个网络计划有若干条线路,如: 图中有几条路线: 第一条:1—2—3—7—9—10 持续时间为10d; 第二条:1—2—3—5—6—7—9—10 持续时间为11d; 第三条:1—2—3—5—6—8—9—10 持续时间为10d;

质量的三要素

质量的三要素 ISO9000:2000对“质量”的定义是,一组固有特性满足要求的程度。从定义可见,质量具有三个要素:固有特性、要求、该特性满足该要求的程度。 每当我们讨论质量的时候,总是指某一个具体、特定事物的质量。譬如某产品的质量、某过程的质量、某体系的质量。一定要同时注意这三个要素,忽视其中任何一个,质量好坏就不好确定了。 1、第一个要素“固有特性”。ISO9000:2000标准第3.5.1条对特性有一个定义是可区分的特征。它可以定性的,也可以定量的。有物理的(机、电、化学、生物)、感官的(味、嗅、触、视、听)、行为的(礼貌、诚实、正直)、时间的(如准时性、可靠性、可用性)、人体工效(生理特性或有关人身安全的)、功能的(如飞机速度)等好多种类。所谓固有特性,是指某特定事物内在的,不是外加的特性。固有特性是具体、特定事物“质量”中“质”的表征,也叫性质。以此从质方面来区别其他事物,所以叫“特”性。特性都可以用某种指标来表述和测量的。 2、第二个要素是“要求”。 ISO9000:2000标准第3.1.2条对要求的定义是,明示的、通常隐含的或必须履行的需求或期望。

针对产品,可以分顾客的使用要求和组织自己根据顾客要求转化的各种规定的要求。如果转化正确,这些规定要求也就成为内部的顾客要求。正是因为我们所提供的产品、服务具有这些符合规定要求的特性才能满足顾客的使用要求。因此,也只能由顾客感知他们的要求是否都得到满足。 3、第三个要素是“满足的程度”。它是具体、特定事物“质量”中“量”的确定。具体、特定事物所具有的固有特性是“质”,满足顾客要求程度是“量”。把前面这两个要素联系起来,就叫质量。相对于把quality翻译成“品质”来说,更加确切一些。 衡量质量的好坏,只能用这些要求是否达到满足来衡量。同样的产品,具有同样的特性,由于顾客要求不同,满足程度就不同。得出质量好坏的结论也就不同。这就是我们常说“质量是由顾客说了算”的道理。 对任何一个事物我们可以从很方面、角度去认识。关键是认识的目的是为什么人服务的,是为了解决什么问题,如何去解决问题。因此,以上的定义和名称根据不同情况都是相对的。 三层次质量——产品、过程和体系的质量

我编写过的最漂亮的代码

第3章我编写过的最漂亮的代码 Jon Bentley 我曾经听一位大师级的程序员这样称赞到,“我通过删除代码来实现功能的提升。”而法国著名作家兼飞行家Antoine de Saint-Exupéry的说法则更具代表性,“只有在不仅没有任何功能可以添加,而且也没有任何功能可以删除的情况下,设计师才能够认为自己的工作已臻完美。”某些时候,在软件中根本就不存在最漂亮的代码,最漂亮的函数,或者最漂亮的程序。 当然,我们很难对不存在的事物进行讨论。本章将对经典Quicksort(快速排序)算法的运行时间进行全面的分析,并试图通过这个分析来说明上述观点。在第一节中,我将首先根据我自己的观点来回顾一下Quicksort,并为后面的内容打下基础。第二节的内容将是本章的重点部分。我们将首先在程序中增加一个计数器,然后通过不断地修改,从而使程序的代码变得越来越短,但程序的功能却会变得越来越强,最终的结果是只需要几行代码就可以使算法的运行时间达到平均水平。在第三节将对前面的技术进行小结,并对二分搜索树的运行开销进行简单的分析。最后的两节将给出学完本章得到的一些启示,这将有助于你在今后写出更为优雅的程序。 3.1 我编写过的最漂亮代码 当Greg Wilson最初告诉我本书的编写计划时,我曾自问编写过的最漂亮的代码是什么。这个有趣的问题在我脑海里盘旋了大半天,然后我发现答案其实很简单:Quicksort算法。但遗憾的是,根据不同的表达方式,这个问题有着三种不同的答案。 当我撰写关于分治(divide-and-conquer)算法的论文时,我发现 C.A.R. Hoare的Quicksort算法(“Quicksort”,Computer Journal 5)无疑是各种Quicksort算法的鼻祖。这是一种解决基本问题的漂亮算法,可以用优雅的代码实现。我很喜欢这个算法,但我总是无法弄明白算法中最内层的循环。我曾经花两天的时间来调试一个使用了这个循环的复杂程序,并且几年以来,当我需要完成类似的任务时,我会很小心地复制这段代码。虽然这段代码能够解决我所遇到的问题,但我却并没有真正地理解它。 我后来从Nico Lomuto那里学到了一种优雅的划分(partitioning)模式,并且最终编写出了我能够理解,甚至能够证明的Quicksort算法。William Strunk Jr.针对英语所提出的“良好的写作风格即为简练”这条经验同样适用于代码的编写,因此我遵循了他的建议,“省略不必要的字词”(来自《The Elements of Style》一书)。我最终将大约40行左右的代码缩减为十几行的代码。因此,如果要回答“你曾编写过的最漂亮代码是什么?”这个问题,那么我的答案就是:在我编写的《Programming Pearls, Second Edition》(Addison-Wesley)一书中给出的Quichsort算法。在示例3-1中给出了用C语言编写的Quicksort函数。我们在接下来的章节中将进一步地研究和改善这个函数。 【示例】 3-1 Quicksort函数 void quicksort(int l, int u) { int i, m; if (l >= u) return;

敏捷开发中编写高质量Java代码+

敏捷开发中编写高质量Java代码收藏 敏捷开发的理念已经流行了很长的时间,在敏捷开发中的开发迭代阶段中,我们可以通过五个步骤,来有效的提高整个项目的代码质量。 Java项目开发过程中,由于开发人员的经验、Java代码编写习惯,以及缺乏统一的标准和管理流程,往往导致整个项目的代码质量较差,难于维护,需要较大的测试投入和周期等问题。这些问题在一个项目组初建、需求和设计均具有不完全可预期性和完备性的全新项目中将尤为突出。 如图1所示,敏捷开发过程经历需求调研,用例分析和用例分解,进入开发迭代阶段。在每个迭代过程中,可以采用以下步骤来保证和提高整个项目的代码质量:统一编码规范、代码样式;静态代码分析(staticcodereview);单元测试;持续集成;代码评审和重构(Review&Refact or)。下文将针对每个步骤和其所使用的工具、方法进行详细描述。 图1.敏捷开发中的Java代码质量保证步骤

步骤一:统一编码规范、代码样式 规范统一的编码会增加项目代码的可读性和可维护性,但实际情况往往是项目组内的Java代码开发人员的编码风格常常各不相同,这可能是由于不同的经验习惯或者缺乏编码规范方面的学习造成的。这样一来,其他项目成员或者维护人员在阅读项目代码时就需要花费更多的时间来理解代码作者的意图,所以制定并采取统一的编码规范就显得很重要。编码规范主要应包含以下几个方面: ◆一般规则和格式规范。例如代码缩进、程序块规范、每行最大代码长度等。 ◆命名规则。例如包名、类名、变量、方法、接口、参数等命名规范 ◆文档规范。例如类文件头声明、类注释、成员变量和方法注释等规范。 ◆编程规范。例如异常、并发、多线程等方面的处理方式。 ◆其他规范。例如日志格式、属性文件格式,返回值和消息格式。 项目的编码规范可以参考已有的一些Java编程规范书籍和其他相关资料并结合项目的本身来制定,可供参考的书籍有《Java编程风格》(英文书名为:TheElementsofJavaStyle)。编码规范要形成文档,而且要简洁明了,并组织项目成员一起学习,确保所有成员正确理解所有条目。 一旦编码规范确定,就可以利用Eclipse自身提供的功能来控制代码样式和格式。具体做法是,点击Eclipse的Windows->Preference菜单项,在打开的Preferences对话框的左侧栏中找到Java节点下的子项CodeStyle(如图2),该项和它的子项允许您对Java代码的样式进行控制。

质量三要素

质量三要素 前言 本文是著者多年从事质量管理工作的心得体会,说明如何从产品、过程和体系三个层次把握好质量的三个要素:固有特性、要求和满足的程度。相信您看了以后一定会有一些启迪。 质量三要素 根据ISO9000:2000对“质量”的定义:一组固有特性满足要求的程度,可见,质量有三个要素:固有特性、要求、满足的程度。我们讨论质量的时候,总是针对具体、特定事物的质量。譬如某产品的质量、某过程的质量、某体系的质量。一定要同时注意这三个要素,忽视其中任何一个,质量好坏就不好确定了。 1、第一个要素“固有特性” 是具体、特定事物“质量”中“质”的表征。所谓固有,是指该特定事物内在的,不是外加的特性。ISO9000:2000标准第3.5.1条对特性有一个定义,可区分的特征。它可以定性的,也可以定量的。有物理的(机、电、化学、生物)、感官的(味、嗅、触、视、听)、行为的(礼貌、诚实、正直)、时间的(如准时性、可靠性、可用性)、人体工效(生理特性或有关人身安全的)、功能的(如飞机速度)等好多种类。它们都可以用各种指标来表征。以此从质方面来区别其他事物,所以叫 “特”性。 2、第二个要素是“要求”。 ISO9000:2000标准第3.1.2条对要求的定义是,明示的、通常隐含的或必须履行的需求或期望。针对产品,可以分顾客的使用要求和组织自己根据顾客要求转化的各种规定的要求。如果转化正确,这些就是内部顾客要求。我们所提供的产品、服务正是因为它们带有能满足顾客使用要求的那些特性才能满足顾客的各种要求。因此,我们常常说,“质量是由顾客说了算”的道理。衡量质量只能用这些要求是否达到满足来衡量。也只能由顾客感知他们的要求是否都得到满足来判定顾客是否满意。 3、“满足的程度”“是具体、特定事物“质量”中“量”的确定。第三个要

编写高质量的代码,从命名入手

编写高质量的代码,从命名入手 笔者从事开发多年,有这样一种感觉,查看一些开源项目,如Spring、Apache Common等源码是一件赏心悦目的事情,究其原因,无外两点:1)代码质量非常高;2)命名特别规范(这可能跟老外的英语水平有关)。 要写高质量的代码,不是一件容易的事,需要长年累月的锻炼,是一个量变到质变的过程,但要写好命名,只需要有比较好的英语语法基础和一种自我意识即可轻松达到。本博文将会结合本人的开发经验,总结出若干命名规则,这些命名规则纯属个人的使用习惯,不代表是一种理想的规则,在这里列举出来,供大家交流讨论。 1.切忌使用没有任何意义的英语字母进行命名 for(int i=0; i<10; i++) { ... } 这是在很多教Java基本语法的书上常见的代码片断,作为教学材料,这样写无可厚非,但作为真正的代码编写,程序员必须要养成良好的习惯,不要使用这种没有任何含义的命名方式,这里可以使用“index”。 2.切忌使用拼音,甚至是拼音首字母组合 cishu =5; // 循环的次数 zzje = 1000.00// 转账金额 笔者在做代码检查的时候,无数次遇到过这样的命名,使人哭笑不得 3.要使用英文,而且要使用准确的英语,无论是拼写还是语法 名词单数,必须使用单数英文,如Account、Customer。 对于数组,列表等对象集合的命名,必须使用复数,而且最好按照英文的语法基础知识使用准确的复数形式,如List accounts、Set strategies。 对于boolean值的属性,很多开发人员习惯使用isXXX,如isClose(是否关闭),但这里有两点建议:1)最好不要带“is”,因为JavaBean的规范,为属性生成get/set方法的时候,会用“get/set/is”,上面的例子,生成get/set方法就会变成“getIsClose/isIsClose/getIsClose”,非常别扭;2)由于boolean值通常反映“是否”,所以准确的用法,应该是是用“形容词”,上面的例子,最终应该被改为closed,那么get/set方法就是“getClosed/isColsed/setClosed”,非常符合英语阅读习惯。 4.方法名的命名,需要使用“动宾结构短语”或“是动词+表语结构短语” 笔者曾看到过千奇百怪的方法命名,有些使用名词,有些甚至是“名词+动词”,而且,如果宾语是一个对象集合,还是最好使用复数: createOrder(Order order) //good orderCreate(Order order) //bad removeOrders(List orders) //good removeOrder(List order) //bad 5.对于常见的“增删改查”方法,命名最好要谨慎: 增加:最常见使用create和add,但最好根据英语的语义进行区分,这有助于理解,create 代表创建,add代表增加。比如,要创建一个Student,用createStudent要比用addStudent 好,为什么?想想如果有个类叫Clazz(班级,避开Java关键字),现在要把一个Student加入到一个Clazz,Clazz很容易就定义了一个addStudent(Student student)的方法,那么就比

双代号网络图基本知识概念

双代号网络图中的基本知识及概念 网络计划技术是20世纪50年代末发展起来的一种编制复杂系统和工程研制计划的有效方法,我国自60年代中期开始引进这种方法,经过多年的实践,该技术得到了不断地推广和发展。建设部1998年关于建筑业进一步推广应用10项新技术的通知:第10项“企业的计算机应用和管理技术”中就提出了企业应积极推广网络计划技术的应用。对于任何一个工程系统,应用网络计划技术解决问题的先行工作是编制一个正确反映该系统各工作间先后顺序及逻辑关系的网络图。 双代号网络图的基本符号 网络图是一种以网状图形表示计划或工程开展顺序的工作流程图,通常有双代号和单代号两种表示方法,其中双代号网络图应用较为广泛。双代号网络图是以箭线表示工作,节点表示一个工作的开始或结束状态以及工作之间的连接点,以工作两端节点编号代表一项工作的网络图,工作、节点、线路是构成双代号网络图的三要素。. 双代号网络图的基本符号 网络图是一种以网状图形表示计划或工程开展顺序的工作流程图,通常有双代号和单代号两种表示方法,其中双代号网络图应用较为广泛。双代号网络图是以箭线表示工作,节点表示一个工作的开始或结束状态以及工作之间的连接点,以工作两端节点编号代表一项工作的网络图,工作、节点、线路是构成双代号网络图的三要素。 双代号网络图的组成 在双代号网络图中工作,节点和线路是其基本组成部分。 是以箭线表示工作 节点表示工作的开始与结束及工作间的连接点 工作两端节点的编号代表一项工作的网络图 一、工作 1、定义:是指把计划任务按实际需要的粗细程度划分而成子项目,是一项要消耗一定时间,而且大多数情况下也要消耗人力、材料等的活动,是网络计划构成的最基本单元。(也可称活动、工序或过程) 由于所在各自工程计划的规模不同,网络计划的作用不同,工作划分的粗细不同,大小范围也不同。 如对一个规模较大的建设项目而言,一项工作可以表示一幢建筑物或构筑物所形成的单位工程。 一个单位工程,既可划分成若干分部工程,也可划分成基本工作,如预制砼构件由支模板、绑钢筋、浇砼等工作组成。 2、工作的分类(三种)

双代号网络图用什么画

双代号网络图用什么画 导语: 双代号网络图主要是以箭线及两端节点的编号来表示某一项工作的一种网络图。有很多人表示不知道用软件画,也不知道有哪些专业的双代号网络图软件。今天小编就给大家放点干货,推荐一款功能强大,适合所有人使用的软件。 免费获取网络拓扑图软件:https://www.360docs.net/doc/6f11510881.html,/network/ 双代号网络图用什么画? 亿图网络图绘制作软件是由亿图软件公司推出的一款专门用来绘制电脑双代号网络图的软件。软件功能强大,容易上手,几乎包含所有网络图的绘制,例如基本网络图、双代号网络图、Cisco网络图、机架图、网络通信图、3D网络图、AWS图等等,可以完美替代Visio。软件采用拖拽的绘图方式,界面简单明了,操作方便,用户即看机即会,无需花费多少时间学习。

软件不仅提供各种专业图库,还提供海量模板,这点是其他软件无法比拟的。强大的定制功能使得用户不仅可以自定义图形的填充和线条颜色,也可以自行绘制图库里的形状。一键导出到PDF,Word, Visio, Png 等17种文件格式,无障碍与他人分享。新版本不仅实现了跨平台,而且还支持云存储,使得团队协作更加容易。亿图网络图绘制软件是您绘制双代号网络图的不二选择。 双代号网络图的三要素: 1、工作:即箭线。是用来表示一项工作需要消耗的人力、物力以及时间的具体活动过程。也称之为工序或者作业。

2、节点:网络图中,箭线出发点和交汇处会使用圆圈,来表示该圆圈前面一项或者多项工作的结束以及允许后面一项或者多项工作的开始的时间,即为节点。 3、线路:在网络图中,从起点节点开始,沿箭头方向连续通过一系列箭线与节点,最后到达终点节点的通路称为线路。 双代号网络图的绘制规则: 1、不能出现从一个节点出发,又顺着箭头方向又回到原出发点的循环回路。 2、不能有两个或者两个以上的箭线从同一节点出发又同时指向同一节点。 3、网络图中的箭线(包括虚箭线,以下同)应保持自左向右的方向,不应出现箭头指向左方的水平箭线和箭头偏向左方的斜向箭线。 4、网络图中的节点编号应该自左向右,由小到大,确保工作的起点节点的编号小于工作终点节点的编号,而且不能出现重复编号的节点,但是可以是非连续的编号。 5、网络图中不能出现双向箭头和无箭头的连线。 6、网络图中不允许出现没有箭尾节点的箭线和没有箭头节点的箭线。 7、禁止在箭线上引入或者引出其他箭线,除非网络图的起点节点有多条箭线引出(外向箭头)或者重点节点有多条箭线引入(内向箭线),此时为了让图形更简洁,则可以使用母线法绘图。 8、绘制网络图时,宜避免箭线交叉。但是当交叉不可避免时,也可以采用过桥法或指向法进行处理。 9、一个网络图中只能有一个起点节点和终点节点。 10、同一项工作不能在一个网络图中重复表达。 双代号网络图的一般绘图步骤: 第一步:进行任务分解,然后具体划分需要施工的工作。 第二步:确定需要完成的工作计划的所有工作及其逻辑关系。 第三步:确定每一项工作需要持续的时间,并制定详细的工程分析表。 第四步:根据所指定的工程分析表,绘制并修改网络图。 获取更多网络拓扑图技巧:https://www.360docs.net/doc/6f11510881.html,/software/network/

相关文档
最新文档