软件工程结对项目:四则运算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编码能力也有了一些提高,但愿以后作的团队项目能够更好!

相关文章
相关标签/搜索