底层代码尽量不要动,如果是改部分功能应该在controller层或者service层修改,否则,如果一个模块被多次使用,可能导致数据不匹配。
开发的测试数据应该尽量简洁,因为对开发者来说,完成功能是首要任务,应该尽量减少其他因素对时间的浪费,复杂繁琐的测试数据,会导致在开发的时候,拖慢功能测试的进度。
在开发的同时应该考虑到性能问题,优化性能对开发者来说主要考虑从程序和数据库方面优化,数据库方面主要是索引,存储过程,缓存等,程序上主要是逻辑上优化。能查部分,不要查全部,这是主旨。
总结一下遇到的比较奇葩的问题:这是一个后台管理的系统,功能也就那些:增删改查,在开发查看详情页面的时候遇到一个比较奇葩的问题,详情页面只显示一部分,因为是用了easyui绑定id显示,显示的东西大部分都是一个个单独的字段,但是有两个是list,而且这个list里是对象,具体说来这个list是险种信息的list里面的对象主要有3个字段:险种名称,保额,保费,结构就类似于list[{险种名称,保额,保费},{险种名称,保额,保费},{险种名称,保额,保费},……],然后还有一个字段【comboNo】,如果comboNo等于”JQX”则为交强险,如果不等于”JQX”,则为商业险,详情页面要根据这个字段分别显示商业险和交强险,但是这两个险种信息从后台传过来是放在同一list里的,因为是easyui绑定id显示,所以页面并无逻辑判断,也就是说无法用easyui根据comboNo的值分别显示交强险和商业险的详情(交强险和商业险都可能存在多条),可能很多人都想到用jstl标签,的确,我也是这么想的,但是后来用了之后出现了一个很奇葩的问题:第一次打开详情页面不显示,第二次才显示。后台是一个servlet,我试过将险种信息放入request中去,在页面通过${requestScope.XXX }取值,然而什么都没有,不管查看多少次,都不显示,后来我改成了HttpSession,在页面用sessionScope取值,但是每次都要第二次才会出现险种信息,但是只要第一次打开了,关闭页面再打开第二次,之后无论怎么打开都可以显示,虽然我极力向老大解释,多点开一次并不麻烦,然而还是被无情打回,后来在经过网友的指点下找到了原因:在点开查看详情的时候,详情页面就先行加载,而此时session中还没有值,然后js通过ajax向后台请求数据,得到数据之后,通过easyui的id绑定再显示出结果,然而虽然险种信息也通过session存入了值,但是因为是页面优先加载而session中的值是后来加入的,才导致了通过session展示的部分在第一次存入的时候为空。后来通过js的html拼接才有效地解决了这一问题,虽然这种方法极不优雅,但也是无奈之举。下面上代码
jsp部分
<!--在原来的位置加入两个div-->
<div id="tt"></div><div id="tt2"></div>
js部分
<!--js部分是在ajax的success里进行html拼接的,拼接的方式也很简单,直接将写在html中的部分追加到html后,然后返回即可-->
$("#aSearchBtn").unbind("click").bind({
click:function(){
var rows = $('#tbDatagrid').datagrid('getSelected');
if (rows){
var idStr = rows.idStr;
if(null == idStr || "" == idStr){
$.messager.alert("标题", "渠道订单表ID未获取到", "info");
return false;
}
$.ajax(ctx+"jobLog/doGetCpfOrderByIdJson.mvc", {
cache: false,
data: {idStr:idStr},
type: "POST",
timeout:60000,
success: function(row){
var html ="",html2="";
row.insList.forEach(function(val,idx,arr){
if(val.comboNo=='JQX'){
var flag=1;
html+="<fieldset><legend>交强险投保信息</legend>";
if(flag==1){
html+="<div class='divWindowRow'><lable>起保日期</lable>"+val.startDate+"</div>";
html+="<div class='divWindowRow'><lable>终保日期</lable>"+val.endDate+"</div>";
flag++;
}
html+="<table style='width: 100%;'><tr style='font-size:10px;'><th>险种</th><th>保额(元)</th><th>保费(元)</th>";
html+="<tr style='font-size:10px' align='center'><td>"+val.kindName+"</td>";
html+="<td>"+val.sumInsured+"</td>";
html+="<td>"+val.sumPremium+"</td>";
html+="</fieldset>"
}
if(val.comboNo!='JQX'){
var flag2=1;
html2+="<fieldset><legend>商业险投保信息</legend>";
if(flag2==1){
html2+=" <div class='divWindowRow'><lable>起保日期</lable>"+val.startDate+"</div>";
html2 +=" <div class='divWindowRow'><lable>终保日期</lable>"+val.endDate+"</div>";
flag2++;
}
html2+="<table style='width: 100%;'><tr style='font-size:10px;'><th>险种</th><th>保额(元)</th><th>保费(元)</th>";
html2+="<tr style='font-size:10px' align='center'><td>"+val.kindName+"</td>";
html2+="<td>"+val.sumInsured+"</td>";
html2+="<td>"+val.sumPremium+"</td>";
html2+="</fieldset>"
}
});
$("#tt").html(html);
$("#tt2").html(html2);
if("success" == row.success){
$("#doFormSearch").form("clear");
$("#aSearchWindow").window({
collapsible: false,
minimizable: false,
maximizable: true,
modal:true,
iconCls:"icon-search"
});
$("#aSearchWindow").window("open");
$('#doFormSearch').form('load',{
idStr:row.idStr,
tradeNo:row.tradeNo,
orderNo:row.orderNo,
proposalNo:row.proposalNo,
policyNo:row.policyNo,
frameNo:row.frameNo,
enginNo:row.enginNo,
brandName:row.brandName,
enrollDate:row.enrollDate,
startDate:row.startDate,
insuredName:row.insuredName,
identifyType:row.identifyType,
identifyNumber:row.identifyNumber,
mobilePhone:row.mobilePhone,
acceptName:row.acceptName,
acceptTelephone:row.acceptTelephone,
acceptAddress:row.acceptAddress,
appointmentTime:row.appointmentTime
});
}
},error:function(row){
alert("error");
}
});
}else{
$.messager.alert("标题", "请选择查看项!", "info");
}
}
});
后面还想到另一种办法:先加载数据,再加载详情页面窗口,不过没有试验过,理论上可行。
调试代码最应该先进行实验性的调试运行,等得到预期的结果后,再修改剩下的类似部分,如果一下子全部都改了,但是debug的时候发现改错,那你花了大把精力改的代码的时间也就浪费了。
命名法在编码的时候很重要,程序的报错极有可能是因为字段的命名规则不一致造成的,对于二次维护来说,即便是命名规则不符合主流也应该沿用原来的命名规则,原因很简单,因为很可能在系统的许多地方都用到了该字段,如果一一修改,很浪费时间。
调试页面是一个非常坑的东西,因为早晚你会遇到一个很奇葩的问题,就是本地怎么试都可以,但是发布到服务器上就是不行。这时候清理一下缓存就什么都解决了(chrome或者firefox的调试还是蛮重要的)。。。
主要想讲一讲这样一个问题:一个下拉框,作用是用来授权的,下拉框里有很多选项,每个选项都是一个接口,选中表示授权该接口,不选中表示禁用该接口。但是出现了这么一个问题,其中有一个接口是生成签名接口,不管选中没选中,都有权限能够生成签名。但是其他接口都是正常的。系统是有两个,一个是管理系统,一个是逻辑系统。管理系统主要是用来配置的,把配置的东西保存到数据库,而逻辑系统主要处理逻辑的,但是需要管理系统存在数据库里的数据来实现逻辑。因为勾选的功能是在管理系统里出现的,所以,我先在看管理系统里的代码。然而,并没有发现异常,因为都是写在一起的,所有接口都是用的一个流程,但是为什么其他接口正常,只有这个接口异常呢。所以推测问题出现在逻辑系统。(我一开始并没有这么清晰,是头儿在数据库写了一条关联三张表的sql,然后在管理系统里操作授权和不授权,数据库里的字段是否有变化来判断的,费老大劲儿了,走了弯路)下面是重点:怎么找到出代码里出问题的地方呢?逻辑系统这么大,我怎么知道问题出在哪儿了呢?答案是:返回信息,以前我以为,返回信息并没有什么L用,但是经过这个坎儿,我才知道,返回信息是多么重要。而且用谁的返回信息也很重要,对于授权接口异常的授不授权返回信息都一样,这对我来说不是个好消息,但是授权正常的接口就不一样了,取消授权后会返回错误信息,既然异常接口没有报这个错误,说明异常接口的问题恰好发生在这里。然后根据返回的错误信息就定位到发生错误的位置了。
修改代码后要养成对原逻辑测试的习惯。有可能修改后的逻辑会影响原逻辑。
问题一旦发现应该及时解决,时间拖得越久,效率越低下,代价也越大。本来只需要10分钟就可以完成的事情,拜你拖延所赐,之后可能需要花数小时才能解决,这不是危言耸听,因为这是成指数增长的。
测试接口用的报文最好用当天的,因为很多系统都有定时清空的功能,如果用比较久远的报文,可能规则已改,或者报文已经失效,会造成本来正常的接口调用失败的假象。
多个功能公用一个出口的情况下,要测试某个模块是否正常,应该把其他的模块都设置为true,只剩下最后那一个要测试的模块,这样就能测试了。这是很理所应当的事情。我TM就搞不懂我当时为什么就停这儿了。
在程序中要尽量减少if…else…,并不是说不用if…else…,但要尽量将情况分为最本质的情况。比如,18~24岁,有会开车的,有不会开车的,25~30岁有会开车的有不会开车的,现在要给这些人审核驾照,那么不要按年龄分,要按会开车和不会开车的分,因为如果按年龄分,你除了要判断年龄还要判断会不会开车,而如果你判断会不会开车只需要一个条件就可以了,这样就减少了判断,这个例子可能不是很准确,但是的确存在这种类似的情况;还有,在写逻辑的时候,应该先把正常的流程从头到尾写下来,然后再考虑其他情况,对于其他情况,可以在正常情况下添加if…else…来限制;从数据库取出数据,很可能会发生为空的情况,在后台应该对其做处理,一般这种情况都采用三目运算解决。
对于具有差异性取值,比如,从数据库里取数据,城市代码是6位数(称之为单列市),但是省份是3位数,省份的三位数和城市的前三位是一样的,例如,四川是520,成都是520100,如果根据cityCode取值,如果先截取前三位,得出的结果会有两个,一个是四川省,一个是成都市,但我们只要求一个,那到底选谁呢,我们应该先用cityCode去查,如果能查到,则说明是单列市,如果查不到,再截取前三位数去查。差异性取值,先用完整的数据去查询,如果无结果,再用筛选后的条件去查。
在写接口的时候我们往往会用到Chrome的Postman或者Firefox的RestClient和HttpRequester等模拟报文请求工具以测试请求信息和返回信息是否有误,由于国内谷歌被墙,Chrome的Postman基本残废,还好有Firefox,但是这两款插件都时不时会出现一点小问题,就是用了一段时间会失效,当然解决办法也很简单:卸载插件->重装。
修复bug的时候如果能立即完成的尽量立即完成,对于需要从别人那里获取数据但是发现数据可能不正确也不要紧(狭隘地讲,将责任推给了对方,但实际上是非常合理的,因为可能人家的东西是对的,只是你觉得不对,假如人家也很忙,你又不好意思打扰,会非常影响bug修复的进程),只要确定是用的对应的内容就行,正确的数据进行修改就行。
对于业务逻辑在听完别人讲完后,自己一定复述一遍,看是否有问题。对逻辑的每一个地方都要据理力争,力求做到完全理解,否则后面会相当麻烦。不要同时问两个人,因为可能两个人对项目的理解并不一定一致,要问就同时问最熟悉流程的那个人。
对实现根据类似例子写不同业务逻辑的任务,在没有头绪的情况下,要尽可能摸清每个细节,哪怕是工具类的方法(很多工具类都是公司自己内部使用),因为业务不同,实现的过程也可能不同。不能完全照搬。如果实在弄不清楚是干嘛的,直接屏蔽,因为那有可能是之前的业务逻辑,屏蔽之后看看执行效果,可能你已经快要接近终点了,却被这些残留的业务挡在门外。
遇到bug最常用的方法:1.debug模式从头到尾走一遍,反正要么是前台要么是后台的问题;2.logger日志,因为在类似生产的环境下可能会导致本地代码无法检测错误,这样就只能靠logger日志了,用法和debug是一样的。3.try…catch块
如果做了一个东西做了很久,还是没有进展,推荐推倒重做,可以拿之前写过类似的东西来改。综合算下来比一直纠结在那儿要节约时间得多。有个页面我写了3天还特么弄不出来,最后我找了一个之前写好的类似的页面复制了一份,然后按照这个正在写的改,一会儿就出来了。
更新代码可以看一下人家的代码,对于团队开发,别人的代码可能有助于自己模块的开发。
要达到快速开发一个功能,其实很多东西都是重复的,前人已经帮我实现了,而且已经做成了工具类,在用的时候直接调用就可以了,不必要再重新设计一边,站在巨人的肩膀上才能走得更远。
开发应该以需求为导向,纵观全局固然是好事,但是要在解决当前问题的前提下进行。不要一直关注一些和解决当前首要问题无关的东西,这是导致开发进度拖延的原因之一。
永远不要深信别人说的话,要是别人说的话对你起不到实际的效果,还是按照自己的想法做。
入行前要做好与未知,压力常伴的准备。