实验三 敏捷开发与XP实践
20155224 实验三 敏捷开发与XP实践 实验报告
实验报告封面:
课程:Java程序设计 班级:1652班 姓名:王高源 学号:20165225
指导教师:娄嘉鹏 实验日期:2018年4月27日
实验时间:3:35 - 5:15 实验序号:实验三
实验名称:敏捷开发与XP实践
实验内容:
1.XP基础
2.XP核心实践
3.相关工具
实验要求:
- 没有Linux基础的同学建议先学习《Linux基础入门(新版)》《Vim编辑器》 课程
- 完成实验、撰写实验报告,实验报告以博客方式发表在博客园,注意实验报告重点是运行结果,遇到的问题(工具查找,安装,使用,程序的编辑,调试,运行等)、解决办法(空洞的方法如“查网络”、“问同学”、“看书”等一律得0分)以及分析(从中可以得到什么启示,有什么收获,教训等)。报告可以参考范飞龙老师的指导
- 严禁抄袭,有该行为者实验成绩归零,并附加其他惩罚措施。
实验步骤:
(一)编码标准
-
编程标准使代码更容易阅读和理解,甚至可以保证其中的错误更少。编程标准包含:具有说明性的名字、清晰的表达式、直截了当的控制流、可读的代码和注释,以及在追求这些内容时一致地使用某些规则和惯用法的重要性。
-
关于程序的缩进,在IDEA中比较智能,它会帮你自动进行缩进,这样也使得程序的可读性大大增强。
-
Java中的一般命名规则:
1.要体现各自的含义
2.包、类、变量用名词
3.方法名用动宾
4.包名全部小写,如:io,awt
5.第一个字母要大写,如:HelloWorldApp
6.变量名第一个字母要小写,如:userName
7.方法名第一个字母要小写:setName
8.在团队操作中,格式规范是为提高效率扫清障碍的做法;命名规
9.范则具有很强灵活性,根据各团队不同的情况和习惯进行,不仅是方便自己,更是方便团队其他成员。
-
结对编程:
-
结对编程中的两个重要角色:驾驶员(Driver)是控制键盘输入的人,领航员(Navigator)起到领航、提醒的作用。
驾驶员:写设计文档,进行编码和单元测试等XP开发流程。领航员:审阅驾驶员的文档、驾驶员对编码等开发流程的执行;考虑单元测试的覆盖率;思考是否需要和如何重构;帮助驾驶员解决具体的技术问题。
驾驶员和领航员不断轮换角色,不要连续工作超过一小时,每工作一小时休息15分钟。领航员要控制时间。 -
我们常见的代码如下:
public class CodeStandard {
public static void main(String [] args){
StringBuffer buffer = new StringBuffer();
buffer.append('S');
buffer.append("tringBuffer");
System.out.println(buffer.charAt(1));
System.out.println(buffer.capacity());
System.out.println(buffer.indexOf("tring"));
System.out.println("buffer = " + buffer.toString());
if(buffer.capacity()<20)
buffer.append("1234567");
for(int i=0; i<buffer.length();i++)
System.out.println(buffer.charAt(i));
}
}
-
但是这样的代码没有缩进,读的很费力,所以我们应该在idea中使用Code->Reformate Code去格式化代码。
-
代码重新格式化后效果如下:
public class CodeStandard {
public static void main(String [] args){
StringBuffer buffer = new StringBuffer();
buffer.append('S');
buffer.append("tringBuffer");
System.out.println(buffer.charAt(1));
System.out.println(buffer.capacity());
System.out.println(buffer.indexOf("tring"));
System.out.println("buffer = " + buffer.toString());
if(buffer.capacity()<20)
buffer.append("1234567");
for(int i=0; i<buffer.length();i++)
System.out.println(buffer.charAt(i));
}
}
- 其实idea还有很多十分实用的功能,如:Surround With(Ctrl+Alt+T):可使用if-else、try-catch、do-while等包装代码段,极大地简化了我们的编程时间:
(二)敏捷开发与XP
-
在码云上把自己的学习搭档加入自己的项目中,确认搭档的项目加入自己后,下载搭档实验二的Complex代码,加入不少于三个JUnit单元测试用例,测试成功后git add .; git commit -m "自己学号 添加内容";git push;
-
完成重构内容的练习,下载搭档的代码,至少进行三项重构,提交重构后代码的截图,加上自己的学号水印。提交搭档的码云项目链接。
-
以结对的方式完成Java密码学相关内容的学习,结合重构,git,代码标准。提交学习成果码云链接和代表性成果截图,要有学号水印。
-
搭档代码:
import java.lang.Integer;
import java.util.Objects;
public class Complex {
//定义属性并生成getter,setter
double RealPart;
double ImagePart;
public double getRealPart(){
return RealPart;
}
public double getImagePart(){
return ImagePart;
}
//定义构造函数
public Complex(){
RealPart = 0;
ImagePart = 1;
}
public Complex(double R,double I){
RealPart = R;
ImagePart = I;
}
//Override Object
public boolean equals(Object obj){
if(this == obj){
return true;
}
if(!(obj instanceof Complex)) {
return false;
}
Complex complex = (Complex) obj;
if(complex.RealPart != ((Complex) obj).RealPart) {
return false;
}
if(complex.ImagePart != ((Complex) obj).ImagePart) {
return false;
}
return true;
}
public String toString(){
String s = new String();
if (ImagePart > 0){
s = getRealPart() + "+" + getImagePart() + "i";
}
if (ImagePart == 0){
s = getRealPart() + "";
}
if(ImagePart < 0){
s = getRealPart() + "" + getImagePart() + "i";
}
if(RealPart == 0){
s = getImagePart() + "i";
}
return s;
}
//定义公有方法:加减乘除
Complex ComplexAdd(Complex a){
return new Complex(RealPart + a.RealPart,ImagePart + a.ImagePart);
}
Complex ComplexSub(Complex a){
return new Complex(RealPart - a.RealPart,ImagePart - a.ImagePart);
}
Complex ComplexMulti(Complex a){
return new Complex(RealPart*a.RealPart-ImagePart*a.ImagePart,RealPart*a.ImagePart + ImagePart*a.RealPart);
}
Complex ComplexDiv(Complex a) {
return new Complex((RealPart * a.ImagePart + ImagePart * a.RealPart) / (a.ImagePart * a.ImagePart + a.RealPart * a.RealPart), (ImagePart * a.ImagePart + RealPart * a.RealPart) / (a.RealPart * a.RealPart + a.RealPart * a.RealPart));
}
}
- 测试代码:
import static org.junit.Assert.*;
import org.junit.Test;
import junit.framework.TestCase;
public class ComplexTest extends TestCase {
Complex complex = new Complex(1,1);
@Test
public void testAdd(){
assertEquals(new Complex(3.3,3.4), complex.ComplexAdd(new Complex(2.3,2.4)));
}
//测试加法
@Test
public void testSub(){
assertEquals(new Complex(-5.3,-2.4), complex.ComplexSub(new Complex(6.3,3.4)));
}
//测试减法
@Test
public void testMulti(){
assertEquals(new Complex(3.0,2.0), complex.ComplexMulti(new Complex(3.0,2.0)));
}
//测试乘法
@Test
public void testDiv(){
assertEquals(new Complex(1.0,1.0), complex.ComplexDiv(new Complex(1.0,1.0)));
assertEquals(new Complex(0.0,0.0), complex.ComplexDiv(new Complex(1.0,0.0)));
//assertEquals(new Complex(0.0,0.0), complex.ComplexDiv(new Complex(3,4)));
//边缘测试
}
@Test
public void testequals(){
assertEquals(true, complex.equals(new Complex(1.0,1.0)));
}
//测试判断相等
}
- 测试结果如下:
- 搭档加入码云项目:
- git命令上传代码:
$ cd /home/shiyanlou/Code/shiyanlou_cs212
# 修改代码文件
# 添加修改文件
$ git add 所有修改的文件
# 提交到环境中本地代码仓库
$ git commit -m '本次修改的描述'
# push到git.shiyanlou.com,无需输入密码
$ git push
- 码云上传截图:
(三)重构
-
重构(Refactor),就是在不改变软件外部行为的基础上,改变软件内部的结构,使其更加易于阅读、易于维护和易于变更 。重构最主要的目标就是清楚“有臭味道”的代码,主要表现为重复代码。
-
我们仍以搭档的complex为例:
-如图选择重构项目:
重构结果如下:
(四)练习
- 维吉尼亚密码:
import java.sql.SQLOutput;
public class vigenere
{
//输入明文和密钥,用输入的密钥对明文进行加密
public static void main(String[] args) {
int i,j,sum,o;
double q,w;
int e=0;
double rate;
char[] c = new char[300];
char[] k1 = new char[300];
char[] k2=new char[100];
char word='a';
for (i=0;i<26;i++) {
k2[i]=word;
word++;
}
//输入
System.out.print("enter a mingwen string:");
String m = MyInput.readString();
System.out.print("enter a key string:");
String k = MyInput.readString();
//构造密钥对照表
for (i = 0; i < k.length(); i++) {
if (k.charAt(i) >= 'a' && k.charAt(i) <= 'z')
k1[i] = (char) (k.charAt(i) - 97);
if (k.charAt(i) >= 'A' && k.charAt(i) <= 'Z')
k1[i] = (char) (k.charAt(i) - 65);
}
//加密
for (i = 0; i < m.length(); i++) {
if (m.charAt(i) >= 'a' && m.charAt(i) <= 'z')
c[i] = (char) ((m.charAt(i) - 97 + k1[i % k.length()]) % 26 + 97);
if (m.charAt(i) >= 'A' && m.charAt(i) <= 'Z')
c[i] = (char) ((m.charAt(i) - 65 + k1[i % k.length()]) % 26 + 65);
}
//计算密文长度
o=i;
System.out.println("密文单词个数为"+o);
System.out.print("密文为");
//输出密文
for (i = 0; i < c.length; i++) {
System.out.print(c[i]);
}
System.out.println();
System.out.println("以下是各字母出现的频率");
//计算每个字母出现的次数和频率
for(j=0;j<=25;j++){
for(i=0;i<o;i++){
if(c[i]==k2[j]){
e++;
}
}
System.out.printf(k2[j]+"出现次数为"+e);
q=e;
w=o;
rate=(q/w)*100;
System.out.println("频率为"+rate+"%");
e=0;
}
//计算重合指数
for(i=0;i<o;i++){
for(j=1;j<o;j++){
if(c[i]==c[j]){
e++;
}
}
}
q=e;
sum=0;
for(i=o;i>0;i--){
sum=i+sum;
}
w=sum;
rate=(q/w)*100;
System.out.println("重合指数为"+rate+"%");
}
}
import java.io.*;
public class MyInput {
public static String readString() {
BufferedReader br
= new BufferedReader(new InputStreamReader(System.in), 1);
String string = "";
try {
string = br.readLine();
} catch (IOException ex) {
System.out.println(ex);
}
return string;
}
}
-
截图:
-
运行结果已放在蓝墨云中。
(五)实验过程中遇到的问题及解决
- clone连接超时:
-
结果发现是自己粘贴的有点过了....
-
已解决:
(六)PSP(Personal Software Process)时间
步骤 | 耗时 | 百分比 |
---|---|---|
需求分析 | 20min | 12.5% |
设计 | 25min | 15.6% |
代码实现 | 60min | 37.5% |
测试 | 35min | 21.9% |
分析总结 | 20min | 12.5% |
心得体会:
-
首先,结对学习真的很棒,还很省心。
-
其次,通过这次实验,我们都简单了解了Java实现密码学算法的方式,由于Java庞大的通用API积累,使用起来确实比C语言这种面向过程的语言方便了不少。
-
最后,附:20165213-周启航博客链接