怎样把java游戏源代码的源代码变成可玩的游戏

java教程|java源码|java游戏|j |数据库|hibernate|struts框架
学习网为广大的
爱好者提供最全最新的
java教程
java源代码
,希望大家多多支持本站,更多的java教程 java源码尽在
输入您的搜索字词
提交搜索表单 Web
www.java125.cn
预览模式:
作者:admi 日期:2007-10-31
由于一些理由,OMG 改良了 UML 。主要的理由是,他们希望 UML 模型能够表达模型驱动架构(MDA),这意味着 UML 必须支持更多的模型驱动的符号。同时, UML 1.x 符号集合有时难以适用于较大的应用程序。此外,为了要使图变成更容易阅读,需要改良符号元件。(举例来说,UML 1.x 的模型逻辑流程太复杂,有时不可能完成。对UML 2 中的序列图的符号集合的改变,已经在序列化逻辑建模方面取得巨大的进步)。
注意我上面所述的文字:“已采纳UML2.0草案规范。”确实,规范仍然处于草案状态,但是关键是草案规范已经被 OMG 采用,OMG是一个直到新标准相当可靠,才会采用它们的组织。 在 UML 2 完全地被采用之前,规范将会有一些修改,但是这些改变应该是极小的。主要的改变将会是在 UML 的内部 —— 包括通常被实施 UML 工具的软件公司使用的功能。
本文的主要目的是继续把我们的重点放在基础UML图上;这个月,我们进一步了解序列图。再次请注意,下面提供的例子正是以新的 UML 2 规范为基础。
图的目的
序列图主要用于按照交互发生的一系列顺序,显示对象之间的这些交互。很象类图,开发者一般认为序列图只对他们有意义。然而,一个组织的业务人员会发现,序列图显示不同的业务对象如何交互,对于交流当前业务如何进行很有用。除记录组织的当前事件外,一个业务级的序列图能被当作一个需求文件使用,为实现一个未来系统传递需求。在项目的需求阶段,分析师能通过提供一个更加正式层次的表达,把用例带入下一层次。那种情况下,用例常常被细化为一个或者更多的序列图。
分类:
| 引用: 444 | 查看次数: 2030
作者:admi 日期:2007-10-31 一个UML部署图(对象管理组织2001)描述了一个运行时的硬件结点,以及在这些结点上运行的软件组件的静态视图。 部署图显示了系统的硬件,***在硬件上的软件,以及用于连接异构的机器之间的中间件。(2002-06-24 15:39:52)
By axing
  一个UML部署图(对象管理组织2001)描述了一个运行时的硬件结点,以及在这些结点上运行的软件组件的静态视图。 部署图显示了系统的硬件,***在硬件上的软件,以及用于连接异构的机器之间的中间件。 创建一个部署模型的目的包括∶
分类:
| 引用: 479 | 查看次数: 2244
作者:admi 日期:2007-10-31
顺序图描述的是用例实例,一个用例是多个用例实例的抽象,所以一个用例描述多种事件流:正常的事件流,可选的事件流,异常的事件流。
那么对于一个用例,要用顺序图描述每一种用例实现(具体的事件流),所以就比较繁琐,一个用例要画多个顺序图(至少三个)。
这一点流程图有强的描述能力,可以在一个图中描述所有分支(通过条件判断分支)。但流程图的缺点是指描述控制流,无法描述对象和信息流。来源于流程图的带泳道和对象流和同步条的活动图补充了不足,可以用来描述用例,也可以通过泳道描述对象,所以可以代替顺序图描述用例实现中对象间的交互。但缺点是对象间的消息不明了。
可以增强顺序图的描述能力,改变顺序图的描述角度:描述用例而不是用例实例,增加分支判断,这样就可以在一张顺序图中描述一个用例的所有的事件流。
分类:
| 引用: 1039 | 查看次数: 2989
作者:admi 日期:2007-10-31
1. 标准建模语言UML的出现
公认的面向对象建模语言出现于70年代中期。从1989年到1994年,其数量从不到十种增加到了五十多种。在众多的建模语言中,语言的创造者努力推崇自己的产品,并在实践中不断完善。但是,OO方法的用户并不了解不同建模语言的优缺点及相互之间的差异,因而很难根据应用特点选择合适的建模语言,于是爆发了一场方法大战。90 年代中,一批新方法出现了,其中最引人注目的是Booch 1993、OOSE和OMT-2等。
Booch是面向对象方法最早的倡导者之一,他提出了面向对象软件工程的概念。1991年,他将以前面向Ada的工作扩展到整个面向对象设计领域。Booch 1993比较适合于系统的设计和构造。Rumbaugh等人提出了面向对象的建模技术(OMT)方法,采用了面向对象的概念,并引入各种独立于语言的表示符。这种方法用对象模型、动态模型、功能模型和用例模型,共同完成对整个系统的建模,所定义的概念和符号可用于软件开发的分析、设计和实现的全过程,软件开发人员不必在开发过程的不同阶段进行概念和符号的转换。OMT-2特别适用于分析和描述以数据为中心的信息系统。Jaco on于1994年提出了 OOSE方法,其最大特点是面向用例(Use-Case),并在用例的描述中引入了外部角色的概念。用例的概念是精确描述需求的重要武器,但用例贯穿于整个开发过程,包括对系统的测试和验证。OOSE比较适合支持商业工程和需求分析。此外,还有Coad/Yourdon方法,即著名的OOA/OOD,它是最早的面向对象的分析和设计方法之一。该方法简单、易学,适合于面向对象技术的初学者使用,但由于该方法在处理能力方面的局限,目前已很少使用。
分类:
| 引用: 451 | 查看次数: 2057
作者:admi 日期:2007-10-31
近日在工作中一直使用Struts2.0,对它的了解也是逐渐的增多哦,嗯嗯,好事一件.不过,在使用中也遇到了一些问题,一般的基本都搞定了,只有一个,到现在也没弄明白,实在不行,就得查看源代码了......
问题是这样的:
上传文件,需要限制上传文件的大小,这个可以在配置Action的interceptor来解决,只需设置一下maximumSize的值就可以了,我这里设置的是1048576(1M).
分类:
| 引用: 4741 | 查看次数: 6307
作者:admi 日期:2007-10-31
问题:
有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取完者为胜者。现在给出初始的两堆石子的数目,如果轮到你先取,假设双方都采取最好的策略,问最后你是胜者还是败者。
碰到这道题时我的思路:
分类:
| 引用: 4204 | 查看次数: 5800
作者:admi 日期:2007-10-31
Problem Statement
NOTE: There are image i the example ectio of thi roblem tatement that hel describe the roblem. Please view the roblem tatement i the HTML window to view them.
Give a icture composed entirely of horizontal and vertical line egments, calculate the minimum umber of time you must lift your e to trace every line egment i the icture exactly times.
Each line egment will e of the form quot lt;x1y1x2y2> quot (quote for clarity), representing a egment from (x1,y1) to (x2,y2). Segment may cro each other. Segment may also overlap, i which case you hould count the overla ing regio a a earing i the drawing only once. For example, ay the drawing were composed of two lines: one from (6,4) to (9,4), and one from (8,4) to (14,4). Eve though they overla from (8,4) to (9,4), you hould treat the drawing a if it were a ingle line from (6,4) to (14,4). You would ot eed to lift your e at all to trace thi drawing.
分类:
| 引用: 478 | 查看次数: 2107
作者:admi 日期:2007-10-31
Subversion之路-----实现精细的目录访问权限控制转
原文:
目 录
分类:
| 引用: 879 | 查看次数: 2033
作者:admi 日期:2007-10-31
1:创建模板标记
需要用到的标签:tiles:i ert gt;
tiles:i ert的作用类似于方法中的形参,该标记将被调用到该模板的页面使用tiles:i ert /和tiles:put /标记指定的具体信息。
下面会有一个例子:
Template.j 模板页:
分类:
| 引用: 920 | 查看次数: 3391
作者:admi 日期:2007-10-31
工作中有维护 Strut 项目,或看别人项目中代码时,要把访问页面链接与相应处理 Actio 类及 FormBean等相关信息对应起来,每每都是打开 Strut 配置文件,Ctrl+F 进行查找,不易准确定位,尤其是项目中有多个 Strut 配置文件时就得这边倒来那边转去的,实为不便。于是乎就为自己写了一个可同时在多个 Strut 配置文件中根据不同条件查找配置信息的小工具,谓之:Strut Config Helper。
这段时间工作上比较的忙,闲暇之间,一点一滴缓慢缀掇而成。也不知对于各位同路人是否有可借鉴之处,张贴出来,希望得到各位的指摘,多给我提些 Bug 出来,不胜感激!
下载地址是:
分类:
| 引用: 1021 | 查看次数: 2758
作者:admi 日期:2007-10-31
WhirlyCache
借着最近项目用到cache,就顺便研究了一下cache 的设计,研究对象WhirlyCache 一个sun公司轻量的cache工具
作为一个cache的整体架构 他分这么几个模块
分类:
| 引用: 937 | 查看次数: 3345
作者:admi 日期:2007-10-30
字段 允许值 允许的特殊字符
秒 0-59 , - * /
分 0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - * ? / L W C
月份 1-12 或者 JAN-DEC , - * /
星期 1-7 或者 SUN-SAT , - * ? / L C #
年(可选) 留空, 1970-2099 , - * /
The '*' character is used to ecify all values. For example, * in the minute field mea every minute.
*字符被用来指定所有的值。如:*在分钟的字段域里表示每分钟。
The '?' character is allowed for the day-of-month and day-of-week fields. It is used to ecify 'no ecific value'. This is useful when you need to ecify something in one of the two fileds, but not the other. See the examples below for clarification.
?字符只在日期域和星期域中使用。它被用来指定非明确的值。当你需要通过在这两个域中的一个来指定一些东西的时候,它是有用的。看下面的例子你就会明白。
月份中的日期和星期中的日期这两个元素时互斥的一起应该通过设置一个问号(?)来表明不想设置那个字段
The '-' character is used to ecify ranges For example 10-12 in the hour field mea the hours 10, 11 and 12.
-字符被用来指定一个范围。如:10-12在小时域意味着10点、11点、12点。
The ',' character is used to ecify additional values. For example MON,WED,FRI in the day-of-week field mea the days Monday, Wednesday, and Friday.
,字符被用来指定另外的值。如:MON,WED,FRI在星期域里表示星期一、星期三、星期五.
The '/' character is used to ecify increments. For example 0/15 in the seconds field mea the seconds 0, 15, 30, and 45. And 5/15 in the seconds field mea the seconds 5, 20, 35, and 50. Specifying '*' before the '/' is equivalent to ecifying 0 is the value to start with. E entially, for each field in the expre ion, there is a set of numbers that can be turned on or off. For seconds and minutes, the numbers range from 0 to 59. For hours 0 to 23, for days of the month 0 to 31, and for months 1 to 12. The / character simply hel you turn on every " th value in the given set. Thus 7/6 in the month field only tur on month 7, it does NOT mean every 6th month, please note that subtlety.
The 'L' character is allowed for the day-of-month and day-of-week fields. This character is short-hand for last, but it has different meaning in each of the two fields. For example, the value L in the day-of-month field mea the last day of the month - day 31 for January, day 28 for February on non-leap years. If used in the day-of-week field by itself, it simply mea 7 or SAT. But if used in the day-of-week field after another value, it mea the last xxx day of the month - for example 6L mea the last friday of the month. When using the 'L' option, it is important not to ecify lists, or ranges of values, as you'll get confusing results.
L是last的省略写法可以表示day-of-month和day-of-week域,但在两个字段中的意思不同,例如day-of-month域中表示一个月的最后一天,
如果在day-of-week域表示7或者SAT,如果在day-of-week域中前面加上数字,它表示一个月的最后几天,例如6L就表示一个月的最后一个
星期五,
The 'W' character is allowed for the day-of-month field. This character is used to ecify the weekday (Monday-Friday) nearest the given day. As an example, if you were to ecify 15W as the value for the day-of-month field, the meaning is: the nearest weekday to the 15th of the month. So if the 15th is a Saturday, the trigger will fire on Friday the 14th. If the 15th is a Sunday, the trigger will fire on Monday the 16th. If the 15th is a Tuesday, then it will fire on Tuesday the 15th. However if you ecify 1W as the value for day-of-month, and the 1st is a Saturday, the trigger will fire on Monday the 3rd, as it will not 'jump' over the boundary of a month's days. The 'W' character can only be ecified when the day-of-month is a single day, not a range or list of days
The 'L' and 'W' characters can also be combined for the day-of-month expre ion to yield 'LW', which tra lates to last weekday of the month.
The '#' character is allowed for the day-of-week field. This character is used to ecify the nth XXX day of the month. For example, the value of 6#3 in the day-of-week field mea the third Friday of the month (day 6 = Friday and #3 = the 3rd one in the month). Other examples: 2#1 = the first Monday of the month and 4#5 = the fifth Wednesday of the month. Note that if you ecify #5 and there is not 5 of the given day-of-week in the month, then no firing will occur that month.
The 'C' character is allowed for the day-of-month and day-of-week fields. This character is short-hand for calendar. This mea values are calculated agai t the a ociated calendar, if any. If no calendar is a ociated, then it is equivalent to having an all-inclusive calendar. A value of 5C in the day-of-month field mea the first day included by the calendar on or after the 5th. A value of 1C in the day-of-week field mea the first day included by the calendar on or after sunday.
关于cronExpre ion的介绍:
字段 允许值 允许的特殊字符
秒 0-59 , - * /
分 0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - * ? / L W C
月份 1-12 或者 JAN-DEC , - * /
星期 1-7 或者 SUN-SAT , - * ? / L C #
年(可选) 留空, 1970-2099 , - * /
表达式意义
0 0 12 * * ? 每天中午12点触发
0 15 10 ? * * 每天上午10:15触发
0 15 10 * * ? 每天上午10:15触发
0 15 10 * * ? * 每天上午10:15触发
0 15 10 * * ? 2005 2005年的每天上午10:15触发
0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟触发
0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发
0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发
0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发
0 15 10 ? * MON-FRI 周一至周五的上午10:15触发
0 15 10 15 * ? 每月15日上午10:15触发
0 15 10 L * ? 每月最后一日的上午10:15触发
0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发
0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最后一个星期五上午10:15触发
0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发
每天早上6点
0 6 * * *
每两个小时
0 */2 * * *
晚上11点到早上8点之间每两个小时,早上八点
0 23-7/2,8 * * *
每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
0 11 4 * 1-3
1月1日早上4点
0 4 1 1 *
quartz的高级特性不仅如此
1 数据库存储
2 集群支持
3 数据库持久化任务,trigger
4 trigger 的停止,运行
5 任务的任意添加
6 比corntrigger 更详尽的任务安排
7 线程的内部数据交换
分类:
| 引用: 414 | 查看次数: 1930
站长推荐
Thinking in java学习系列
java技术交流群31233206
Category
Calendar
2007年10月
User Panel
Statistics
日志:
会员:
访问:
6663035
在线:
建站时间:
2007-06-11
Recent Comments
Archive
站内搜索
关键字 类 型
日志标题
日志内容
日志评论
引用通告
Powered By
CopyRight 2007,
java学习
Proce ed in
0.218750
second(s) ,
queries
Design By#1楼 得分:0
回复于:2006-01-14 23:58:12
先用 小颖反编译软件 把.cla 反编译成.java文件
如果加过混淆器的,就再小批量小批量的改吧,就像单元测试,一般手机游戏比较小,用个IDE如JB,然后手工改也费不了多少时间
(有酒醉)
等 级:
#2楼 得分:0
回复于:2006-01-15 00:01:20
路过.. : )
(fjfjfjfj)
等 级:
#3楼 得分:0
回复于:2006-01-16 09:07:50
使用专门的反编译软件。
如果是混淆过的源码,也可以反编译,但是反编译之后,看到的变量名称都变成了a,b这样的。
在看的时候比较费劲。
如果是学习,那么建议楼主到开源的社区去,那里有开源的J2ME程序,不用反编译。
等 级:
#4楼 得分:0
回复于:2006-01-16 13:45:22
网上开源的J2ME程序多如牛毛啊!
等 级:
#5楼 得分:0
回复于:2006-01-16 16:42:45
我刚接触过一个经过混淆的反编译的代码.可读性非常差.这样的代码只能自己一步步摸索了.
(www.demc.cn)
等 级:
#6楼 得分:0
回复于:2006-01-18 16:58:28
如果反编译以后。。。。。。
那么,作者的心血不就白流了吗?
(不想穿裤叉)
等 级:
#7楼 得分:0
回复于:2006-01-22 14:57:59
反编译以后的代码,你重新打包也运行不了~~
(精于心,简于形)
等 级:
#8楼 得分:0
回复于:2006-01-23 16:03:56
你自己编译的,如果你只是一个初学者,而且没有做过几个游戏,你根本看不懂混淆后反编译的代码,如果你根据aa ccdd之类的变量名强行理解代码的含义,我觉得那根本就是浪费你的时间。
网络上有反编译的西伯利亚攻击源代码,还可以凑合看,加了某人的自己的感悟,譬如:
// Decompiled by DJ v3.7.7.81 Copyright 2004 Atanas Neshkov Date: 2005-8-19 17:57:32
// Home Page : http://members.fortunecity.com/neshkov/dj.html - Check often for new version!
// Decompiler optio : packimports(3)
package Si import com.nokia.mid.sound.Sound;
import com.nokia.mid.ui.*;
import java.io.IOExceptio import java.io.I utStream;
import java.util.Random;
import javax.microedition.lcdui.*;
// Referenced cla es of package Sib:
// b, Sib, c, a
cla MainEngine extends FullCanvas implements Ru able
{ MainEngine() { Di lay.getDi lay(Sib.i tance).setCurrent(this); (new Thread(this)).start(); } public static int init() { percent = 0; initImage(); percent = 0;
// for(int i = 0; i GameData.ch; i++){
// cT[i] = false;
// } isIniting = true; gScreenY = 24; gScreenX = 8; a1 = 0; if(!Game.isReadHighS) Game.readHighScore(); Game.isReadHighS = true; L = -1; percent = 0; if(gameState != 9) { percent = 0; Game.keyDelay = 1; menuState = 0; gameState = 5;// 进入游戏状态 } return 1; } short readShort(I utStream i utstream) throws IOException { byte abyte0[] = new byte[2]; i utstream.read(abyte0); short word0 = abyte0[0]; word0 &am = 0xff; word0 |= (short)(abyte0[1] 8); return word0; } short readByte(I utStream i utstream) throws IOException { byte abyte0[] = new byte[1]; i utstream.read(abyte0); return (short)abyte0[0]; } void initStg() throws Exception { isIniting = true; percent = 0; repaint(); serviceRepaints(); if(actorArrays == null) { actorArrays = new Item[arrawLen.length][];//8 for(int i = 0; i arrawLen.length; i++) { actorArrays[i] = new Item[arrawLen[i]]; for(int j = 0; j arrawLen[i]; j++) actorArrays[i][j] = new Item(); } itemCountByType = new short[arrawLen.length]; layerArrays = new Item[9][];//9*80 for(int j1 = 0; j1 9; j1++) layerArrays[j1] = new Item[80]; itemCountByLayer = new byte[9];//length mainActor = actorArrays[3][0];//3 = 1 2 = 2 createMainActor(3);//创建主角飞机 } else { for(int i = 0; i arrawLen.length; i++){ if (i != 3) { itemCountByType[i] = 0; for (int j = 0; j arrawLen[i]; j++) actorArrays[i][j].isHide = true; } } //清空 for(int i = 0; i 9; i++) { itemCountByLayer[i] = 0; for(int j = 0; j layerArrays[i].length; j++) layerArrays[i][j] = null; } addItemInLayer(mainActor); } //读取关卡数据 I utStream i utstream = getCla ().getResourceAsStream(stageData); headLen = readShort(i utstream); //=11
(不想穿裤叉)
等 级:
#9楼 得分:0
回复于:2006-01-30 17:17:26
如果谁对反编译西伯利亚攻击源代码看不懂,我可以翻译一下~~教程 | | 当前位置: > > > 正文
敏捷开发中高质量Java代码开发实践
作者:
发表于 2010-4-28 13:33:44 评论(0) 阅读(353)  
项目开发过程中,由于开发人员的经验、代码风格各不相同,以及缺乏统一的标准和管理流程,往往导致整个项目的代码质量较差,难于维护,需要较大的
投入和周期等问题。这些问题在一个项目组初建、需求和设计均具有不完全可预期性和完备性的全新项目中将尤为突出。本文将结合敏捷开发周期短,变化快等特点,介绍如何通过在开发过程中采取一系列步骤来保证和提高整个开发团队的代码质量,并阐述了每一步可以利用的工具和最佳实践,从而使开发过程更加规范化,成就高质量的代码,减少
的投入,并促进整个团队的技能提高,最终提高开发效率和质量。
  如图 1 所示,敏捷开发过程经历需求调研,用例分析和用例***,进入开发迭代阶段。在每个迭代过程中,可以采用以下五个步骤来保证和提高整个项目的代码质量:统一编码规范、代码样式;静态代码分析(static code review);单元测试;持续集成;代码评审和重构(Review &am Refactor)。下文将针对每个步骤和其所使用的工具、方法进行详细描述。
  图 1. 敏捷开发中的
代码质量保证步骤
 步骤一:统一编码规范、代码样式
  规范统一的编码会增加项目代码的可读性和可维护性,但实际情况往往是项目组内的 Java 代码开发人员的编码风格常常各不相同,这可能是由于不同的经验习惯或者缺乏编码规范方面的学习造成的。这样一来,其他项目成员或者维护人员在阅读项目代码时就需要花费更多的时间来理解代码作者的意图,所以制定并采取统一的编码规范就显得很重要。编码规范主要应包含以下几个方面:
  一般规则和格式规范。例如代码缩进、程序块规范、每行最大代码长度等。
  命名规则。例如包名、类名、变量、方法、接口、参数等命名规范
  文档规范。例如类文件头声明、类注释、成员变量和方法注释等规范。
  编程规范。例如异常、并发、多线程等方面的处理方式。
  其他规范。例如日志格式、属性文件格式,返回值和消息格式。
  项目的编码规范可以参考已有的一些 Java 编程规范书籍和其他相关资料并结合项目的本身来制定,可供参考的书籍有《 Java 编程风格》(英文书名为:The Elements of Java Style)。编码规范要形成文档,而且要简洁明了,并组织项目成员一起学习,确保所有成员正确理解所有条目。
  一旦编码规范确定,就可以利用 Ecli e 自身提供的功能来控制代码样式和格式。具体做法是,点击 Ecli e 的
Windows
- Preference 菜单项,在打开的 Preferences 对话框的左侧栏中找到 Java 节点下的子项 Code Style(如图 2),该项和它的子项允许您对 Java 代码的样式进行控制。
  图 2. Ecli e 代码样式设置窗口
  例如,为了使用自动格式化工具,可以在 Ecli e 提供的默认代码格式配置的基础上建立自定义的格式。在 Formatter 面板中,点击 New,输入新的名字并选择一个默认的配置作为初始化格式,如图 3 所示。
  图 3. 创建新的代码格式配置
  单击 OK 后就可以在新打开的窗口中进行修改定制自己需要的格式。如图 4 所示。
  图 4. 创建新的代码格式配置
  修改完成后点击 A ly 保存所作修改。同时可以点击 Export 将当前的格式定义导出成一个 XML 文件,这样项目组的其他成员就可以很方便通过点击图 3 中的 Import 按钮来导入该 XML 文件来使用同一个代码格式定义。
  这样每次在提交代码到版本控制
服务器
前就可以通过 Ecli e 界面里的 Source-Format 菜单来对代码进行格式化,从而使整个项目的代码具有相同的格式。同样可以通过对 Code Style 下的其他项目进行设置来帮助对 Java 代码的样式进行控制。将所有这些样式文件导出成 XML 文件后,同编码规范一起归档,供所有项目成员使用。
  步骤二:静态代码分析
  在完成源代码的开发以后,下面要进行的工作就是审视和测试代码。除了通过运行测试代码来检查功能之外,还能利用一些静态分析工具来快速、直接地提高代码质量。静态代码分析工具并不需要运行代码,可以直接对 Java 文件和 Cla 文件进行分析,通过一些检查条件的设置,快速找到代码中的错误和潜在缺陷。现在的静态分析工具很多,有 FindBugs、PMD、IBM Rational Tool,等等。在这里,选择 FindBugs 作为静态代码分析工具。FindBugs 可以和日常开发工具 Ecli e 进行集成,在开发过程中,就可以方便的开始静态代码的检查。通过检查 Cla 文件或者 JAR 文件,将字节码和一组缺陷模式进行对比,来发现可能存在的代码问题。在 Ecli e 的开发环境中,用插件***的方式***了 Findbugs 后,在 Ecli e 的配置选项中就会多出来 FindBugs 的配置选项。可以对自己的项目进行配置,选择需要的 Detector 检查代码。
  图 5. FindBugs 的配置选项
  设置好自己的规则后,在需要检查的代码文件夹上点击右键,就可以启动 FindBugs 检查。代码可以是一个项目,也可以只是几个文件。
  图 6. 运行 FindBugs
‖JL_STAR‖  检查完毕后,会出现 FindBugs 视图,把所有检查的结果根据错误分组展示。点击结果里面的每一个错误,会自动打开对应的代码。当根据规则改正了所有的错误,或者说潜在错误,这些代码也就通过了静态代码检查。FindBugs 的检查结果可以是 XML 文件,也可以是文本文件,便于项目的集成管理和检查保存。
  图 7. FindBugs 检查结果
  步骤三:单元测试
  单元测试用例设计和评审
  单元测试是软件开发过程中重要的质量保证环节,在此环节中,设计和评审对于保证整个单元测试过程的完整性和有效性来说十分重要。设计阶段需要具体考虑要对哪些代码单元进行测试,被测单元之间的关系,测试策略,以及单元测试用例设计等,并最终输出《单元测试用例设计》文档,用来指导具体的单元测试执行。在用例设计中,通过对代码单元输入和期待输出的定义来保证该单元的功能正确性,边界值的测试和异常测试非常重要。同时也配合测试用例和功能块的匹配方法来衡量用例设计的完整性。
  在用例设计完成之后,下一步的工作就是进行测试用例的评审。个人的理解和经验始终是有限的,用例评审可以借集体之力,对用例设计进入查漏补缺,进一步保证测试用例的有效性。由于单元测试属于白盒测试范畴,它主要通过对代码的逻辑结构进行分析来设计测试用例,因此,评审员的选择最好以理解代码逻辑结构为前提,如果评审员来自相关模块,还能够有效的发现模块相关性和依赖性所带来的问题。
  模拟对象技术
  在实际项目中,开发人员自己的代码往往需要和其他的代码模块或系统进行交互,但在测试的过程中,这些需要被调用的真实对象常常很难被实例化,或者这些对象在某些情况下无法被用来测试,例如,真实对象的行为无法预测,真实对象的行为难以触发,或者真实对象的运行速度很慢。这时候,就需要使用模拟对象技术(Mock),利用一个模拟对象来模拟我们的代码所依赖的真实对象,来帮助完成测试,提高测试覆盖率,从而提高代码质量。模拟对象技术利用了在面向接口的编程中,由于代码直接对接口进行调用,所以代码并不知道引用的是真实对象还是模拟对象,这样就可以顺利的完成对代码的测试。
  模拟技术有很多种,如 jMock,EasyMock,Mockito,PowerMock 等等。其中 Mockito 消除了对期望行为的需求,避免了这些代码的大量初始化。
  图 8. Mockito 示例
  在模拟对象过程中,先模拟一个需要调用的 List 对象 LinkedList,再设定这个对象的行为,当调用 get(0) 的时候,返回”first”。这样,测试代码就可以利用这个对象来测试我们的功能代码,需要调用和返回值的时候,可以顺利的得到模拟对象的返回值。也需要对模拟对象进行错误情况的模拟,保证代码对错误的处理的正确性。
  测试覆盖率分析
  为了衡量单元测试的质量和覆盖的范围,需要对单元测试的代码进行测试覆盖分析。常用的衡量测试覆盖率的指标主要有语句覆盖率、分支覆盖率、路径覆盖率、条件覆盖率和方法覆盖率等。具体采用哪些指标可以根据项目的实际情况来定,以避免因过高的指标增加了代码开发人员的工作量而影响了项目整体的进度。
  EMMA 是一款比较流行的开源 Java 测试覆盖率分析工具,支持类、方法、代码行、基本代码块等多种类型的测试覆盖率分析,支持将覆盖率分析结果导出为多种格式的报告,并采用多种颜色来高亮显示不同的覆盖率状态。EclEmma 是一款基于 EMMA 的 Ecli e 插件,方便在 Ecli e IDE 中进行测试覆盖率分析。如图 9,在测试用例写好后,可以在右键点击测试类,选择 Coverage As - JUnit Test.
  图 9. 运行测试覆盖分析
  单元测试跑完后,Coverage视图中会显示所选择的测试的覆盖率。双击打开某一具体的类后,可以看到高亮显示的覆盖分析结果,如图 10 所示。红色代表测试没有覆盖到该行,***表示部分覆盖,绿色的行表示该行在本次测试中被覆盖到。
  图 10. 查看测试覆盖分析结果
  在 Coverage 视图中可以通过点击鼠标右键将测试覆盖分析的结果导出成需要的格式,例如 HTML。
  图 11. 导出测试覆盖分析结果
  图 12 显示了导出的 report。
  图 12. 测试覆盖分析报告
  为了保证单元测试的有效性和质量,可以规定一个测试覆盖率的下限,例如所有的包和类的覆盖率必须达到 80% 以上。不过值得注意的是,不要单纯追求高覆盖率,要同时注意测试用例的质量,如果测试用例本身就写的有错误,那么即使测试覆盖率很高也没有意义。、
 步骤四:持续集成
  持续集成(Continuous Integration)是利用一系列的工具,方法和规则,做到快速的构建开发代码,自动的测试化,来提高开发代码的效率和质量。利用自动构建工具,随时都能把提交的代码构建出来,提供一个可以测试使用的版本,让用户和开发人员同时看到相同的功能,尽早的发现问题和错误,也可以尽快的得到测试人员和用户的反馈。
  要做到持续集成,就要利用一系列工具,把开发过程中的重复工作自动化。搭建自动的构建
服务器
,自动的进行单元测试和发布新版本,一个集成的服务器可以提供构建过程的结果报告,自动通知开发人员构建结果,并且保存历史数据。IBM Rational Team Concert (RTC) 可以提供工作任务的管理,项目计划的安排,代码版本管理控制,自动构建可用版本,生成构建结果报告。这些过程构成了项目的持续集成过程,其中,版本的自动构建和代码的自动单元测试是持续集成的关键过程,RTC 在这些过程上提供了有力的支持。
  自动构建
  RTC 提供了 build engine 来负责构建 build,首选,启动 build engine,并和 RTC 服务器建立了连接。再创建项目的 build 定义。在这个定义中,需要设定编译哪些模块的代码,需要跳动哪个 ANT 文件来启动编译,和一些编译过程中的参数的设定。当这些都准备好了,编译对于项目而言,就变成一个简单的事情。
  可以看到,通过在 build 定义上,点击请求构建,就可以触发一次构建过程。选择需要的构建参数,这个过程就会在后台运行。每一个开发人员,做了稍许的代码改变和提交,都可以触发新的构建过程,来保证我们代码的有效性。申请一个新的构建的过程如图 13、图 14 所示。
  图 13. 申请一个新的构建
  图 14. 构建申请界面
  当构建结束后。RTC 服务器会提供构建结果报告。开发人员可以查询到这次构建的详细信息。
  图 15. 构建结果
  整个开发过程中,构建版本的过程应该是无数次的,通过每次构建,都可以得到当时代码的编译情况,并且可以得到一个可运行的软件版本。在构建定义上,RTC 支持设置构建计划。定时自动的触发一次构建。
  图 16. 构建定义
  自动单元测试
  构建可以自动了,重点提高代码质量的单元测试呢?如果每一天的代码,每一个版本的代码,都已经通过了我们的单元测试,这样我们就能对代码的质量有了基本的保证。在构建脚本的自动调用过程中,通过 ANT 的脚本,可以加上 JUnit,EMMA,FindBugs 的 ANT 脚本调用,每一次的构建,都可以把这些检查工作自动的进行一遍测试。这些测试都要生成测试结果报告, RTC 不能提供这些报告的展示,就可以利用 Hudson 这个开源工具,集成测试报告来方便查阅。
  图 17. 自动测试报告
  步骤五:代码评审和重构
  代码评审(Code Review)是 Java 项目开发过程中的一个重要步骤,代码评审可以帮助发现静态代码分析过程中无法发现的一些问题,例如代码的编写是否符合编码规范,代码在逻辑上或者功能上是否存在错误,代码在执行效率和性能上是否有需要改进的地方,代码的注释是否完整正确,代码是否存在冗余和重复。代码评审还可以帮助新进入项目组的成员快速学习和了解项目,促进经验分享,同时也能保证项目成员的良好沟通。代码评审主要包括两种形式,同级评审(Peer Review)和小组评审(Group Review)。同级评审主要指项目成员间的互相评审,小组评审是指通过召开评审会议,项目成员一起对项目代码进行评审。
  为了提高代码评审的有效性和效率,可以借助一些外部工具,比较常用的代码评审工具有 Jupiter 和 Code Striker。Jupiter 是一款开源的 Ecli e 插件,允许成员将评审意见定位到真实代码的具体行,由于代码评审的结果以 XML 文件的形式保存,所以可以把结果提交到版本管理服务器进行共享。图 18 显示了使用 Jupiter 进行代码评审的界面。
  图 18. Jupiter 代码评审界面
  在代码评审任务创建后,Jupiter 将代码评审分成三个阶段,个人评审阶段 (Individual Phase)、团队评审阶段(Team Phase)和问题修复阶段(Rework Phase)。在个人评审阶段,评审成员将发现的代码问题或者缺陷记录下来,每个问题都会作为一个记录保存在评审表格中。在团队评审阶段,团队的全部或者部分成员会一起对个人评审阶段发现的问题进行定性,如果问题确实存在,就将该问题分配给某个成员去解决,并在 Jupiter 中将该问题设置成相应的状态。在问题修复阶段,团队成员会修复属于自己的问题,并将相应的记录设置成已解决等正确的状态。
  Codestriker 是一款基于 Web 的常用代码评审工具,对代码的评审可以针对某一具体行,也可以针对整个代码文件,评审意见会被保存在数据库中。评审人员可以同时看到其他人的评论,代码作者也可以针对某一具体的评论回复。Codestriker 支持邮件通知,还可以同版本控制服务器进行集成,以跟踪和显示文件内容的改变。图 19 显示了 Codestriker 的界面。
  图 19. Codestriker 报告界面
  在实践中对所有代码进行小组评审会比较费时,所以可以根据实际情况来挑选一些核心代码进行小组评审,或者在项目的前期安排较多的小组评审,等项目组的成员对代码评审的标准和要求有较好的理解,进行代码评审的经验提高后,就可以逐渐减少小组评审的次数,从而达到大部分代码即使只进行同级评审也能保证很好的质量。
  通过代码评审发现的问题要通过代码重构及时解决掉,较小的不涉及多人代码的重构可以由项目成员自己借助 Ecli e 的重构功能完成,不同项目成员写的实现相同功能的不同代码要通过讨论整合成公共的类或者方法。比较复杂的或者比较高层次的重构工作,例如整个项目层面的代码组织形式的改变需要由整个项目组共同讨论完成。
  结论
  软件开发没有一成不变、万能通用的流程和方法,希望大家能从本文得到启发和收益,结合您的实际项目特点,实践以上步骤和方法,并加以完善和改进,共同打造高效高质量的 Java 代码,为您的项目成功奠定坚实的基础。 评论
悄悄话
手机游戏开发相关文章
Copyright 2008 北京汇众益智科技有限公司. All Rights Reserved
京ICP备09092043号

参考资料