2016012032四則運算網頁版結對項目報告

1、測試的url地址及Coding.net地址javascript

可測試的url地址:http://39.105.6.214/myWeb_war/css

Coding.net源碼倉庫地址:https://git.coding.net/wanghz499/2016012032partnerWork.githtml

命令行測試command.java類(用到本身作的core.jar):前端

(注:請使用win+R命令提示符,不要使用PowerShell)
1.打開命令行進入src文件夾:
cd C:\Users\wangh\Desktop\2016012032partnerWork\src
(注意根據本身放的位置調整路徑,下同)

2.編譯command.java和core.jar:
javac -cp C:\Users\wangh\Desktop\2016012032partnerWork\web\WEB-INF\lib\core.jar -encoding utf-8 C:\Users\wangh\Desktop\2016012032partnerWork\src\Command.java
(-cp表示路徑,core.jar包放在web的WEB-INF的lib文件夾下)

3.運行command.java和core.jar,並輸入參數:
java -cp ..\web\WEB-INF\lib\core.jar; Command -n 10 -m 1 100 -o 5html5

運行成功,result.txt生成在與src同級的目錄下。java

 

2、估計項目開發時間react

    已記錄在結尾的PSP表格,此處不重複顯示。git

3、設計接口原則
web

   在設計接口以前,咱們應該明白接口是作什麼的,它有什麼設計原則,怎樣才能設計出好的接口。因而我去知乎上瀏覽了相關內容,有幾點是我印象比較深入的:算法

    1.職責單一化,不要想着作件大事,提供各類通用性,儘可能接口拆細,交給調用方本身去組合。

    這句話代表一個接口就是作一件事的,所以咱們在設計接口的時候要明確接口的做用,且做用不能普遍,應該清晰而單一。

    2.業務的獨立性,儘可能對外屏蔽你的業務細節,同時也對調用者更加友好。

    接口是提供給用戶調用的,所以最好將接口的信息隱藏,而用戶沒必要知道接口內的具體代碼實現。而在本次結對項目中,咱們的接口用戶就是本身,儘管如此,咱們也應該將它的具體實現隱藏起來,所以咱們最終會將接口作成一個core.jar包。

    3.拼寫要準確,接口函數一旦發佈就不能改了。函數最好是動賓結構doSomething,如openFilesetName站在使用者的角度去思考,API設計也要講究用戶體驗

    這些是接口命名的規範,接口的命名要能一眼就看出它的做用,這樣會有更好的用戶體驗。而且在設計接口時,要從使用者的角度出發,若是這個接口讓用戶以爲使用起來很複雜,那麼這就是個失敗的接口了。

 

4、計算模塊接口的設計與實現過程

    在設計接口前,我先分析了下這個接口的做用:產生必定數量的符合條件的式子。所以這個接口須要接收關於數量和條件限制的參數,分別是如下6個參數:題目數量n,數值下界downBound,數值上界upBound,最大運算符數largeOperatorCount,是否有乘除hasMulDiv,是否有括號hasBracket。

    首先,這個接口裏共有2個類:Creat類和Calculator類,前者做用是產生規定數量的式子,後者的做用是判斷某條式子是否符合條件。在Create類中,專門設計了一個方法generate()來接收並判斷上述6個參數正確性,隨後generate()方法再經過for循環調用n次createProblem()方法,createProblem()每次產生一條式子,在產生式子時createProblem()方法會調用Caculator類的algorithm()方法來預先計算這條式子的答案,因爲algorithm()方法是用的調度場算法和後綴表達式求值,所以能夠判斷當前式子在計算過程當中是否會產生小數、負數等,以此來達到篩選符合條件的式子的做用。這個接口最終返回的是一個裝滿符合條件式子的字符串數組。最後再考慮到接口信息隱藏的特性,將這兩個類封裝成了一個core.jar包,而後就能夠直接調用了。core.jar內部結構示意圖:

         

    實現的關鍵在於generate()接收的6個參數在以上各個方法之間的傳遞,如generate()調用createProblem()時會將6個參數都傳過去,隨後createProblem()根據參數進行條件判斷產生相應的式子;在createProblem()調用algorithm()時,會將數值下界downBound和上界upBound傳過去以篩選計算過程和最終結果都在數值範圍內的式子。

   

5、計算模塊接口部分的性能改進

    起初個人計算模塊只是稍微改了一下第一次我的做業的代碼,多接收了幾個參數而已。後來發現當限制的數值範圍比較小的時候,控制檯報棧溢出異常。我去網上搜才發現是遞歸調用過分,線程已滿致使程序崩潰。後來我檢查個人代碼的確好幾處都用了遞歸,好比當前生成的式子不知足條件時就再遞歸調用生成式子的createProblem方法,再如運算符下標數組只要所有同樣(即式子的運算符全同樣)我也會再遞歸調用index()方法從新生成一個下標數組,總之多處用到了遞歸。當數值範圍比較小時,生成的式子大可能是不知足條件的,因而會頻頻遞歸產生新式子,當運算符個數比較少時,下標數組也很容易同樣,會頻繁遞歸調用index()方法,最終致使程序跑不了。

    在知道是遞歸調用過分的緣由後,根據報錯信息我得知index()方法是程序中消耗最大的函數,因而我修改了index()方法,使其不使用遞歸。修改思路:當下標數組的前n-1個都同樣時,第n個必定與前n個不同,這樣就保證了下標數組至少有2個不一樣,即保證了一條式子至少有2中運算符。通過此次棧溢出異常後,我明白了遞歸要慎用,雖然它簡單,但它及可能會拖慢程序速度或使程序崩潰,我也是第一次意識到代碼性能分析的重要性。下面是效能分析的圖。

 

6、計算模塊部分單元測試展現

    我是用junit進行單元測試的。測試的類有Command類和Creat類

    Command類負責接收命令行的參數,而後再調用Creat類產生式子。測試的函數有主方法main()。構造測試數據時主要依據還沒被測到的代碼,哪一行代碼還未被執行,就輸入那行代碼相應的異常參數。將各類參數異常的狀況都測一遍,代碼覆蓋率就會逐步提升。Command類最終的代碼覆蓋率達到了97%:

Command類測試代碼:

import org.junit.Before;
import org.junit.Test;

public class CommandTest {
    @Before
    public void setUp() throws Exception {
        Command command = new Command();
    }

    @Test
    public void main() throws Exception {
        String[] args = {"-n","10","-m","1","999","-o","9","-c","-b"};
        Command.main(args);

        String[] args1 = {"-n","10","-m","1","999","-o","9"};
        Command.main(args1);

        String[] args2 = {"-n","10","-m","1","999"};
        Command.main(args2);

        String[] args3 = {"啦啦啦"};
        Command.main(args3);

        String[] args4 = {"-n","10","-m","110","999","-o","9"};
        Command.main(args4);

        String[] args5 = {"-n","10","-m","1","99999","-o","9"};
        Command.main(args5);

        String[] args6 = {"-n","10","-m","99","60","-o","9"};
        Command.main(args6);

        String[] args7 = {"-n","0","-m","99","60","-o","9"};
        Command.main(args7);

        String[] args8 = {"-n","a","-m","99","60","-o","9"};
        Command.main(args8);

        String[] args9 = {"-n"};
        Command.main(args9);

        String[] args10 = {"-n","3","-m","60","-o","9"};
        Command.main(args10);

        String[] args11 = {"-n","3","-m"};
        Command.main(args11);

        String[] args12 = {"-o","-2","-m"};
        Command.main(args12);

        String[] args13 = {"-o"};
        Command.main(args13);

        String[] args14 = {"-o","b"};
        Command.main(args14);

        String[] args15 = {"-m","1","999","-o","9"};
        Command.main(args15);

        String[] args16 = {"-n","10","-m","1","999","-o","9","-b"};
        Command.main(args16);

        String[] args17 = {"-n","10","-o","9","-c","-b"};
        Command.main(args17);

    }


}

 

    Creat類負責接收Command類傳來的各類條件參數,產生符合的題目數組。測試的函數有generate(),createProblem(),index(),構造測試數據時主要是按照函數的參數列表,根據參數個數和類型構造合適的測試數據。起初代碼覆蓋率只有70%多,緣由是不少if語句沒被執行,後來我又構造知足if判斷條件的參數進行測試,代碼覆蓋率便逐步提高。最終我把各類if語句的條件都測試到了,代碼覆蓋率達到了100%:

    Creat類測試代碼:

import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;

public class CreateTest {
    private Create create;
    @Before
    public void setUp() throws Exception {
         create = new Create();

    }

    @Test
    public void generate() throws Exception {
        create.generate(10,10,100,3,true,true);
        create.generate(10,100,10,12,true,true);
        create.generate(10,10,1000,12,true,true);
        create.generate(10,1,10000,8,true,true);
        create.generate(10,101,1000,8,true,true);
        create.generate(0,1,1000,8,true,true);
        create.generate(10,1,1000,8,true,true);
        create.generate(10,1,1000,8,false,true);
        create.generate(10,1,1000,8,true,false);
        create.generate(10,1,1000,8,false,false);

    }

    @Test
    public void createProblem() throws Exception {
        create.generate(10,1,1000,8,true,true);
        create.generate(10,1,1000,8,false,true);
        create.generate(10,1,1000,8,true,false);
        create.generate(10,1,1000,8,false,false);

    }

    @Test
    public void index() throws Exception {
        create.index(3,4);

    }

}

 

 

7、計算模塊部分異常處理說明   

    計算模塊共需接收的參數有6個,異常都圍繞這6個參數展開。

   1.關於題目數量n的參數異常有3種:數量範圍越界、未輸入題目數量和非法字符輸入。

 

case "-n": {
                    try {
                        n = Integer.parseInt(args[i + 1]);
                        if (n < 1 || n > 10000) {
                            System.out.println("對不起,題目數量只能是1-10000!");
                            return; //結束運行
                        }
                    } catch (ArrayIndexOutOfBoundsException e) { //未輸入數字時args[i+1]會數組越界
                        System.out.println("未輸入題目數量!");
                        return;
                    }catch (NumberFormatException e) { //輸入非數字字符等
                        System.out.println("對不起,題目數量只容許輸入1-10000的數字!");
                        return; //結束運行
                    }

                    break;
                }

 

    單元測試樣例:

@Test
    public void main() throws Exception {
        String[] args7 = {"-n","0","-m","99","60","-o","9"};
        Command.main(args7);

        String[] args8 = {"-n","a","-m","99","60","-o","9"};
        Command.main(args8);

        String[] args9 = {"-n"};
    }

    2.關於數值上下界的異常有4種:數值下界大於上界、數值上下界沒有在相應規定的範圍、未輸入數值上下界、非法字符輸入。

case "-m": {
                    try {
                        downBound = Integer.parseInt(args[i + 1]);
                        upBound = Integer.parseInt(args[i + 2]);
                        if (downBound >= upBound) {
                            System.out.println("數值下界不能大於等於上界!");
                            return;
                        } else if (downBound < 1 || downBound > 100 || upBound < 50 || upBound > 1000) {
                            System.out.println("數值下界只能是1-100,數值上界只能是50-1000!");
                            return;
                        }

                    } catch (ArrayIndexOutOfBoundsException e) {
                        System.out.println("未分別輸入數值上下界!");
                        return;
                    }catch (NumberFormatException e) {
                        System.out.println("對不起,數值上下界只容許數字格式!");
                        return;
                    }

                    break;
                }

    單元測試樣例:

 @Test
    public void main() throws Exception {
        String[] args6 = {"-n","10","-m","99","60","-o","9"};
        Command.main(args6);

        String[] args11 = {"-n","3","-m"};
        Command.main(args11);

        String[] args4 = {"-n","10","-m","110","999","-o","9"};
        Command.main(args4);

        String[] args18 = {"-n","10","-m","hhh","kkk","-o","9"};
        Command.main(args18);
  

    3.關於最大運算符數量的異常3種:不在規定範圍、未輸入、非法輸入

case "-o": {
                    try {
                        largeOperatorCount = Integer.parseInt(args[i + 1]);
                        if (largeOperatorCount < 1 || largeOperatorCount > 10) {
                            System.out.println("對不起,運算符數量只能是1-10!");
                            return;
                        }
                    } catch (ArrayIndexOutOfBoundsException e) {
                        System.out.println("未輸入最大運算符數量!");
                        return;
                    }catch (NumberFormatException e) {
                        System.out.println("對不起,運算符數量只容許輸入1-10的數字!");
                        return;
                    }

                    break;
                }

    單元測試樣例:

 

 @Test
    public void main() throws Exception {
        String[] args12 = {"-o","-2","-m"};
        Command.main(args12);

        String[] args13 = {"-o"};
        Command.main(args13);

        String[] args14 = {"-o","b"};
        Command.main(args14);
    }

 

4.什麼相關的參數都沒輸,只輸非法字符等:

if (n == 0 && downBound == 0 && upBound == 0) {
            System.out.println("參數格式有誤!");
            return;
        } else if (n == 0) {
            System.out.println("未輸入題目數量!");
            return;
        } else if (downBound == 0 || upBound == 0) {
            System.out.println("未分別輸入數值上下界!");
            return;
        }

    單元測試樣例:

 

@Test
    public void main() throws Exception {
        String[] args3 = {"啦啦啦"};
        Command.main(args3);
    }

 

 

8、界面模塊的詳細設計過程

    本次項目是運用jsp+servlet作的四則運算網頁版,jsp負責視圖層,servlet負責邏輯業務處理。所以前端界面都是在jsp寫的(結合了html\css\javaScript)。因爲實現了附加功能的多個用戶並能查看答題歷史記錄,所以會有用戶登陸註冊、修改密碼、查看歷史答題等頁面。

1.用戶登陸界面:有判空、識別用戶不存在和密碼錯誤等功能。界面採用了小學生喜歡的風格。

2.註冊頁面:有判斷用戶名已存在、兩次密碼輸入不一致的功能。

3.出題大廳界面:用戶在此能夠設定出題條件。文本框採用了html5的number類型,保證用戶只能輸入限定範圍的數字。

題目數量:<input placeholder="1-10000" type="number" min="1" max="10000" name="n"/>
數值範圍:<input placeholder="1-100" type="number" min="1" max="100" name="downBound"> -
<input placeholder="1-100" type="number" min="50" max="1000" name="upBound">

 

4.點擊開始出題,會跳到result.txt文件下載頁面:

5.點擊下載:

6.下載完後,點擊開始作題,進入答題界面:此頁面有計時器。

7.答完題後,點擊提交,進入成績反饋界面:會顯示答對多少題,答錯多少題,所用時長,以及錯題卡片(包含錯題與正確答案),可供孩子鞏固複習。

8.隨後點擊查看歷史答題記錄,進入歷史答題界面:能夠看到剛剛的答題已經呈如今歷史列表裏。此頁面會按時間前後順序展現以往的答題記錄,並會顯示歷史最佳成績,還可顯示該練習的類型是系統產生仍是用戶本身上傳的。

9.點擊其中一條答題記錄,查看該次練習的詳情。點擊橙色下拉按鈕可查看具體答題記錄(作對和作錯的題都顯示)。再點擊按鈕可收起,此效果由javascript實現。

<script language="javascript" type="text/javascript">
    function aaa(){
        if(document.getElementById("contentTable").style.display == 'none')
        {document.getElementById("contentTable").style.display='';}
        else
        {document.getElementById("contentTable").style.display='none';}
    }
</script>

 

10.點擊側欄「上傳題目」,用戶可上傳本身的題目進行答題:這裏有個文件格式限制,若上傳正確格式文件,會出現一個開始答題按鈕;若上傳錯誤格式的文件開始答題的按鈕是不會出現的。此效果是經過javascript識別後臺傳來el表達式的值實現的。

<script type="text/javascript">
    var msg = "${msg}";
    if(msg=='題目上傳成功!'){
        document.getElementById('begin').style.display="inline-block";
    }else {
        document.getElementById('begin').style.display="none";
    }
</script>

 

11.點擊開始答題就會進入答題界面,題目內容是用戶本身上傳的題。界面與上述答題界面同樣就不展現啦。

12.修改密碼界面:要求輸入原密碼與新密碼。有原密碼輸入錯誤判斷,有必定安全性。

13.點擊退出帳號,退回登陸頁面並顯示退出成功。

 

 

9、界面模塊與計算模塊的對接

    界面模塊與計算模塊的對接即jsp與servlet的對接。因爲計算模塊已經封裝好了,servlet只需調用計算模塊的Create類產生題目,將答案存於另外一個數組中,並將題目置於ArrayList中利用request.setAttribute()傳給jsp,在jsp中利用jstl標籤<c:foreach>循環列出。用戶答完題後經過Form表單將答案傳給servlet,servlet用一個數組接收用戶答案,再將用戶答案數組與正確答案數組對比,便可判斷對錯。

    相關代碼以下:

 

/**
     * 生成題目
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    private void create(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException
    {
        int n = Integer.parseInt(request.getParameter("n"));
        int downBound = Integer.parseInt(request.getParameter("downBound"));
        int upBound = Integer.parseInt(request.getParameter("upBound"));
        int MulDiv = Integer.parseInt(request.getParameter("hasMulDiv"));
        int Bracket = Integer.parseInt(request.getParameter("hasBracket"));
        int largeOperatorCount = Integer.parseInt(request.getParameter("largeOperatorCount"));

        RequestDispatcher rd;
        if(downBound>=upBound){
            request.setAttribute("msg","數值下界不能大於上界!");
            rd = request.getRequestDispatcher(WebContents.MAIN);
            rd.forward(request,response);
        }

        boolean hasBracket = false;
        boolean hasMulDiv = false;
        if(Bracket==1){
            hasBracket=true;
        }
        if(MulDiv==1){
            hasMulDiv=true;
        }

        //將生成的result.txt放在web/file下
        Create create = new Create();
        String[] result = create.generate(n,downBound,upBound,largeOperatorCount,hasMulDiv,hasBracket);

        //將題目(不含答案)存入session
        String[] question = new String[n];
        for(int i=0;i<n;i++){
            int index = result[i].indexOf("=");
            question[i]=result[i].substring(0,index);
        }
        request.getSession().setAttribute("question",question);

        //將正確答案存入session
        String[] realAnswer = new String[n];
        for(int i=0;i<n;i++){
            int index = result[i].indexOf("=");
            realAnswer[i]=result[i].substring(index+1);
        }
        request.getSession().setAttribute("realAnswer",realAnswer);


        MakeFile2 makeFile2 = new MakeFile2();
        String path = request.getSession().getServletContext().getRealPath("file")+"/";
        File f = new File(path); //文件夾也是個文件
        if(!f.exists()){
            f.mkdirs();  //若是該文件夾不存在,則建立該文件夾
        }
        String fileName = UUID.randomUUID()+"result.txt";
        File file = makeFile2.creatFile(result,path+fileName);

        //將該練習存入數據庫
        String relativePath = "../../../file/"+fileName;
        User user = (User) request.getSession().getAttribute("user");
        int userId = user.getId();
        String creatType = "系統產生";
        PracticeDao practiceDao = new PracticeDaoImpl();
        Practice practice = new Practice(relativePath,creatType,userId);
        practiceDao.insertPractice(practice);
        Practice practice1 = practiceDao.selectPracticeByPath(relativePath);
        request.getSession().setAttribute("practiceId",practice1.getId());

        request.setAttribute("filepath",path+fileName);
        request.getSession().setAttribute("file",file);
        request.setAttribute("n",n);

        rd = request.getRequestDispatcher(WebContents.DOWNLOAD);
        rd.forward(request,response);
    }

/**
     * 開始答題(返回題目內容)
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    private void begin(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
        File file = (File)request.getSession().getAttribute("file");
        int n = Integer.parseInt(request.getParameter("n"));
        ReadFile readFile = new ReadFile();
        List<Problem> list= readFile.getFileContent(file,n);
        request.setAttribute("list",list); //將讀的文件內容賦給list,給前臺遍歷
        request.setAttribute("n",n);
        RequestDispatcher rd;
        rd = request.getRequestDispatcher(WebContents.BEGIN);
        rd.forward(request,response);

    }

 /**
     * 檢查用戶答案
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    private void check(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
        String timelong = request.getParameter("timelong");
        System.out.println(timelong);

        int n = Integer.parseInt(request.getParameter("n"));
        String[] userAnswer = new String[n];
        for(int i=0;i<n;i++){
            userAnswer[i] = request.getParameter("s"+i); //得到用戶答案
        }

        String[] question = (String[]) request.getSession().getAttribute("question");
        String[] userContent = new String[n];
        for(int i=0;i<n;i++){
            userContent[i]=question[i]+"="+userAnswer[i];
        }

        String[] realAnswer = (String[])request.getSession().getAttribute("realAnswer");

        int correctCount=0;
        int wrongCount=0;

        List<FeedBack> feedBackList = new ArrayList<>(); //答錯的題+正確答案

        for(int i=0;i<n;i++){
            if(!userAnswer[i].equals(realAnswer[i])){
                wrongCount++;
                String a = userContent[i];
                String b =  realAnswer[i];
                FeedBack feedBack = new FeedBack(a,b);
                feedBackList.add(feedBack);
            }else correctCount++;
        }


        String[] wrongProblem = new String[feedBackList.size()];
        String[] correctAnswer = new String[feedBackList.size()];
        for(int i=0;i<feedBackList.size();i++){
            wrongProblem[i] = feedBackList.get(i).getWrongUserContent();
            correctAnswer[i] = feedBackList.get(i).getCorrectAnswer();
        }


        //將這次練習信息存入數據庫
        int practiceId = (int)request.getSession().getAttribute("practiceId");
        Practice practice = new Practice(practiceId,Arrays.toString(wrongProblem),Arrays.toString(correctAnswer),Arrays.toString(userContent),correctCount,wrongCount,timelong);
        PracticeDao practiceDao = new PracticeDaoImpl();
        practiceDao.updatePractice(practice);

        request.setAttribute("correctCount",correctCount);
        request.setAttribute("wrongCount",wrongCount);
        request.setAttribute("timelong",timelong);
        request.setAttribute("feedBackList",feedBackList);

        RequestDispatcher rd;
        rd = request.getRequestDispatcher(WebContents.FEEDBACK);
        rd.forward(request,response);

    }

 

    因爲實現了用戶功能,因此這次項目用到了數據庫,數據庫中有2張表——用戶表和練習題表。

                             

 

        整個項目結構以下:

                          

其中entity是實體,dao層負責數據庫的鏈接實現數據的增刪改查,servlet負責業務邏輯處理,sql封裝了全部用到的sql語句,util是servlet須要用到的的一些工具類,test放着全部的測試類(包括增刪改查方法測試、計算模塊Create類測試、命令行測試),web的WEB-INF下放着jar包和jsp等。

   

10、結對過程描述

    個人結對小夥伴是鄧旭,因爲她要參加省運會,所以上週她都在進行高強度的訓練並參加最終的比賽,沒有時間和我一塊兒作項目啦,因此這個項目大部分是我完成的。好在咱們提前商量一致決定作網頁版,肯定目標後首先開始修改上一次做業的計算模塊,隨後就開始定製網頁版的需求,設計數據庫開始寫jsp和servlet.整個項目製做持續了一個多星期。鄧旭比賽回來後,項目也正好作完,她很積極主動地找我想看看這個項目,因而我就詳細地將整個項目的實現過程向她介紹了一遍,從數據庫的設計、到代碼底層與數據庫的鏈接再到jsp與servlet的交互,在給她講的過程當中我對整個項目的結構與實現更加清晰了,她也會時不時地詢問一些細節的問題好比界面的友好設計,有問題的地方我就會進行相應的修改,至關於代碼複審了。

    項目肯定最終版本後,咱們將項目放到了本身的阿里雲服務器上,因爲是第一次接觸雲服務器,將這個項目放上去可謂是一波三折,在購買雲主機、配置雲主機上就花了不少時間、查閱了不少博客。將項目放到雲主機後,起初加載不出圖片和樣式,查了好久最後發現是路徑的問題。當咱們在本身的瀏覽器經過url地址成功訪問項目時,咱們心中的喜悅是無與倫比的。最後,咱們兩個一塊兒完成了博客。

               

11、結對編程的優缺點

      優勢:我以爲結對編程的優勢在於2我的會互相督促,加快項目進度,並且由於都不想拖後腿,因此態度會很積極。當遇到困難時,兩我的共同面對會使心理壓力小不少,會下降對bug和其餘技術困難的畏懼。因爲結對編程時每一行代碼都由兩我的思考過,所以出錯和修改代碼的概率會小不少,從而提升編程效率。最重要的是,結對編程可以加深兩我的的友誼,以爲對方就是與本身共患難的戰友。

    缺點:結對編程最大的缺點就是兩我的的工做量不一致,極可能會出現一人奮鬥、一人打醬油的局面。若是在不少小問題上沒溝通好兩人容易發生矛盾。

    我對鄧旭的評價:優勢是態度很積極,並且很謙虛,會傾聽個人建議,老是給人帶來正能量,會鼓勵支持我。缺點就是此次去參加比賽,沒能和我一塊兒敲大部分的代碼,不過這也沒辦法呀,省運會比較重要,我很理解~總之此次與鄧旭一塊兒的結對項目仍是比較愉快的!

 

12、PSP

 

SP2.1

任務內容

計劃共完成須要的時間(h)

實際完成須要的時間(h)

Planning

計劃

74.5

108.5

·        Estimate

·   估計這個任務須要多少時間,並規劃大體工做步驟

1

1

Development

開發

67.5

98.5

·        Analysis

·         需求分析 (包括學習新技術)

3

5

·        Design Review

·         代碼設計

4

5

·        Coding Standard

·         代碼規範 (爲目前的開發制定合適的規範)

0.5

0.5

·        Design

·         具體設計

3

5

·        Coding

·        在計算模塊花費的時間

          在UI模塊花費的時間

          在後臺處理模塊花費的時間

15

10

30

20

10

40

·        Code Review

·         代碼複審

2

3

·        Test

·         測試(自我測試,修改代碼,提交修改)

2

10

Reporting

報告

6

9

·         Test Report

·         測試報告

5

8

·         Size Measurement

·         計算工做量

0.5

0.5

·         Postmortem & Process Improvement Plan

·         過後總結, 並提出過程改進計劃

0.5

0.5

 

十3、總結

    爲了完成此次項目,我過去一個多星期的時間除了吃飯睡覺上課,其他的每分每秒幾乎都花在了這個項目上。過程雖然很辛苦,但收穫確實是很大,我學到了不少新的東西。感觸比較深的是對javascript這門語言的認識了,我是個作javaweb後端的,之前沒怎麼寫過js,可是此次項目組沒有前端的小夥伴,因此我就本身寫前端頁面了,在寫的過程當中會遇到不少前臺頁面的事件處理,我想實現某個功能可我不會寫相應的前臺代碼,因此我就去百度搜,就這麼一步步認識了javascript,它是門很棒很方便的語言。其中在將前臺用戶的答案傳給後臺時js幫了我很大的忙,未知的多個循環出的input框要判空後才能傳給後臺,這就是利用js實現的。

    還有一項感觸比較深的要屬雲服務器的配置了,之前歷來沒接觸過。此次我用的是阿里雲,果真實際操做和想象中的同樣難,對於我這個服務器小白來講把項目放在雲主機的過程十分地艱辛。可是這個過程讓我受益不淺,我知道了什麼是雲服務器,它有個雲主機,就像咱們普通的電腦同樣能夠遠程操控,真的是個神奇的東西,十分佩服開發雲服務的團隊。項目完成後將其打成war包放在雲主機tomcat的webapps下,再啓動tomcat就能夠在其餘電腦經過url訪問本身的項目了!

    最後,作完此次項目我有一種更上一層樓的感受,真的學到了不少,內容很豐富,也嘗試了不少從何嘗試過的東西,這些東西給我帶來驚喜和快樂。學習就是一件痛苦並快樂的事情。我始終堅信這麼簡單的一句話:世上無難事,只怕有心人。加油!

相關文章
相關標籤/搜索