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.modtồn tại; và cóconfig.yamlhoặcconfig.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.gokhai báopackage main; sử dụng pattern bootstrap của fountain (.WithAppInstances,fountain.New(), hoặcServing()); 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.gothiếu hoặc không đọc được; thiếupackage main; thiếu pattern bootstrap; hoặc thiếu lời gọiServing().
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 structserver; cófunc NewServer(); cài đặt các lifecycle methodInitialize(),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.gothiếu/không parse được; thiếu blank importbiz; thiếu structserver; thiếuNewServer(); 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.gotồ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.gocó blank import cho các package controller (biz/core/*); thư mụcbiz/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 trongbiz/core/; hoặc số domain nhiều hơn số blank import (có thể thiếu import). - Lỗi:
biz/biz.gothiếu/không parse được; hoặcbiz/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ùngsync.Oncecho singleton; cài đặtInstallController(); và cài đặtRegisterCallback()(tìm thấy trongcontroller.gohoặc file khác của domain). - Cảnh báo: không tìm thấy file
controller.go/RegisterCoreControllertrong một domain; không dùngsync.Once; hoặc không tìm thấy controller domain nào. - Lỗi: thiếu
RegisterCoreController(),InstallController(), hoặcRegisterCallback()cho một domain; hoặcbiz/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.gochỉ khai báoInstallController(),RegisterCallback(),AfterInstalledDone(),init(), và một accessorGet<Name>ControllerInstance(). - Cảnh báo: thiếu
biz/core/; không parse được mộtcontroller.go; hoặc không tìm thấy filecontroller.gonà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ó constructorNew*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ó constructorNew*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.govà 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.gokhô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.gonào. - Lỗi: một method trong
*_impl.gonhậ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.gotồn tại; có các hằng số cache/db/storage (*_CACHE/*_DB/*_STO); cófunc init(); dùng patternRegisterDAO; 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ặcbiz/dal/models/; thiếumanagers.go; hoặcmanagers.gothiếu hằng số,init(), hoặc patternRegisterDAO. - 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ả models và do.
- Đạ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 falsevà đ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ặcbiz/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ặcbiz/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ằngDAO,Cache, hoặcSTO. - Cảnh báo: thiếu
biz/core/; hoặc không tìm thấyInstallController()nào để kiểm tra. - Lỗi: một type parameter
GetDAO[...]không kết thúc bằngDAO,Cache, hoặcSTO.
15. Cách dùng logging (verifyLoggingUsage)
Duyệt biz/ và 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ọifmt.Print*haylog.*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/Printfnào, hoặc bất kỳ lời gọilog.*nào (nhóm Print/Fatal/Panic) ngoài comment — chỉ được phép dùngflog.
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ằngDAO/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.gokhai 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ềerrorthuầ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
errorthuầ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ặcany. - Cảnh báo: thiếu
biz/core/; hoặc không tìm thấy file controller nào (ngoàicontroller.go). - Lỗi: một function controller (ngoài
controller.go) nhận tham số empty-interface; hoặcbiz/core/không đọc được.controller.gođược miễn trừ vìRegisterCallback(cb any)là một phần của interfaceCoreController.
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.gotồn tại. - Cảnh báo: thiếu
pkg/; thiếu thư mục client library; hoặc thiếuclient.gobê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.