项目地址
Information Hiding : 信息隐藏。在这次结对编程中,我们把计算核心和输入输出处理全部封装在core模块中,通过接口将core模块和外界联系起来,但具体的实现和错误处理都被隐藏在模块中。
Interface Design : 由于和结对队友所用语言不同,我们之间的对接至关重要,我们定义了一套公共的接口,极大程度的方便了各个模块之间的通讯。
Loose Coupling : 松耦合,通过模块的封装减少了通过接口连接的各个模块的影响。
在性能改进这一块我花费了大约2小时,除了将原本的命令行程序扩展命令格式以外,我还优化了字符串存储方式,详细内容如下:
当输入参数为时 效能分析图为
经分析String内存占用较大,原因是因为我用一个String存储了全部的算式并且没有释放内存,优化代码后性能明显改善了许多。
另外我还发现了一个有趣的现象,当代码执行完成后,内存并没有释放而是叠加了起来,如图所示:
当题目为50时内存变化,之后内存不断攀升达到一定数值后稳定下来。
当我再次输入50时,内存变化
经研究发现这是因为java特殊的内存释放机制所导致的。
我的测试思路是测试所有的正常和异常情况,确保程序能够正常运行。
@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%以上
我负责的主要有:
1.js提示:main界面定制题目时,不可有非正常输入,
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); } }
实现过程:
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; 100%; height: 100%; background: #3FE2D9; border-radius: 40px; } .bt{ float: left; }
提交结果页面与之相似,在上面的gif图里可以看见效果。
(1)UI设计
我们现在纸上完成了基本的UI 界面设计,然后由我负责实现和美化,详细内容在8.中都已说明。
(2)前后端对接
我采用servlet+JavaBean+form表单的方法将前后端联系起来。
例如在产生算式时,用form表单将用户输入的参数获取至servlet,将命令行程序import进servlet中,使用接口调用命令行程序产生算式。然后将生成的算式保存至数据库中,再在前端使用JavaBean链接数据库,把算式输出到前端。用户注册、答题等同理。
(3)功能展示
①登录和注册功能:
②附加功能1 多语言功能:
③题库生成功能,若参数错误前后端均提供了异常处理,前端显示提示并使得表单无法提交,后端throw catch处理异常。
④做题功能,计时功能,本次正确率统计功能,错题展示功能
⑤附加功能2 分用户历史做题记录展示,并显示最佳记录
我们小队分工比较明确,队友主要负责后端,我主要负责前端。队友为我们小组的领航员~
我们的第一步:选择了队友的第一次作业代码,队友在原本的基础上面进行更改,我开始做基本的前端页面。我们先自己做自己的,在各自擅长的领域奋斗前行~
我们的第二步:队友开始写单元测试,我继续美化我们的web界面,我们对web界面有比较高的要求,一致认为好的界面是吸引用户的最好手段!
我们的第三步:初步前后端合体,实现一些基本功能,如:题目定制,在线答题,输出结果……因为我们是舍友,进行交流也比较方便,虽然出过一些bug,但是也很快就解决了。开心
我们的第四步:一起为模块增加异常处理,主要为“生成算式数量”异常和登录异常,在核心模块写入后,我们又考虑到用户体验,使用jQuery撰写了相应的及时提醒以及防止跳转,双重保障更贴心呢!
我们的第五步:检查整个项目,并进行优化。
← 队友:顾思宇(大佬) : 我(小弟)→
http://www.cnblogs.com/xinz/archive/2011/08/07/2130332.html
在编程中,相互讨论,可以更快更有效地解决问题。比如在这次项目中,我们在做jQuery表单验证时,防止页面跳转的点怎么也做不出来,尝试过百度给的所有解决方法,大晚上把所有宿舍串了一遍也没
解决,然后有天闲聊,聊着聊着就聊出了一个新的方法。也验证了那句,语言是思维碰撞的开始。
3. 最深有感触的一点:bug解决的更快了!
- 对于有不同习惯的同学,在一起编程可能会有比较多的麻烦,导致效率底下。
- 部分人可能更适合个人编程,而不习惯在编码的时候还要应对他人的感受,甚至导致1+1<1
我可爱的队友:优点1. 能力强,有责任心
优点2. 人真的真的好,在编程的过程中对我关照有加,
优点3. 有耐心,在我调bug调到崩溃的适合,她会继续调。。(简直全世界最好的老顾顾)
缺点:太好了。太棒了,棒到我快开心死!会觉得自己拖了她的后腿...
实现原理:通过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");
});
}
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);
}
主要通过数据库来实现。
主要通过javaBean+JSP连接数据库来实现,建立Users表和Score表,分别记录用户信息和得分信息。
13)团队项目总结
总的来说,这次合作对我而言是一次很愉快又不愉快的经历。愉快在于和舍友有着和睦的交流方式,做项目比起其他小组要轻松许多,也做出了一个自我感觉还不错的作品;不愉快则在于我的后端编码能力较弱,无意中就加大了舍友的重担。其次,做项目的过程本身也让我觉得有一点痛苦,项目时间短任务重,清明三天假期都是在高压中度过,每天都处于早上朝八点到凌晨两点不间歇的紧绷状态,每天晚上躺在床上都会因为想到项目的某个bug而睡不着。一度以为自己可能完成不了这个项目。
所幸,我们的结果是好的。再这次合作中,我觉得自己的java编码能力也有了一些提升,希望之后做的团队项目可以更好!