Java開發規范(參照阿里規范改編)


JAVA 開發規范

v1.0.0 2021/08/27

本篇規范基於阿里巴巴、華為的開發手冊,補充了一些細節。

規范不是為了約束和禁錮大家的創造力,而是為了幫助大家能夠在正確的道路上,盡可能的避免踩坑和跑偏。
規范可以讓我們無論單槍匹馬還是與眾人同行的時候都能得心應手。
規范可以讓我們在面對日益變態的需求和做代碼接盤俠的時候,更優雅從容。

一、編程規范

1、好代碼的原則

我們參考 Kent Beck 的簡單設計四原則來指導我們的如何寫出優秀的代碼,如何有效地判斷我們的代碼是優秀的。

  • 通過所有測試(Passes its tests):強調的是外部需求,這是代碼實現最重要的
  • 盡可能消除重復 (Minimizes duplication):代碼的模塊架構設計,保證代碼的正交性,保證代碼更容易修改
  • 盡可能清晰表達 (Maximizes clarity):代碼的可閱讀性,保證代碼是容易閱讀的
  • 更少代碼元素 (Has fewer elements):保證代碼是簡潔的,在簡潔和表達力之間,我們更看重表達力

以上四個原則的重要程度依次降低, 這組定義被稱做簡單設計原則。

2、命名規范

2-1、項目命名規范

全部采用小寫方式, 以中划線分隔。

正例:mall-management-system / order-service-client / user-api

反例:mall_management-system / mallManagementSystem / orderServiceClient

2-2、模塊命名風格(多模塊項目)

模塊名稱:{項目名稱}-{模塊名稱} 模塊名稱簡潔體現職責

模塊名字作為模塊組件的名稱(即maven中的 標簽)

2-3、包命名規范

包名不應該用來表達模塊完整的意思,包名應該僅用作與同包下的其他包做區分。

但盡可能使用單個單詞命名,如果單個單詞無法正確表達,可采用.分割,實在不行可采用全部單詞小寫(參考的spring命名)

2-4、類命名規范

  • 類名使用 UpperCamelCase 風格,必須遵從駝峰形式,但以下情形例外:DO / BO / DTO / VO / AO ;
  • 抽象類命名使用 Abstract 或 Base 開頭;
  • 異常類命名使用 Exception 結尾;
  • 測試類命名以它要測試的類的名稱開始,以 Test 結尾;
  • 如果使用到了設計模式,建議在類名中體現出具體模式;
  • 枚舉類名建議帶上 Enum 后綴,枚舉成員名稱需要全大寫,單詞間用下划線隔開。

正例:

MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion 

反例:

macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion

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 對象。

  1. 方便他人調用,降低出錯幾率。尤其是當參數是同一種類型,僅僅依靠順序區分,稍有不慎便是災難性后果,而且排查起來也極其惡心。
  2. 保持代碼整潔、清晰度。當一個個方法里充斥着一堆堆參數的時候,再堅強的人,也會身心疲憊。

反例:

/**
* 使用證書加密數據工具方法
*
* @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@Datapublic 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 不能一次性查找出來)

正例:

@RestControllerpublic 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方法上的事務注解並不會起作用

@Servicepublic 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無法攔截到這次調用,也就無法通過注解保證事務了。簡單來說,在同一個類中的方法調用,不會被方法攔截器攔截到,因此事務不會起作用。

解決方案:

  1. 可以將方法放入另一個類,如新增 manager層,通過spring注入,這樣符合了在對象之間調用的條件。
  2. 啟動類添加 @EnableAspectJAutoProxy(exposeProxy = true),方法內使用AopContext.currentProxy()獲得代理類,使用事務。
SpringBootApplication.java@EnableAspectJAutoProxy(exposeProxy = true)@SpringBootApplicationpublic class SpringBootApplication {}OrderService.javapublic 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層方法命名規范(適用於service

  • 獲取單個對象的方法用 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

四、數據庫 規范

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、代碼提交規范

  • master: 主分支,主要用來版本發布。

  • develop:日常開發分支,該分支正常保存了開發的最新代碼。

  • feature:具體的功能開發分支,只與 develop 分支交互。

  • release:release 分支可以認為是 master 分支的未測試版。比如說某一期的功能全部開發完成,那么就將 develop 分支合並到 release 分支,測試沒有問題並且到了發布日期就合並到 master 分支,進行發布。

  • hotfix:線上 bug 修復分支。

  • 提交前應該冷靜、仔細檢查一下,確保沒有忘記加入版本控制或不應該提交的文件。

  • 提交前應該先編譯一次(idea里ctrl+F9),防止出現編譯都報錯的情況。

  • 提交前先更新pull一次代碼,提交前發生沖突要比提交后發生沖突容易解決的多。

  • 提交前檢查代碼是否格式化,是否符合代碼規范,無用的包引入、變量是否清除等等。

  • 提交時檢查注釋是否准確簡潔的表達出了本次提交的內容。

2、maven項目

  • pom禁止出現相同 groupId,artifactId 的依賴配置。
  • 項目名稱應該與 artifactId 保持一致。
  • 定期檢查jar包依賴關系,及時排除解決沖突的jar包。

3、保持項目整潔

使用git,必須添加 .gitignore 忽略配置文件。

不要提交與項目無關的內容文件:idea配置、target包等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM