Hardcode trong phát triển phần mềm: nó là gì, rủi ro và cách tránh

Tác giả: IT Sectr Đã đăng: 2026-07-31 Thời gian đọc: 7 phút

“Đóng đinh” và “hardcode” là các thuật ngữ lóng chỉ việc cố định giá trị trực tiếp trong mã nguồn, thay vì đưa chúng vào cài đặt hoặc cấu hình. Hardcode là một trong những phản mẫu nổi tiếng nhất trong phát triển phần mềm vì nó làm giảm tính linh hoạt và khả năng tái sử dụng mã. Theo Refactoring Guru, hardcode làm phức tạp việc kiểm thử, bảo trì và thích ứng ứng dụng với các môi trường khác nhau. Việc có ý thức sử dụng hằng số thay vì hardcode là dấu hiệu của kiến trúc trưởng thành.

Điểm chính

  • Hardcode — viết một giá trị cụ thể trực tiếp trong mã nguồn
  • Hardcode được coi là phản mẫu do mất tính linh hoạt và khó bảo trì
  • Ngoại lệ: hằng số toán học, kích thước mảng, giá trị mặc định
  • Giải pháp thay thế: tệp cấu hình, biến môi trường, tài nguyên
  • Tái cấu trúc hardcode cải thiện khả năng kiểm thử và mở rộng mã

“Đóng đinh” và “hardcode” có nghĩa là gì

Hardcode (đóng đinh) — nhúng một giá trị cụ thể vào mã chương trình đến mức để thay đổi nó cần phải chỉnh sửa mã nguồn và biên dịch lại ứng dụng. Phép ẩn dụ “đóng đinh” phản ánh chính xác bản chất: giá trị bị cố định vĩnh viễn và chỉ có thể tách khỏi mã bằng nỗ lực.

Ví dụ về hardcode — URL máy chủ được viết dưới dạng chuỗi trực tiếp trong thân hàm. Nếu máy chủ chuyển sang địa chỉ khác, nhà phát triển phải tìm chuỗi trong mã, thay đổi nó, xây dựng lại ứng dụng và phát hành bản phát hành. Trong một ứng dụng có kiến trúc đúng đắn, URL như vậy sẽ được đưa vào tệp cấu hình, biến môi trường hoặc dịch vụ cấu hình.

Thuật ngữ “đóng đinh” mang sắc thái cảm xúc hơn: nó nhấn mạnh rằng giá trị được gắn vĩnh viễn và không thể thay thế nhanh chóng. Trong môi trường nói tiếng Nga, cả hai biểu thức được sử dụng như từ đồng nghĩa hoàn toàn với hàm ý tiêu cực. Đôi khi hardcode được gọi một cách mỉa mai là “hằng số được trích xuất thành một hằng số riêng từ một hằng số”.

Tại sao hardcode được coi là phản mẫu

Hardcode là một phản mẫu vì nó vi phạm các nguyên tắc bảo trì, kiểm thử và mở rộng mã. Trong mã mà các giá trị bị “đóng đinh”, bất kỳ thay đổi nào về môi trường, thiết kế hoặc logic đều yêu cầu tìm kiếm và thay thế thủ công trong mã nguồn. Điều này làm tăng nguy cơ lỗi và làm chậm quá trình phát triển.

Hãy xem xét hậu quả cụ thể của hardcode với ví dụ về một ứng dụng di động điển hình. Nếu lề của tất cả các nút được xác định bằng một số trong mã thay vì thông qua tài nguyên — thay đổi thiết kế sẽ yêu cầu tìm tất cả các lần xuất hiện và thay thế chúng. Nếu URL điểm cuối bị cố định — việc chuyển đổi giữa các môi trường (dev, stage, prod) là không thể nếu không xây dựng lại.

Hậu quảMô tảMức nghiêm trọng
Khó bảo trìThay đổi yêu cầu tìm kiếm trong toàn bộ mãCao
Lỗi khi sao chépKhông tìm thấy và thay thế được tất cả các lần xuất hiệnCao
Không thể kiểm thửKhông thể thay thế dữ liệu kiểm thửTrung bình
Vấn đề bản địa hóaVăn bản trong mã không được dịchTrung bình
Phức tạp review mãNgười review phải nhớ tất cả các ngữ cảnhThấp

Ví dụ về hardcode tồi

Một hàm sử dụng số ma thuật và chuỗi cố định — ví dụ kinh điển của hardcode. Sau một tháng, tác giả sẽ không nhớ 18, 0.07 và 2.5 có nghĩa là gì. Sau một năm — không ai trong nhóm dám thay đổi những con số này vì sợ làm hỏng logic. Việc đưa các giá trị vào hằng số có tên làm cho mã tự ghi chú.

kotlin
// Xấu: số ma thuật và chuỗi
fun calculatePrice(base: Double): Double {
    val tax = base * 0.07
    val tip = base * 0.15
    val discount = if (base > 100) 10 else 0
    return base + tax + tip - discount
}

Ảnh hưởng đến kiểm thử

Một URL cơ sở dữ liệu hardcode sẽ không cho phép chạy kiểm thử trên cơ sở dữ liệu in-memory cục bộ. Nhà phát triển sẽ phải khởi động một máy chủ đầy đủ hoặc chỉnh sửa mã trước khi kiểm thử. Việc đưa cấu hình ra khỏi mã giải quyết vấn đề: kiểm thử sử dụng tham số kiểm thử, production sử dụng tham số thực tế, và mã không thay đổi.

Khi nào hardcode được chấp nhận: ngoại lệ

Hardcode là một phản mẫu, nhưng có những ngoại lệ chính đáng khi giá trị cố định không chỉ được chấp nhận mà còn được ưu tiên. Ranh giới nằm ở trục khả biến: nếu giá trị không bao giờ hoặc hầu như không bao giờ thay đổi trong vòng đời của ứng dụng, nó có thể được hardcode. Nếu có khả năng thay đổi — hãy đưa nó vào cấu hình.

Các hằng số toán học và vật lý — Pi, gia tốc trọng trường, số mili giây trong một giây — an toàn để hardcode. Chúng được xác định bởi tự nhiên hoặc tiêu chuẩn và sẽ không thay đổi. Kích thước mảng hằng số được xác định bởi đặc tả kỹ thuật cũng có thể cố định, nhưng kèm theo chú thích về nguồn gốc của con số.

Ví dụ về hardcode chấp nhận được

Số mili giây trong một giây là một hằng số ổn định được xác định bởi tiêu chuẩn thời gian. Không có ý nghĩa gì khi đưa nó vào config vì nó sẽ không bao giờ thay đổi. Tuy nhiên, ngay cả những hằng số như vậy cũng nên được khai báo với tên có ý nghĩa, để mã không chứa “số ma thuật”: thay vì 1000, hãy viết MILLISECONDS_IN_SECOND.

kotlin
// Hardcode chấp nhận được: hằng số ổn định
private const val MILLIS_IN_SECOND = 1000
private const val LOGIN_TIMEOUT_SECONDS = 30

fun formatDuration(ms: Long): String {
    val seconds = ms / MILLIS_IN_SECOND
    return "${seconds} sec."
}

Giải pháp thay thế hardcode: config, ENV, DI

Có một số cách được kiểm chứng để tránh hardcode, mỗi cách phù hợp với loại giá trị của nó. Việc lựa chọn giải pháp thay thế phụ thuộc vào tần suất thay đổi của giá trị và ai thay đổi nó: nhà phát triển, devops hay người dùng cuối.

Tệp cấu hình

Đối với URL máy chủ, khóa API và cờ tính năng, hãy sử dụng tệp cấu hình ở các định dạng JSON, YAML hoặc TOML. Trên Android, đó là build.gradle với buildConfigField hoặc res/values/config.xml. Trên iOS — Info.plist hoặc xcconfig. Các tệp cấu hình được xây dựng cùng với ứng dụng nhưng có thể khác nhau cho các lược đồ xây dựng khác nhau.

Biến môi trường

Đối với bí mật (token, mật khẩu) và tham số môi trường, hãy sử dụng biến môi trường. Chúng không được đưa vào kho lưu trữ và có thể khác nhau trên các máy chủ dev, stage và prod. Trong phát triển di động, các biến môi trường thường được mô phỏng thông qua lược đồ xây dựng Xcode hoặc build flavors trong Gradle.

Tài nguyên ứng dụng

Chuỗi, màu sắc, kích thước, hình ảnh nên được đưa vào tệp tài nguyên: strings.xml trên Android, Localizable.strings trên iOS, tệp ARB trong Flutter. Điều này giúp dễ dàng bản địa hóa, thích ứng với các màn hình khác nhau và chế độ tối. Thay đổi một chuỗi trong tài nguyên không yêu cầu viết lại mã.

xml
<!-- Android: res/values/strings.xml -->
<resources>
    <string name="app_name">MyApp</string>
    <string name="api_base_url">https://api.example.com</string>
</resources>

Tiêm phụ thuộc (DI)

Đối với dịch vụ và nhà cung cấp, hãy sử dụng Dependency Injection thông qua Dagger, Hilt hoặc Koin trên Android, Swinject trên iOS. Các framework DI cho phép thay thế các triển khai khi đang chạy — cho kiểm thử, cho các môi trường khác nhau, cho các người dùng khác nhau. Đây là mức trừu tượng cao nhất, nơi việc “cố định” giá trị được thay thế bằng tiêm bên ngoài.

Cách tái cấu trúc mã hardcode

Tái cấu trúc hardcode là quá trình đưa các giá trị cố định vào cấu hình hoặc tài nguyên. Đây là một trong những thao tác tái cấu trúc an toàn nhất nếu được thực hiện một cách có phương pháp. Trình tự được mô tả dưới đây phù hợp cho bất kỳ ngôn ngữ và nền tảng nào.

Bước 1: tìm tất cả các số ma thuật và chuỗi

Có thể tìm kiếm thông qua IDE (Search in Project) hoặc script. Tìm chuỗi, URL, ký tự số, kích thước, thời gian chờ. Đặc biệt chú ý — các giá trị lặp lại: nếu cùng một số xuất hiện ở năm nơi, đó là ứng cử viên để đưa vào hằng số. Sử dụng grep hoặc tìm kiếm tích hợp của IDEA / Xcode.

Bước 2: thay thế bằng hằng số có tên

Cho mỗi giá trị được tìm thấy, hãy tạo một hằng số với tên có ý nghĩa. Nhóm các hằng số theo mô-đun hoặc lớp. Tên nên giải thích ý nghĩa của giá trị, không phải cách nó được sử dụng: API_TIMEOUT, không phải TIMEOUT_30. Sau khi thay thế, không còn số nào trong mã mà không có giải thích.

swift
// Trước: số ma thuật 0.4
let cardHeight = screenHeight * 0.4

// Sau: hằng số có tên
private let cardHeightRatio: CGFloat = 0.4
let cardHeight = screenHeight * cardHeightRatio

Bước 3: đưa vào cấu hình hoặc tài nguyên

Nếu giá trị có thể thay đổi giữa các bản dựng hoặc môi trường — hãy đưa nó vào tệp cấu hình hoặc tài nguyên ứng dụng. Đối với chuỗi, sử dụng tệp bản địa hóa. Đối với URL — build config hoặc xcconfig. Đối với kích thước — tệp tài nguyên (dimens.xml trên Android). Kiểm tra ứng dụng xây dựng và hoạt động chính xác sau khi đưa ra.

Bước 4: viết kiểm thử

Sau khi tái cấu trúc, hãy viết một kiểm thử xác nhận rằng cấu hình được tải chính xác và các giá trị tương ứng với kỳ vọng. Nếu trong tương lai ai đó thay đổi config, kiểm thử sẽ chỉ ra sự không khớp. Kiểm thử cấu hình là một cách nhanh chóng và đáng tin cậy để ngăn chặn hồi quy.

Bước 5: xóa các bản sao

Sau khi đưa vào config, hãy kiểm tra rằng tất cả các nơi đã sử dụng giá trị cũ đều tham chiếu đến nguồn duy nhất. Xóa mã đã chú thích và các hằng số cũ không còn được sử dụng. Hoàn tất việc tái cấu trúc bằng một commit với thông điệp mô tả những giá trị nào đã được đưa vào đâu.

Câu hỏi thường gặp

“Hardcode” trong lập trình có nghĩa là gì?

Hardcode — viết một giá trị trực tiếp trong mã nguồn thay vì đưa nó vào cấu hình hoặc tài nguyên. Điều này làm cho mã kém linh hoạt hơn và khó bảo trì hơn.

Tại sao hardcode được coi là thực hành xấu?

Hardcode làm phức tạp việc thay đổi hành vi ứng dụng, cản trở kiểm thử, tạo ra sự trùng lặp và tăng nguy cơ lỗi khi sao chép. Thay đổi một giá trị hardcode đòi hỏi phải xây dựng lại và phát hành lại ứng dụng.

Khi nào hardcode được chấp nhận?

Được chấp nhận cho các hằng số toán học, các giá trị ổn định không thay đổi trong vòng đời ứng dụng và cho các nguyên mẫu tạm thời. Trong production, ngay cả hằng số cũng nên được đưa vào biến có tên.

Làm thế nào để thay thế hardcode trong mã hiện có?

Tìm tất cả các số ma thuật qua tìm kiếm, thay thế chúng bằng hằng số có tên hoặc đưa vào tệp cấu hình. Viết kiểm thử xác nhận việc tải cấu hình. Xóa các bản sao và thực hiện commit với mô tả các thay đổi.

Sự khác biệt giữa hằng số và hardcode là gì?

Hằng số — giá trị có tên trong mã, có thể thay đổi tại một nơi. Hardcode — các giá trị không tên rải rác trong mã. Thực hành tốt: luôn sử dụng hằng số có tên với tên có ý nghĩa.

Tổng kết

  • Hardcode (đóng đinh) — viết giá trị trong mã không có khả năng thay thế nhanh
  • Hardcode — phản mẫu làm suy yếu bảo trì, kiểm thử và khả năng mở rộng
  • Số ma thuật và chuỗi không tên — dạng hardcode phổ biến nhất
  • Ngoại lệ: hằng số toán học và giá trị mặc định ổn định
  • Giải pháp thay thế: tệp cấu hình, tài nguyên, ENV, bộ chứa DI
  • Tái cấu trúc hardcode bắt đầu bằng tìm kiếm bản sao và thay thế bằng hằng số có tên
  • Sau khi tái cấu trúc, hãy viết kiểm thử cho việc tải cấu hình

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm