提出问题

项目中碰到的几个代码优化问题???
简书地址:http://www.jianshu.com/users/d38a3668be58/latest_articles

解决问题

先看看下面的代码,不知道给你的第一感觉是什么?

  1. /**
  2. * 获得设计件当前编辑的章节名称
  3. * @param deView
  4. * @return
  5. */
  6. @Override
  7. public List<FormResult> getEditChapter(DeView deView,List<FormResult> formResultList) throws Exception{
  8. /** 从后端查询出来的数据,不用管是什么数据 **/
  9. ResultData resultData = webFormService.getDesignSuitHis(deView.getVid(), deView.getProjectId(), deView.getRevision());
  10. for(int i=0;i<10;i++){
  11. ........
  12. //连接数据库,查询数据代码(只是伪代码,不用太较真)
  13. webForm = webFormService.findId(id);
  14. ........
  15. }
  16. /** 判空 待修改(2) **/
  17. if(null != formResultList && formResultList.size() >0){
  18. for(int i=0;i<formResultList.size();i++){
  19. StringBuffer editorChapper = null;
  20. List<TreeModel<TitleDTO>> treeModels = (List<TreeModel<TitleDTO>>)resultData.getEntities().get("titleTreeModel");
  21. /** 判空 **/
  22. if(null != treeModels && treeModels.size() >0){
  23. AllBreak:
  24. for(TreeModel<TitleDTO> treeModel:treeModels){
  25. List<TitleDTO> titleDTOList = treeModel.getData().getChildren();
  26. /** 判空 **/
  27. if(null != titleDTOList && titleDTOList.size() > 0){
  28. for(TitleDTO titleDTO:titleDTOList){
  29. editorChapper = new StringBuffer();
  30. /** 判空 **/
  31. if((null != titleDTO.getChildForm()) && titleDTO.getChildForm().equals(formResultList.get(i).getFormId())){
  32. if(null != titleDTO.getBindAttribute()){
  33. String bindEntityVariable = titleDTO.getBindEntityVariable();
  34. Map<String, IDataObject> map = (Map<String, IDataObject>)resultData.getEntities().get("dataObjects");
  35. IDataObject iDataObject = map.get(bindEntityVariable);
  36. String text = iDataObject.getAttributes().get("name").toString();
  37. /** 拼凑完整章节 **/
  38. editorChapper.append(titleDTO.getTitleNumber()).append(" ").append(text);
  39. /** 设置章节名称 **/
  40. formResultList.get(i).setChapterName(editorChapper.toString());
  41. /** 设置章节Id**/
  42. formResultList.get(i).setTitleId(titleDTO.getId());
  43. }else{
  44. /** 拼凑完整章节 **/
  45. editorChapper.append(titleDTO.getTitleNumber());
  46. editorChapper.append(" ");
  47. editorChapper.append(titleDTO.getText());
  48. /** 设置章节名称 **/
  49. formResultList.get(i).setChapterName(editorChapper.toString());
  50. /** 设置章节Id**/
  51. formResultList.get(i).setTitleId(titleDTO.getId());
  52. }
  53. break AllBreak;
  54. }
  55. }
  56. }
  57. }
  58. }
  59. }
  60. }
  61. return formResultList;
  62. }

上面代码有很多问题,我们一个一个解决:

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
}

一切目的都是验证代码简洁之道的那句话!
再看下面的代码:
优雅编程-1:抛砖引玉 - 图1
代码开始new一个PpProject对象,但是在下面的if逻辑中才使用上,假如if逻辑没进入的话,那new出来的对象就使用不上,针对这种情况,就该把上面的代码移到if逻辑判断中,这样才是合理的