编码规范约定(Java)

编码规范约定(初稿)

标签: Java

此规范是前公司写的一份约定初稿,这里我只是简单的记录一下,有时间再对其进行修改和完善。


[TOC]


1. 注释

1.1 代码注释

每个类和自建的public方法必须包含Javadoc注释,注释至少要包含描述该类或方法用途的语句,并且该语句应该用第三人称的动词形式来开头。

例如:

    /**
     * Tools for doing something.
     */
    public class SomeTools {
    }

    /**
     * Returns true if the string is null or 0-length.
     */
    public static boolean isEmpty(CharSequence str) {
    }

对于那些无关紧要的类似setFoo()的get和set语句是不必撰写注释;如果方法执行了比较复杂的操作(比如执行强制约束或者产生很重要的副作用),那就必须进行注释。如果“Foo”属性的意义不容易理解,也应该进行注释。


1.2 使用TODO注释

对那些临时性的、短期的、够棒但不完美的代码,请使用TODO注释;TODO注释应该包含全部大写的TODO,后跟一个冒号,如:

// TODO: Change this to use a flag instead of a constant.

此外,如果TODO注释是“将来要做某事”的格式,则请确保包含一个很明确的日期(“在2005年11月会修正”),或是一个很明确的事件(如:“在所有代码整合人员理解了V7协议之后删除本段代码”)。

下面以一段因产品临时需求变更但又 有可能随时回滚 的场景为例:

Bad

    
    //void doChangedSomething(){
    //    ...
    //}
    

Good

    //TODO: 由于产品需求变更:去除逻辑XXX(之前的逻辑描述),将“这版本 5.0 正式发布后删除此代码”
    //void doChangedSomething(){
    //    ...
    //}

1.3 代码注释注意事项

  • 注释应该增加代码的清晰度
  • 保持注释的简洁
  • 在写代码之前写注释
  • 注释出为什么做了一些事,而不仅仅是做了什么
  • 文档注释:在紧靠接口、类、成员函数和字段声明的前面注释它们。
  • 在成员函数内采用单行注释,来说明业务逻辑、代码段和暂时变量的声明。注释符"//"后必须紧跟一个空格,然后才是注释信息。
  • 注释哪些部分:
  1. 类。类的目的、即类所完成的功能,注释出采用的变量。
  2. 接口。 设置接口的目的、它应如何被使用以及如何不被使用。
  3. 成员函数注释。对于设置与获取成员函数,在成员变量已有说明的情况下,可以不加注释;普通成员函数要求说明完成什么功能,参数含义是什么返回什么。
  4. 普通成员函数内部注释。 控制结构,代码做了些什么以及为什么这样做,处理顺序等。
  5. 实参/参数。 参数含义、及其它任何约束或前提条件。
  6. 字段/属性。 字段描述。
  7. 局部变量。 无特别意义的情况下不加注释。

2. Java 代码编写约定

2.1 遵守字段命名惯例

  • 非public的、非static的字段名称以m开头

  • 非final 的static字段名称以s开头

  • 其它字段以小写字母开头

  • public static final 字段(常量)全部字母大写并用下划线分隔

    Bad

        class CodeStyle{
    
        private int count;
        
        private static int NextAccessibilityViewId;
        
        public static final int drawing_cache_quality_high = 0x00100000;
        
        public void doSomething(String mParams){
            
            ...
        }
    }
    

    Good

        class CodeStyle{
    
        private int mCount;
        
        private static int sNextAccessibilityViewId;
        
        public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
        
        public void doSomething(String params){
            
            ...
        }
    }
    

2.2 尽量采用英语语义来声明类,变量及方法名

尽可能采用英语的语义拼写来命名并尽可能符合如下规则:

  1. 使用完整描述符来准确地描述变量、字段或类。

  2. 使用适用于领域内的术语。如果您的用户将他们的客户称为顾客,则对这个类使用术语Customer来代替Client。

  3. 避免长型名称,一般不要超过15个字符。

  4. 避免使用下划线。

  5. 类的普通方法一般采用完整的英文描述说明成员方法功能,第一个单词应是采用一个生动的 动词,并且首字母小写,其它每个单词首字母大写。例如 openFile(), addAccount()。

  6. 类的获取方法(一般具有返回值)一般要求被方法名使用被访问字段名,前面加上前缀get,例如getFirstName(), getLastName()。

  7. 类的布尔型的判断方法一般要求方法名使用单词 is 做前缀,如isPersistent(),isString()。或者使用具有逻辑意义的单词,例如equal 或equals。

  8. 类的设置方法(一般返回类型为void):被访问字段名的前面加上前缀 set,例如setFirstName(),setLastName(),setWarpSpeed()。

  9. 构造方法应该用递增的方式写(比如:参数多的写在后面)。例如:

    public CounterSet(){
    
    }
    
    public CounterSet(int size){ 
       this.size = size;
    }
    

2.3 编写简短的方法

为了把规模控制在合理范围内,方法应该保持简短和重点突出。不过,有时较长的方法也是合适的,所以对方法的代码长度并 没有硬性的限制 。如果方法代码超过了40行,就该考虑是否可以 在不损害程序结构的前提下 进行分拆。


2.4 在标准的位置定义成员变量和方法

  1. 重载永不分离
    当一个类有多个构造函数,或是多个同名方法,这些函数/方法应该按顺序出现在一起,中间不要放进其它函数/方法

    Bad

        public class LinearLayout extends ViewGroup {
        
        public LinearLayout(Context context) {
            super(context);
        }
        
        public void doSomething(){
            ...
        }
        
        public LinearLayout(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
        
        public LinearLayout(Context context, AttributeSet attrs, int defStyle) {
            
            super(context, attrs, defStyle);
            
            ...
        }
      }
    

    Good

        public class LinearLayout extends ViewGroup {
        
        public LinearLayout(Context context) {
            super(context);
        }
        
        public LinearLayout(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
        
        public LinearLayout(Context context, AttributeSet attrs, int defStyle) {
            
            super(context, attrs, defStyle);
            
            ...
        }
        
        public void doSomething(){
            ...
        }
      }
    
  2. 以逻辑分块排列每个类的成员
    每个类应该以某种逻辑去排序它的成员,维护者应该要能解释这种排序逻辑。比如, 新的方法不能总是习惯性地添加到类的结尾,因为这样就是按时间顺序而非某种逻辑来排序的;
    再比如activity生命周期的成员方法应集中放置并放置在类的前方;在功能上存在逻辑关联的变量应集中放置;在功能上存在逻辑关联的方法应集中放置;该类实现的接口或重载的父方法应该集中放置并放置在类的前方。

    Bad

          public class BaseActivity extends Activity {
    
          @Override
          protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
          }
          
          public void doSomething(){
            
          }
        
          @Override
          protected void onRestart() {
            super.onRestart();
          }
          
          public void doOtherSomething(){
            
          }
        
          @Override
          protected void onPostResume() {
            super.onPostResume();
          }
          
          public static Intent newInstance(Bundle paramBundle){
            
            Intent intent = new Intent();
            
            // doSomething
            
            return intent;
          }
        
          @Override
          public CharSequence onCreateDescription() {
            return super.onCreateDescription();
          }
        
          @Override
          protected void onDestroy() {
            super.onDestroy();
          }
     }
    

    Good

          public class BaseActivity extends Activity {
      
          public static Intent newInstance(Bundle paramBundle){
            
            Intent intent = new Intent();
            
            // doSomething
            
            return intent;
          }
    
          @Override
          protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
          }
          
          @Override
          protected void onRestart() {
            super.onRestart();
          }
          
          @Override
          protected void onPostResume() {
            super.onPostResume();
          }
          
          @Override
          public CharSequence onCreateDescription() {
            return super.onCreateDescription();
          }
        
          @Override
          protected void onDestroy() {
            super.onDestroy();
          }
          
          public void doSomething(){
            
          }
          
          public void doOtherSomething(){
            
          }
     }
    

2.5 限制局部变量的作用范围

局部变量的作用范围应该是限制为最小的(Effective Java第29条)。使用局部变量,可以增加代码的可读性和可维护性,并且降低发生错误的可能性。每个变量都应该在 最小范围的代码块中进行声明 ,该代码块的大小只要能够包含所有对该变量的使用即可。应该在第一次用到局部变量的地方对其进行声明。几乎所有局部变量声明都应该进行初始化。 如果还缺少足够的信息来正确地初始化变量,那就应该推迟声明,直至可以初始化为止


2.6 大括号

大括号与if, else, for, do, while语句一起使用,即使只有一条语句(或是空),也应该把大括号写上。

Bad

    ... ...
    
    if(isOk)
        doSomething();
    else
        doOtherSomething();
    
    ... ...

Good

    ... ...
    
    if(isOk){
        doSomething();
    }else{
        doOtherSomething();
    }
    ... ...

2.7 慎用Log

记录日志会对性能产生显著的负面影响。如果日志内容不够简炼的话,很快会丧失可用性。但鉴于我们项目在 发布版本前都会删除Log ,需要必须遵守的是, 绝对不要使用System.out.println() (或本地代码中的printf()) 。System.out 和 System.err会重定向到/dev/null,因此print语句不会产生任何可见的效果。可是,这些调用中的所有字符串创建工作都仍然会执行。


3. Git约定

3.1 分支命名

  1. 对于每个版本的基础分支以 “develop/<当前版本号>”命名;
  2. 对于某个版本中的每个功能点的分支以“feature/<当前版本号>/<功能点名称>”命名;
  3. 对于体验优化线每个功能点的分支以“feature/ueo/<功能点名称>”命名;
  4. 对于某个专版渠道的版本以“custom/<当前版本号>-<专版名称>”命名;
  5. 原则上功能点名称不能包含develop、master、feature、ueo、custom相关字段。

3.2 版本发布注意事项

  1. 确认最终封版后,必须以当前的develop分支打好对应的tag,tag 名称为v_<当前版本号>;
  2. 输出了发布的Apk包后,必须以最终发布代码打好对应的tag,tag 名称为v_release-<当前版本号>,注意此时分支应该是已删log的代码且记得把对应的混淆输出文件(如:mapping.txt文件等)上传。

4. 结语

我们的最终目标是:保持代码的一致性,提高代码的可读性来保证代码的高质量及高维护性。

这个仅仅是初稿,有任何建议大家均可加入和修改。

5. 参考资料

Google Java代码风格规范

Code Style Guidelines for Contributors

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335

推荐阅读更多精彩内容

  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,331评论 0 17
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,513评论 18 399
  • 1 enum不能用作 变量名 备注:java 5以后enum是关键字 2 equals(obj)和hashCode...
    落落落落大大方方阅读 961评论 0 1
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,502评论 18 139
  • 总想着,自己应该洒脱点。 却总是,爱驻足在留有故事的地方。 庆幸的是,总是可以找个冠冕堂皇理由逃离。 不幸的是,在...
    征鸿_阅读 133评论 0 0