小學四則運算結對項目javascript
一.項目地址css
https://git.coding.net/chenxin1998/Arithmetic.githtml
結對成員:馬樂平,地址:https://git.coding.net/maleping/Amerithic.gitjava
二.預計完成項目時間(PSP)jquery
PSP2.1git |
任務內容web |
計劃共完成須要的時間(h)正則表達式 |
實際完成須要的時間(h)spring |
Planning編程 |
計劃 |
15 |
17 |
· Estimate |
· 估計這個任務須要多少時間,並規劃大體工做步驟 |
18 |
20 |
Development |
開發 |
98 |
100 |
·· Analysis |
需求分析 (包括學習新技術) |
52 |
54 |
· Design Spec |
· 生成設計文檔 |
22 |
24 |
· Design Review |
· 設計複審 (和同事審覈設計文檔) |
18 |
20 |
· Coding Standard |
代碼規範 (爲目前的開發制定合適的規範) |
12 |
16 |
· Design |
具體設計 |
26 |
28 |
· Coding |
具體編碼 |
48 |
56 |
· Code Review |
· 代碼複審 |
7 |
9 |
· Test |
· 測試(自我測試,修改代碼,提交修改) |
18 |
24 |
Reporting |
報告 |
9 |
6 |
·· Test Report |
· 測試報告 |
3 |
2 |
· Size Measurement |
計算工做量 |
2 |
1 |
· Postmortem & Process Improvement Plan |
· 過後總結 ,並提出過程改進計劃 |
3 |
3 |
三.如何進行接口設計*
在進行接口設計以前,咱們認真閱讀了教材中的相應章節,以及相關的博客,如下是一些介紹接口設計的優秀博客:
https://blog.csdn.net/yu870646595/article/details/51900478
https://blog.csdn.net/blueangle17/article/details/54965597
首先要想好是給什麼業務提供的接口,好比是給旅遊業務提供的接口,能夠叫作TravelService,意思就是說須要根據業務給項目起名字。
信息隱藏:信息隱藏是指在設計和肯定模塊時,使得一個模塊內包含的特定信息(過程或數據),對於不須要這些信息的其餘模塊來講,是不可訪問的。所以,咱們在最初設計時決定運用java的private進行將其私有化,向外提供訪問的方法。
鬆耦合:下降耦合度的過程就是模塊化編程的過程。咱們在設計的過程當中,決定採用先後端分離的模式,運算模塊,與界面模塊相對獨立,以此來下降耦合度。
接口設計:面向接口編程是軟件工程領域經常使用的設計手段。
四.計算模塊接口的設計與實現過程*
在計算模塊,實現小學四則運算的這部分代碼中,主要分爲三個類,其中RandomArithmetic類負責開啓程序運行的入口,CreateProblem主要用於處理運算式,WriteResult用於文件寫入,整個程序由這三個類塊構成,實現了功能的模塊化。
關鍵函數:
其中在CreateProblem類中又分離出了private Stack<Integer> stackOfNum=new Stack<Integer>();//計算結果所用棧;private Stack<Character> suffix=new Stack<Character>();//後綴表達式private Stack<Character> stackOfOperation=new Stack<Character>();//計算後綴表達式所用棧;這樣設計使得各功能再次模塊化,使得程序更加的便於維護和擴展。
獨到之處:
1.用兩個Character棧存儲數字和符號,而後用兩個棧分別用做轉換的緩衝棧和計算結果的緩衝棧
2. 通常Character裏面的編碼是ascii,但我沒有那樣作,就是一種新的編碼,用ascii0-99表達0-99,而符號和數字衝突,因此符號是100-105
五.計算模塊接口部分的性能改進
(記錄在改進計算模塊性能上所花費的時間,描述你改進的思路,並展現一張性能分析圖,並展現你程序中消耗最大的函數。)
|
用時 |
使用JProfiler工具分析調試 |
3(h) |
查找影響性能的程序模塊 |
3(h) |
性能改進 |
6(h) |
咱們在性能分析的過程當中花費了比較多的時間。
性能優化涉及面很廣。通常而言,性能優化指下降響應時間和提升系統吞吐量兩個方面,但在流量高峯時候,性能問題每每會表現爲服務可用性降低,因此性能優化也能夠包括提升服務可用性。在某些狀況下,下降響應時間、提升系統吞吐量和提升服務可用性三者相互矛盾,不可兼得。
一開始的時候,咱們用了比較多的正則表達式,發現:正則表達式給人的印象是快捷簡便。可是在 N.O.P.E 分支中使用正則表達式將是最糟糕的決定。若是萬不得已非要在計算密集型代碼中使用正則表達式的話,至少要將Pattern緩存下來,避免反覆編譯Pattern。最好仍是用普通的 char[] 數組或者是基於索引的操做。還有就是使用了大量的泛型,致使的結果是使用了 byte、 short、 int 和 long 的包裝類,當咱們處於 N.O.P.E. 分支的深處時,應該極力避免使用包裝類。這樣作的壞處是給GC帶來了很大的壓力。GC將會爲清除包裝類生成的對象而忙得不可開交。因此最後優化方法是使用基本數據類型、定長數組,並用一系列分割變量來標識對象在數組中所處的位置。
如下是一些JAVA性能優化的辦法:http://www.importnew.com/16181.html
性能分析圖:
六. 計算模塊部分單元測試展現
部分單元測試代碼以下:
package cn.bravedawn.airthmeticwebappse; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class AirthmeticwebappseApplicationTests { @Test public void contextLoads() { } }
部分函數代碼以下:
package cn.bravedawn.airthmeticwebappse.common.util; public class CalculateUtil { public static void main(String[] args) { System.out.println(compute(1, 2, "+")); } public static Integer compute(int firstNum, int secNum, String operator) { switch (operator) { case Const.Operator.add: { return firstNum + secNum; } case Const.Operator.subtraction: { return firstNum - secNum; } case Const.Operator.multiplication: { return firstNum * secNum; } case Const.Operator.division: { return firstNum / secNum; } default: { return null; } } } }
package cn.bravedawn.airthmeticwebappse.common.util; import java.util.HashMap; import java.util.Map; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class CookiesUtil { /** * 添加cookie * * @param response * @param name * @param value */ public static void addCookie(HttpServletResponse response, String name, String value, int time) { Cookie cookie = new Cookie(name.trim(), value.trim()); cookie.setMaxAge(time);// 設置爲30min cookie.setPath("/"); System.out.println("已添加==============="); response.addCookie(cookie); } /** * 修改cookie * * @param request * @param response * @param name * @param value 注意1、修改、刪除Cookie時,新建的Cookie除value、maxAge以外的全部屬性,例如name、path、domain等,都要與原Cookie徹底同樣。不然,瀏覽器將視爲兩個不一樣的Cookie不予覆蓋,致使修改、刪除失敗。 */ public void editCookie(HttpServletRequest request, HttpServletResponse response, String name, String value) { Cookie[] cookies = request.getCookies(); if (null == cookies) { System.out.println("沒有cookie=============="); } else { for (Cookie cookie : cookies) { if (cookie.getName().equals(name)) { System.out.println("原值爲:" + cookie.getValue()); cookie.setValue(value); cookie.setPath("/"); cookie.setMaxAge(60 * 60 * 7);// 設置爲30min System.out.println("被修改的cookie名字爲:" + cookie.getName() + ",新值爲:" + cookie.getValue()); response.addCookie(cookie); break; } } } } /** * 刪除cookie * * @param request * @param response * @param name */ public void delCookie(HttpServletRequest request, HttpServletResponse response, String name) { Cookie[] cookies = request.getCookies(); if (null == cookies) { System.out.println("沒有cookie=============="); } else { for (Cookie cookie : cookies) { if (cookie.getName().equals(name)) { cookie.setValue(null); cookie.setMaxAge(0);// 當即銷燬cookie cookie.setPath("/"); System.out.println("被刪除的cookie名字爲:" + cookie.getName()); response.addCookie(cookie); break; } } } } /** * 根據名字獲取cookie * * @param request * @param name cookie名字 * @return */ public static Cookie getCookieByName(HttpServletRequest request, String name) { Map<String, Cookie> cookieMap = ReadCookieMap(request); if (cookieMap.containsKey(name)) { Cookie cookie = (Cookie) cookieMap.get(name); return cookie; } else { return null; } } /** * 將cookie封裝到Map裏面 * * @param request * @return */ private static Map<String, Cookie> ReadCookieMap(HttpServletRequest request) { Map<String, Cookie> cookieMap = new HashMap<String, Cookie>(); Cookie[] cookies = request.getCookies(); if (null != cookies) { for (Cookie cookie : cookies) { cookieMap.put(cookie.getName(), cookie); } } return cookieMap; } }
單元測試覆蓋率:
七. 計算模塊部分異常處理說明
異常處理代碼以下:
package cn.bravedawn.airthmeticwebappse; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class AirthmeticwebappseApplicationTests { @Test public void contextLoads() { } }
八.界面模塊的詳細設計過程*
首先,爲了提升完成項目的效率,咱們採用了先後端分離的方式進行項目開發。在最初的界面設計中,考慮到咱們的目標用戶中有小學生、家長、以及教師,所以界面的適用性比較重要。因此咱們如今Photoshop上規劃出頁面的大致格局及初步界面樣式。咱們分了三個界面,分別是進入界面,答題界面,和結果界面。在編程過程當中,頁面實現採用了html+css+js+jquery進行編碼。
初步重要代碼以下:
! function(a, b) { var c = "function" == typeof define, d = "undefined" != typeof module && module.exports; c ? define(a, b) : d ? module.exports = b() : this[a] = b() }("Calculagraph", function() { function a() { this.time = 0, this.isRunning = !1, this._callback = null, this._interval = 0, this.last = 0 } return a.prototype.increase = function(a, b, c, d) { var e = this; return e._curry(0)(a, b, c, d), e }, a.prototype.decrease = function(a, b, c, d) { var e = this; return e._curry(1)(a, b, c, d), e }, a.prototype._curry = function(a) { var b = this; return a && (b._set = b.time), function(c, d, e, f) { if(b.isRunning) return !1; b.isRunning = !0, b._callback = c, b._interval = d, b._tick = e || 1e3, b._finish = f || function() {}, b.last = a; var g = +new Date; ! function h() { var f = +new Date, i = parseInt((f - g) / 1e3); return c(b.time / 1e3), a ? b.time -= e : b.time += e, b.time < 0 || d && i >= d ? (b.stop(), void b._finish()) : void(b.times = setTimeout(function() { h() }, e)) }() } }, a.prototype.set = function(a) { var b = this; return b.isRunning ? !1 : (b.time = 1e3 * a, void(b._time = b.time)) }, a.prototype.stop = function() { var a = this; clearTimeout(a.times), a.time = null, a.isRunning = !1 }, a.prototype.parse = function() { var a = this; clearTimeout(a.times), a.isRunning = !1 }, a.prototype.restore = function() { var a = this; a.last ? a.decrease(a._callback, a._interval, a._tick, a._finish) : a.increase(a._callback, a._interval, a._tick, a._finish) }, a.prototype.restart = function() { var a = this; a.stop(), a._time && (a.time = a._time), a.restore() }, a });
九.界面模塊與計算模塊的對接*
UI模塊設計過程:咱們分爲三個頁面:用戶進入頁面,作題頁面,結果分析頁面。
用戶進入頁面:前臺使用form表單把用戶輸入的信息傳到後臺進行出題。這部分對用戶輸入信息的各類狀況的判斷,由前臺的js判斷並實現。
作題界面:打開作題頁面,頁面上能夠呈現出全部題目。經過js對答案對錯進行判斷。後臺把全部題目和全部題目答案放在list裏傳遞到前臺,答題者完成題目後,能夠進行檢查。檢查無誤後,答題狀況便可提交到後臺。
結果界面:答題者提交答題後,由後臺JSP頁面返回結果。
十.描述結對的過程
十一.結對編程的優勢和缺點
同時指出結對的每個人的優勢和缺點在哪裏 (要列出至少三個優勢和一個缺點)。
經過此次結對項目,我以爲結對編程可以帶來1+1>2的效果。
結對編程有如下優勢:
1.以前一我的作的時候,遇到不懂得問題時,就會陷入迷茫。當兩我的一塊兒編程時,有不懂的能夠一塊兒討論,說出本身的意見,也爲整個編程過程節約了時間。
2.除此以外,兩我的一塊兒合做時就會產生更多更好的想法,能夠更好的優化整個項目的設計,遇到問題時能夠相互幫助解決問題,效率也比較高。
3.兩我的合做還能夠發現多方身上的優勢,找出本身身上的不足,並能相互監督讓彼此變得更好,還能夠彼此分享好的學習經驗。綜上所述,咱們認爲兩我的合做的效率遠遠大於一我的。
要說結對編程的缺點:
1.我以爲主要在完成項目的過程當中,會產生分歧。每一個人有每一個人本身的想法,若是不能及時解決分歧,達成一致,頗有可能演化成矛盾,進而使合做關係破裂,沒法完成項目。
2.對於一個有經驗的編程人員來講,更習慣於一我的編程。畢竟,在編程的過程當中有別人在看的感受有些奇怪。
小組成員互評:
馬樂平:優勢:認真細心,勤奮好問,善於思考;
缺點:理解能力欠佳,不善溝通
陳逸璇:優勢:對學習充滿熱情,不怕困難,善於溝通;
缺點:技術還有待提升
十二.實際完成項目時間(PSP)
PSP2.1 |
任務內容 |
計劃共完成須要的時間(h) |
實際完成須要的時間(h) |
Planning |
計劃 |
15 |
17 |
· Estimate |
· 估計這個任務須要多少時間,並規劃大體工做步驟 |
18 |
20 |
Development |
開發 |
98 |
100 |
·· Analysis |
需求分析 (包括學習新技術) |
52 |
54 |
· Design Spec |
· 生成設計文檔 |
22 |
24 |
· Design Review |
· 設計複審 (和同事審覈設計文檔) |
18 |
20 |
· Coding Standard |
代碼規範 (爲目前的開發制定合適的規範) |
12 |
16 |
· Design |
具體設計 |
26 |
28 |
· Coding |
具體編碼 |
48 |
56 |
· Code Review |
· 代碼複審 |
7 |
9 |
· Test |
· 測試(自我測試,修改代碼,提交修改) |
18 |
24 |
Reporting |
報告 |
9 |
6 |
·· Test Report |
· 測試報告 |
3 |
2 |
· Size Measurement |
計算工做量 |
2 |
1 |
· Postmortem & Process Improvement Plan |
· 過後總結 ,並提出過程改進計劃 |
3 |
3 |
總結:通過這次結對項目,讓我感覺到結對編程的優勢及樂趣。同時,通過這次項目的鍛鍊,讓我對後端的學習更急深刻,同時培養了個人許多能力,如:如何與別人溝通,如何合做等等。總之,這次做業中收穫很大。