寫在前面
經歷了兩周的結對編程,我和王旌含在相互幫助中學到了不少,進步了不少。但我們認為這還不是我們理想中結對編程—我們起初當定義過自己在結對編程中角色,但在結對過程中卻發生了改變,就像是在玩蹺蹺板,一個胖子和一個瘦子一起玩必定是索然無味的。唯有體重相差不大的人才能體會。有時候我們都想當瘦子,有時候我又成了大胖子,不斷催促他個瘦子。對此我們詢問了班上其他的結對對象,發現他們也陷入了此類問題,也許他們的編程速度比我們快,但其實並沒有體現出結對編程,只是個人寫個人的類,做自己的單元測試,自己修改,到最后只是將自己的類的作用解釋給同伴。因為我們兩人的能力不同,為了都能在結對編程中體現價值,在這周我們做了以下決定:
並不是蹺蹺板胖瘦不同的人就不能玩了,我們決定不再關注兩人的編程能力是否一樣。
我們決定不是所有的任務都采用結對編程的模式。
對於程序中的重要類我們決定不斷“復審”,我們開始“強迫”兩人交流,開始根據能力的不同進行角色分工和互換
代碼重構
- 這周我們剛的第一件事就是一起將我們生成題目的類進行升級重構
public class Project {
Random in = new Random();
int a = in.nextInt(10)+1;
int b = in.nextInt(10)+1;
int c = in.nextInt(10)+1;
int num = in.nextInt(4);
int num2 = in.nextInt(4);
String [] Operator = {"*","+","-","/"};
public String HighPro(){
int a = in.nextInt(6)+5;
int b = 2*a+1;
StringBuilder result = new StringBuilder(100);
for (int i = 0;i<b;i++){
int num3 = in.nextInt(10);
int num4 = in.nextInt(4);
if (i%2==0){
result.append(num3);
}
if(i%2!=0){
result.append(Operator[num4]);
}
}
return String.valueOf(result);
}
}
這是我起初編寫的生成題目的代碼,她有以下個問題
- 沒有排除除數為零的情況
- 沒有添加函數的方法
- 代碼不規范不整潔
對此我們改變了生成題目的方式
/*例子:1+(2+3)*4+5
將此類題目分成三部分
前部:1+
中部:(2+3)
后部:*4+5
最后將幾個部分結合
*/
這是之后的代碼
import java.util.Random;
/**
* Created by asus on 2017/5/18.
*/
public class NewProject extends SetNum{
public String Front(){
String result;
switch (getC()){
case 0:
result = getA()+Operator[getB()];
break;
case 1:
result = getA()+Operator[getB()]+getA()+Operator[getB()];
break;
default:
result = getA()+Operator[getB()]+getA()+Operator[getB()]+getA()+Operator[getB()];
}
return result;
}
public String Middle(){
String result;
switch (getC()){
case 0:
result = getA()+"";
break;
case 1:
result ="("+getA()+Operator[getB()]+getA()+")";
break;
default:
result = "("+getA()+Operator[getB()]+"("+getA()+Operator[getB()]+getA()+")"+Operator[getB()]+getA()+")";
}
return result;
}
public String End(){
String result;
switch (getC()){
case 0:
result = Operator[getB()]+getA();
break;
case 1:
result = Operator[getB()]+getA()+Operator[getB()]+getA();
break;
default:
result = Operator[getB()]+getA()+Operator[getB()]+getA()+Operator[getB()]+getA();
}
return result;
}
public String Allpart(){
String result;
switch (getC()){
case 0:
result = Front()+Middle();
break;
case 1:
result = Middle()+Front();
default:
result = Front()+Middle()+End();
}
return result;
}
public String JudgeAllpart(){
String result =Allpart();
for(int i = 0;i<result.length();i++){
if ((result.charAt(i)=='/')&&(result.charAt(i+1)=='0')){
result = Allpart();
}
}
return result;
}
}
import java.util.Random;
/**
* Created by asus on 2017/5/18.
*/
public class SetNum {
Random in = new Random();
int a;
int b;
int c;
public int getC() {
setC();
return c;
}
public void setC() {
this.c = in.nextInt(3);
}
String [] Operator = {"+","-","*","/"};
public int getB() {
setB();
return b;
}
public void setB() {
this.b = in.nextInt(4);
}
public void setA() {
this.a = in.nextInt(10);
}
public int getA() {
setA();
return a;
}
}
當然以上代碼是我們對其重構后的結果,中間代碼因為重構了沒有保留源
具體重構如下:
- 原代碼並沒有gettrt and setter而是每次都要使用隨機數生成造成代碼重復很多
於是我們將其添加gettrt and setter,為了是每次調用都隨機產生數,於是在get中在調用set- 我們考慮的其他類的編寫中都會用到相同范圍的隨機數,於是定義SetNum類來作為父類,要使用的子類只需要繼承即可,避免代碼重復
- 第二件事情是我們繼續上周未能完成的Junit測試
我們主要測試的是修改后的postfix類是否能繼續勝任她的工作
public void testCount() throws Exception {
//TODO: Test goes here...
String line;
BufferedReader rdr = new BufferedReader(new FileReader("testdata.txt"));
while ((line = rdr.readLine()) != null) {
if (line.startsWith("#")) {
continue;
}
StringTokenizer st = new StringTokenizer(line);
if (!st.hasMoreTokens()) {
continue;
}
String val = st.nextToken();
String expected = val;
LinkedList<String> argument_list = new LinkedList();
while (st.hasMoreTokens()) {
argument_list.add(st.nextToken());
}
Postfix a = new Postfix();
a.transferToPostfix(argument_list);
assertEquals(expected, a.transferToPostfix(argument_list));;
}
}
因為用到大量測試數據,我們考慮用到一個獨立的數據文件來儲存這些測試數據,然后讓單元測試讀取該文件
數據文件的格式是:第一個數字是想要運算的結果,后面是所要運算的題目,用空格隔開;
用井號#表示所在行是注釋
自動忽略空行
這是我們的成果
我的感悟
這次的結對編程我們學到了不少,代碼在兩個人的不斷重構和復審之間變得更完美,但也有不好的地方就是當結對人員變得懶散時你不得不督促他。我認為這是不好的,結對編程要求投入,你盡可以偷懶,因為你的工作伙伴可以完成,但這不是我想要的結對編程,因為我們從中得不到任何好處,不會提高效率,更不會有所成長。
當這個統計結果出來之后是難以置信的,在具體編碼的用時上我們兩人花了將近10個小時在寫各自的代碼,之所以是各自的代碼(無論復雜簡單)是因為我們回頭反思發現在做具體的需求分析,具體設計是沒能合理安排,在一開始階段沒能達成統一,導致我寫代碼他不懂,他的代碼我不知怎么用,我們之間沒有復審與重構,更沒有角色的交換;其次,伙伴對於單元測試能力的欠缺導致在測試上也花了不少時間,可能比統計的多。總之這次的結對效果很是不理想,設計的程序不是很能說明問題,因為一個人做也能做出來。我們跟很多結對者有過交流,發現我們的結對編程還是有一定效果的,這給了我們很大信心。說句實話話,我並不是很贊成結對編程,因為相比結對,我更喜歡一個人編代碼,因為在某些問題上我不需要跟別人解釋。但既然結對編程了,我們是真心想要做好,拭目以待。