Vnstock Logo

Quy ước đặt tên (Naming Convention): Rules cho người và AI

03/11/2026đọc 24 phút
Quy ước đặt tên (Naming Convention): Rules cho người và AI

Một dự án nhỏ thường bắt đầu rất vô hại: test.py, data.csv, analysis.ipynb. Sau vài lần nhờ AI sửa code, thư mục có thêm test2.py, final.py, final_new.py, data_clean.csv và data_clean_final.csv.

Các file vẫn chạy. Vấn đề chỉ xuất hiện khi bạn quay lại sau một tháng và không còn nhớ “final” nào mới là bản cuối, data chứa dữ liệu gì, hoặc biến x2 được tính theo công thức nào. Bạn hỏi một AI khác tiếp tục phát triển, nó lại đặt tên theo một cách mới. Cùng một khái niệm lúc thì là ticker, lúc là symbol, lúc lại là stock_code.

Đây không phải lỗi riêng của người mới. Dự án của lập trình viên có kinh nghiệm cũng trở nên lộn xộn nếu thiếu quy ước chung. Khác biệt nằm ở chỗ họ thường đưa quy ước vào tài liệu, công cụ định dạng và bước kiểm tra để mọi người — kể cả AI agent — làm theo.

Naming convention, cách gọi tự nhiên bằng tiếng Việt là quy ước đặt tên, là điểm bắt đầu của cách làm đó. “Quy tắc đặt tên” vẫn dễ hiểu, nhưng chữ quy ước diễn đạt đúng hơn việc một dự án chủ động chọn một cách gọi chung trong số nhiều cách đều có thể hợp lệ.

Tuy nhiên, chỉ thống nhất snake_case hay camelCase chưa đủ. Một không gian lập trình dễ phát triển còn cần quy ước tổ chức mã nguồn: file nào chứa phần gì, chức năng được chia ra sao, dữ liệu đi qua những lớp nào và AI phải kiểm tra gì trước khi kết thúc công việc.

Bài viết này giúp bạn xây một bộ quy tắc vừa đủ chặt để dự án có trật tự, nhưng không nặng nề tới mức một script cá nhân cũng phải vận hành như phần mềm lớn.

Quy ước đặt tên (naming convention) là gì?

Quy ước đặt tên là cách một dự án thống nhất tên cho các thành phần trong chương trình: biến, hàm, lớp, hằng số, tham số, file, thư mục, bảng dữ liệu và trường dữ liệu.

Quy ước trả lời hai nhóm câu hỏi:

  1. Tên được viết theo hình thức nào? Ví dụ close_price, closePrice hay ClosePrice.
  2. Tên phải truyền đạt ý nghĩa gì? Ví dụ close_price_vnd rõ hơn value, vì người đọc biết đây là giá đóng cửa và đơn vị là đồng.

Nhóm thứ hai quan trọng hơn. Một dự án có thể tuân thủ hoàn hảo kiểu snake_case nhưng vẫn khó hiểu nếu biến được đặt là data_1, result_new và temp_final.

Quy ước đặt tên cũng không hoàn toàn giống coding convention, hay quy ước viết và tổ chức mã nguồn:

  • Quy ước đặt tên tập trung vào cách gọi và cách viết tên.
  • Coding convention rộng hơn, bao gồm cách định dạng, tổ chức file, chia hàm, xử lý lỗi, viết kiểm thử và những quy tắc khác khi tạo mã nguồn.
  • Coding rules cho AI agent là cách viết các convention ấy thành chỉ dẫn để AI có thể đọc và áp dụng trong dự án cụ thể.

Phần coding convention được trình bày riêng trong bài Coding convention là gì? Quy ước cho Python và Next.js, gồm cấu trúc dự án, type, xử lý lỗi, formatter, linter và bước kiểm chứng trước khi AI bàn giao code.

Một data contract giữ cho các bên hiểu cùng ý nghĩa dữ liệu. Một schema dữ liệu khai báo cấu trúc mà dữ liệu cần tuân theo. Quy ước đặt tên giúp phần còn lại của chương trình sử dụng cùng một từ vựng để nói về cấu trúc đó.

Những kiểu viết tên thường gặp

Các ngôn ngữ lập trình có truyền thống khác nhau. Không nên chọn kiểu tên chỉ vì nhìn đẹp; hãy theo quy ước của ngôn ngữ, framework và dự án đang dùng.

Kiểu tênVí dụNơi thường gặp
snake_casedaily_returnBiến, hàm và module Python
camelCasedailyReturnBiến và hàm JavaScript/TypeScript
PascalCasePortfolioAnalyzerLớp, component hoặc kiểu dữ liệu
UPPER_SNAKE_CASEMAX_RETRY_COUNTHằng số
kebab-caseportfolio-summaryTên đường dẫn, thư mục hoặc file trong một số dự án web

PEP 8 — hướng dẫn phong cách của Python — khuyến nghị hàm và biến dùng snake_case, lớp dùng kiểu CapWords hay PascalCase, còn hằng số cấp module dùng UPPER_SNAKE_CASE.1 PEP 8 cũng nhấn mạnh một nguyên tắc thực tế: nếu dự án hiện có dùng convention khác, tính nhất quán nội bộ thường quan trọng hơn việc sửa mọi thứ chỉ để giống tài liệu mẫu.

Ví dụ Python:

Python
MAX_RETRY_COUNT = 3


class PortfolioAnalyzer:
    def calculate_daily_return(self, close_prices):
        ...

Ví dụ TypeScript:

TS
const maxRetryCount = 3;

class PortfolioAnalyzer {
  calculateDailyReturn(closePrices: number[]) {
    // ...
  }
}

Hai đoạn code khác nhau về hình thức nhưng cùng tuân theo một logic: hằng số, lớp, phương thức và biến có vai trò rõ ràng. Không cần ép TypeScript viết như Python hoặc ngược lại.

Năm kiểu viết tên thường gặp trong lập trình: snake_case, camelCase, PascalCase, UPPER_SNAKE_CASE và kebab-caseNăm kiểu viết tên phổ biến và ngữ cảnh áp dụng phù hợp theo ngôn ngữ

Một bảng Do/Don't ngắn có thể dùng khi rà code:

DoDon'tVấn đề cần tránh
daily_returnsdr, data2Tên viết tắt hoặc phụ thuộc thứ tự
calculate_drawdown()process()Không biết hàm thực hiện việc gì
is_validnot_invalidPhủ định kép khó đọc
timeout_secondstimeoutKhông rõ đơn vị
PortfolioAnalyzerPortfolio_AnalyzerTrộn hai kiểu đặt tên
normalization.pyutils_new_final.pyFile chung chung và mang trạng thái tạm thời

Một cái tên tốt cần nói được điều gì?

Tên tốt giúp người đọc hiểu vai trò mà chưa phải mở toàn bộ phần triển khai. Với AI agent, tên tốt còn là ngữ cảnh để mô hình đoán ít hơn khi sửa code.

Đặt tên theo ý nghĩa, không theo hình dạng tạm thời

list_1 nói rằng dữ liệu hiện là một danh sách, nhưng không nói danh sách chứa gì. symbols cho biết nội dung, kể cả sau này kiểu lưu trữ đổi từ danh sách sang một cấu trúc khác.

Tên khó hiểuTên rõ hơnVì sao
ddaily_pricesNêu nội dung và phạm vi thời gian
df2financial_statementsKhông buộc người đọc nhớ DataFrame thứ hai là gì
resultmonthly_returnsNêu kết quả cụ thể
new_datanormalized_pricesNêu trạng thái sau xử lý
final_outputportfolio_summaryNêu sản phẩm đầu ra thay vì trạng thái “cuối”

Những tên như new, old, temp, final chỉ có ý nghĩa trong một thời điểm ngắn. Khi chương trình tiếp tục phát triển, final nhanh chóng có thêm final_v2. Tên theo vai trò bền hơn tên theo thứ tự hình thành.

Đặt tên theo ý nghĩa và vai trò dữ liệu thay vì hình dạng tạm thời hoặc trạng thái new hay finalĐặt tên theo ý nghĩa giúp mã nguồn tự giải thích và bền vững theo thời gian

Biến và danh từ

Biến thường đại diện cho một vật, một giá trị hoặc một tập hợp, nên tên thường là danh từ:

Python
symbol = "FPT"
close_price = 100.5
daily_prices = load_daily_prices(symbol)

Tập hợp nên dùng danh từ số nhiều như symbols, orders hoặc price_rows. Một phần tử riêng lẻ dùng số ít như symbol, order, price_row. Quy tắc đơn giản này làm vòng lặp dễ đọc:

Python
for symbol in symbols:
    ...

Hàm và động từ

Hàm thực hiện một hành động nên bắt đầu bằng động từ:

  • load_prices() — đọc dữ liệu vào chương trình;
  • normalize_columns() — chuẩn hóa tên cột;
  • calculate_returns() — tính lợi suất;
  • save_report() — lưu báo cáo;
  • validate_schema() — kiểm tra schema.

Tên price_data() hoặc handler() quá chung vì không cho biết hàm làm gì. Nếu hàm vừa tải, vừa làm sạch, vừa tính toán, vấn đề có thể không nằm ở tên: hàm đang gánh quá nhiều trách nhiệm và nên được tách nhỏ.

Biến đúng/sai nên đọc như một câu hỏi

Biến Boolean chỉ nhận True hoặc False. Các tiền tố is_, has_, can_, should_ giúp người đọc nhận ra điều đó ngay:

Python
is_market_open = True
has_missing_values = prices.isna().any().any()
should_refresh_cache = cache_age_minutes > 30

Tránh tên phủ định kép như is_not_invalid. is_valid ngắn hơn và giảm nguy cơ viết nhầm điều kiện.

Tên cần mang đơn vị khi đơn vị chưa hiển nhiên

Trong bài toán tài chính, cùng một con số có thể là đồng, nghìn đồng, phần trăm hoặc tỷ lệ thập phân. Nếu hệ thống chưa có kiểu dữ liệu chuyên biệt, hậu tố đơn vị giúp ngăn lỗi:

Python
close_price_vnd = 100_500
return_percent = 1.25
timeout_seconds = 30
lookback_days = 20

Không phải trường nào cũng cần nhét đơn vị vào tên. Nếu schema và phạm vi module đã quy định rõ mọi giá đều dùng cùng một đơn vị, lặp hậu tố ở mọi nơi có thể làm tên dài. Nguyên tắc là: ghi đơn vị tại nơi người đọc có khả năng hiểu nhầm.

Tránh viết tắt chỉ một người hiểu

avg và min đã quen thuộc trong lập trình. dly_prc_adj_v2 thì buộc người khác giải mã. Viết tên đầy đủ thường rẻ hơn thời gian giải thích lại:

Python
adjusted_close_price   # rõ
adj_cls_prc            # khó đọc

Tên quá dài cũng là tín hiệu cần xem lại. calculate_average_adjusted_close_price_for_last_twenty_trading_days() có thể được rút thành calculate_moving_average() nếu khái niệm đã được định nghĩa rõ bằng tham số window=20.

Có nên dùng tiếng Việt không dấu trong tên biến và trường API?

Những tên như ma_ck, khoi_luong, gia_dong_cua có ưu điểm là người Việt mới học lập trình nhìn vào có thể đoán nghĩa khá nhanh. Chúng không phải code “sai”, và đôi khi còn phản ánh nguyên trạng tên trường mà một hệ thống bên ngoài trả về.

Tuy vậy, với code dự kiến phát triển lâu dài, tác giả ưu tiên tên tiếng Anh có nghĩa rõ ràng:

Không ưu tiên trong code mớiƯu tiênLý do
ma_cksymbolTránh viết tắt và dùng được nhất quán giữa nhiều loại tài sản
khoi_luongvolumeKhớp từ vựng phổ biến của thư viện phân tích
gia_dong_cuaclose hoặc close_priceDễ nối với schema OHLCV và công cụ quốc tế
ngay_giao_dichtrading_dateRõ ranh giới từ bằng snake_case, không phụ thuộc dấu tiếng Việt
du_lieu_moinormalized_pricesMô tả trạng thái nghiệp vụ thay vì “mới” một cách tạm thời

Có bốn lý do cho lựa chọn này:

  1. Tính tương thích: thư viện, tài liệu kỹ thuật và công cụ kiểm tra chủ yếu dùng thuật ngữ tiếng Anh.
  2. Khả năng tìm kiếm: volume hoặc close_price dễ đối chiếu với tài liệu và ví dụ bên ngoài hơn khoi_luong.
  3. Tránh hai hệ từ vựng: nếu API dùng tiếng Anh còn code nội bộ dùng tiếng Việt không dấu, dự án phải duy trì thêm một lớp dịch tên.
  4. AI có thêm ngữ cảnh: những tên phổ biến cung cấp nhiều tín hiệu hơn tên viết tắt hoặc từ ghép riêng của một dự án.

Điều đó không có nghĩa phải sửa tên ngay tại điểm tiếp nhận. Nếu một nguồn bên ngoài trả trường khoi_luong, lớp kết nối có thể giữ nguyên phản hồi để đối chiếu, rồi ánh xạ có chủ đích sang volume ở lớp chuẩn hóa:

Python
SOURCE_TO_STANDARD_COLUMNS = {
    "ma_ck": "symbol",
    "khoi_luong": "volume",
    "gia_dong_cua": "close",
}

Cách làm này không phán xét convention của nguồn. Nó chỉ tách rõ tên bên ngoài mà bạn không kiểm soát và tên chuẩn bên trong mà dự án của bạn chịu trách nhiệm duy trì.

Tên trong code có thể dùng tiếng Anh, trong khi thông báo cho người dùng, tài liệu hướng dẫn hoặc nhãn giao diện vẫn dùng tiếng Việt có dấu. File rule từng được tác giả sử dụng trong một webinar chọn cả docstring và comment bằng tiếng Anh để thuận tiện chia sẻ quốc tế. Đây là lựa chọn theo đối tượng đọc, không phải luật bắt buộc cho mọi dự án. Điều quan trọng hơn là đừng trộn ngôn ngữ tùy hứng giữa các file.

Đặt tên nhất quán với ngôn ngữ của lĩnh vực

Chương trình phân tích không chỉ có ngôn ngữ lập trình; nó còn có ngôn ngữ tài chính. Nếu cùng một khái niệm được gọi bằng ba tên, AI và con người đều có thể tưởng đó là ba thứ khác nhau.

Hãy tạo một bảng từ vựng nhỏ cho dự án:

Khái niệmTên chuẩnTên không dùng thêm
Mã định danh tài sảnsymbolticker, stock_code, code
Giá đóng cửacloseclosing, close_price, price_close
Khối lượngvolumevol, qty
Thời điểm kỳ dữ liệutimedate, datetime, timestamp nếu không phân biệt rõ

Bảng trên chỉ là ví dụ. Dự án khác có thể chọn ticker thay cho symbol; điều quan trọng là chọn một từ, định nghĩa nó và dùng nhất quán.

Đây là điểm naming convention nối trực tiếp với schema. Nếu schema công khai dùng symbol, code chuyển đổi không nên tự đổi thành stock_code rồi giao diện lại gọi là ticker nếu không có lý do. Mỗi lần đổi từ là thêm một lớp mapping phải duy trì.

Một từ vựng chung còn giúp đặt tên xuyên suốt:

Text
load_symbols()
validate_symbols()
selected_symbols
symbols.csv
tests/test_symbols.py

Người đọc nhìn tên đã biết các phần này cùng liên quan tới một khái niệm.

Từ vựng chung trong dự án: một khái niệm được dùng xuyên suốt từ tên biến, hàm, file đến test và mapping cộtMột khái niệm một tên gọi duy nhất xuyên suốt mã nguồn giúp AI và người đọc không bị phân tâm

Bài học từ cách tổ chức API của thư viện vnstock

Tài liệu thử nghiệm Vnstock thế hệ 6 cho thấy quy ước đặt tên không tồn tại riêng lẻ. Tên class, nhóm chức năng, method, parameter và cột trả về cần ghép thành một câu có trật tự. Nếu chưa quen các từ này, có thể hiểu class là khuôn tổ chức một nhóm đối tượng, method là hàm nằm trong class, còn parameter là lựa chọn bạn truyền vào khi gọi hàm.

Ví dụ:

Python
Market("<nguồn>").equity("FPT").ohlcv(
    start="2026-10-01",
    end="2026-10-30",
    interval="1D",
)

Lời gọi đi từ phạm vi lớn tới nhỏ:

  1. Market — miền dữ liệu thị trường;
  2. equity — nhóm tài sản;
  3. FPT — đối tượng cụ thể;
  4. ohlcv — dạng kết quả cần lấy;
  5. start, end, interval — điều kiện của lần gọi.

Người dùng không cần nhớ một hàm dài như get_fpt_equity_daily_historical_prices(). Cấu trúc đối tượng đã mang phần lớn ngữ cảnh, nên tên method có thể ngắn mà vẫn rõ.

Thiết kế lời gọi API đọc như một câu hoàn chỉnh: chủ ngữ, hành động, đối tượng và điều kiện lọcCấu trúc lời gọi API mạch lạc giúp mã nguồn trực quan và dễ đoán tham số

Điều này cũng bổ sung một ngoại lệ cho quy tắc “hàm phải bắt đầu bằng động từ”. Hàm hành động độc lập nên dùng động từ như calculate_returns() hoặc validate_schema(). Nhưng method nằm trong một API có ngữ cảnh rõ có thể dùng danh từ hoặc thuật ngữ quen thuộc như quote(), trades(), members() hay ohlcv(). Mục tiêu là để toàn bộ lời gọi đọc có logic, không phải ép từng tên đứng riêng tuân theo một công thức.

Ba class cấp cao phân chia trách nhiệm ngay bằng tên:

ClassCâu hỏi nó trả lờiVí dụ nhóm bên trong
ReferenceĐối tượng nào tồn tại và thông tin tham chiếu là gì?company, index, market, search
MarketDiễn biến và trạng thái thị trường được biểu diễn thế nào?equity, index, futures, crypto
FundamentalThông tin cơ bản và báo cáo tài chính được tổ chức ra sao?equity, balance_sheet, income_statement

Cách chia này giúp tránh dồn mọi thứ vào một class chung như DataClient với hàng trăm method không có quan hệ rõ ràng.

Parameter cần dùng cùng một từ cho cùng một ý

Các lời gọi dùng lại những parameter chung như source, symbol, start, end, columns và compat. Nếu cùng ý “ngày bắt đầu” lúc được gọi là start, lúc là from_date, lúc là begin, người dùng và AI phải tra lại từng hàm.

DoDon'tLý do
Dùng start và end nhất quánTrộn start_date, from_date, begin_time mà không có khác biệt ngữ nghĩaGiảm số từ người dùng phải nhớ
Dùng symbol cho một mã định danhLúc dùng ticker, lúc dùng codeTránh tạo nhiều tên cho cùng khái niệm
Dùng parameter theo tên khi lời gọi dàiTruyền nhiều chuỗi và số chỉ theo vị tríNgười đọc thấy ngay mỗi giá trị có vai trò gì
Từ chối parameter không được hỗ trợNhận mọi **kwargs rồi âm thầm bỏ quaPhát hiện lỗi gõ tên sớm hơn

Tên đầu ra là một phần của giao diện công khai

Ở lớp dữ liệu trả về, Vnstock thế hệ 6 hướng tới “một tên, một nghĩa” giữa các bảng. Các trường OHLCV dùng time, open, high, low, close, volume; metadata như nguồn, thời điểm lấy và thay đổi schema nằm trong df.attrs thay vì trộn vào các cột tính toán.

Tham số columns còn phân biệt ba nhu cầu: bộ cột chuẩn, phần giao nhau giữa các nguồn và trường riêng của nguồn. Tên riêng được đặt sau tiền tố src_ để người dùng nhận ra đây không phải giao diện ổn định dùng chung.

Đó là một quy tắc đáng tái sử dụng:

  • tên chuẩn dành cho phần dự án chủ động duy trì;
  • tên bên ngoài được giữ ở ranh giới tích hợp để truy vết;
  • bước mapping được viết rõ thay vì đổi tên rải rác trong notebook;
  • thay đổi tên công khai cần có phiên bản, cảnh báo hoặc hướng dẫn chuyển đổi.

Tài liệu hiện tại ghi rõ đây là bản thử nghiệm 6.0.0rc1, nên tên hàm và parameter vẫn có thể thay đổi trước khi phát hành. Chính giai đoạn thử nghiệm là lúc convention cần được kiểm tra kỹ; sau khi nhiều người đã viết code dựa vào một tên, chi phí đổi tên tăng lên rất nhanh.

Tổ chức file và thư mục để AI không phải đi tìm trong mê cung

Tên biến tốt không cứu được một dự án có mọi thứ nằm trong một file 4.000 dòng. Coding convention cần quy định cả nơi mỗi loại mã được đặt.

Một dự án phân tích cá nhân có thể bắt đầu bằng cấu trúc vừa phải:

Text
market-research/
├── README.md
├── AGENTS.md
├── pyproject.toml
├── .env.example
├── notebooks/
│   └── 01_explore_prices.ipynb
├── src/
│   └── market_research/
│       ├── __init__.py
│       ├── data_access.py
│       ├── normalization.py
│       ├── indicators.py
│       └── reporting.py
├── tests/
│   ├── test_normalization.py
│   └── test_indicators.py
└── output/
    └── .gitkeep

Mỗi nơi có một vai trò:

  • README.md: giải thích dự án làm gì và cách chạy;
  • AGENTS.md: quy tắc để AI agent làm việc trong dự án;
  • notebooks/: khám phá, thử giả thuyết và trình bày;
  • src/: phần code cần dùng lại;
  • tests/: các phép kiểm tự động;
  • output/: kết quả sinh ra, thường không nên đưa toàn bộ vào Git.
Tổ chức thư mục dự án theo trách nhiệm rõ ràng: tách biệt nguồn vào, logic tính toán, lưu trữ và giao diệnCấu trúc thư mục mạch lạc giúp AI agent định vị đúng file cần sửa mà không làm xáo trộn toàn bộ dự án

Bạn không cần tạo đủ cấu trúc này cho đoạn script 20 dòng. Hãy tách khi một phần bắt đầu được dùng lại, cần kiểm thử riêng hoặc có thể thay đổi độc lập.

Quy tắc đặt tên file

Tên file nên nói rõ trách nhiệm:

  • data_access.py thay cho utils.py nếu file chỉ xử lý truy cập đầu vào;
  • normalization.py thay cho helpers.py nếu file chứa quy tắc chuẩn hóa;
  • test_indicators.py cho kiểm thử tương ứng với indicators.py;
  • 01_explore_prices.ipynb và 02_compare_sources.ipynb nếu notebook có thứ tự học hoặc thực hiện.

Những file như utils.py, common.py, misc.py dễ trở thành nơi chứa mọi hàm chưa biết đặt ở đâu. Chúng không luôn sai, nhưng khi file bắt đầu lớn, hãy tách theo trách nhiệm thực tế.

Tên ngày tháng nên dùng dạng YYYY-MM-DD nếu cần sắp xếp theo thời gian. Tránh report_final_latest.xlsx; dùng portfolio-summary-2026-11-05.xlsx sẽ dễ tìm và tự sắp xếp hơn.

Định dạng code cũng là một phần của convention

Hai đoạn code có thể chạy giống nhau nhưng khác cách xuống dòng, thụt lề và dùng dấu nháy. Nếu mỗi lần AI chỉnh một kiểu, phần thay đổi trong Git trở nên nhiễu: rất khó biết logic nào thực sự đã đổi.

Đừng dành nhiều thời gian tranh luận bằng tay về khoảng trắng. Hãy chọn công cụ phù hợp với ngôn ngữ:

  • Python có thể dùng formatter như Black hoặc Ruff;
  • JavaScript/TypeScript thường dùng Prettier;
  • linter như Ruff hoặc ESLint giúp phát hiện thêm lỗi và quy ước không thể xử lý chỉ bằng định dạng.

Formatter tự sửa hình thức trình bày. Linter phân tích code để cảnh báo lỗi hoặc cách viết không phù hợp. Hai công cụ có phần giao nhau nhưng không hoàn toàn thay thế nhau.

Quy tắc cho AI nên yêu cầu chạy formatter, linter và kiểm thử đã có sau khi sửa. Khi convention được thực thi bằng công cụ, bạn không phải nhắc lại cùng một điều ở mỗi cuộc trò chuyện.

Comment và tài liệu không nên kể lại từng dòng code

Comment hữu ích giải thích vì sao có một quyết định, giới hạn hoặc cách xử lý không hiển nhiên. Comment yếu chỉ dịch code sang câu chữ.

Python
# Không tốt: cộng một vào retry_count
retry_count += 1

# Hữu ích: nguồn có thể trả 429 trong thời gian ngắn; chỉ thử lại lỗi này
retry_count += 1

Nếu cần một đoạn văn dài để giải thích hàm làm gì, tên hàm hoặc cách chia hàm có thể chưa đủ rõ. Với hàm công khai, docstring nên mô tả đầu vào, đầu ra, ngoại lệ quan trọng và đơn vị dễ nhầm.

Không để comment cũ mâu thuẫn với code mới. AI agent thường có xu hướng sửa logic mà bỏ quên chú thích; coding rules nên yêu cầu cập nhật hoặc xóa comment không còn đúng trong cùng thay đổi.

Quy tắc nào nên giao cho AI agent?

AI agent không chỉ sinh một đoạn code trong khung chat. Nó có thể đọc nhiều file, sửa cấu trúc, chạy lệnh và tiếp tục công việc qua nhiều bước. Vì vậy, chỉ dẫn cần nói rõ cả cách viết lẫn cách thay đổi dự án.

Một bộ rules hữu ích nên bao phủ sáu lớp:

  1. Ngôn ngữ và từ vựng: tên trong code dùng ngôn ngữ nào; thuật ngữ lĩnh vực nào là tên chuẩn.
  2. Tên và định dạng: snake_case, camelCase, tên lớp, hằng số, file và thư mục.
  3. Kiến trúc: code mới đặt ở đâu; khi nào tách module; lớp nào không được gọi trực tiếp lớp nào.
  4. An toàn thay đổi: không tự ý đổi public API, schema hay xóa file; bảo toàn hành vi ngoài phạm vi yêu cầu.
  5. Kiểm chứng: phải chạy formatter, linter, type checker và test nào.
  6. Bàn giao: nói rõ file đã sửa, giả định đã dùng và phần chưa kiểm chứng.
Sáu lớp quy tắc mã nguồn cần khai báo cho AI agent: nguyên tắc chung, đặt tên, tổ chức code, tài liệu và lỗi, dữ liệu và kiểm chứngSáu lớp quy tắc trong file hướng dẫn agent giúp kiểm soát chất lượng code do AI sinh ra

Quy tắc càng chung chung, AI càng phải tự diễn giải. “Viết clean code” gần như không cung cấp gì để kiểm tra. “Hàm và biến Python dùng snake_case; biến Boolean bắt đầu bằng is_, has_, can_ hoặc should_” cụ thể hơn nhiều.

Tuy nhiên, không nên nhét toàn bộ giáo trình lập trình vào AGENTS.md. Tệp chỉ dẫn nên ghi những điều riêng của dự án, những quyết định có nhiều phương án hợp lệ và các lệnh kiểm tra thực tế. Chuẩn phổ biến có thể được nhắc bằng tên, chẳng hạn “tuân theo PEP 8”, rồi chỉ bổ sung ngoại lệ.

Bộ coding rules mẫu để dùng với AI agent

Khối dưới đây là điểm khởi đầu cho một dự án Python phân tích dữ liệu. Bạn có thể đặt nó trong AGENTS.md, CLAUDE.md hoặc tệp rules mà công cụ đang dùng. Hãy sửa tên thư mục và lệnh kiểm tra theo dự án thật; đừng chép nguyên nếu chúng không tồn tại.

Khối này kế thừa một số ý từ file GitHub Copilot Instructions từng được tác giả chia sẻ trong webinar: tuân theo PEP 8, dùng type hint, chia module theo một trách nhiệm, ghi rõ giả định của công thức, kiểm tra đầu vào và không lưu khóa bí mật dưới dạng văn bản trong code. Bản webinar giới hạn tên trong khoảng một đến ba từ để giữ sự ngắn gọn; ở đây quy tắc được nới thành “ngắn nhất có thể nhưng vẫn đủ nghĩa”, vì số từ không quan trọng bằng việc người đọc hiểu đúng.

MD
## Coding conventions

### Nguyên tắc chung
- Đọc cấu trúc và code hiện có trước khi tạo file hoặc abstraction mới.
- Ưu tiên convention đang được dùng nhất quán trong dự án.
- Tuân theo PEP 8 và dùng type hint cho đầu vào, đầu ra không hiển nhiên.
- Chỉ sửa trong phạm vi yêu cầu; không đổi public API, schema hoặc định dạng đầu ra nếu chưa được yêu cầu.
- Không tạo bản sao kiểu `final`, `new`, `v2`; sửa đúng file hoặc đặt tên theo trách nhiệm.

### Đặt tên
- Tên hàm, biến, module và file Python dùng `snake_case`.
- Tên lớp dùng `PascalCase`; hằng số dùng `UPPER_SNAKE_CASE`.
- Tên trong code dùng tiếng Anh; nội dung hiển thị cho người dùng có thể dùng tiếng Việt.
- Hàm hành động bắt đầu bằng động từ; method truy vấn có thể dùng danh từ quen thuộc khi class đã cung cấp đủ ngữ cảnh.
- Tập hợp dùng danh từ số nhiều; một phần tử dùng danh từ số ít.
- Boolean bắt đầu bằng `is_`, `has_`, `can_` hoặc `should_`.
- Không dùng tên chung chung như `data`, `result`, `temp`, `helper` nếu có thể nêu vai trò cụ thể.
- Ghi đơn vị trong tên khi có nguy cơ nhầm, ví dụ `_vnd`, `_percent`, `_seconds`, `_days`.
- Dùng `symbol` cho mã định danh tài sản; không tạo thêm biến thể `ticker` hoặc `stock_code`.

### Tổ chức code
- Code dùng lại đặt trong `src/`; notebook chỉ dùng để khám phá và trình bày.
- Kiểm thử đặt trong `tests/` và đặt tên tương ứng với module được kiểm tra.
- Không tạo file `utils.py` hoặc `helpers.py` mới; đặt file theo trách nhiệm nghiệp vụ.
- Tách hàm khi một hàm vừa truy xuất, vừa chuẩn hóa, vừa tính toán hoặc vừa ghi kết quả.
- Không đưa API key, mật khẩu hoặc dữ liệu nhạy cảm vào code, notebook, log hay commit.

### Tài liệu và lỗi
- Docstring của hàm tài chính ghi rõ parameter, kiểu trả về, đơn vị, công thức, giả định và giới hạn quan trọng.
- Comment giải thích lý do hoặc quyết định khó thấy; không kể lại từng dòng code.
- Khi sửa logic, cập nhật hoặc xóa comment và docstring không còn đúng.
- Không âm thầm bỏ qua lỗi đầu vào, lỗi mạng hoặc giá trị ngoài enum; trả lỗi có nguyên nhân và cách xử lý tiếp theo.
- Log đủ ngữ cảnh để đối chiếu nhưng không ghi API key, token hoặc dữ liệu nhạy cảm.

### Dữ liệu
- Kiểm tra schema đầu vào trước khi tính toán.
- Không tự thay `null` bằng `0` nếu data contract chưa quy định.
- Không đổi tên trường, đơn vị, múi giờ hoặc enum mà không ghi rõ bước chuyển đổi.
- Giữ bước truy xuất, chuẩn hóa và phân tích thành các phần riêng.

### Kiểm chứng
- Cập nhật hoặc thêm test cho hành vi bị thay đổi.
- Chạy formatter, linter và test liên quan trước khi kết thúc.
- Không tuyên bố hoàn thành nếu chưa chạy được bước kiểm tra; nói rõ bước nào chưa chạy và vì sao.
- Khi bàn giao, liệt kê file đã sửa và ảnh hưởng đáng chú ý.

Rules không phải phép bảo đảm AI luôn làm đúng. Chúng tạo một tiêu chuẩn để agent tự kiểm tra và để bạn nhận ra khi kết quả đi lệch. Với nhiệm vụ chuyên biệt, có thể tách hướng dẫn dài thành Agent Skills thay vì làm tệp rules ngày càng phình to.

Áp dụng convention cho dự án đang lộn xộn

Đừng yêu cầu AI đổi tên toàn bộ dự án trong một lần. Một đợt thay tên lớn có thể làm hỏng import, công thức notebook, tên cột, đường dẫn file và chương trình bên ngoài đang sử dụng.

Hãy chuyển đổi theo từng vòng nhỏ.

Bước 1 — Lập danh sách từ đang dùng.

Tìm các biến thể cùng một khái niệm như ticker, symbol, stock_code. Xác định tên nào xuất hiện trong public API, tên nào chỉ dùng nội bộ và tên nào đến từ nguồn bên ngoài.

Bước 2 — Chọn tên chuẩn và phạm vi áp dụng.

Viết bảng từ vựng ngắn. Nếu tên cũ đã là một phần của API công khai, không đổi ngay chỉ vì tên mới đẹp hơn. Có thể giữ lớp tương thích hoặc lên kế hoạch chuyển đổi theo phiên bản.

Bước 3 — Tách đổi tên khỏi đổi logic.

Một commit chỉ đổi tên sẽ dễ kiểm tra hơn commit vừa đổi tên, vừa sửa công thức, vừa di chuyển file. Với người không dùng Git thường xuyên, nguyên tắc này vẫn hữu ích: hoàn tất và chạy thử từng loại thay đổi trước khi làm bước tiếp theo.

Bước 4 — Dùng công cụ để giữ convention.

Cấu hình formatter và linter, thêm lệnh kiểm tra vào tài liệu, rồi yêu cầu AI chạy chúng. Convention được máy kiểm tra sẽ bền hơn convention chỉ tồn tại trong trí nhớ.

Bước 5 — Sửa dần khi chạm vào code cũ.

Không nhất thiết dọn toàn bộ dự án trước khi phát triển tiếp. Khi sửa một module, hãy làm rõ tên và cấu trúc trong phạm vi đó, miễn là không tạo thay đổi phá vỡ tương thích ngoài dự kiến.

Convention tốt làm giảm chi phí bảo trì như thế nào?

Tên gọi và cấu trúc nhất quán không làm thuật toán chạy nhanh hơn, nhưng làm quá trình phát triển ít tốn sức hơn.

  • Bạn tìm đúng file nhanh hơn.
  • AI đọc tên đã có thể nhận ra vai trò của biến và hàm.
  • Code review tập trung vào logic thay vì tranh luận hình thức.
  • Việc đổi nguồn hoặc đổi schema ít lan sang các phần không liên quan.
  • Lỗi đơn vị, thời gian và giá trị đúng/sai dễ được nhận biết hơn.
  • Người khác có thể tái lập quy trình mà không cần hỏi tác giả từng tên viết tắt.

Kinh nghiệm phát triển các lớp chuẩn hóa trong thư viện vnstock cũng cho thấy tên công khai càng được nhiều người sử dụng, chi phí thay đổi càng lớn. Một cái tên ban đầu chỉ là lựa chọn tiện tay có thể trở thành điểm phụ thuộc của notebook, dashboard và quy trình phân tích. Vì vậy, đặt tên là một phần của thiết kế giao diện, không chỉ là việc làm đẹp code.

Convention tốt không yêu cầu mọi dự án giống nhau. Nó yêu cầu mỗi dự án biết mình đang chọn gì, ghi lại lựa chọn đó và áp dụng đủ nhất quán để con người lẫn AI không phải sáng tác lại quy tắc sau mỗi lần làm việc.

Điều cần nhớ

Quy ước đặt tên bắt đầu từ snake_case và camelCase, nhưng giá trị thực nằm ở việc tạo một ngôn ngữ chung cho dự án. Tên cần thể hiện vai trò, từ vựng tài chính cần nhất quán, file và thư mục cần có trách nhiệm rõ, còn định dạng nên được công cụ tự động kiểm tra.

Với vibe coder, bộ rules không thay thế kiến thức lập trình. Nó giúp biến những lựa chọn quan trọng thành chỉ dẫn có thể dùng lại: AI biết tên nào nên dùng, code nên đặt ở đâu, thay đổi nào cần tránh và phải kiểm tra gì trước khi nói đã hoàn thành.

Bạn có thể bắt đầu rất nhỏ: chọn một tên chuẩn cho mã tài sản, đổi df1 thành tên có nghĩa, tách một notebook thành phần khám phá và module dùng lại, rồi thêm khối coding rules vào dự án. Khi cách tổ chức đã thành quy ước, lần làm việc tiếp theo không còn bắt đầu từ một thư mục hỗn độn và một prompt trắng.


Nội dung phục vụ học tập, nghiên cứu và tham khảo. Ví dụ trong bài là điểm khởi đầu; hãy ưu tiên convention chính thức của ngôn ngữ, framework và dự án bạn đang sử dụng.

Footnotes

  1. PEP 8 mô tả convention hiện hành cho mã Python, gồm tên module, hàm, biến, lớp và hằng số: PEP 8 – Style Guide for Python Code ↩

Bài liên quan