code style 2014-07-18-pub
Post on 12-Aug-2015
106 Views
Preview:
TRANSCRIPT
Code StylePersiaCai
2014-07-18
一致的风格比“正确”的风格更重要
目录
Why Code Style What’s Code Style about How to follow
WHY
1、业界约定俗成
2、代码结构美学3、工程化的需要
WHAT
1、Specification(根据GoogleCodeStyle) 源文件及其结构 格式及注释 声明及命名
2、Best Practice方法、命名
1.1源文件及其结构
1、编码格式:UTF-82、换行:UNIX/LINUX 换行 (git设置)3、import,不使用通配符4、类成员顺序:
A、public – protected – private B、类成员在上,方法在下
2.1格式—括号
1、可选大括号也加上 if, else, for, do, while语句一起使用,即使只有一条语句(或是空),也应该把大括号写上
2、Kernighan和Ritchie风格
左大括号前不换行左大括号后换行右大括号前换行
if (condition()) { try {
something(); } catch (ProblemException e) { recover(); }}
2.2格式—注释
1、字段 /** xxx */2、方法
/** * */public void push(PaintBoard paintBoard) { doSomething(); }
2.2格式--注释
3、好代码>坏代码+注释4、记录你的思想 //这个用法是出于…考虑
2.3格式-缩进
1、语句块缩进每当一个新的语句块产生,缩进就增加两个空格。
当这个语句块结束时,缩进恢复到上一层级的缩进格数。
2、每句代码的结束都需要换行。3、行长度限制:80或100 长行要断行,断行缩进4字符
2.4格式-空白
1、垂直空白方法间空白行间隔
方法体类空白行进行逻辑分组
类成员之间,可以不空白行间隔
2、水平空白赋值等号前后的空白间隔
3.1声明
1、每次声明一个变量不要采用一个声明,声明多个变量。例如 int a, b;
2、不能像C风格一样声明数组应该是String[] args,而不是 String args[]
3、修饰符顺序public protected private abstract static final transient volatile synchronized
native strictfp
3.2命名
1、标示符只应该使用ASCII字母、数字和下划线,字母大小写敏感
尽量不使用前后缀,比如name_, s_name
2、包名全小写,并不使用下划线3、类名 class命名一般使用名词或名词短语。interface的命名有时也可以使用形容词或形容词短语;测试类以Test结尾;接口不加I,实现类Impl结尾
3.2命名
4、方法名 方法命名一般使用动词或者动词短语,在JUnit的测试方法中,可以使用下划线,用来区分测试逻辑的名字经常使用如下的结构:test<MethodUnderTest>_<state> 。例如:testPop_emptyStack 。
5、常量 大写加下划线分隔;一般使用名词或者名词短语命名。
6、变量非常量的成员变量命名(包括静态变量和非静态变量),采用lowerCamelCase命名;
Camel case 命名:XMLHTTPRequest改为XmlHttpRequest
7、参数名应该避免使用一个字符作为参数的命名方式。
Best Practice
代码的写法应当使别人理解它的时间最小化
可读性基本原理
一、命名
1、提防使用不同之处较小的名称 XYZControllerForEfficientHandlingOfStrings 与
XYZControllerForEfficientStorageOfStrings
在IDE自动补全,容易补全错。
2、使用可搜索的名称 变量作用域大的可以命名相对长一些,便于搜索。
3、每个概念对应一个词 fetch、retrieve、get等若同时出现,容易造成混乱,尽量统一只用一个词。
一、命名4、布尔值 经常以is开头后面跟名称或名称短语
isDigit,isProbablePrime,isEmpty,isEnabled,hasSiblings
缺点是降低逻辑表达式可读性:if isEmpty (if empty)
5、类型转换 使用toType,比如toString,toArray
6、返回视图使用asType,比如asList
7、返回基本类型使用typeValue,比如intValue
8、静态工厂经常使用valueOf,of,getInstance,newInstance,getType,newType
一、命名
9、避免泛泛的词downloadPage()要优于getPage()
countSize(),calculateSize()要优于getSize(),size(),前者表示重量级的,需要消耗时间
maxChars要优于maxLength
一、命名
10、用min,max表示上下限 minInputSize,maxInputSize
11、first,last表示包含的范围 firstDate,lastDate
12、begin,end表示包含-排除的范围 beginDate,endDate
13、动宾结构描述好所做的全部事情 printDocument, calcMonthlyRevenues
描述好返回值 printer.isReady()
14、计算值限定词加到名字最后revenueTotal、revenueAverage这样比totalRevenue、averageRevenue更容易看出命名含义、更有规则性
一、命名
15、常用对仗词begin/end、first/last、locked/unlocked、min/max、next/previous、old/new、opened/closed、visible/invisible、source/target、up/down
15、缩写的一般指导原则去掉所有非前置元音(computer->cmptr,apple->appl)使用每个单词的第一个或前几个字母
保留每个单词的第一个和最后一个字母
去除无用的后缀(ing、ed等)
二、函数
1、函数参数越少越好 调用方不用了解细节
2、同类型函数参数最好间隔 不间隔容易传错而不自知
3、避免out型参数 容易引起混乱,统一在返回值里返回
4、避免boolean参数 调用方不知道啥意思,采用枚举替代5、超过4个参数最好封装为类 同时增加precondition校验
二、函数
6、参数避免传null null值意义不明确
7、返回值避免传null 集合类型返回EMPTY_LIST/EMPTY_MAP/EMPTY_SET, EMPTY_ARR?
8、分隔指令与询问 函数要做什么,要回答什么,二者不可兼得。
只做一件事情,提供功能内聚性。
if(set("username","unclebob")){ ...}
if(attributeExists("username")){ setAttribute("username","unclebob");}
二、函数
9、异常代替错误码 错误码常常暗示这枚举,应变性差,容易造成if嵌套,改用exception,错误处理就能从主路径代码中分离出来,得到简化。
10、不要使用异常控制循环体
for(Item item : items){ try{ doSomething(item); }catch(Exception e){ continue; } }
try{ Iterator<Foo> i = collection.iterator(); while(true){ Foo foo = i.next(); }}catch(NoSuchElementException e){}
二、函数
11、分离try/catch的主体 抽出方法,简洁
12、使用卫述句void compute(){ Server server=getServer(); if(server==null) return; Client client=server.getClient(); if(client==null) return; Request current=client.getRequest(); if(current==null) return; processRequest(current);}
二、函数
13、容器成员提供额外封装 封装增加或删除元素方法,对于返回整个容器,尽量返回不可变类型
List<Book> getBooks(){ return Collections.unmodifiableList(books);}
void addBook(Book arrival){ books.add(arrival);}
int bookCount(){ return books.size();}
Iterator getBooks(){ return books.iterator();}
二、函数
14、尽量避免连续调用 builder,stream等模式除外
predeal.getPlanTask().getProduct().getCoverImg();
二、函数
15、方法命名帮助传参
16、描述化
assertEquals(expected,actual),让调用者需要注意传入的顺序,有一定的犯错的概率。
assertExpectedEqualsActual(expected,actual),这样的函数命名,就大大减轻了记忆参数顺序的负担。
List moduleDependees = module.getDependSubsystems();String ourSubSystem = subSysMod.getSubSystem();if(moduleDependees.contains(ourSubSystem ))
//does the module from the global ....if(module.getDependSubsystems().contains(subSysMod.getSubSystem()))
二、函数
17、防卫式校验
18、慎用可变参数
public Period(Date start, Date end) { if (start.compareTo(end) > 0) throw new IllegalArgumentException( start + " after " + end); this.start = start; this.end = end; }
#wrongSystem.out.println(Arrays.asList(myArray));#rightSystem.out.println(Arrays.toString(myArray));
二、函数
19、for优先于whileIterator<Element> i = c.iterator();while(i.hasNext()){ doSomething(i.next());} for(Iterator<Element> i =c.iterator();i.hasNext();){ doSomething(i.next());} �
Iterator<Element> i2 = c2.iterator();//BUG,拷贝出错了while(i.hasNext()){ doSomething(i.next());}//compile errorfor(Iterator<Element> i2 =c2.iterator();i.hasNext();){ doSomething(i.next());}
二、函数
20、for-each优先于forpublic class NestedIteration { public static void main(String[] args) { Collection<Suit> suits = Arrays.asList(Suit.values()); Collection<Rank> ranks = Arrays.asList(Rank.values()); List<Card> deck = new ArrayList<Card>(); //BUG,NoSuchElementException for (Iterator<Suit> i = suits.iterator(); i.hasNext(); ) for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); ) deck.add(new Card(i.next(), j.next())); // Preferred idiom for nested iteration on collections and arrays// for (Suit suit : suits)// for (Rank rank : ranks)// deck.add(new Card(suit, rank)); }}
二、函数
21、不要修改入参
inputVal是入参,容易理解为不变的,后续修改者可能把它当做不变量用。
public int sample(int inputVal){ inputVal = inputVal * 2; … return inputVal; }
public int sample(int inputVal){ int workingVal= inputVal * 2; … return workingVal; }
二、函数
22、异常的抽象层次应与方法一致
此处不应该把底层异常抛出去,暴露了实现细节,应该包装为与之在同一层次的异常
class Employee{ public TaxId getTaxId() throws EOFException{ }}
class Employee{ public TaxId getTaxId() throws EmployeeDataNotAvailable{ }}
二、函数
23、用布尔变量对程序加以文档说明
目的不明确的布尔判断 VS 目的明确的布尔判断
if( (elementIndex < 0) || (MAX_ELEMENTS < elementIndex) || (elementInddex == lastElementIndex) ){}
finished = (elementIndex < 0) || (MAX_ELEMENTS < elementIndex) ;repeatedEntry = elementInddex == lastElementIndex ;If (finished || repeatedEntry){
}
函数
相对于追求最小化代码行数,一个更好的度量方法是最小化人们理解它所需的时间。
if (exponent >= 0) {return mantissa * (1 << exponent);
} else {return mantissa / (1 << -exponent);
}
return exponent >= 0 ? mantissa * (1 << exponent) : mantissa / (1 << -exponent);
三、循环
1、在写一个比较时
(while(bytes_expected>bytes_received)),
把改变的值写在左边并且把更稳定的值写在右边更好一些(while(bytes_received<bytes_expected))。
三、循环
2、什么时候使用while,什么时候使用for
while是灵活的循环,适用于预先不知道循环要迭代多少次;
for循环用来执行那些不需要循环内部控制的简单操作,适合循环控制就是简单的递增或递减,无须在循环内部去控制循环条件。
尽量不要在for循环通过直接修改下标值的方式迫使它终止。
三、循环
3、带退出循环,更容易维护
while(true){ if(rating < target){ break; } rating = cal(parm);}
rating = cal(param);while(rating < target){ rating = cal(param);}
重复的代码,在修改的时候,常常忘记保持一致
三、循环
4、循环内务操作尽量放到循环体内,循环头仅仅控制条件
while((inputChar = dataFile.getChar()) != EOF_CHAR){ ;}
do{ inputChar = dataFile.getChar();} while( inputChar != EOF_CHAR)
三、循环
4、误用for循环
for(inputFlie.moveToStart(),recordCount =0; !inputFile.endOfFile(); recordCount++){ inputFile.getRecord();}
For循环头的位置保留给循环控制语句。
inputFile.moveToStart();recordCount=0;while(!inputFile.endOfFile()){ inputFile.getRecord(); recordCount++;}
单元测试
(1)快速(Fast) 快速运行
(2)独立(Independent) 每个测试相互独立,某个测试不应该为下一个测试的设定条件
(3)可重复(Repeatable) 在任何环境可以重复通过
(4)自足验证(Self-Validating) 测试应该有布尔值输出,无论是通过还是失败,不应该通过日志文件来确认测
试是否通过。
(5)及时(Timely) 在编写代码之前编写测试
单元测试
1、一个单元测试是一段代码,这段代码调用一个工作单元,并检验该工作单元的一个具体的最终结果。如果关于这个最终结果的假设是错误的,单元测试就失败了。一个单元测试的范围可以小到一个方法,大到多个类。
2、集成测试是对一个工作单元进行的测试,这个测试对被测试的工作单元没有完全的控制,并使用该单元的一个或多个真实依赖物,例如时间、网络、数据库、线程或随机数产生器等。
3、单元测试方法的命名:[UnitOfWorkName]_[ScenarioUnderTest]_[ExpectedBehavior]
实例:isValidFileName_badExtension_returnFalse()
isValidFileName_goodExtensionLowercase_returnsTrue()
4、一个测试通常包括Arrange、Act和Assert这3部分,分别表示测试准备、调用带测方法、验证结果是否符合预期。
5、在一个测试中先写最后的Assert部分,然后推导出Act和Arrange这两部分代码,会更加符合TDD的测试驱动风格,营造出分形的和谐气氛。
单元测试臭味
1、强制的测试顺序
不能保证测试的可重复性
2、测试方法中调用其他测试方法
破坏了测试的独立性
3、破坏共享状态
破坏了测试的稳定性
HOW
Reference
Google Java Code Style
Reference
Reference
Q
A
top related