軟件工程結對項目:四則運算web

 

1)Coding.Net項目地址

https://git.coding.net/DandelionClaw/WEB_Calculator.git

注:本項目爲web端,而且須要鏈接SQL Server數據庫。javascript

可以使用已註冊用戶名:admin 密碼:「admin」登陸,或註冊新用戶登陸。css

首頁目錄/WEB_Calculator/mysite/WebRoot/index.jsphtml

  隊友:顧思宇 2016011993(後端 領頭羊)

   我 :程  羚 2016012050(前端 小羊) 

隊友博客:http://www.cnblogs.com/DandelionClaw/p/8759867.html


 

2)PSP表格

估計將在程序的各個模塊的開發上耗費的時間)

  注:計劃時間與實際用時融合在了一張表格上前端

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

3)接口設計說明

看教科書和其它資料中關於Information Hiding, Interface Design, Loose Coupling的章節,說明大家在結對編程中是如何利用這些方法對接口進行設計的。(3')java

Information Hiding : 信息隱藏。在此次結對編程中,咱們把計算核心和輸入輸出處理所有封裝在core模塊中,經過接口將core模塊和外界聯繫起來,但具體的實現和錯誤處理都被隱藏在模塊中。jquery

Interface Design : 因爲和結對隊友所用語言不一樣,咱們之間的對接相當重要,咱們定義了一套公共的接口,極大程度的方便了各個模塊之間的通信。git

Loose Coupling : 鬆耦合,經過模塊的封裝減小了經過接口鏈接的各個模塊的影響。web

 


 

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

設計包括代碼如何組織,好比會有幾個類,幾個函數,他們之間關係如何,關鍵函數是否須要畫出流程圖?說明你的算法的關鍵(沒必要列出源代碼),以及獨到之處。(4')ajax

我主要負責前端,核心算法這一塊主要是隊友在作,算法

在計算模塊,我主要負責了:未輸入結果時防止跳轉並進行相應提示,以及最終結果界面對接

 

 

 


 

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

記錄在改進計算模塊性能上所花費的時間,描述你改進的思路,並展現一張性能分析圖,並展現你程序中消耗最大的函數。(4')

 

在性能改進這一塊我花費了大約2小時,除了將本來的命令行程序擴展命令格式之外,我還優化了字符串存儲方式,詳細內容以下:

 當輸入參數爲時 效能分析圖爲

經分析String內存佔用較大,緣由是由於我用一個String存儲了所有的算式而且沒有釋放內存,優化代碼後性能明顯改善了許多。

另外我還發現了一個有趣的現象,當代碼執行完成後,內存並無釋放而是疊加了起來,如圖所示:

當題目爲50時內存變化,以後內存不斷攀升達到必定數值後穩定下來。

當我再次輸入50時,內存變化

經研究發現這是由於java特殊的內存釋放機制所致使的。


 

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

展現出項目部分單元測試代碼,並說明測試的函數,構造測試數據的思路。並將單元測試獲得的測試覆蓋率截圖,發表在博客中。只須要測試命令行部分,且該部分覆蓋率到90%以上,不然單元測試部分視做無效。(6')

 

個人測試思路是測試全部的正常和異常狀況,確保程序可以正常運行。

複製代碼
    @Test
    public void testMain(){//本函數爲正確輸入形式,並打亂了命令輸入順序
        String[] args = {"-o","2","-n","20","-c","-b","-m","1","100"};
        command.main(args);
    }
    @Test
    public void testMain1(){//本函數只正確輸入了-n命令,但沒有輸入另外一個必須輸入的命令-m
        String[] args = {"-n","20"};
        command.main(args);
    }
    @Test
    public void testMain2(){//本函數測試不輸入任何命令的狀況
        String[] args = {};
        command.main(args);
    }
    @Test
    public void testMain3(){//本函數測試輸入了必須輸入的-n、-m命令,但-m命令少輸入了一個參數
        String[] args = {"-n","20","-m","1"};
        command.main(args);
    }
    @Test
    public void testMain4(){//本函數測試輸入錯誤命令
        String[] args = {"aaaa"};
        command.main(args);
    }
    @Test
    public void testMain5(){//本函數測試輸入了-n命令,但缺乏了參數
        String[] args = {"-n"};
        command.main(args);
    }
    @Test
    public void testMain6(){//本函數測試輸入了-0命令,但缺乏了參數
        String[] args = {"-o"};
        command.main(args);
    }
    @Test
    public void testMain7(){//本函數測試輸入了必須輸入的-n、-m命令,但-n參數範圍錯誤
        String[] args = {"-n","1000000","-m","1","100"};
        command.main(args);
    }
    @Test
    public void testMain8(){//本函數測試輸入了必須輸入的-n、-m命令,但-n參數類型錯誤
        String[] args = {"-n","aaa","-m","1","100"};
        command.main(args);
    }
    @Test
    public void testMain9(){//本函數測試輸入了必須輸入的-n、-m命令,但-m參數範圍錯誤
        String[] args = {"-n","10","-m","100","50"};
        command.main(args);
    }
    @Test
    public void testMain10(){//本函數本函數測試輸入了必須輸入的-n、-m命令,但-o參數範圍錯誤
        String[] args = {"-n","10","-m","1","100","-o","-100"};
        command.main(args);
    }
複製代碼

 

 11個測試函數均運行正確

覆蓋率達到了90%以上

 


 

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

在博客中詳細介紹每種異常的設計目標。

每種異常都要選擇一個單元測試樣例發佈在博客中,並指明錯誤對應的場景。(5')

我負責的主要有:

1.js提示:main界面定製題目時,不可有非正常輸入,

 

 

核心jquery代碼

 

2.js:index界面登陸時,對未註冊用戶攔截,組織頁面跳轉

這裏只貼出核心的代碼:

// 判斷用戶名密碼的js
//數據庫通常存儲的密碼是md5格式,判斷密碼是否正確時,先將密碼轉爲md5格式,再判斷;(轉md5格式,先引用md5js,再寫hex_md5("2121212") 便可)
$(function() {
     //根據localStorage中是否有值,判斷用戶是否登陸過
        if(window.localStorage){  //用戶登陸過
            var name1 = localStorage.getItem("usename"); //獲取存儲的用戶名
            var pwd1 = localStorage.getItem("pwd");        //獲取存儲的密碼
            $("input[name=usename]").val(name1);         //用戶名賦值 
            $("input[name=pwd]").val(pwd1);                //密碼賦值
        }else{ 
            $("input[name=usename]").val("");
            $("input[name=pwd]").val("");
        }
    })
  //點擊登陸按鈕
    $('#btnYes').click(function (event) {        
        if($("input[name=usename]").val()=="") {  //用戶名爲空時
            $(".mixfirm").show();
            mixfirm("用戶名不能爲空");
            setTimeout(function() {
                $(".mixfirm").hide();
            },1000);
            return false;
        }
        if($("input[name=pwd]").val()=="") {  //密碼爲空
            $(".mixfirm").show();
            mixfirm("密碼不能爲空");
            setTimeout(function() {
                $(".mixfirm").hide();
            },1000);
            return false;
        }

        var list1 = $("input[name=usename]").val();   //獲取當前輸入的用戶名,根據用戶名查SQL
        sql("select * from Users where usename='"+list1+"'",function(data) {
            if(data!=null) {  //若是用戶名存在
                var ps1 = data.pwd;  //獲取數據庫密碼
                var ps2 = hex_md5($("input[name=pwd]").val());   //獲取輸入的密碼,並轉成md5格式
                if(ps1 == ps2) {  //若是輸入的密碼正確,執行loginAfter方法
                    //用ttyu平臺獲取全部用戶的信息的方法,能夠在此寫SQL直接查數據庫
            $("#form1").send({ table: "Users", action: "login", backAfter: "loginAfter" });
                }else {  //密碼錯誤,彈框提示
                    $(".mixfirm").show();
                    mixfirm("密碼錯誤");
                    setTimeout(function() {
                        $(".mixfirm").hide();
                    },1000);
                    return false;
                }
                
            }else{  //用戶名不存在
                $(".mixfirm").show();
                mixfirm("該用戶不存在");
                setTimeout(function() {
                    $(".mixfirm").hide();
                },1000);
                return false;
            }
            
        })
    });
    //登陸回調函數
    function loginAfter(result) {  //result -- 全部用戶信息
        try {
            ttyu.user.saveUser(result);  //當前用戶信息
            var names = $("input[name=usename]").val();  //獲取輸入的用戶名
            var pwds = $("input[name=pwd]").val();         //獲取輸入的密碼
            localStorage.setItem("usename",names);       //本地存儲
            localStorage.setItem("pwd",pwds); 
           // location = "index.html";                       //跳轉到首頁面
        } catch (e) { 
            firm(result);
        }
    }

  

 


 

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

在博客中詳細介紹界面模塊是如何設計的,並寫一些必要的代碼說明解釋實現過程。(5')

界面模塊設計:(用圖更清晰~)

 

實現過程:

1. index.jsp 登錄界面

註冊頁面與之相像

2. main.jsp

html代碼相對簡單,用了css+jquery進行美化

界面圖見        12)附加功能版塊

3. replyonline.jsp

 利用數據庫+servlt 實現了逐個答題功能,並加上了異常處理。比較喜歡在這個界面作的button按鈕,在下面給出了button按鈕的css樣式,喜歡的能夠採納

 

button{
  margin: 20px;
}
button a{
  color: black;
}
.button{
  margin:60px 220px;
  margin-top: 60px;
}
.bt{
  -webkit-transition: all 300ms cubic-bezier(0.19, 1, 0.22, 1);
  transition: all 300ms cubic-bezier(0.19, 1, 0.22, 1);
  -webkit-transform: translateX(47px);
  will-change: transform;
  z-index: 3;
  overflow: hidden;
  border-radius: 40px;
  padding: 12px 15px;
  background: #43CB9D;
  color: white;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 1px;
  line-height: 1;
  text-transform: uppercase;
}
.bt:before {
  -webkit-transition: opacity 300ms ease-out, -webkit-transform 0ms 300ms;
  transition: opacity 300ms ease-out, -webkit-transform 0ms 300ms;
  transition: opacity 300ms ease-out, transform 0ms 300ms;
  transition: opacity 300ms ease-out, transform 0ms 300ms, -webkit-transform 0ms 300ms;
  opacity: 0;
  -webkit-transform-origin: center center;
          transform-origin: center center;
  -webkit-transform: scale(0);
          transform: scale(0);
  will-change: transform, opacity;
  content: "";
  display: block;
  z-index: -1;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #3FE2D9;
  border-radius: 40px;
}
.bt{
  float: left;
}

  

 提交結果頁面與之類似,在上面的gif圖裏能夠看見效果。

 


 

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

詳細地描述UI模塊的設計與兩個模塊的對接,並在博客中截圖實現的功能。(4')

 

(1)UI設計

咱們如今紙上完成了基本的UI 界面設計,而後由我負責實現和美化,詳細內容在8.中都已說明。

(2)先後端對接

我採用servlet+JavaBean+form表單的方法將先後端聯繫起來。

例如在產生算式時,用form表單將用戶輸入的參數獲取至servlet,將命令行程序import進servlet中,使用接口調用命令行程序產生算式。而後將生成的算式保存至數據庫中,再在前端使用JavaBean連接數據庫,把算式輸出到前端。用戶註冊、答題等同理。

 

(3)功能展現

①登陸和註冊功能:

    

②附加功能1 多語言功能:

③題庫生成功能,若參數錯誤先後端均提供了異常處理,前端顯示提示並使得表單沒法提交,後端throw catch處理異常。

④作題功能,計時功能,本次正確率統計功能,錯題展現功能

⑤附加功能2 分用戶歷史作題記錄展現,並顯示最佳記錄

 


 

10)結對過程

  咱們小隊分工比較明確,隊友主要負責後端,我主要負責前端。隊友爲咱們小組的領航員~

咱們的第一步:選擇了隊友的第一次做業代碼,隊友在本來的基礎上面進行更改,我開始作基本的前端頁面。咱們先本身作本身的,在各自擅長的領域奮鬥前行~

咱們的第二步:隊友開始寫單元測試,我繼續美化咱們的web界面,咱們對web界面有比較高的要求,一致認爲好的界面是吸引用戶的最好手段!

咱們的第三步:初步先後端合體,實現一些基本功能,如:題目定製,在線答題,輸出結果……由於咱們是舍友,進行交流也比較方便,雖然出過一些bug,可是也很快就解決了。開心

咱們的第四步:一塊兒爲模塊增長異常處理,主要爲「生成算式數量」異常和登陸異常,在覈心模塊寫入後,咱們又考慮到用戶體驗,使用jQuery撰寫了相應的及時提醒以及防止跳轉,雙重保障更貼心呢!

咱們的第五步:檢查整個項目,並進行優化。

 

 

← 隊友:顧思宇(大佬)     :         我(小弟)→

 


 

 

11)結對編程的優勢和缺點

看教科書和其它參考書,網站中關於結對編程的章節,例如:

http://www.cnblogs.com/xinz/archive/2011/08/07/2130332.html

說明結對編程的優勢和缺點。同時指出結對的每個人的優勢和缺點在哪裏 (要列出至少三個優勢和一個缺點)。(5')

結對編程的優勢:

        1. 在此次結對項目中,個人隊友擔任的是領航員的角色,咱們各有所長,且把這份長處最大化。因此我以爲結對編程最大的好處在於1+1>2,作出的項目會更加的完美。

        2. 在編程中,相互討論,能夠更快更有效地解決問題。好比在此次項目中,咱們在作jQuery表單驗證時,防止頁面跳轉的點怎麼也作不出來,嘗試過百度給的全部解決方法,大晚上把全部宿舍串了一遍也沒

          解決,而後有天閒聊,聊着聊着就聊出了一個新的方法。也驗證了那句,語言是思惟碰撞的開始。

        3. 最深有感觸的一點:bug解決的更快了

結對編程的缺點:

  1. 對於有不一樣習慣的同窗,在一塊兒編程可能會有比較多的麻煩,致使效率底下。
  2. 部分人可能更適合我的編程,而不習慣在編碼的時候還要應對他人的感覺,甚至致使1+1<1

我可愛的隊友:優勢1. 能力強,有責任心

       優勢2. 人真的真的好,在編程的過程當中對我關照有加,

       優勢3. 有耐心,在我調bug調到崩潰的適合,她會繼續調。。(簡直全世界最好的老顧顧)

       缺點:太好了。太棒了,棒到我快開心死!會以爲本身拖了她的後腿...

   


 

12)附加題!!!

1、 多語言支持

 

 

實現原理:經過jquery+ajax實現。核心思想是經過i18n屬性設置多語言的key,而後插件對全部帶i18n屬性的dom進行掃描處理。可是前端多語言並不只僅是這一個需求,進而延伸的還有事件函數中須要使用的消息,好比

     新增一條數據後的提示消息「新增成功」。這時,就須要對普通字符串對象,即String對象進行處理,使其支持多語言。

這裏貼出部分代碼:

1. 瀏覽器語言的獲取

/**
 * 獲取瀏覽器語言
 * @returns language
 */
function getLang(){
    if(typeof(cacheLang) != "undefined"){
        return cacheLang;
    }
    if (navigator.language) {
        cacheLang = navigator.language.toLowerCase();
        return cacheLang;
    }else {
        cacheLang = navigator.browserLanguage.toLowerCase();
        return cacheLang;
    }
}
獲取瀏覽器語言

 

2.多語言配置的加載  

var url = $.type(p) == "string" ? p : "i18n/" + getLang() + ".json";//p爲參數,可經過p手動指定配置路徑,此時不根據默認路徑加載多語言消息配置
$.ajax({
    url : url,
    dataType : 'json',
    type : "GET",
    success : function(data, textStatus, jqXHR) {
        messages = data;//緩存消息
        run(data);//執行dom處理
        callback(self);//回調處理,self爲插件自己對象
    },
    error : function(a, b, c) {
        throw "Load i18n message error [" + p + "], cause by : " + b;
    }
});
配置的加載

 

3.DOM處理

/**
 * 替換國際化消息
 * @param ms 消息對象
 */
function run(ms){
    $("*[i18n]").each(function(){
        var o = $(this);
        var key = o.attr("i18n");//獲取key
        var val = o.attr("i18n-set");//獲取消息設置目標
        var message = _getMessage(ms, key);//取得消息
        switch(val){//根據不一樣目標設置到不一樣的地方
        case undefined:
            o.html(message);
            break;
        case "append":
            o.html(o.html() + message);
            break;
        case "html":
            o.html(message);
            break;
        case "value":
            o.val(message);
            break;
        default:
            o.attr(val, message);
            break;
        }
        o.removeAttr("i18n");//移除屬性,避免二次處理
        o.removeAttr("i18n-set");
    });
}
dom處理

 

 4. 獲取多語言的方法

/**
 * 獲取多語言消息
 * @param msgs 消息對象
 * @param key 消息名稱
 * @returns value 消息
 */
function _getMessage(msgs, key){
    var message;
    try{
        message = msgs[key];
    }catch(e){
        message = key;
    }
    return message;
}
5.實現對String對象的改造
/**
 * 爲String提供local方法獲取多語言消息
 * @return value 消息
 */
String.prototype.local = function(){
    return _getMessage(messages, this);
}
獲取多語言的方法

 

2、多用戶支持

 主要經過數據庫來實現。

 

 主要經過javaBean+JSP鏈接數據庫來實現,創建Users表和Score表,分別記錄用戶信息和得分信息。

 

 

 


13)團隊項目總結

   總的來講,此次合做對我而言是一次很愉快又不愉快的經歷。愉快在於和舍友有着和氣的交流方式,作項目比起其餘小組要輕鬆許多,也作出了一個自我感受還不錯的做品;不愉快則在於個人後端編碼能力較弱,無心中就加大了舍友的重擔。其次,作項目的過程自己也讓我以爲有一點痛苦,項目時間短任務重,清明三天假期都是在高壓中度過,天天都處於早上朝八點到凌晨兩點不間歇的緊繃狀態,天天晚上躺在牀上都會由於想到項目的某個bug而睡不着。一度覺得本身可能完成不了這個項目。

  所幸,咱們的結果是好的。再此次合做中,我以爲本身的java編碼能力也有了一些提高,但願以後作的團隊項目能夠更好!

相關文章
相關標籤/搜索