基于Oracle,Google,Twitter和SpringFramework的编码标准
本文的目的是为您提供基于Oracle,Google,Twitter和SpringFramework等技术巨头的编码标准的"做与不做"的简要概述,换句话说,您更喜欢和避免。
您可能同意或不同意此处介绍的一些最佳做法,并且只要有某种编码标准就可以了。
为什么首先要编码标准?如果您使用Google进行搜索,有很多充分的理由,下面将为您提供以下插图
编码标准文档可能冗长而乏味。本文从Google,Oracle,Twitter和Spring的编码约定中挑选了一些零碎的内容,其目的是为您提供易于理解且较无聊的做法,以使您的代码易于阅读和维护。
几乎总是您会加入使用现有软件的团队,并且大多数作者很有可能离开或切换到其他项目,这使您陷入困扰人类的部分代码。
让我们深入了解各种编码标准中的最佳做法。
Java源文件
关于Java源文件,以下内容被视为最佳实践:
·源文件长度小于2,000行代码
packagecom.example.model;
/**
*Implementation-freeperspectivetobereadbydevelopers
*whomightnotnecessarilyhavethesourcecodeathand
*
*@authorx,y,z
*@date
*@version
*@copyright
*/
importcom.example.util.FileUtil;
/*
*Optionalclassspecificcomment
publicclassSomeClass{
//Staticvariablesinorderofvisibility
publicstaticfinalIntegerPUBLIC_COUNT=1;
staticfinalIntegerPROTECTED_COUNT=1;
privatestaticfinalIntegerPRIVATE_COUNT=1;
//Instancevariablesinorderofvisibility
publicStringname;StringpostalCode;
privateStringaddress;
//Constructorandoverloadedinsequentialorder
publicSomeClass(){}
publicSomeClass(Stringname){
this.name=name;
}
//Methods
publicStringdoSomethingUseful(){
return"Somethinguseful";
//getters,setters,equals,hashCodeandtoStringattheend
}命名
类和接口的名称均为CamelCase,建议使用整个单词,并避免使用缩写词/缩写。例如Raster类或ImageSprite类
·包-在com.deepSpace或com.deep_space上命名com.deepspace
·文件-名称为CamelCase,以.java结尾,与类名匹配。每个文件有一个公共类,文件中有每个顶级类
·方法-名称应为混合大小写的动词,每个内部单词用大写字母表示,例如run();或runFast();
·常量-应该用大写字母"_"分隔每个单词,例如intMIN_WIDTH=44;并且intMAX_WIDTH=99;
·变量-一个名称,告诉程序的读者变量代表什么,即,如果要存储测试等级,则选择等级vsvar1。变量名要简短,避免包含元数据。
//Prefer()-variablenamesshortanddescribewhatitstores
intschoolId;
int[]filteredSchoolIds;
int[]uniqueSchooldIds;
MapusersById;
Stringvalue;
//Avoid(x)-Toodetailedvariablenaming
intschoolIdentificationNumber;
int[]userProvidedSchoolIds;
int[]schoolIdsAfterRemovingDuplicates;
MapidToUserMap;
StringvalueString;
请记住,变量名应该简短,并易于告诉读者它代表什么值。用你的判断。
倾向性和避免
格式和缩进都是组织代码以使其易于阅读,其中包括间距,行长,换行和换行等
·缩进-使用2或4个空格或制表符并保持一致
·行长-取决于可读性的影响,最多70至120个字符。消除水平滚动和在逗号和运算符后放置换行符的需求非常重要。
方法-以下是最佳做法清单
//Prefer()Linebreaksarearbitraryandbreakafteracomma.
StringdownloadAnInternet(Internetinternet,
Tubestubes,
Blogosphereblogs,
Amountbandwidth){
tubes.download(internet);
//Avoid(x)Hardtodiffmethodargstomethodbody
//Prefer()Add8(doubleof2or4)spacesfordeepindent
privatestaticsynchronizedhorkingLongMethodName(intanArg,
ObjectanotherArg,
StringyetAnotherArg,
ObjectandStillAnother){
...
//Prefer()Easyscanningandextracolumnspace.
publicStringdownloadAnInternet(Internetinternet,
>Aunittestwouldhavecaughtthat
//Avoid(x)Donotomit{}
if(condition)
statement;
//Avoid(x)
if(x<0)negative(x);
if(a==b&&c==d){
//Prefer()
if((a==b)&&(c==d)){
if(condition){
statements;
}elseif(condition){
if((condition1&&condition2)
||(condition3&&condition4)
||!(condition5&&condition6)){//BADWRAPS
doSomethingAboutIt();//MAKETHISLINEEASYTOMISS
||!(condition5&&condition6)){
doSomethingAboutIt();
三元运算符-以下是推荐做法
alpha=(aLongBooleanExpression)beta:gamma;
alpha=(aLongBooleanExpression)beta
:gamma;
alpha=(aLongBooleanExpression)
beta
Switch-切换时,最佳做法是
·即使没有代码也总是有默认default情况
·使用/*fallsthrough*/表示控件属于下一种情况
switch(condition){
caseABC:
/*fallsthrough*/
caseDEF:
break;
default:
异常消息-引发异常时,这里是缩进和缩进不好的消息的示例。
//Avoid(x)-Noteasytoread
thrownewIllegalStateException("Failedtoprocessrequest"+request.getId()
//Prefer()-Fairlyeasiertoread
thrownewIllegalStateException("Failedtoprocess"
+"request"+request.getId()
+"foruser"+user.getId()
迭代器和流-流变得越来越普遍,有时可能非常复杂,因此,缩进以便于阅读非常重要。
Iterablemodules=ImmutableList.builder().add(newLifecycleModule())
.add(newAppLauncherModule()).addAll(application.getModules()).build();
Iterablemodules=ImmutableList.builder()
.add(newLifecycleModule())
.add(newAppLauncherModule())
.addAll(application.getModules())
>Justfollowacodingstandard—anyreally
intlevel;//indentationlevel
intsizeMeter;//sizeoftable
//Avoid(x)infavourofabove
intlevel,sizeMeter;
//Prefer()-Includeunitinvariablenameortype
longpollIntervalMs;
intfileSizeGb;
AmountfileSize;
//Avoid(x)mixingtypes
intfoo,fooarray[];
//Avoid(x)-Donotseparatewithcomma
Format.print(System.out,“error”),exit(1);
//Avoid(x)multipleassignment
//Avoid(x)embeddedassignmentsinattempttoincreaseperformance//orsavealine.Iamguiltyofdoingthis:(
d=(a=b+c)+r;
//Prefer()overabove
a=b+c;
d=a+r;
String[]args
Stringargs[]
//Prefer()Longuse"L"insteadof"l"toavoidconfusionwith1
longtimeout=3000000000L;
//Avoid(x)-Hardtotelllastletterislandnot1
longtimeout=3000000000l;
//Prefer()declareatthebeginningoftheblock.
publicvoiddoSomething(){
intwhatIRepresent;//beginningofmethodblock
intsomeFlag;//beginningof“if”block
…
intcount;
intcount;//AVOID!
间距和换行符—避免以牺牲可读性为代价来保存1-2行代码的诱惑。这是有关间距和空白行的所有最佳实践(空格确实有所作为)
·方法和Spring开发人员之间的一(1)条空行建议在构造函数,静态块,字段和内部类之后的两(2)条空行
·空格键运算符,即使用intfoo=a+b+1;而非intfoo=a+b+1;
·分隔除"."外的所有二进制运算符。使用空格分割
//Prefer()-Spaceafter"while"andbefore"("
while(true){
//Avoid(x)-Unlikeabovenospace
//Prefer()-Nospacebetween"doSomething"and"("
//Avoid(x)-Unlikeabovespace
//Prefer()-Addaspaceafteranargument
publicvoiddoSomething(inta,intb){
//Prefer()-Spacebetweenoperandandoperators(i.e.+,=)
a+=c+d;
a=(a+b)/(c*d);
while(d++=s++){
n++;
}文档和注释
值得一提的是,几乎所有代码都会在其整个生命周期中进行更改,除非您明确说明,否则有时您或某人会试图弄清楚打算使用复杂的代码块,方法或类做什么。现实几乎总是如下
有时,对复杂的代码,方法,类的注释不会增加任何值或无法达到其目的。为此,通常在注释时会发生这种情况。
实施注释—用于注释掉代码或对代码的特定实现进行注释。
文档注释—旨在从无实现的角度描述代码规范,以供可能不一定拥有源代码的开发人员阅读。
注释的类型
共有四(4)种实施注释,如下所示
·块注释-请参见下面的示例
·单行注释-当注释不超过一行时
·行尾注释—开始注释,并继续到换行符。它可以注释掉整行或仅部分行。不应在连续的多行中使用它来进行文本注释;但是,它可以在连续的多行中用于注释掉代码段。
//Blockcomment
*Usage:Providesdescriptionoffiles,methods,datastructures
*andalgorithms.Canbeusedatthebeginningofeachfileand
*beforeeachmethod.Usedforlongcommentsthatdonotfita
*singleline.1Blanklinetoproceedaftertheblockcomment.
//Singlelinecomment
/*Handlethecondition.*/
//Trailingcomment
if(a==2){
returnTRUE;/*specialcase*/
}else{
returnisPrime(a);/*worksonlyforodda*/
//Endoflinecomment
if(foo>1){
//Doadouble-flip.
returnfalse;//Explainwhyhere.
//if(bar>1){
//
////Doatriple-flip.
//...
//}
//else
//returnfalse;文档注释(即Javadoc)
Javadoc是一种工具,它使用以/**开头和以*/结束的注释从Java代码生成HTML文档,有关Javadoc的工作方式或阅读全文,请参阅Wikipedia。
这是一个Javadoc示例
*ReturnsanImageobjectthatcanthenbepaintedonthescreen.
*Theurlargumentmustspecifyanabsolute{@linkURL}.Thename
*argumentisaspecifierthatisrelativetotheurlargument.
*Thismethodalwaysreturnsimmediately,whetherornotthe
*imageexists.Whenthisappletattemptstodrawtheimageon
*thescreen,thedatawillbeloaded.Thegraphicsprimitives
*thatdrawtheimagewillincrementallypaintonthescreen.
*@paramurlanabsoluteURLgivingthebaselocationoftheimage
*@paramnamethelocationoftheimage,relativetotheurlargument
*@returntheimageatthespecifiedURL
*@seeImage
publicImagegetImage(URLurl,Stringname){
try{
returngetImage(newURL(url,name));
}catch(MalformedURLExceptione){
returnnull;
当对具有以上代码的代码运行javadoc时,以上代码将导致HTML如下所示
>Seehereformore
这是一些关键标记,可用于增强生成的Java文档的质量。
@author=>@authorRaf
@code=>{@codeAC}
@deprecated=>@deprecateddeprecation-message
@exception=>@exceptionIOExceptionthrownwhen
@link=>{@linkpackage.class#memberlabel}
@param=>@paramparameter-namedescription
@return=>Whatthemethodreturns
@see=>@see"string"OR@see
@since=>Toindicatetheversionwhenapubliclyaccessiblemethodisadded
有关完整列表和更详细的说明,请参见
oracle/technetwork/java/javase/tech/index-137868.html
Twitter的编码标准建议不要使用@author标签
代码可以在其生命周期内无数次换手,并且源文件的原始作者在经过多次迭代后常常是无关紧要的。我们发现最好信任提交历史记录和OWNERS文件来确定代码主体的所有权。
以下示例说明了如何按照Twitter的编码标准中的描述撰写有见地的文档注释
//Bad.
*Splitsastring.
*@paramsAstring.
*@returnAlistofstrings.
Listsplit(Strings);
//Better.
//-Weknowwhatthemethodsplitson.
//-Stillsomeundefinedbehavior.
*Splitsastringonwhitespace.
*@paramsThestringtosplit.An{@codenull}stringistreatedasanemptystring.
*@returnAlistofthewhitespace-delimitedpartsoftheinput.
//Great.
//-Coversyetanotheredgecase.
*Splitsastringonwhitespace.Repeatedwhitespacecharacters
*arecollapsed.
写注释时专业很重要的
userId=Integer.parseInt(xml.getField("id"));
}catch(NumberFormatExceptione){
//TODO(Jim):Tuckfieldvalidationawayinalibrary.
而且重要的是要记住,除非实现已更改,否则不要记录重写的方法。
还有几点需要牢记
·覆盖时始终使用@Override注解
·鼓励在字段或方法返回null时使用@Nullable
//FIXME(Raf):Anactionablemessagedescribewhatneedstobedone
//TODO(Raf):Anactionablemessagedescribewhatneedstobedone
最终的目的是编写使将来的作者和维护者的生活变得轻松的代码。