实用主义编程规范:JAVA篇

JAVA代码规范

1.规范说明

此规范包含:避免出现常见恶劣代码的禁令;指导编写合格代码的基本规则

此规范不包含:分析与设计出符合业务需求的代码;

2.基本原则

a)规范代码的原因

写程序的过程中,读代码的时间和写代码的时间只比为:10比1

软件生命周期中有80%的时间是维护

丢弃代码,对于老板来说,等于丢弃金钱

b)何时执行规范

童子军第一军规:离开营地前,让营地比你来的时候更干净。

提交代码时,让代码比你打开的时候更规范

如果不随时执行规范,规范将永远不会被执行

修改每行代码的时候,思考一下怎么写才是规范的,不要只急着完成功能

c)一号禁令

不可重复!

重复的代码带来重复的修改,漏掉处理的BUG,重复的修改会让你没日没夜的加班!如果没有重复代码,表示日后不管怎么修改,都不会被以往的代码所“拖累”,特别是另外一个人来修改这份代码的时候

写下段代码之后,回忆一下是否有别处有类似的功能,如果有就立刻抽取相同部分合并成一个新的函数,然后两个地方都调用这个新函数

d)追求表达力

像写文章一样写源代码

文章讲究用词、表达顺序,电脑确不关心源代码的可读性。如果只满足电脑的阅读性,源代码将很快连作者都看不懂

写代码除了关注如何实现功能,动手之前还要考虑一下命名和段落顺序、注释等要数,要为将来一年后重新阅读这些代码的人做好准备,很可能这个人就是你自己,或者是你的老板

e)简单就是美

尽量少的架构,尽量少的类,尽量少的函数,尽量少的源代码

为了满足复杂的需求,需要复杂的代码;但对于我们还不清楚的事情,我们才会搞的复杂。复杂并不会带来将来的简单。写代码不是攒钱,现在多做的工作往往不会减少将来的工作,反而会让你将来难以决定是否应该重新写一个

只完成最清楚的需求,尽量清晰的完成代码,功能越单一,将来可重用的机会越大

f)不可忽视警告

不可关闭IDE和编译器的警告

不可糊弄IDE和编译器的警告

确保你明白这些警告的意义,并且以推荐的方式修改代码解决

IDE和编译器的警告都是很多真正的行家所设定的,如果不了解这些行家为什么设置这些东西,你就一定会在某个地方吃亏

积极认真的对待警告,了解产生警告的原因,认真的思考如果要解决这些警告应该如何做,结果往往是一段高质量的代码,甚至是优秀的程序设计思路

3.命名

a)原则

i.超过1个字符的名字,使用英语单词,禁止使用汉语拼音,禁止使用无意义字符串,禁止使用不通用的缩写

代码是必须要被人阅读的,混杂着缩写、拼音、代号的文章就类似解谜游戏,好玩但浪费时间

虽然英语不是母语,但是用英语键盘输入英语单词,是意思表达最准确的而且效率最高的做法。

ii.禁止出现2个以上近义词

类似Manager和Driver或者Controller都是类似的含义,但如果在代码中表达不同的概念,容易混淆;如果表达相同的概率,让人厌烦,最好只用其中之一

当你难以给一个东西决定名字,而要“随便”搞一个的时候,请看下一条。

iii.优先使用业务逻辑领域词;其次使用技术领域词

一堆和你的业务领域完全无关的名字,很难让人知道这些代码是搞什么功能的,就和你用10000111100这种二进制来表达数字一样。同样如果你在使用某种明显的技术、模式、框架,而用另外一些奇怪的名字,也会让人难以了解你的实现细节,甚至误解你的实现

如果你的代码明确的为某一业务功能所写,大胆用业务功能作为名字,这是最好的选择。如果你的代码属于技术内部实现的部分,则使用你选定的技术惯用的名字,学习标准API里面的名字是个不错的做法。

b)包名(目录名)

全小写,使用URL域名组织。禁止使用不按域名倒序设定包名。

结构:公司域名.项目名.系统名.*

禁止使用纯数字作为包名的一个小节,因为JAVA规范不支持(如com.163.*就是非法的)

例子:com.netease.mail.uià网易邮箱项目的UI系统的包

在混乱的目录中难以找到文件,在不同的逻辑组织成的目录树中也难以找到文件

域名作为几乎免费可以拥有,并且可以良好组织的命名资源来说,几乎是独一无二的。全世界的资源都可以使用这个名字来管理,何况是自己的那一点代码?

c)类名(文件名)

类名必须是名词

必须是完整单词,禁止使用非通用缩写,通用缩写使用全大写,如URL,而不是Url或者url

首字母必须大写

例子:FightingSkillà战斗技能类

类表示了代码的组织,名词更容易分类和理解

使用业务领域或技术解决方案的名词作类名,可以让读者直接从名字就了解这些代码的用途。

d)方法名

方法名必须是动词或动词短语

首字母必须小写,后续单词的首字母必须大写

例子:startFighting() à开始战斗

你定义了一段代码,在做某些事,如果是一个名词,会很误解读者

使用功能作为方法名,参数作为方法名的宾语,参数名即是宾语,阅读这样的方法定义甚至完全不需要文档

e)变量名

变量名除了只有一个字符的循环技术器外,全部都必须是名词

首字母必须小写,后续单词的首字母必须大写

只有一个字符作为名字的变量,不得用作公开属性(表示位置的x,y,z除外)

例子:i,j,k à用于for循环的变量

userNameà用户名

变量代表了某些东西,这些东西需要被人通过阅读所理解,为啥不直接就叫它的名字呢?

使用业务领域或技术解决方案的名词作变量名,可以让读者直接从名字就了解这些代码的用途。ß和类名的做法是一样的

f)常量名

必须用全大写,单词间用下划线连接

例子:MAX_USER à最大用户数

常量必须和变量区分开来

4.格式

a)源文件布局

每个源文件只包含一个公共类或者接口。

公共类必须是这个文件中的第一个类或接口。

每个文件需要有以下三部分:

  • 开头注释

/*

* 类名

* 建立此文件时的版本说明(最初开发版、内测版、公测版、某个对外版本代号)

* 版权说明

*/

  • 包和引入语句

package java.awt

import java.awt.peer.CanvasPeer;

  • 类和接口声明:

i. 使用/**……*/编写“文档注释”;

ii. 类/接口的声明

iii. 类/接口实现的注释,用/*……*/编写,该注释应包含针对整个类或接口,是怎样实现的大概说明,而这些信息不适合作为文档的一部分。

iv. 类的静态变量,首先是类的公共变量,随后是保护变量,之后是包一级变量,最后是私有变量

v. 实例变量,按公共、保护、包一级、私有排列

vi. 构造器

vii. 方法,应该按功能分组排列,一个主要功能的方法后,跟着被调用的一系列方法,即自上向下展示各方法的依赖顺序。而不是杂乱的堆放。

b)垂直格式

i. 单个文件禁止超过1000行

ii. 两个方法之间只是用一个空行

iii. 方法内局部变量和方法的第一条语句之间要有一个空行

iv. 块注释或单行注释之前要有一个空行

c)水平格式

i. 每行禁止超过120个字符

ii. 是用标准的C++或者JAVA缩进格式,并且一直使用。禁止混用两种缩进格式。

iii. 是用一个制表符(TAB键)而不是空格产生一个缩进

5.注释

a)文档注释

是用标准JAVADOC语法产生文档注释。每个公共类、公共方法、公共变量必须要有中文的文档注释。

b)实现注释

i. 注释内容:编写“为什么”要写下这段代码的原因,而非“如何实现”

ii. 翻译英文:对于一些比较复杂的英文命名,必须要用注释翻译

iii. 禁止的注释:禁止出现注释掉的代码残留在代码中;禁止出现明显误导或者无用的注释。

6.属性(变量)与常量

a) 每行声明变量的数量

b) 初始化

c) 声明变量的位置

d) 禁止继承常量,使用静态属性

e) 禁止在定义语句以外写入字面值常量

在需要多国语言版本时,遍布代码的字面常量将是一场灾难。

7.方法(函数)

a) 禁止多于4个参数

b) 禁止使用“输出参数”

c) 除非必要情况,禁止返回null

d) 禁止返回“错误码”,使用“异常”来代替“错误码”

e) 禁止一个方法中多于5层的缩进

f) 禁止一个方法多于300行

g) 从容器类(Map,ArrayList,Vector,数组等)中获取对象一定要检查是否null值

8.语句

a)简单语句

每行只包括一条语句,禁止出现一行中有两个或以上的分号

b)for语句

禁止使用三个以上计数器变量。

禁止在for()语句以外修改计数器变量的内容。

计数器变量是最容易导致产生死循环的地方,for语句每次循环更新计数器变量,程序在另外一个地方修改这个变量,会让事情变得非常复杂,导致产生致命的BUG。

c)while语句

在使用可能长时间死循环的while语句时,必须在循环体中增加一句让当前线程暂停50毫秒的语句,如Thread.sleep(50);

一个死循环线程会大大占用CPU,导致CPU使用率轻易达到100%

尽量少用while循环,除非你在写多线程相关的程序,使用for循环较少出现死循环以及无穷递归

d)switch语句

每个case子句中最后一个必须要有一个break;

9.错误处理

a) 使用异常而非返回码

b) 定义常规流程,而不是把所有流程情况用if来描述,当出现常规流程外的业务逻辑流程,使用自定义异常类来跳出流程。

c) 为调用者定义异常类,异常类应该具备业务逻辑含义

d) 非业务流程问题,而是API抛出的异常,应该捕捉并且抛出不可控异常(Error类)。避免API异常类被到处抛出和捕捉。

e) 给出异常发生的环境说明,至少要打印printStackTrace()

相同的一个if判断业务逻辑,可能大量重复存在。

为了避免大量重复某种业务逻辑判断,应该使用自定义异常类,来说明这种业务逻辑上的异常。并且在最原始的操作函数处检查并且抛出这个异常。

错误应该分为两类:一类是和用户操作、数据无关的,如SQL异常、文件读写异常、网络异常,应该使用“不可控异常”,由一个统一的地方接收并且处理;另外一类是和用户操作有关的,在业务逻辑的流程中有定义,但是不属于常规流程的情况,应该定义一个以业务逻辑状态为含义的异常,由可能出异常的最原子函数抛出,并且由调用者根据业务逻辑的流程定义来处理。

10.工程目录约定

a) 统一目录结构

使用Maven目录结构,或者——

使用Eclispe标准项目目录:

工作区目录/项目名/系统名(如客户端、服务端)/

/src ß源代码目录

/binß编译后目录

/libß使用的工具库目录,包括工具库需要的配置文件

/resß源代码需要用到的其他数据文件,包括配置文件

/docß文档目录

b) 统一开发工具以及设定参数

i. 统一使用一个版本的开发工具

ii. 统一开发工具的所有设定,包括安装目录、库设定等参数(除字体、工具栏等表现部分)

c) 对整个工作区作版本管理

i. 统一工作区目录路径位置

ii. 对整个工作区目录使用SVN,作为源代码部分的版本管理,但剔除bin目录

11.代码外三要素:

a)文档编写

严格按照注释要求编写javadoc类型文档注释。并且每次发布版本都自动更新文档。

如果懒得写文档,或者想少写注释,尽量少用公共类和公开方法、变量。简化代码结构能同时减轻文档的工作量

对于超过一周以上的开发项目,画UML的类结构图。

对于参与者超过三个的流程,画UML的流程图。

对于每个数据表,都必须要有数据字典文档。每次修改数据表结构都必须更新此文档。

你可以使用数据库管理工具,在建立表的时候就一并做好这个工作。

每一种自定义资源文件,如XML或者美术资源文件,都需要最少一个文档介绍其结构。

以上所有文档应该跟随源代码一起在SVN上管理。

b)版本管理

  • 源代码使用一个单独的SVN库,设置三类分支管理
    • branch类分支:开发中的多个分支,进入QA测试前合并至trunk分支;开发新功能时从trunk分支建立出来。
    • trunk分支:一个单一的分支,用来存放当前正在QA人员测试的源代码,通常是下一个即将发布的版本。所有的其他分支都是从这个分支建立出来的。
    • tag分支:多个已经发布版本的分支。每次发布版本就建立一个此类分支用于备份源代码状态。便于将来回溯版本。
  • 发布文件使用一个单独的SVN库管理
  • 部署安装脚本以及配置文件和发布文件使用SVN管理
    • 包括每个安装环境的不同配置文件
    • 包括多个安装环境公有的文件

c)自动构建

从源代码变成发布文件,并且安装部署到即使是空白的目标环境上,必须使用自动构建程序。可以是make或者ant系统,又或者是自己额外写的脚本。

自动构建程序必须可以仅用一个步骤就自动运行完成。并且写下构建日志以提供分析问题的依据。

感谢大家的阅读,如觉得此文对你有那么一丁点的作用,麻烦动动手指转发或分享至朋友圈。如有不同意见,欢迎后台留言探讨。

原文发布于微信公众号 - 韩大(handa1740168)

原文发表时间:2015-12-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏逸鹏说道

无图片字体icon

W3C 仍然在对 CSS3 规范进行开发。不过,现代浏览器已经实现了相当多的 CSS3 属性。CSS3也从前几年的初试探到如今的广泛应用。最近折腾这方面的东西其...

3269
来自专栏腾讯开源的专栏

有了libco,异步化都成了小case!

张俊强 腾讯互娱工程师,目前负责腾讯互娱心悦俱乐部的后台开发,先后参与过心悦用户体系下沉,后台服务协程化改造,心悦积分体系搭建等项目,致力于海量、高可用、高性能...

3794
来自专栏性能与架构

条件语句小技巧

“高性能javascript” 这本书中提到了一个“查找表”的概念,建议在有大量离散值要测试时,if-else 和 switch 都比使用查找表慢很多,依据是运...

2597
来自专栏编程

canvas 入门实战-邀请卡生成与下载

来源:守候 https://segmentfault.com/a/1190000012418898 1.前言 写了很多的javascript和css3的文章,是...

19610
来自专栏农夫安全

高级PHP应用程序漏洞审核技术【一】

前言 小编入门代码审计时看的几篇写的比较经典的PDF文档之一,分享出来希望能帮助到想学习代码审计的小伙伴。 [目录] 1. 前言 2. 传统的代码审计技...

29511
来自专栏微信小程序开发

微信小程序开发应该注意的问题

小程序是微信主推的产品,现在也有不少公司的产品已经开发了小程序版本。那么,开发小程序你需要了解哪些知识? 1、使用微信web开发者工具 此工具是微信官方提供的小...

2788
来自专栏更流畅、简洁的软件开发方式

【自然框架】——思路、结构、特点的介绍(初稿,欢迎大家多提意见)

开场白   面向过程:面向过程是“写代码”,根据客户提出来的需求来写代码,包括函数。一步一步的写,都写完了,功能也就实现了。 面向对象:面向对象是“做设计”...

2227
来自专栏达摩兵的技术空间

“不吹不黑”说一说列表页多“简单”

相信随着前端职业的兴起,有不少后端或者项目经理觉得前端不就那么回事么?甚至于有些时候,后端一看这么个简单的东西也要做一天?那么本文就带大家了解一下一个还算正常的...

532
来自专栏从流域到海域

《笨办法学Python》 第37课手记

《笨办法学Python》 第37课手记 本节课是复习课。关键字是指系统预先定义好的含有特定含义的字符串或者函数,注意你在自定义函数时不能与关键字重名。可是该课中...

17310
来自专栏IMWeb前端团队

关于javascript错误捕获

``` javascript的出错我们应该都很熟悉,例如`xxx undefined`,`SyntaxError`等。 我们team将出现错误的javas...

1967

扫码关注云+社区