Skip to content

Checklist chuẩn

Checklist này phản ánh chính xác những gì ftkit CLI thực thi khi bạn chạy ftkit verify (bí danh ftkit v) tại thư mục gốc của một repo service. Lệnh này duyệt qua repo, chạy lần lượt từng kiểm tra dưới đây theo thứ tự, và in ra (đạt), (cảnh báo), hoặc (lỗi) cho từng khẳng định. Sau đó nó thoát với mã khác 0 nếu bất kỳ kiểm tra nào sinh ra lỗi, nhờ vậy có thể tích hợp vào CI như một cổng chất lượng.

Trình verifier thực hiện 20 kiểm tra theo một thứ tự cố định. Mỗi mục dưới đây tương ứng với một kiểm tra, được đặt nhãn dễ đọc kèm tên hàm verifier bên dưới trong dấu ngoặc đơn, và liệt kê điều gì kích hoạt một lần đạt, một cảnh báo, hoặc một lỗi.

Các kiểm tra

1. Cấu trúc dự án (verifyProjectStructure)

  • Đạt: mỗi thư mục bắt buộc tồn tại (server, biz, biz/core, biz/dal); mỗi thư mục tùy chọn tồn tại (biz/dal/dao, biz/dal/models, biz/dal/do, pkg, cmd, docs, scripts); go.mod tồn tại; và có config.yaml hoặc config.example.yaml.
  • Cảnh báo: thiếu một thư mục tùy chọn, hoặc không tìm thấy file config.
  • Lỗi: thiếu một thư mục bắt buộc, hoặc thiếu go.mod.

2. File main (verifyMainFile)

Kiểm tra main.go ở thư mục gốc của repo.

  • Đạt: main.go khai báo package main; sử dụng pattern bootstrap của fountain (.WithAppInstances, fountain.New(), hoặc Serving()); khởi tạo một server instance (server.NewServer() / server.New); và gọi .Serving().
  • Cảnh báo: không tìm thấy pattern server.NewServer().
  • Lỗi: main.go thiếu hoặc không đọc được; thiếu package main; thiếu pattern bootstrap; hoặc thiếu lời gọi Serving().

3. Cấu trúc server (verifyServerStructure)

Phân tích server/server.go và kiểm tra vòng đời server.

  • Đạt: file có blank import _ ".../biz"; định nghĩa struct server; có func NewServer(); cài đặt các lifecycle method Initialize(), Serving(), Destroy(), Info(); và phát hiện được một thứ tự initialize.
  • Cảnh báo: thứ tự install trong Initialize() lệch so với thứ tự khuyến nghị (logger → caches → databases → dao → clients → servers → controllers → handlers).
  • Lỗi: server/server.go thiếu/không parse được; thiếu blank import biz; thiếu struct server; thiếu NewServer(); hoặc thiếu bất kỳ lifecycle method nào.

4. File route (verifyRouteFile)

Kiểm tra server/route.go.

  • Đạt: initHTTPHandle() tồn tại; có cấu hình versioning API (api/v*); có một hoặc nhiều route group (.Group(); và tìm thấy các tham chiếu handler (s.<Name>Handler.<method>).
  • Cảnh báo: thiếu server/route.go; hoặc không tìm thấy bất kỳ pattern nào ở trên (initHTTPHandle, api/v*, route group, tham chiếu handler).
  • Lỗi: server/route.go tồn tại nhưng không đọc được.

5. Tầng biz (verifyBizLayer)

Phân tích biz/biz.go và quét biz/core/.

  • Đạt: biz.go có blank import cho các package controller (biz/core/*); thư mục biz/core/ tồn tại; và tìm thấy một hoặc nhiều controller domain.
  • Cảnh báo: không có blank import controller trong biz.go; không có domain nào trong biz/core/; hoặc số domain nhiều hơn số blank import (có thể thiếu import).
  • Lỗi: biz/biz.go thiếu/không parse được; hoặc biz/core/ thiếu/không đọc được.

6. Controllers (verifyControllers)

Quét từng domain trong biz/core/ theo hợp đồng CoreController.

  • Đạt (theo từng domain): có gọi RegisterCoreController(); dùng sync.Once cho singleton; cài đặt InstallController(); và cài đặt RegisterCallback() (tìm thấy trong controller.go hoặc file khác của domain).
  • Cảnh báo: không tìm thấy file controller.go / RegisterCoreController trong một domain; không dùng sync.Once; hoặc không tìm thấy controller domain nào.
  • Lỗi: thiếu RegisterCoreController(), InstallController(), hoặc RegisterCallback() cho một domain; hoặc biz/core/ thiếu/không đọc được.

7. Nội dung file controller (verifyControllerFileContents)

Khẳng định mỗi biz/core/*/controller.go chỉ chứa phần plumbing của CoreController.

  • Đạt: controller.go chỉ khai báo InstallController(), RegisterCallback(), AfterInstalledDone(), init(), và một accessor Get<Name>ControllerInstance().
  • Cảnh báo: thiếu biz/core/; không parse được một controller.go; hoặc không tìm thấy file controller.go nào để kiểm tra.
  • Lỗi: có bất kỳ hàm hay method nào khác được khai báo trong controller.go — các business method phải được tách sang file khác.

8. Handlers (verifyHandlers)

Quét từng domain trong server/ theo bố cục handler.

  • Đạt (theo từng domain): có file *_impl.go; có constructor New*API(); constructor nhận []core.CoreController; có một hoặc nhiều file <group>.<op>_handler.go; và file impl được đặt tên <domain>_impl.go.
  • Cảnh báo: thiếu *_impl.go; không có constructor New*API(); constructor không nhận []core.CoreController; không có file handler chuẩn; impl đặt tên sai; hoặc không tìm thấy handler domain nào.
  • Lỗi: thư mục server/ thiếu/không đọc được.

9. Handler một hàm duy nhất (verifyHandlerSingleFunc)

Kiểm tra cách đặt tên của mọi file *_handler.go và mỗi file chỉ chứa đúng một handler.

  • Đạt: tên file khớp {group}.{camelCase}_handler.go và file chứa đúng một receiver method (một handler).
  • Cảnh báo: phần group không khớp tên thư mục; không parse được một file; một file không có method handler nào; hoặc không tìm thấy file handler nào.
  • Lỗi: tên file không tuân theo {group}.{camelCase}_handler.go; phần operation không phải camelCase; hoặc file chứa nhiều hơn một method handler.

10. Không có route handler trong impl (verifyNoRouteHandlersInImpl)

Đảm bảo các file *_impl.go không chứa route handler (method nhận *fiber.Ctx).

  • Đạt: một file *_impl.go không chứa method nào nhận *fiber.Ctx.
  • Cảnh báo: không parse được một file *_impl.go; hoặc không tìm thấy file *_impl.go nào.
  • Lỗi: một method trong *_impl.go nhận *fiber.Ctx — route handler phải nằm trong file *_handler.go, không được đặt trong *_impl.go.

11. Tầng DAO (verifyDAOLayer)

Kiểm tra biz/dal/ và cấu trúc thư mục DAO.

  • Đạt: biz/dal/dao/ tồn tại; dao/managers.go tồn tại; có các hằng số cache/db/storage (*_CACHE/*_DB/*_STO); có func init(); dùng pattern RegisterDAO; phát hiện các thư mục con theo loại DAO; biz/dal/models/ tồn tại; và có các file model.
  • Cảnh báo: thiếu biz/dal/, biz/dal/dao/, hoặc biz/dal/models/; thiếu managers.go; hoặc managers.go thiếu hằng số, init(), hoặc pattern RegisterDAO.
  • Lỗi: không có (kiểm tra này chỉ đạt hoặc cảnh báo).

12. Quy tắc import của DAO (verifyDAOImportRules)

Dự kiến bắt buộc DB DAO chỉ import models, còn cache DAO được import cả modelsdo.

  • Đạt: biz/dal/dao/ tồn tại (kiểm tra hiện là no-op — xem ghi chú).
  • Cảnh báo: biz/dal/dao/ không tồn tại nên kiểm tra bị bỏ qua.
  • Lỗi: không có. Ghi chú: phần thân bắt buộc quy tắc import được bọc trong if false và đang tạm thời bị vô hiệu hóa, vì một số repo chưa tuân thủ; nó sẽ được bật lại sau khi migrate dần. Hiện tại kiểm tra này thực chất không làm gì ngoài cảnh báo về sự tồn tại của thư mục.

13. Quyền sở hữu DAO (verifyDAOOwnership)

Xác minh mỗi DAO type chỉ thuộc một controller và chỉ được thao tác trong một file.

  • Đạt: một DAO type được tham chiếu (dưới dạng struct field) bởi đúng một controller domain; và trong một domain, một DAO type được dùng trong tối đa một file không phải controller.go.
  • Cảnh báo: thiếu biz/core/ hoặc biz/dal/dao/ (bỏ qua kiểm tra); hoặc không tìm thấy DAO type nào để kiểm tra.
  • Lỗi: một DAO type được dùng bởi nhiều hơn một controller; hoặc một domain thao tác một DAO trên nhiều hơn một file (ngoài controller.go); hoặc biz/core/ không đọc được.

14. Suffix của DAO type trong InstallController (verifyDAOTypeSuffixInInstallController)

Kiểm tra mọi type argument của dao.GetDAO[...] / f_dao.GetDAO[...] bên trong InstallController().

  • Đạt: mọi type parameter GetDAO[...] kết thúc bằng DAO, Cache, hoặc STO.
  • Cảnh báo: thiếu biz/core/; hoặc không tìm thấy InstallController() nào để kiểm tra.
  • Lỗi: một type parameter GetDAO[...] không kết thúc bằng DAO, Cache, hoặc STO.

15. Cách dùng logging (verifyLoggingUsage)

Duyệt biz/server/ để đảm bảo chỉ dùng flog cho logging.

  • Đạt: không có import logging bị cấm (log, log/slog, logrus, zap, zerolog, go-logging) và không có lời gọi fmt.Print* hay log.* dùng để logging.
  • Cảnh báo: không có.
  • Lỗi: bất kỳ import logging bị cấm nào (không phải blank import), bất kỳ fmt.Print/Println/Printf nào, hoặc bất kỳ lời gọi log.* nào (nhóm Print/Fatal/Panic) ngoài comment — chỉ được phép dùng flog.

16. Không khai báo data struct trong controller/DAO/handler (verifyNoDataStructs)

Đảm bảo data struct nằm trong biz/dal/do, không nằm trong file controller, DAO, hay handler.

  • Đạt: không có khai báo struct nào bị cấm. Được phép: trong file controller, tên kết thúc bằng Controller/DAO/Dao/Callback/Observer/API/Handler/Impl; trong file DAO, tên kết thúc bằng DAO/Dao/Cache.
  • Cảnh báo: không có.
  • Lỗi: một file controller khai báo struct không khớp các suffix được phép; một file DAO khai báo struct không khớp DAO/Cache; hoặc một file *_handler.go khai báo bất kỳ struct nào (file handler không được khai báo struct).

17. Kiểu error trả về của controller (verifyControllerErrors)

Yêu cầu mọi function/method exported của controller trả về *froto.RpcError thay vì kiểu error thuần.

  • Đạt: không có function/method exported nào trong biz/core/ trả về error thuần.
  • Cảnh báo: biz/core/ không tồn tại (bỏ qua kiểm tra).
  • Lỗi: một function/method exported trả về kiểu error thuần — phải trả về *froto.RpcError. (biz/core/ không đọc được cũng là lỗi.)

18. Không dùng tham số interface trong controller (verifyNoInterfaceParamsInControllers)

Cấm tham số interface{} / any trong file controller, ngoại trừ controller.go.

  • Đạt: không có function nào trong biz/core/*/ (trừ controller.go) nhận tham số interface{} hoặc any.
  • Cảnh báo: thiếu biz/core/; hoặc không tìm thấy file controller nào (ngoài controller.go).
  • Lỗi: một function controller (ngoài controller.go) nhận tham số empty-interface; hoặc biz/core/ không đọc được. controller.go được miễn trừ vì RegisterCallback(cb any) là một phần của interface CoreController.

19. Thư mục pkg và client library (verifyPkgDirectory)

Kiểm tra pkg/ và client library được sinh ra <service>_client/.

  • Đạt: pkg/ tồn tại; các package của nó được liệt kê; thư mục <service>_client/ tồn tại; và <service>_client/client.go tồn tại.
  • Cảnh báo: thiếu pkg/; thiếu thư mục client library; hoặc thiếu client.go bên trong nó.
  • Lỗi: không có.

20. Header của file Go (verifyGoFileHeaders)

Duyệt mọi file .go không phải generated (bỏ qua thư mục ẩn, vendor, bin, node_modules, docs, *.pb.go, *_test.go, và các file Code generated ... DO NOT EDIT) rồi báo cáo tỉ lệ phủ header.

  • Đạt: báo cáo số file đã kiểm tra và phần trăm số file mang header chuẩn /* !! ... * File:.
  • Cảnh báo: liệt kê các file thiếu header (giới hạn 10 tên) và gợi ý chạy ftkit header; đồng thời cảnh báo nếu không tìm thấy file Go nào.
  • Lỗi: xảy ra lỗi khi duyệt các file Go.

Ngữ nghĩa kết quả

Sau khi chạy hết các kiểm tra, ftkit verify in ra phần tổng kết với số lượng đạt, cảnh báo, và lỗi, rồi quyết định kết quả:

  • Lỗi > 0 → thất bại. Lệnh in ra danh sách lỗi được đánh số cần fix, in "Repo chưa đạt chuẩn Fountain", và thoát với mã trạng thái 1. Đây là điều làm fail một cổng CI.
  • Chỉ có cảnh báo (không lỗi) → đạt nhưng có lưu ý. Lệnh báo repo đạt chuẩn Fountain nhưng có các cảnh báo cần xem xét, và thoát 0.
  • Không lỗi và không cảnh báo → hoàn toàn đạt chuẩn. Lệnh báo repo hoàn toàn đạt chuẩn Fountain và thoát 0.