結對編程?這是什麼鬼?趕快google了一下,根據維基百科給出的定義,結對編程(英語:Pair programming)是一種敏捷軟件開發的方法,兩個程序員在一個計算機上共同工做。 一我的輸入代碼,而另外一我的審查他輸入的每一行代碼。 輸入代碼的人稱做駕駛員,審查代碼的人稱做觀察員(或導航員)。 兩個程序員常常互換角色。其實說白了就是兩我的輪流操做一個機器(人閒機不閒),一人編碼,一人審查。體現了1+1>2的思想。廢話少說,進入正題。前端
結對夥伴:李星明java
代碼託管地址:Codingc++
做業博客地址:結對編程第2次做業程序員
通過和結對夥伴商量,此次咱們選擇題目一做爲結對編程的實戰項目。算法
題目1:編程
軟件系統圖詳解:圖中雖然寫得是mvc,其實這個設計更接近於mvp的模式。在V層採起java的編程語言,CM層採起的是C語言編程
設計過程:在設計的時候是咱們一塊兒本着下降耦合性、模塊化、易於維護和可擴展的原則下進行設計和建模,最終選擇了上圖結構;這樣的話,M層都是最基本的模塊(戲稱爲「原子劃分」),尤爲是Random;C層只依賴於M層,只有一個模塊,下降了耦合性;V層依賴於C層;其中M層的功能只暴露給C層,M層的Random模塊只暴露給M層的其餘模塊。這樣的話就知足了功能單一和下降耦合性的原則。爲了完善題目需求,添加了去重和求值模塊後端
軟件建模完成後,咱們又一塊兒討論了其中M層幾個模塊的具體實現方法:數組
因爲個人結對夥伴李同窗不擅長java,而我對Java情有獨鍾;因此通過商量,咱們決定用兩種語言開發一個軟件,分配任務以下:
(1)C、M層:李同窗採起c/c++編寫,李同窗是駕駛員,我是領航員;數據結構
(2)V層:即視圖層,採用java語言編寫;我是駕駛員,李同窗是領航員;架構
(3)測試:因爲前面李同窗編寫了兩層的大部分代碼,我只編寫了一層的代碼。所以我來設計測試用例。
補充:編程期間必要時候角色能夠互換一段時間,這樣能夠高效編程,作到人閒機不閒
操做系統 | window10 |
---|---|
JDK | 1.8.0_71 |
開發語言 | java,C++ |
開發工具 | eclipse Mars Release (4.5.0),Code Blocks |
單元測試工具 | Junit4.12,google test |
package site.yuanrui.four_arithmetic; import java.awt.EventQueue; import java.awt.FileDialog; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.border.EmptyBorder; import site.yuanrui.Tools.*; import javax.swing.JLabel; import javax.swing.JOptionPane; import java.awt.Font; import java.awt.Frame; import java.awt.Color; import javax.swing.JTextField; import javax.swing.JButton; import javax.swing.JCheckBox; import java.awt.event.ActionListener; import java.io.IOException; import java.awt.event.ActionEvent; import javax.swing.JTextArea; /** * 主窗口類 * @author YUANRUI * */ public class MainFrame extends JFrame { private JPanel contentPane; private JTextField textNum; private JTextField textCount; private JTextField textMax; /** * main函數入口 * @param args參數列表 */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { SubstanceTools.useSkin();//使用皮膚 SubstanceTools.useTheme();//使用主題 MainFrame frame = new MainFrame(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * 窗口建立函數 */ public MainFrame() { setTitle("小學四則運算自動生成程序"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setResizable(false); setBounds(100, 100, 437, 339); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); JLabel title = new JLabel("小學四則運算自動生成程序"); title.setForeground(Color.BLACK); title.setFont(new Font("幼圓", Font.BOLD, 13)); title.setBounds(128, 10, 171, 40); contentPane.add(title); JLabel lblNewLabel = new JLabel("題目數量:"); lblNewLabel.setBounds(10, 63, 66, 15); contentPane.add(lblNewLabel); textNum = new JTextField(); textNum.setBounds(70, 60, 66, 21); contentPane.add(textNum); textNum.setColumns(10); JLabel label = new JLabel("操做數個數:"); label.setBounds(144, 63, 85, 15); contentPane.add(label); textCount = new JTextField(); textCount.setBounds(215, 60, 66, 21); contentPane.add(textCount); textCount.setColumns(10); JLabel label_1 = new JLabel("最大數:"); label_1.setBounds(291, 63, 54, 15); contentPane.add(label_1); textMax = new JTextField(); textMax.setBounds(339, 60, 66, 21); contentPane.add(textMax); textMax.setColumns(10); JLabel label_2 = new JLabel("運算符選擇:"); label_2.setBounds(10, 100, 85, 15); contentPane.add(label_2); JButton OKbtn = new JButton("生成題目"); OKbtn.setBounds(57, 171, 126, 37); contentPane.add(OKbtn); JCheckBox checkBoxAdd = new JCheckBox("+"); checkBoxAdd.setBounds(84, 96, 47, 23); contentPane.add(checkBoxAdd); JCheckBox checkBoxSub = new JCheckBox("-"); checkBoxSub.setBounds(128, 96, 38, 23); contentPane.add(checkBoxSub); JCheckBox checkBoxMul = new JCheckBox("*"); checkBoxMul.setBounds(168, 96, 38, 23); contentPane.add(checkBoxMul); JCheckBox checkBoxDiv = new JCheckBox("/"); checkBoxDiv.setBounds(210, 96, 47, 23); contentPane.add(checkBoxDiv); JLabel labelDel = new JLabel("小數:"); labelDel.setBounds(10, 132, 45, 15); contentPane.add(labelDel); JCheckBox checkBoxDel = new JCheckBox("有"); checkBoxDel.setBounds(48, 128, 47, 23); contentPane.add(checkBoxDel); JLabel label_3 = new JLabel("負數:"); label_3.setBounds(168, 132, 47, 15); contentPane.add(label_3); JCheckBox checkBoxNeg = new JCheckBox("有"); checkBoxNeg.setBounds(210, 128, 54, 23); contentPane.add(checkBoxNeg); JLabel label_4 = new JLabel("括號:"); label_4.setBounds(301, 132, 44, 15); contentPane.add(label_4); JCheckBox checkBoxBra = new JCheckBox("有"); checkBoxBra.setBounds(339, 128, 38, 23); contentPane.add(checkBoxBra); JTextArea textAreaResult = new JTextArea(); textAreaResult.setBounds(10, 218, 411, 82); contentPane.add(textAreaResult); JButton buttonSave = new JButton("保存生成的題目"); buttonSave.setBounds(251, 171, 126, 37); contentPane.add(buttonSave); JScrollPane scrollPane = new JScrollPane(); scrollPane.setBounds(0, 187, 591, 98); contentPane.add(scrollPane); scrollPane.setViewportView(textAreaResult); /** * 生成題目點擊事件 */ OKbtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int number = 0; int max = 10; int operandNumber = 2; int decimal = 0; int negative = 0; int bracketint = 0; int opreation = 0; if (checkBoxDel.isSelected()) { decimal = 1; } if (checkBoxNeg.isSelected()) { negative = 1; } if (checkBoxBra.isSelected()) { bracketint = 1; } if (checkBoxDiv.isSelected()) { opreation+=1; } if (checkBoxMul.isSelected()) { opreation+=2; } if (checkBoxSub.isSelected()) { opreation+=4; } if (checkBoxAdd.isSelected()) { opreation+=8; } //參數驗證 try { number = Integer.parseInt(textNum.getText()); max = Integer.parseInt(textMax.getText()); operandNumber = Integer.parseInt(textCount.getText()); } catch (Exception e2) { e2.printStackTrace(); JOptionPane.showMessageDialog(null, "【題目數量、操做數、最大數格式錯誤,請從新輸入】", "參數格式錯誤", JOptionPane.ERROR_MESSAGE); System.out.println("【題目數量、操做數、最大數格式錯誤,請從新輸入】"); return; } if (number>1000||number<=0) { JOptionPane.showMessageDialog(null, "【題目數量範圍1~1000,請從新輸入】", "題目數量超出範圍", JOptionPane.ERROR_MESSAGE); System.out.println("【題目數量範圍1~1000,請從新輸入】"); return; } if (max>1000||max<=2) { JOptionPane.showMessageDialog(null, "【最大值範圍1~1000,請從新輸入】", "最大值超出範圍", JOptionPane.ERROR_MESSAGE); System.out.println("【最大值範圍1~1000,請從新輸入】"); return; } if (operandNumber>20||operandNumber<=1) { JOptionPane.showMessageDialog(null, "【操做數個數範圍2~20,請從新輸入】", "操做數個數超出範圍", JOptionPane.ERROR_MESSAGE); System.out.println("【操做數個數範圍2~20,請從新輸入】"); return; } if (opreation>15||opreation<=0) { JOptionPane.showMessageDialog(null, "【至少選擇一個運算符】", "運算符選擇錯誤", JOptionPane.ERROR_MESSAGE); System.out.println("【至少選擇一個運算符】"); return; } String result = ShellTool.execCmd("Four_operation "+number+" "+max+" "+operandNumber+" "+decimal+" "+negative+" "+bracketint+" "+opreation+" 0",null); System.out.println(number+" "+max+" "+operandNumber+" "+decimal+" "+negative+" "+bracketint+" "+opreation+" 0"); textAreaResult.setText(result); } }); /** * 保存題目點擊事件 */ buttonSave.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (textAreaResult.getText().isEmpty()) { JOptionPane.showMessageDialog(null, "【請先點擊生成題目】", "題目未生成", JOptionPane.ERROR_MESSAGE); return; } FileDialog openFile = new FileDialog(new Frame(), "另存爲", FileDialog.SAVE); openFile.setVisible(true); String dirName=openFile.getDirectory(); String fileName=openFile.getFile(); if(dirName==null || fileName==null){ return; } try { FileUtil.writeToFile(dirName+fileName+".txt",textAreaResult.getText()); } catch (IOException e1) { e1.printStackTrace(); System.out.println("文件寫入錯誤!!!"); } } }); } }
測試用例 | 參數 | 期待結果 |
---|---|---|
測試用例1 | 0 | 0 |
測試用例2 | 5 | 0~4 |
測試用例 | 參數 | 期待結果 |
---|---|---|
測試用例1 | 100,0 | 101 |
測試用例2 | 100,1 | 100,101 |
測試用例3 | 100,5 | 100,101 |
測試用例 | 參數 | 期待結果 |
---|---|---|
測試用例1 | 10,0,0 | 10之內的正整數 |
測試用例2 | 10,1,0 | 10,0,0 |
測試用例3 | 10,0,1 | 10之內的整數 |
測試用例4 | 10,1,1 | 10之內的浮點數 |
測試用例 | 參數 | 期待結果 |
---|---|---|
測試用例1 | {{12,8,10,4,20},{12,8,10,4,20}} | true |
測試用例 | 參數 | 期待結果 |
---|---|---|
測試用例1 | {{12,8,10,4,20} | 2 |
測試用例 | 參數 | 期待結果 |
---|---|---|
測試用例1 | 10, 100, 4, 0, 0, 0, 15, 0 | 10道100之內的加減乘除正整數運算題 |
李同窗是一個性格溫和的人,善於思考,作事認真,力求完美的人。在結對編程過程當中,對於同一個問題有本身的見解,可以指出我編程過程當中出現的bug。當我遇到問題時,能提供一些思路,能把本身的想法和見解說出來;李同窗也是一個善問的人,在我當駕駛員的時候,當看不懂的時候,提出疑問,正是由於這樣才使我經過講解對本身的算法瞭解更深。同時李同窗仍是一個友善的人,善於合做和與交流,在和他的合做學習和探討活動中,能選擇本身擅長的方式(好比記筆記,畫圖)表述他的想法,互相交流本身的想法,能傾聽和討論咱們兩我的之間不一樣的意見。感觸最深的是,李同窗在軟件設計討論中善於記筆記,這也是我從他身上學到的。記筆記方便後續的查看,也方便進一步討論理清思路。跟李同窗進行合做能體會到合做的愉快和合做的高效率。大概就是這些。
經過上一次結對編程之代碼審查,我經過對他的代碼進行了審查,並指出了一些不足,好比變量沒有初始化;變量命名方式簡單,不易讀;函數之間的大空間參數傳遞沒有用引用或者指針;重複的代碼塊未抽取等,在此次結對編程中李同窗對這幾個方面有特別的注意,並進行的改正。李同窗的代碼完整規範,有卓越的數據結構功底,這在他編寫求值模塊的過程當中能體會獲得;敲代碼速度快速,思惟廣闊,想法獨特有創新 。
經過結對編程實戰,對結對編程的理解更透徹,而後就是經過結對編程實戰使我從隊友學習了一些本身身上所沒有的東西。前面討論如何分工,其實在真正編程的時候,分工跟預想的並不徹底同樣,咱們首先討論出了軟件的具體架構,還有一些模塊的核心算法。在編程中,有些算法由於不合適,改進了一些。那些算法改進的話程序效率提升的最多。其中算法的主要代碼是咱們共同完成的,其中核心代碼是李同窗完成的,李同窗主要是編寫須要C語言編寫的M、C層部分,我主要負責V層代碼、測試和審查代碼。
零零散散歷經大約一週時間完成,只有經歷了才知道。就我的觀點談下結對編程的優缺點吧,首先說下好處。第一,能夠發散思惟,兩我的一個小時能討論出來的東西,或許一我的一個星期都無法想出來,畢竟兩我的看問題的角度不同。第2、邊編程邊複查,當一我的寫出一段代碼的時候,另外一我的做爲旁觀者每每更容易發現其中的問題,這就所謂「旁觀者清,當局者迷」。第3、在技術和性格互補的狀況下,能夠極大提升開發效率,達到1+1>2的效果,好比李同窗用C語言編寫後端代碼,我用java編寫前端視圖代碼。其次是缺點,最大的問題就是編程習慣問題,不一樣的代碼風格,在一塊兒工做時會產生麻煩,尤爲對於有強迫症的人;其次就是結對編程也容易滋生不良氣氛,敷衍了事。而後兩我的在一塊兒工做可能會出現工做精力不能集中的狀況。程序員可能會交談一些與工做無關的事情,反而分散注意力,致使效率比單人更爲低下;還有就是習慣了一我的敲代碼,當有我的在旁邊看着你敲,感受也挺彆扭,進而影響進度。讓我慶幸的是,在我和李同窗的結對編程中這些缺點不是很突出,多是性格和編程習慣各方面緣由。
以上就是我對本次結對編程的感想,總的說來,經過結對編程的收穫是很是大的,經過此次做業,不只學到了技術知識,並且更得到了許多寶貴的合做經驗,更收穫了深厚的友誼,期待下一次和李同窗的合做。