提出问题
项目中碰到的几个代码优化问题???
简书地址:http://www.jianshu.com/users/d38a3668be58/latest_articles
解决问题
先看看下面的代码,不知道给你的第一感觉是什么?
/**
* 获得设计件当前编辑的章节名称
* @param deView
* @return
*/
@Override
public List<FormResult> getEditChapter(DeView deView,List<FormResult> formResultList) throws Exception{
/** 从后端查询出来的数据,不用管是什么数据 **/
ResultData resultData = webFormService.getDesignSuitHis(deView.getVid(), deView.getProjectId(), deView.getRevision());
for(int i=0;i<10;i++){
........
//连接数据库,查询数据代码(只是伪代码,不用太较真)
webForm = webFormService.findId(id);
........
}
/** 判空 待修改(2) **/
if(null != formResultList && formResultList.size() >0){
for(int i=0;i<formResultList.size();i++){
StringBuffer editorChapper = null;
List<TreeModel<TitleDTO>> treeModels = (List<TreeModel<TitleDTO>>)resultData.getEntities().get("titleTreeModel");
/** 判空 **/
if(null != treeModels && treeModels.size() >0){
AllBreak:
for(TreeModel<TitleDTO> treeModel:treeModels){
List<TitleDTO> titleDTOList = treeModel.getData().getChildren();
/** 判空 **/
if(null != titleDTOList && titleDTOList.size() > 0){
for(TitleDTO titleDTO:titleDTOList){
editorChapper = new StringBuffer();
/** 判空 **/
if((null != titleDTO.getChildForm()) && titleDTO.getChildForm().equals(formResultList.get(i).getFormId())){
if(null != titleDTO.getBindAttribute()){
String bindEntityVariable = titleDTO.getBindEntityVariable();
Map<String, IDataObject> map = (Map<String, IDataObject>)resultData.getEntities().get("dataObjects");
IDataObject iDataObject = map.get(bindEntityVariable);
String text = iDataObject.getAttributes().get("name").toString();
/** 拼凑完整章节 **/
editorChapper.append(titleDTO.getTitleNumber()).append(" ").append(text);
/** 设置章节名称 **/
formResultList.get(i).setChapterName(editorChapper.toString());
/** 设置章节Id**/
formResultList.get(i).setTitleId(titleDTO.getId());
}else{
/** 拼凑完整章节 **/
editorChapper.append(titleDTO.getTitleNumber());
editorChapper.append(" ");
editorChapper.append(titleDTO.getText());
/** 设置章节名称 **/
formResultList.get(i).setChapterName(editorChapper.toString());
/** 设置章节Id**/
formResultList.get(i).setTitleId(titleDTO.getId());
}
break AllBreak;
}
}
}
}
}
}
}
return formResultList;
}
上面代码有很多问题,我们一个一个解决:
1.for循环中查询数据库
既下面这段代码,在for循环中,连接数据库,查询数据。我们都知道,连接数据库,本身就很耗性能
for(int i=0;i<10;i++){
……..
//连接数据库,查询数据代码(只是伪代码,不用太较真)
webForm = webFormService.findId(id);
……..
}
解决:
根据业务场景,把for循环中的多次连接数据库查询,写到sql中去查询,既一次性查询出来
根据业务场景,看是否可以利用缓存,提高查询效率
2.代码层级太深的问题
解决:
针对待修改(2),我们要学会用逆向思维的方法,修改如下:
/**
* 获得设计件当前编辑的章节名称
* @param deView
* @return
*/
@Override
public List<FormResult> getEditChapter(DeView deView,List<FormResult> formResultList) throws Exception{
/** 从后端查询出来的数据,不用管是什么数据 **/
ResultData resultData = webFormService.getDesignSuitHis(deView.getVid(), deView.getProjectId(), deView.getRevision());
/** 判空 待修改(1) ,现在用逆向思维的方法,修改如下**/
if(null == formResultList || formResultList.size() == 0) return;
for(int i=0;i<formResultList.size();i++){
......
省略代码
......
}
return formResultList;
}
3.方法过长
代码整洁之道,对于函数有这么一句话:函数只应该做一件事情,把一件事情做好,而且只由它来做这一件事情
所有上面的代码其实可以抽出很多方法出来:
既:
/**
* 获得设计件当前编辑的章节名称
* @param deView
* @return
*/
@Override
public List<FormResult> getEditChapter(DeView deView,List<FormResult> formResultList) throws Exception{
/** 从后端查询出来的数据,不用管是什么数据 **/
ResultData resultData = webFormService.getDesignSuitHis(deView.getVid(), deView.getProjectId(), deView.getRevision());
for(int i=0;i<10;i++){
........
//连接数据库,查询数据代码(只是伪代码,不用太较真)
webForm = webFormService.findId(id);
........
}
/** 判空 待修改(2) **/
if(null == formResultList || formResultList.size() == 0) return;
for(int i=0;i<formResultList.size();i++){
StringBuffer editorChapper = null;
List<TreeModel<TitleDTO>> treeModels = (List<TreeModel<TitleDTO>>)resultData.getEntities().get("titleTreeModel");
/** 判空 **/
if(null != treeModels && treeModels.size() >0){
AllBreak:
for(TreeModel<TitleDTO> treeModel:treeModels){
List<TitleDTO> titleDTOList = treeModel.getData().getChildren();
/** 判空 **/
if(null != titleDTOList && titleDTOList.size() > 0){
for(TitleDTO titleDTO:titleDTOList){
editorChapper = new StringBuffer();
/** 判空 **/
if((null != titleDTO.getChildForm()) && titleDTO.getChildForm().equals(formResultList.get(i).getFormId())){
if(null != titleDTO.getBindAttribute()){
//伪代码而已,不用太计较
method3();
}else{
method4();
}
break AllBreak;
}
}
}
}
}
}
return formResultList;
}
/**
*方法3
*/
public void method3(){
String bindEntityVariable = titleDTO.getBindEntityVariable();
Map<String, IDataObject> map = (Map<String, IDataObject>)resultData.getEntities().get("dataObjects");
IDataObject iDataObject = map.get(bindEntityVariable);
String text = iDataObject.getAttributes().get("name").toString();
/** 拼凑完整章节 **/
editorChapper.append(titleDTO.getTitleNumber()).append(" ").append(text);
/** 设置章节名称 **/
formResultList.get(i).setChapterName(editorChapper.toString());
/** 设置章节Id**/
formResultList.get(i).setTitleId(titleDTO.getId());
}
/**
*方法4
*/
public void method4(){
/** 拼凑完整章节 **/
editorChapper.append(titleDTO.getTitleNumber());
editorChapper.append(" ");
editorChapper.append(titleDTO.getText());
/** 设置章节名称 **/
formResultList.get(i).setChapterName(editorChapper.toString());
/** 设置章节Id**/
formResultList.get(i).setTitleId(titleDTO.getId());
}
不知道大家有没有注意一点
if(){
..业务代码1
}else{
..业务代码2
}
for(int i=0;i<100;i++){
..业务代码3
}
对于if,和for中的代码,如果是处理业务代码,一般可以抽出单独的一个代码,改成
if(){
method1();
}else{
method2();
}
for(int i=0;i<100;i++){
method3();
}
method1(){
//业务代码1
}
method2(){
//业务代码2
}
method3(){
//业务代码3
}
一切目的都是验证代码简洁之道的那句话!
再看下面的代码:
代码开始new一个PpProject对象,但是在下面的if逻辑中才使用上,假如if逻辑没进入的话,那new出来的对象就使用不上,针对这种情况,就该把上面的代码移到if逻辑判断中,这样才是合理的