本篇規范基於阿里巴巴、華為的開發手冊,添加了我們團隊的開發風格規范,補充了一些細節。感謝前人的經驗和付出,讓我們可以有機會站在巨人的肩膀上眺望星辰大海。
規范不是為了約束和禁錮大家的創造力,而是為了幫助大家能夠在正確的道路上,盡可能的避免踩坑和跑偏。
規范可以讓我們無論單槍匹馬還是與眾人同行的時候都能得心應手。
規范可以讓我們在面對日益變態的需求和做代碼接盤俠的時候,更優雅從容。
規則並不是完美的,通過約束和禁止在特定情況下的特性,可能會對代碼實現造成影響。
但是我們制定規則的目的:為了大多數程序員小伙伴可以得到更多的好處,如果在團隊實際運作中認為某個規則無法遵循或有更好的做法,希望大家可以共同改進該規范。
一、編程規范
1、好代碼的原則
我們參考 Kent Beck 的簡單設計四原則來指導我們的如何寫出優秀的代碼,如何有效地判斷我們的代碼是優秀的。
- 通過所有測試(Passes its tests):強調的是外部需求,這是代碼實現最重要的
- 盡可能消除重復 (Minimizes duplication):代碼的模塊架構設計,保證代碼的正交性,保證代碼更容易修改
- 盡可能清晰表達 (Maximizes clarity):代碼的可閱讀性,保證代碼是容易閱讀的
- 更少代碼元素 (Has fewer elements):保證代碼是簡潔的,在簡潔和表達力之間,我們更看重表達力
以上四個原則的重要程度依次降低, 這組定義被稱做簡單設計原則。
2、項目命名規范
全部采用小寫方式, 以中划線分隔。
正例:mall-management-system / order-service-client / user-api
反例:mall_management-system / mallManagementSystem / orderServiceClient
3、TODO/FIXME 規范
TODO/TBD(to be determined)
注釋一般用來描述已知待改進、待補充的修改點,並且加上作者名稱。
FIXME
注釋一般用來描述已知缺陷,它們都應該有統一風格,方便文本搜索統一處理。如:
// TODO <author-name>: 補充XX處理
// FIXME <author-name>: XX缺陷
4、方法參數規范
無論是 controller,service,manager,dao
亦或是其他的代碼,每個方法最多 3
個參數,如果超出 3
個參數的話,要封裝成 javabean
對象。
- 方便他人調用,降低出錯幾率。尤其是當參數是同一種類型,僅僅依靠順序區分,稍有不慎便是災難性后果,而且排查起來也極其惡心。
- 保持代碼整潔、清晰度。當一個個方法里充斥着一堆堆參數的時候,再堅強的人,也會身心疲憊。
反例:
/**
* 使用證書加密數據工具方法
*
* @param param
* @param password 加密密碼
* @param priCert 私鑰
* @param pubCert 公鑰
* @return 返回加密后的字符串
*/
public String signEnvelop(JdRequestParam param, String password, String priCert, String pubCert){}
5、注釋規范
5-1、注釋和代碼一樣重要
注釋是我們披荊斬棘歷經磨難翻越需求這座大山時,留下的蹤跡和收獲的經驗教訓,這些寶貴的知識除了證明我們曾經存在過,也提醒着后來的人們殷鑒不遠、繼往開來。
注釋除了說明作用、邏輯之外。還有一個很重要的原因:當業務邏輯過於復雜,代碼過於龐大的時候,注釋就變成了一道道美化環境、分離與整理邏輯思路的路標。這是很重要的一點,它能有效得幫助我們免於陷入代碼與業務邏輯的泥沼之中。
正例:
/**
* 開始抽獎方法
* 保存中獎信息、獎勵用戶積分等
* @param luckDrawDTO
* @return ResponseDTO 返回中獎信息
*/
public ResponseDTO<String> startLuckDraw(LuckDrawDTO luckDrawDTO) {
// -------------- 1、校驗抽獎活動基本信息 ------------------------
xxx偽代碼一頓操作
// -------------- 2、新增抽獎記錄 -------------------------------
xxx偽代碼一頓操作
// -------------- 3、如果需要消耗積分,則扣除鋼鏰積分 -------------
xxx偽代碼一頓操作
// -------------- 4、獲取獎品信息,開始翻滾吧 --------------------
xxx偽代碼一頓操作
return ResponseDTO.succ(luckDrawPrizeVO);
}
5-2、注釋和代碼的一致性
注釋並不是越多越好,當注釋過多,維護代碼的同時,還需要維護注釋,不僅變成了一種負擔,也與我們當初添加注釋的初衷背道而馳。
首先:大家應該通過清晰的邏輯架構,好的變量命名來提高代碼可讀性;需要的時候,才輔以注釋說明。注釋是為了幫助閱讀者快速讀懂代碼,所以要從讀者的角度出發,按需注釋。注釋內容要簡潔、明了、無二義性,信息全面且不冗余。
其次:無論是修改、復制代碼時,都要仔細核對注釋內容是否正確。只改代碼,不改注釋是一種不文明行為,破壞了代碼與注釋的一致性,會讓閱讀者迷惑、費解,甚至誤解。
反例:
// 查詢部門
EmployeeDTO employee = employeeDao.listByDeptId(deptId);
5-3、方法注釋
方法要盡量通過方法名自解釋,不要寫無用、信息冗余的方法頭,不要寫空有格式的方法頭注釋。
方法頭注釋內容可選,但不限於:功能說明、返回值,用法、算法實現等等。尤其是對外的方法接口聲明,其注釋,應當將重要、有用的信息表達清楚。
正例:
/**
* 解析轉換時間字符串為 LocalDate 時間類
* 調用前必須校驗字符串格式 否則可能造成解析失敗的錯誤異常
*
* @param dateStr 必須是 yyyy-MM-dd 格式的字符串
* @return LocalDate
*/
public static LocalDate parseYMD(String dateStr){}
反例:
/**
* 校驗對象
*
* @param t
* @return String
*/
public static <T> String checkObj(T t);
反例中出現的問題:
- 方法注釋沒有說明具體的作用、使用事項。
- 參數、返回值,空有格式沒內容。這是非常重要一點,任何人調用任何方法之前都需要知道方法對參數的要求,以及返回值是什么。
二、項目規范
1、代碼目錄結構
統一的目錄結構是所有項目的基礎。
src 源碼目錄
|-- common 各個項目的通用類庫
|-- config 項目的配置信息
|-- constant 全局公共常量
|-- handler 全局處理器
|-- interceptor 全局連接器
|-- listener 全局監聽器
|-- module 各個業務
|-- |--- employee 員工模塊
|-- |--- role 角色模塊
|-- |--- login 登錄模塊
|-- third 三方服務,比如redis, oss,微信sdk等等
|-- util 全局工具類
|-- Application.java 啟動類
2、common 目錄規范
common 目錄用於存放各個項目通用的項目,但是又可以依照項目進行特定的修改。
src 源碼目錄
|-- common 各個項目的通用類庫
|-- |--- anno 通用注解,比如權限,登錄等等
|-- |--- constant 通用常量,比如 ResponseCodeConst
|-- |--- domain 全局的 javabean,比如 BaseEntity,PageParamDTO 等
|-- |--- exception 全局異常,如 BusinessException
|-- |--- json json 類庫,如 LongJsonDeserializer,LongJsonSerializer
|-- |--- swagger swagger 文檔
|-- |--- validator 適合各個項目的通用 validator,如 CheckEnum,CheckBigDecimal 等
3、config 目錄規范
config 目錄用於存放各個項目通用的項目,但是又可以依照項目進行特定的修改。
src 源碼目錄
|-- config 項目的所有配置信息
|-- |--- MvcConfig mvc的相關配置,如interceptor,filter等
|-- |--- DataSourceConfig 數據庫連接池的配置
|-- |--- MybatisConfig mybatis的配置
|-- |--- .... 其他
4、module 目錄規范
module 目錄里寫項目的各個業務,每個業務一個獨立的頂級文件夾,在文件里進行 mvc 的相關划分。
其中,domain 包里存放 entity, dto, vo,bo 等 javabean 對象
src
|-- module 所有業務模塊
|-- |-- role 角色模塊
|-- |-- |--RoleController.java controller
|-- |-- |--RoleConst.java role相關的常量
|-- |-- |--RoleService.java service
|-- |-- |--RoleDao.java dao
|-- |-- |--domain domain
|-- |-- |-- |-- RoleEntity.java 表對應實體
|-- |-- |-- |-- RoleDTO.java dto對象
|-- |-- |-- |-- RoleVO.java 返回對象
|-- |-- employee 員工模塊
|-- |-- login 登錄模塊
|-- |-- email 郵件模塊
|-- |-- .... 其他
5、 domain 包中的 javabean 命名規范
1) javabean
的整體要求:
- 不得有任何的業務邏輯或者計算
- 基本數據類型必須使用包裝類型
(Integer, Double、Boolean 等)
- 不允許有任何的默認值
- 每個屬性必須添加注釋,並且必須使用多行注釋。
- 必須使用
lombok
簡化getter/setter
方法 - 建議對象使用
lombok
的@Builder ,@NoArgsConstructor
,同時使用這兩個注解,簡化對象構造方法以及set方法。
正例:
@Builder
@NoArgsConstructor
@Data
public class DemoDTO {
private String name;
private Integer age;
}
// 使用示例:
DemoDTO demo = DemoDTO.builder()
.name("yeqiu")
.age(66)
.build();
2)數據對象;XxxxEntity
,要求:
- 以
Entity
為結尾(阿里是為 DO 為結尾) - Xxxx 與數據庫表名保持一致
- 類中字段要與數據庫字段保持一致,不能缺失或者多余
- 類中的每個字段添加注釋,並與數據庫注釋保持一致
- 不允許有組合
- 項目內的日期類型必須統一,建議使用
java.util.Date,java.sql.Timestamp,java.time.LocalDateTime
其中只一。
3)傳輸對象;XxxxDTO
,要求:
- 不可以繼承自
Entity
DTO
可以繼承、組合其他DTO,VO,BO
等對象DTO
只能用於前端、RPC 的請求參數
3)視圖對象;XxxxVO
,要求:
- 不可繼承自
Entity
VO
可以繼承、組合其他DTO,VO,BO
等對象VO
只能用於返回前端、rpc 的業務數據封裝對象
4)業務對象 BO
,要求:
- 不可以繼承自
Entity
BO
對象只能用於service,manager,dao
層,不得用於controller
層
三、MVC 規范
1、整體分層
- controller 層
- service 層
- manager 層
- dao 層
2、 controller
層規范
1) 只允許在 method 上添加 RequestMapping
注解,不允許加在 class 上(為了方便的查找 url,放到 url 不能一次性查找出來)
正例:
@RestController
public class DepartmentController {
@GetMapping("/department/list")
public ResponseDTO<List<DepartmentVO>> listDepartment() {
return departmentService.listDepartment();
}
反例:
@RequestMapping ("/department")
public class DepartmentController {
@GetMapping("/list")
public ResponseDTO<List<DepartmentVO>> listDepartment() {
return departmentService.listDepartment();
}
2)不推薦使用 rest 命名 url, 只能使用 get/post
方法。url 命名上規范如下:
雖然 Rest 大法好,但是有時並不能一眼根據 url 看出來是什么操作,所以我們選擇了后者,這個沒有對與錯,只有哪個更適合我們的團隊。
/業務模塊/子模塊/動作
正例:
GET /department/get/{id} 查詢某個部門詳細信息
POST /department/query 復雜查詢
POST /department/add 添加部門
POST /department/update 更新部門
GET /department/delete/{id} 刪除部門
3)每個方法必須添加 swagger
文檔注解 @ApiOperation
,並填寫接口描述信息,描述最后必須加上作者信息 @author 哪吒
。
正例:
@ApiOperation("更新部門信息 @author 哪吒")
@PostMapping("/department/update")
public ResponseDTO<String> updateDepartment(@Valid @RequestBody DeptUpdateDTO deptUpdateDTO) {
return departmentService.updateDepartment(deptUpdateDTO);
}
4)controller 負責協同和委派業務,充當路由的角色,每個方法要保持簡潔:
- 不做任何的業務邏輯操作
- 不做任何的參數、業務校驗,參數校驗只允許使用@Valid 注解做簡單的校驗
- 不做任何的數據組合、拼裝、賦值等操作
正例:
@ApiOperation("添加部門 @author 哪吒")
@PostMapping("/department/add")
public ResponseDTO<String> addDepartment(@Valid @RequestBody DepartmentCreateDTO departmentCreateDTO) {
return departmentService.addDepartment(departmentCreateDTO);
}
5)只能在 controller
層獲取當前請求用戶,並傳遞給 service
層。
因為獲取當前請求用戶是從 ThreadLocal 里獲取取的,在 service、manager、dao 層極有可能是其他非 request 線程調用,會出現 null 的情況,盡量避免
@ApiOperation("添加員工 @author yandanyang")
@PostMapping("/employee/add")
public ResponseDTO<String> addEmployee(@Valid @RequestBody EmployeeAddDTO employeeAddDTO) {
LoginTokenBO requestToken = SmartRequestTokenUtil.getRequestUser();
return employeeService.addEmployee(employeeAddDTO, requestToken);
}
3、 service
層規范
1)合理拆分 service 文件,如果業務較大,請拆分為多個 service。
如訂單業務,所有業務都寫到 OrderService 中會導致文件過大,故需要進行拆分如下:
OrderQueryService
訂單查詢業務OrderCreateService
訂單新建業務OrderDeliverService
訂單發貨業務OrderValidatorService
訂單驗證業務
2)謹慎處理 @Transactional
事務注解的使用,不要簡單對 service
的方法添加個 @Transactional
注解就覺得萬事大吉了。應當合並對數據庫的操作,盡量減少添加了@Transactional
方法內的業務邏輯。
@Transactional
注解內的 rollbackFor
值必須使用異常的基類 Throwable.class
對於@Transactional 注解,當 spring 遇到該注解時,會自動從數據庫連接池中獲取 connection,並開啟事務然后綁定到 ThreadLocal 上,如果業務並沒有進入到最終的 操作數據庫環節,那么就沒有必要獲取連接並開啟事務,應該直接將 connection 返回給數據庫連接池,供其他使用(比較難以講解清楚,如果不懂的話就主動去問)。
反例:
@Transactional(rollbackFor = Throwable.class)
public ResponseDTO<String> upOrDown(Long departmentId, Long swapId) {
// 驗證 1
DepartmentEntity departmentEntity = departmentDao.selectById(departmentId);
if (departmentEntity == null) {
return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS);
}
// 驗證 2
DepartmentEntity swapEntity = departmentDao.selectById(swapId);
if (swapEntity == null) {
return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS);
}
// 驗證 3
Long count = employeeDao.countByDepartmentId(departmentId)
if (count != null && count > 0) {
return ResponseDTO.wrap(DepartmentResponseCodeConst.EXIST_EMPLOYEE);
}
// 操作數據庫 4
Long departmentSort = departmentEntity.getSort();
departmentEntity.setSort(swapEntity.getSort());
departmentDao.updateById(departmentEntity);
swapEntity.setSort(departmentSort);
departmentDao.updateById(swapEntity);
return ResponseDTO.succ();
}
以上代碼前三步都是使用 connection 進行驗證操作,由於方法上有@Transactional 注解,所以這三個驗證都是使用的同一個 connection。
若對於復雜業務、復雜的驗證邏輯,會導致整個驗證過程始終占用該 connection 連接,占用時間可能會很長,直至方法結束,connection 才會交還給數據庫連接池。
對於復雜業務的不可預計的情況,長時間占用同一個 connection 連接不是好的事情,應該盡量縮短占用時間。
正例:
DepartmentService.java
public ResponseDTO<String> upOrDown(Long departmentId, Long swapId) {
DepartmentEntity departmentEntity = departmentDao.selectById(departmentId);
if (departmentEntity == null) {
return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS);
}
DepartmentEntity swapEntity = departmentDao.selectById(swapId);
if (swapEntity == null) {
return ResponseDTO.wrap(DepartmentResponseCodeConst.NOT_EXISTS);
}
Long count = employeeDao.countByDepartmentId(departmentId)
if (count != null && count > 0) {
return ResponseDTO.wrap(DepartmentResponseCodeConst.EXIST_EMPLOYEE);
}
departmentManager.upOrDown(departmentSort,swapEntity);
return ResponseDTO.succ();
}
DepartmentManager.java
@Transactional(rollbackFor = Throwable.class)
public void upOrDown(DepartmentEntity departmentEntity ,DepartmentEntity swapEntity){
Long departmentSort = departmentEntity.getSort();
departmentEntity.setSort(swapEntity.getSort());
departmentDao.updateById(departmentEntity);
swapEntity.setSort(departmentSort);
departmentDao.updateById(swapEntity);
}
將數據在 service 層准備好,然后傳遞給 manager 層,由 manager 層添加@Transactional 進行數據庫操作。
3)需要注意的是:注解 @Transactional
事務在類的內部方法調用是不會生效的
反例:如果發生異常,saveData方法上的事務注解並不會起作用
@Service
public class OrderService{
public void createOrder(OrderCreateDTO createDTO){
this.saveData(createDTO);
}
@Transactional(rollbackFor = Throwable.class)
public void saveData(OrderCreateDTO createDTO){
orderDao.insert(createDTO);
}
}
Spring采用動態代理(AOP)實現對bean的管理和切片,它為我們的每個class生成一個代理對象。只有在代理對象之間進行調用時,可以觸發切面邏輯。而在同一個class中,方法A調用方法B,調用的是原對象的方法,而不通過代理對象。所以Spring無法攔截到這次調用,也就無法通過注解保證事務了。簡單來說,在同一個類中的方法調用,不會被方法攔截器攔截到,因此事務不會起作用。
解決方案:
- 可以將方法放入另一個類,如新增
manager層
,通過spring注入,這樣符合了在對象之間調用的條件。 - 啟動類添加
@EnableAspectJAutoProxy(exposeProxy = true)
,方法內使用AopContext.currentProxy()
獲得代理類,使用事務。
SpringBootApplication.java
@EnableAspectJAutoProxy(exposeProxy = true)
@SpringBootApplication
public class SpringBootApplication {}
OrderService.java
public void createOrder(OrderCreateDTO createDTO){
OrderService orderService = (OrderService)AopContext.currentProxy();
orderService.saveData(createDTO);
}
4)service是具體的業務處理邏輯服務層,盡量避免將web層某些參數傳遞到service中。
反例:
public ResponseDTO<String> handlePinganRequest(HttpServletRequest request){
InputStreamReader inputStreamReader = new InputStreamReader(request.getInputStream(), "GBK");
BufferedReader reader = new BufferedReader(inputStreamReader);
StringBuilder sb = new StringBuilder();
String str;
while ((str = reader.readLine()) != null) {
sb.append(str);
}
if(!JSON.isValid(msg)){
return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM);
}
PinganMsgDTO PinganMsgDTO = JSON.parseObject(msg,PinganMsgDTO.class);
// 示例結束
}
反例中出現的問題:
- 反例中把
HttpServletRequest
傳遞到service中,是為了獲取Request流中的字符信息,然后才是真正的業務處理。按照分層的初衷:將代碼、業務邏輯解耦,正確的做法應該是handlePinganRequest
方法將String
字符作為參數直接處理業務,將從Request
中獲取字符的操作放入controller
中。 - 另一個壞處是不方便做單元測試,還得一個
new
一個HttpServletRequest
並制造一個InputStream
,然而這樣做並不能模擬到真實的業務情景及數據。
4、 manager 層規范
manager 層的作用(引自《阿里 java 手冊》):
- 對第三方平台封裝的層,預處理返回結果及轉化異常信息;
- 對 Service 層通用能力的下沉,如緩存方案、中間件通用處理;
- 與 DAO 層交互,對多個 DAO 的組合復用。
5、 dao 層規范
優先使用 mybatis-plus 框架。如果需要多個數據源操作的,可以選擇使用 SmartDb 框架。
1)所有 Dao 繼承自 BaseMapper
2)禁止使用 Mybatis-plus 的 Wrapper 條件構建器
3)禁止直接在 mybatis xml 中寫死常量,應從 dao 中傳入到 xml 中
3)建議不要使用星號 *
代替所有字段
正例:
NoticeDao.java
Integer noticeCount(@Param("sendStatus") Integer sendStatus);
---------------------------------------------
NoticeMapper.xml
<select id="noticeCount" resultType="integer">
select
count(1)
from t_notice
where
send_status = #{sendStatus}
</select>
反例:
NoticeDao.java
Integer noticeCount();
---------------------------------------------
NoticeMapper.xml
<select id="noticeCount" resultType="integer">
select
count(1)
from t_notice
where
send_status = 0
</select>
3)dao層方法命名規范
- 獲取單個對象的方法用
get
做前綴。 - 獲取多個對象的方法用
list
做前綴。 - 獲取統計值的方法用
count
做前綴。 - 插入的方法用
save/insert
做前綴。 - 刪除的方法用
remove/delete
做前綴。 - 修改的方法用
update
做前綴。
建議:dao層方法命名盡量以sql語義命名,避免與業務關聯。
正例:
List<PerformanceDTO> listByMonthAndItemId(@Param("month") String month, @Param("itemId") Integer itemId);
反例:
List<PerformanceDTO> getInternalData(@Param("month") String month, @Param("itemId") Integer itemId);
反例中出現的不規范操作:
- get代表單個查詢,批量查詢的應該 list 開頭。
- 命名與業務關聯,局限了dao方法的使用場景和范圍,降低了方法的復用性,造成他人困惑以及重復造輪子。
6、boolean類型的屬性命名規范
類中布爾類型的變量,都不要加is,否則部分框架解析會引起序列化錯誤。反例:定義為基本數據類型 Boolean isDeleted;的屬性,它的方法也是 isDeleted(),RPC在反向解析的時候,“以為”對應的屬性名稱是 deleted,導致屬性獲取不到,進而拋出異常。
這是阿里巴巴開發手冊中的原文,我們團隊的規定是:boolean
類型的類屬性和數據表字段都統一使用 flag
結尾。雖然使用 isDeleted,is_deleted
從字面語義上更直觀,但是比起可能出現的潛在錯誤,這點犧牲還是值得的。
正例:
deletedFlag,deleted_flag,onlineFlag,online_flag
7、
四、數據庫 規范
1 建表規范
表必備三字段:id, create_time, update_time
- id 字段 Long 類型,單表自增,自增長度為 1
- create_time 字段 datetime 類型,默認值 CURRENT_TIMESTAMP
- update_time 字段 datetime 類型,默認值 CURRENT_TIMESTAMP, On update CURRENT_TIMESTAMP
2 枚舉類表字段注釋需要將所有枚舉含義進行注釋
修改或增加字段的狀態描述,必須要及時同步更新注釋。
如下表的 sync_status
字段 同步狀態 0 未開始 1同步中 2同步成功 3失敗
。
正例:
CREATE TABLE `t_change_data` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`sync_status` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '同步狀態 0 未開始 1同步中 2同步成功 3失敗',
`sync_time` DATETIME NULL DEFAULT NULL COMMENT '同步時間',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`change_data_id`)
)
反例:
CREATE TABLE `t_change_data` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`sync_status` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '同步狀態 ',
`sync_time` DATETIME NULL DEFAULT NULL COMMENT '同步時間',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`change_data_id`)
)
3 合理結合業務給表字段添加索引和唯一索引
具體索引規范請參照《阿里巴巴 Java 開發手冊》索引規約
五、其他
1、代碼提交規范
- 提交前應該冷靜、仔細檢查一下,確保沒有忘記加入版本控制或不應該提交的文件。
- 提交前應該先編譯一次(idea里ctrl+F9),防止出現編譯都報錯的情況。
- 提交前先更新pull一次代碼,提交前發生沖突要比提交后發生沖突容易解決的多。
- 提交前檢查代碼是否格式化,是否符合代碼規范,無用的包引入、變量是否清除等等。
- 提交時檢查注釋是否准確簡潔的表達出了本次提交的內容。
2、maven項目
- pom禁止出現相同 groupId,artifactId 的依賴配置。
- 項目名稱應該與 artifactId 保持一致。
- 定期檢查jar包依賴關系,及時排除解決沖突的jar包。
3、保持項目整潔
使用git,必須添加 .gitignore 忽略配置文件。
不要提交與項目無關的內容文件:idea配置、target包等。