-
Notifications
You must be signed in to change notification settings - Fork 522
HugeGraph Code Style Guide
Note: 加入 Apache (ASF) 后, 为了尽量降低用户提交代码的门槛以及减少不必要的风格检查 review, 注意换行/对齐时应尽量使用 IDE 推荐/自动的格式化, 减少以前大量的"手动"格式化, 因为这会给新用户带来很大的格式化困扰 (由于存在手动格式化与自动格式化产生冲突)
尤其要避免/减少无法定义规则的对齐, 我们的目标是尽可能让
95%+
的代码可以自动被格式化, 极少数历史遗留代码需要思考/手动换行, 但仍不应该使用特殊人工 format 的规则, 后文中以此为基准再进行理解 (不确定度可以联系 PMC 同学)
建议单行 ≤100
, IDEA 强烈建议导入项目根下的 .editorconfig
配置文件进行格式化
Eclipse、Idea 等 IDE 均可针对项目进行设置,下文所述的换行对齐规则一般 IDE 也可设置。
好处:
- 便于阅读
- 命令行及 Github 可一行容纳下
- 符合流行社区习惯
对于字符串和函数参数,对齐优先级高于缩进。也就是说换行时,如果能与上一行同类代码对齐则尽量对齐。(不强制, 请勿使用人工且无法被 IDE 自动 format 的对齐规则)
注意: 下面的所有 case 都是当前行 > 100
字符的时候才考虑执行, 如果没有超过则优先一行, 历史 80 字符换行的, 看到可以合并到一行 (也可以 ignore)
这里为了美观忽略内部规范:多条件并列时,建议逻辑运算符写在行尾,下行条件与上行括号对齐。如:
if (query.condition(HugeKeys.SOURCE_VERTEX) != null &&
query.condition(HugeKeys.DIRECTION) != null &&
!keys.isEmpty() && query.matchUserpropKeys(keys)) {
建议括号内的逗号处换行。如:
注:不同浏览器上对齐效果可能不一致,两个 Set 首字母是竖直对齐的。
protected void prepareAdditions(Set<HugeVertex> updatedVertexes,
Set<HugeEdge> updatedEdges) {
另外 throws 换行对齐是与函数参数保持一致。
建议括号内的逗号处换行,如:
instance.longFunction(param1,
param2);
instance.longLongFunction(
param1,
param2);
建议在明显分隔符出换行,如逗号后,且空格保留在上行。如果能在第二行容纳得下所有内容,则第一行空着以保留完整字符串。如:
throw new BackendException(
"Not support querying by multi edge-labels");
保持与条件判断语句风格一致,符号写在行末,两个分支都另起一行
Number n1 = (first instanceof Number) ?
(Number) first :
toBig.apply(first);
为了直观区分各个代码块,如下情况需要添加空行:
- package 下一行
- class、enum 定义的前一行和后一行
- 成员变量定义完成与方法定义开始之间加空行
- 方法定义、内部类定义、静态代码块等,它们之间加空行
- 文件末尾保持一行空行
- 方法内部逻辑相对独立的代码块使用空行分隔
- 变量、方法命名:驼峰命名,保持与 Google 规范一致即可。
- 方法前缀:方法名不需要 get、set、is 前缀,以保持方法名称的简洁。
关于 if-return-else-return 语句的清理咱们遵循的原则是:简短的错误处理代码放在方法体前部,if 后直接 return,后面不接 else;如果是并列的业务逻辑代码,可使用 if-return else-if-return else-return 以使得逻辑更加清晰;关于是否判断为并列逻辑,如果没有明显的边界,那么倾向使用原则 1。
-
注释写在代码上面,不要写在代码右边或下面 (不使用行尾注释)
-
一行注释用
//
,多行注释用/**/
-
类变量/方法的注释都使用 java-doc 的写法,即:
/**
* xxx
*/
- 方法内的注释使用首行单星号的多行注释,即:
/*
* xxx
* xx
*/
错误检查建议使用:E.checkArgument()
、E.checkState()
等工具函数代替 if
+ throw
的方式。
E.checkArgument(!primaryKeyIds.contains(propKey.id()),
"Can't remove primary key '%s'", propKey);
E.checkState(prop.element() != null,
"No owner for removing property '%s'", prop.key());
事实上
org.apache.hugegraph.util.E
直接调用com.google.common.base.Preconditions
,错误检查需频繁使用,使用 "E" 代替 "Preconditions" 的原因是为了减少代码的长度。
异常的处理一般在最上层调用处进行,或者外部 API 调用处进行。
如果进行异常转换时,建议通过日志打印原始异常的堆栈信息,或者将原始异常作为新异常的 cause 以记录异常栈。
try {
return new GraphTransaction(this, this.loadGraphStore());
} catch (BackendException e) {
String message = "Failed to open graph transaction";
LOG.error("{}", message, e);
throw new HugeException(message);
}
不允许存在吞异常的行为,吞异常会导致上层逻辑混乱:
try {
return new GraphTransaction(this, this.loadGraphStore());
} catch (BackendException e) {
e.printStackTrace();
}
如果明确的可以忽略异常,请使用 "ignored" 进行说明
try {...} catch (XxException ignored) {}
。
日志实例统一使用 LOG
命名,通过 Log.logger()
获取:
private static final Logger LOG = Log.logger(HugeGraph.class);
日志打印需要 "{}" 作为填充,而不是使用字符串拼接。
LOG.info("Opening backend store '{}' for graph '{}'",
backend, this.name);
事实上
org.apache.hugegraph.util.Log
直接调用org.slf4j.LoggerFactory
,日志需频繁使用,使用 "Log" 代替 "LoggerFactory" 的原因依然是为了减少代码的长度。
建议优先使用 String.format()
进行字符串拼接,以增强代码可读性。
String message = String.format("Graph '%s' start backup!", this.graph);
不允许在打印日志或错误检查时拼接字符串,以避免无谓的浪费。
LOG.debug("Do query: " + query);
E.checkArgument(!query.empty(), "The query is empty: " + query);
其它未提及方面请以 Google Java Style Guide 为准。
ASF 标准头 (file header), 新的代码/配置文件都应该采用这个排版 (注释方式自行调整), 有些旧排版的换行对齐不太合理, 应该予以统一替换
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Documentation license here.