SlideShare a Scribd company logo
1 of 47
Download to read offline
Keep Your Code Clean
        ——如何编写整洁代码
               2011年 7月
“   任何一个傻瓜都可以写出计算
机可以理解的代码。唯有写出人类



                            ”
容易理解的代码,才是优秀程序员。


     -- Martin Fowler《重构》
1   命名: 有意义

2   方法: 有层次


3   类: 合理封装

4   注释: 够简洁

5   格式: 能统一

6   重构: 持续改进
整洁代码的标准
什么才是整洁代码

可读性


 可维护性


      可扩展性
好命名带来高效率(code once, read more)
名副其实就不需要注释

/**
     * 用来处理买家付 款之 后, 将sku从一个换成另外 一个, 同时减库
存, 这里会导致商品 的库 存 被多 减
     *
     * @param itemId
                              掉 的库
     * @param quantity 需 要 减 掉的 库 存
     * @param skuId 要 替 换 成的 目 标 sku
                    要替 成 的 目标
     * @param bizOrderId
     * @param sellerId
     * @return
     * @throws IcException
     */
    public UpdateAuctionQuantityResultDO
updateAuctionQuantityAndSku(           itemId,
updateAuctionQuantityAndSku(final long itemId, final int
quantity,
                       skuId,            bizOrderId,
            final long skuId, final long bizOrderId, final long
sellerId)        IcException;
sellerId) throws IcException;
避免命名之间的混淆
我碰到的一些例子


StdCategoryDO getCategory(long catID)
                          long catID)
StdCategoryDO getCategory(int categoryId);
                          int categoryId);




StdCategoryDO
getCategoryThrowExceptionIfNull(int
                                int
categoryId);
categoryId);
请抵制缩写的诱惑
名称长度与作用范围成正比


for(
for(int i = 0; i < array.length; i++) {
     //do something
}


/** 小 二 删 除 的 状 态 */
public static final int DELETED_BY_XIAOER = -4;

/** 小 二 下 架 的 状 态 */
public static final int INSTOCK_BY_XIAOER = -3;
取个好名字是一种艺术




鸟宿池中树,僧推(敲)月下门。
       推
一些命名借鉴
add/remove                up/down                   send/receive

        lock/unlock               first/last               start/stop

open/close     next/previous      show/hide          source/target


 old/new          insert/delete           min/max           begin/end



    Factory                Template                      Composite
                 Proxy                         Visitor
Command                        Builder
                                                           Adapter
              Decorator
                               Observer         Strategy
如何改善已有代码中的命名



    ?
一个很常见的例子



List<int
      int[]> theList;
      int
public List<intint[]> getThem(){
               int
    List<intint[]> list1 = new ArrayList<int
            int                          int[]>();
                                         int
    for(int[] x : theList) {
    for(int
          if (x[0] == 4) {
                list1.add(x);
          }
    }
    return list1;
}
做第一次改进后的结果

private static final int FLAGGED = 4;
private static final int STATUS_VALUE = 0;
List<int
     int[]> gameBoard;
     int             ;
public List<int
            int[]> getFlaggedCells(){
            int                   (){
    List<int
         int[]> flaggedCells = new ArrayList<int[]>();
         int
         int[] cell : gameBoard) {
    for (int                   )
        if (cell[STATUS_VALUE] == FLAGGED) {
             flaggedCells.add(cell);
         }
    }
    return flaggedCells;
                       ;
}
再一次重构后的结果
class Cell{
    int status;
    private static final int FLAGGED = 4;
    boolean isFlegged() {
        return status == FLAGGED;
    }
}

List<Cell> gameBoard;
public List<Cell> getFlaggedCells(){
    List<Cell> flaggedCells = new ArrayList<Cell>();
    for (Cell cell : gameBoard) {
       if (cell.isFlagged()){
          flaggedCells.add(cell);
       }
    }
    return flaggedCells;
}
一个方法只做一件事情
借鉴Shell
               Shell脚本编程原则
               Shell



egrep '(Operation|Method)Exception' -B1
/home/admin/itemcenter/logs/hsf.log | fgrep '执
行 HSF服 务 [' | sed 's/]时 出 现 未 知 异 常 : 未 找 到 需
要 调 用 的 方 法 : [a-zA-Z]+; '| sort | uniq |
fgrep -v '===' | sort | uniq -c
如何判断”一个方法只做一件事”?




能用”为了...,   需要...” 来描述这个方法
保持同一抽象层级
保持同一抽象层级
public void increaseItemQuantity(… ) throws IcException {
        …
       // 判断宝贝是 否 需 要 被 更 新
       if (isNotModified(… )) {
           return;
       }

       doIncreaseItemQuantity(… );

       // 如果下架的 是 拍 卖 的 商 品 ,则 更 新 快 照
       updateSnapIfAuction(… );

       // 清缓存
       itemTairCacheService.removeItemDO(itemId);

       // 发送notify消息
       sendModifyQuantityNotify(… );

       // 更新实时搜 索
       updateModifyQuantityDocument(… );
}
参数越少越好: 0>1>2>3 (参数封装类)
参数的顺序最好反应被使用的顺序
标识参数表明函数不止做一件事
尽量将异常处理从主流程中分离出来
一个异常的使用例子
private ProcessResultDO updateItemAndSkuQuantity(… ) throws IcException {
        // 获 取 卖 家 信 息
        BaseUserDO seller = getUser(sellerId);
        if (seller == null){
            …
            return result;
        }

       //获 取 宝 贝 以 及宝 贝 的SKU
       ItemDO dbItem = getItemWithSku(itemId);
       if (dbItem == null){
           …
           return result;
       }

       //校 验 是 否 允 许更 改 库存
       stepCheckModifyQuantity(… );

       //更 新 宝 贝 库 存
       doModifyItemQuantity(… );
}
重构之后

private ProcessResultDO updateItemAndSkuQuantity(… ) throws IcException {
       final ProcessResultDO result = new ProcessResultDO();
       try {
           // 获 取 卖 家 信 息
           BaseUserDO seller = getUserThrowExceptionIfNull
                                      ThrowExceptionIfNull(sellerId);
                                      ThrowExceptionIfNull

           //获 取 宝 贝 以 及 宝 贝 的SKU
           ItemDO dbItem = getItemWithSkuThrowExceptionIfNull
                                         ThrowExceptionIfNull(itemId);
                                         ThrowExceptionIfNull

           //校 验 是 否 允 许 更 改 库存
           stepCheckModifyQuantity(… );

           //更 新 宝 贝 库 存
           doModifyItemQuantity(… );
       }catch
        catch(ErrorCodeException e) {
        catch
           return injectErrorCodeTo(result, e);
       }catch
        catch(Exception e) {
        catch
           throwIcException(e);
       }
封装的内容太多, 就拆分它
对外暴露内容太多, 封装
                    封装它

public Map<String, String> getFeatures() {
   return features;
}

features = item.getFeatures();
if (features == null) {… … }
features.get(“ prop” );



item.getFeatures().get(“ prop” )


public String getPropertyFeature(){… }
那些令人喷饭的注释




         //当我写这段代码的时候,只有老天和我自己知道我在做什么。
         //现在,只剩老天知道了。




//我不对以下代码负责。
//是他们逼我写的,是违背我意愿的。
注释尽量做到简洁




绅士的演讲,应该像女人的裙子,越短越好。
                       --林语堂
最好不写注释



写注释说明表达意图的失败

糟糕代码是注释存在的动机之一
必须写的注释



警告他人
版权协议
公共API
写注释的注意事项


无法自注释的情况(副作用)

注释与代码同步

注释只说明Why
“   对代码采用一致的格式, 这不是
浪费时间的愚蠢修饰, 而是一种重
浪费时间的愚蠢修饰,
要的交流工具。
          ”
      --Andy Hunt《程序员的思维修炼》
像报纸一样, 头版只放重要信息,细节放里面
选择一款赏心悦目的字体
代码排版的注意事项



紧密相关的代码放在一起

保持代码短小(width:80)

合理的运用空行和空格

保持格式统一一致
允许先写肮脏的代码, 但必须重构它
尽量借助工具重构, 避免人为错误
持续改进, 避免破窗效应
类    注释

 方法             格式

          整洁
命名               重构
          代码
参考资料

More Related Content

What's hot

Clean Code II - Dependency Injection
Clean Code II - Dependency InjectionClean Code II - Dependency Injection
Clean Code II - Dependency Injection
Theo Jungeblut
 
Clean Code I - Best Practices
Clean Code I - Best PracticesClean Code I - Best Practices
Clean Code I - Best Practices
Theo Jungeblut
 

What's hot (20)

Clean Code II - Dependency Injection
Clean Code II - Dependency InjectionClean Code II - Dependency Injection
Clean Code II - Dependency Injection
 
Clean architecture - Protecting the Domain
Clean architecture - Protecting the DomainClean architecture - Protecting the Domain
Clean architecture - Protecting the Domain
 
Clean Code - Writing code for human
Clean Code - Writing code for humanClean Code - Writing code for human
Clean Code - Writing code for human
 
Clean code and Code Smells
Clean code and Code SmellsClean code and Code Smells
Clean code and Code Smells
 
TRICK 2022 Results
TRICK 2022 ResultsTRICK 2022 Results
TRICK 2022 Results
 
Clean code
Clean codeClean code
Clean code
 
Clean Code I - Best Practices
Clean Code I - Best PracticesClean Code I - Best Practices
Clean Code I - Best Practices
 
Writing clean code
Writing clean codeWriting clean code
Writing clean code
 
SOLID Design Principles
SOLID Design PrinciplesSOLID Design Principles
SOLID Design Principles
 
Clojureの世界と実際のWeb開発
Clojureの世界と実際のWeb開発Clojureの世界と実際のWeb開発
Clojureの世界と実際のWeb開発
 
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
 
"Simple Made Easy" Made Easy
"Simple Made Easy" Made Easy"Simple Made Easy" Made Easy
"Simple Made Easy" Made Easy
 
Docker at Spotify - Dockercon14
Docker at Spotify - Dockercon14Docker at Spotify - Dockercon14
Docker at Spotify - Dockercon14
 
Design patterns
Design patternsDesign patterns
Design patterns
 
Clean code
Clean codeClean code
Clean code
 
[JCConf 2022] Compose for Desktop - 開發桌面軟體的新選擇
[JCConf 2022] Compose for Desktop - 開發桌面軟體的新選擇[JCConf 2022] Compose for Desktop - 開發桌面軟體的新選擇
[JCConf 2022] Compose for Desktop - 開發桌面軟體的新選擇
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
MVC の Model を考える
MVC の Model を考えるMVC の Model を考える
MVC の Model を考える
 
Clean code
Clean codeClean code
Clean code
 
The Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable DesignThe Art of Unit Testing - Towards a Testable Design
The Art of Unit Testing - Towards a Testable Design
 

Viewers also liked

Viewers also liked (7)

An Introduction to Clean Code Developer
An Introduction to Clean Code DeveloperAn Introduction to Clean Code Developer
An Introduction to Clean Code Developer
 
Clean code with SOLID principles
Clean code with SOLID principlesClean code with SOLID principles
Clean code with SOLID principles
 
Clean Code and Common Engineering Practices
Clean Code and Common Engineering PracticesClean Code and Common Engineering Practices
Clean Code and Common Engineering Practices
 
Don't Be STUPID, Grasp SOLID - ConFoo Edition
Don't Be STUPID, Grasp SOLID - ConFoo EditionDon't Be STUPID, Grasp SOLID - ConFoo Edition
Don't Be STUPID, Grasp SOLID - ConFoo Edition
 
Clean Code Development
Clean Code DevelopmentClean Code Development
Clean Code Development
 
Password Storage And Attacking In PHP - PHP Argentina
Password Storage And Attacking In PHP - PHP ArgentinaPassword Storage And Attacking In PHP - PHP Argentina
Password Storage And Attacking In PHP - PHP Argentina
 
Beyond design patterns phpnw14
Beyond design patterns   phpnw14Beyond design patterns   phpnw14
Beyond design patterns phpnw14
 

Similar to Keep your code clean

由一个简单的程序谈起--之四
由一个简单的程序谈起--之四由一个简单的程序谈起--之四
由一个简单的程序谈起--之四
yiditushe
 
Ejb工作原理学习笔记
Ejb工作原理学习笔记Ejb工作原理学习笔记
Ejb工作原理学习笔记
yiditushe
 
Java script closures
Java script closuresJava script closures
Java script closures
skywalker1114
 
重構—改善既有程式的設計(chapter 7)
重構—改善既有程式的設計(chapter 7)重構—改善既有程式的設計(chapter 7)
重構—改善既有程式的設計(chapter 7)
Chris Huang
 
Javascript之昨是今非
Javascript之昨是今非Javascript之昨是今非
Javascript之昨是今非
Tony Deng
 
所谓闭包
所谓闭包所谓闭包
所谓闭包
youzitang
 
GTest交流与经验总结
GTest交流与经验总结GTest交流与经验总结
GTest交流与经验总结
coderzh
 
由一个简单的程序谈起――之五(精华)
由一个简单的程序谈起――之五(精华)由一个简单的程序谈起――之五(精华)
由一个简单的程序谈起――之五(精华)
yiditushe
 
Node.js开发体验
Node.js开发体验Node.js开发体验
Node.js开发体验
QLeelulu
 
用Jquery实现拖拽层
用Jquery实现拖拽层用Jquery实现拖拽层
用Jquery实现拖拽层
yiditushe
 
Java多线程设计模式
Java多线程设计模式Java多线程设计模式
Java多线程设计模式
Tony Deng
 
改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法
crasysatan
 

Similar to Keep your code clean (20)

JavaScript Advanced Skill
JavaScript Advanced SkillJavaScript Advanced Skill
JavaScript Advanced Skill
 
由一个简单的程序谈起--之四
由一个简单的程序谈起--之四由一个简单的程序谈起--之四
由一个简单的程序谈起--之四
 
Ejb工作原理学习笔记
Ejb工作原理学习笔记Ejb工作原理学习笔记
Ejb工作原理学习笔记
 
Effective java 摘選條目分享 1 - 物件、複合、可變性、leak
Effective java   摘選條目分享 1 - 物件、複合、可變性、leakEffective java   摘選條目分享 1 - 物件、複合、可變性、leak
Effective java 摘選條目分享 1 - 物件、複合、可變性、leak
 
Java script closures
Java script closuresJava script closures
Java script closures
 
Java script closures
Java script closuresJava script closures
Java script closures
 
重構—改善既有程式的設計(chapter 7)
重構—改善既有程式的設計(chapter 7)重構—改善既有程式的設計(chapter 7)
重構—改善既有程式的設計(chapter 7)
 
Javascript之昨是今非
Javascript之昨是今非Javascript之昨是今非
Javascript之昨是今非
 
所谓闭包
所谓闭包所谓闭包
所谓闭包
 
GTest交流与经验总结
GTest交流与经验总结GTest交流与经验总结
GTest交流与经验总结
 
由一个简单的程序谈起――之五(精华)
由一个简单的程序谈起――之五(精华)由一个简单的程序谈起――之五(精华)
由一个简单的程序谈起――之五(精华)
 
Node.js开发体验
Node.js开发体验Node.js开发体验
Node.js开发体验
 
PHPUnit + Xdebug 单元测试技术
PHPUnit + Xdebug 单元测试技术PHPUnit + Xdebug 单元测试技术
PHPUnit + Xdebug 单元测试技术
 
用Jquery实现拖拽层
用Jquery实现拖拽层用Jquery实现拖拽层
用Jquery实现拖拽层
 
Java Thread
Java ThreadJava Thread
Java Thread
 
Arduino應用系統設計 - Arduino程式快速入門
Arduino應用系統設計 - Arduino程式快速入門Arduino應用系統設計 - Arduino程式快速入門
Arduino應用系統設計 - Arduino程式快速入門
 
前端测试
前端测试前端测试
前端测试
 
前端测试
前端测试前端测试
前端测试
 
Java多线程设计模式
Java多线程设计模式Java多线程设计模式
Java多线程设计模式
 
改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法改善程序设计技术的50个有效做法
改善程序设计技术的50个有效做法
 

Keep your code clean