Giải pháp tạm thời trong lập trình: nó là gì, có những loại nào và cách hoạt động

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

Giải pháp tạm thời (tiếng Anh: workaround, kludge, hotfix) là một giải pháp tạm thời hoặc không tối ưu cho một vấn đề trong mã, nó hoạt động nhưng vi phạm các nguyên tắc về kiến trúc sạch, khả năng đọc hoặc hiệu suất. Các giải pháp tạm thời là không thể tránh khỏi trong phát triển thực tế: thời hạn, không tương thích phiên bản, mã kế thừa và hành vi không được ghi chép của framework buộc các nhà phát triển phải thỏa hiệp. Theo Martin Fowler (2025), sự khác biệt chính giữa một giải pháp tạm thời hợp lý và nợ kỹ thuật là sự tồn tại của kế hoạch loại bỏ nó và đánh dấu rõ ràng trong mã.

Những điểm chính

  • Giải pháp tạm thời — một giải pháp tạm thời hoạt động nhưng vi phạm các phương pháp tốt nhất.
  • Nguyên nhân chính của giải pháp tạm thời: thời hạn, mã kế thừa, không tương thích API.
  • Một giải pháp tạm thời hợp lý luôn chứa TODO và kế hoạch sửa chữa.
  • Tích lũy các giải pháp tạm thời dẫn đến nợ kỹ thuật và làm chậm quá trình phát triển.
  • Tái cấu trúc giải pháp tạm thời đòi hỏi kiểm thử và ưu tiên theo tần suất thay đổi của mô-đun.

Giải pháp tạm thời trong lập trình là gì?

Giải pháp tạm thời là một thuật ngữ thông tục cho một giải pháp phần mềm đúng về mặt chức năng nhưng không tối ưu về mặt kỹ thuật. Mã như vậy hoạt động, vượt qua kiểm thử và thậm chí đến được môi trường sản xuất, nhưng đọc nó khiến bạn muốn viết lại mọi thứ từ đầu. Trong môi trường nói tiếng Anh, các thuật ngữ workaround, kludge (kluge), hack hoặc quick-and-dirty fix được sử dụng.

Thuật ngữ này xuất phát từ một phép ẩn dụ gia đình: nếu chân ghế bị gãy, bạn có thể buộc nó bằng băng dính — chiếc ghế lại hoạt động, nhưng giải pháp này tạm thời và xấu xí. Điều tương tự cũng xảy ra trong lập trình: một lỗi được sửa bằng hardcode, giải pháp tạm thời bằng timeout hoặc cách vòng qua API không được ghi chép. Mã biên dịch, ứng dụng không bị sập, nhưng giải pháp không thể gọi là chất lượng.

Một điểm khác biệt quan trọng: lỗi (bug) — là khi mã không hoạt động như mong đợi. Giải pháp tạm thời — là khi mã hoạt động nhưng được thiết kế kém. Giải pháp tạm thời luôn là lựa chọn có ý thức của nhà phát triển: “Tôi biết điều này thật xấu, nhưng hiện tại nó giải quyết được vấn đề.”

Theo Stripe (2024), các nhà phát triển dành trung bình 17 giờ mỗi tuần để xử lý nợ kỹ thuật và các giải pháp tạm thời — gần một nửa thời gian làm việc của họ. Đây là sự mất mát trực tiếp về năng suất của nhóm.

Khi nào và tại sao các giải pháp tạm thời xuất hiện

Nguyên nhân đầu tiên và chính là thời hạn. Khi còn một ngày trước khi phát hành và một lỗi nghiêm trọng vẫn chưa được sửa, nhóm chọn giải pháp nhanh thay vì giải pháp đúng. Hardcode một giá trị, vô hiệu hóa kiểm tra, thêm sleep() — những ví dụ kinh điển về giải pháp tạm thời do thời hạn. Một nhà phát triển giàu kinh nghiệm luôn đánh dấu những nơi như vậy bằng TODO hoặc FIXME.

Nguyên nhân thứ hai là không tương thích API. Một thư viện hoặc framework của bên thứ ba hoạt động khác với tài liệu. Framework không xuất lớp cần thiết, một phương thức bị đánh dấu là không được khuyến khích và không có giải pháp thay thế. Nhà phát triển buộc phải sử dụng phản xạ (reflection), API nội bộ hoặc cách giải quyết. Trong Java, điều này có thể là truy cập qua setAccessible(true); trong Swift — @objc và performSelector.

Nguyên nhân thứ ba là mã kế thừa. Một nhà phát triển kế thừa một dự án được viết cách đây 5-10 năm trên một phiên bản framework cũ. Không có thời gian hoặc ngân sách để viết lại toàn bộ mô-đun, vì vậy chức năng mới được “dán” vào mã cũ thông qua các giải pháp tạm thời. Dần dần, quá nhiều lớp chồng chất đến nỗi mô-đun biến thành một “quả bóng bùn lớn” (big ball of mud).

Nguyên nhân thứ tư là thiếu kiểm thử. Tái cấu trúc mà không có kiểm thử rất nguy hiểm: thay đổi kiến trúc có thể phá vỡ chức năng đang hoạt động. Khi không có kiểm thử, nhà phát triển thích thêm một giải pháp tạm thời lên trên mã đang hoạt động hơn là mạo hiểm sự ổn định. Theo Google Testing Blog (2024), các nhóm không có kiểm thử sử dụng giải pháp tạm thời nhiều gấp 3 lần.

Các loại giải pháp tạm thời

Phân loại các giải pháp tạm thời giúp nhóm hiểu loại nợ kỹ thuật nào họ đang đối mặt và chọn chiến lược loại bỏ phù hợp. Hãy xem xét các loại chính.

Hardcode — loại phổ biến nhất. Thay vì cấu hình, tài nguyên hoặc tham số, một giá trị cố định được sử dụng trong mã. Ví dụ: URL máy chủ được hardcode, thời gian chờ 5 giây, cỡ chữ 16pt. Hardcode làm cho mã không thể mở rộng và yêu cầu biên dịch lại cho bất kỳ thay đổi nào.

Sao chép-dán — nhân bản một đoạn mã với những thay đổi nhỏ thay vì trích xuất logic chung. Triệu chứng kinh điển: có 3 phương thức tương tự trong dự án chỉ khác nhau một dòng. Sao chép-dán giúp tăng tốc viết mã tại thời điểm làm việc nhưng làm chậm bảo trì gấp 10 lần trong tương lai — sửa chữa cần được áp dụng ở 3 nơi thay vì một.

Try-catch rỗng — một khối catch không làm gì hoặc chỉ ghi nhật ký lỗi mà không xử lý nó. Giải pháp tạm thời này “làm im” ngoại lệ nhưng không giải quyết nguyên nhân của nó. Ứng dụng tiếp tục hoạt động, nhưng dữ liệu có thể bị hỏng và người dùng có thể không nhận được phản hồi.

Sleep trong mã — Thread.sleep(500) hoặc DispatchQueue.main.asyncAfter để chờ đợi khi đáng lẽ phải có một sự kiện hoặc callback. Mã như vậy không đáng tin cậy: trên thiết bị chậm, 500 ms có thể không đủ; trên thiết bị nhanh, việc tạm dừng là không cần thiết. Sử dụng CountDownLatch, Semaphore hoặc async/await với thời gian phù hợp.

Cờ tương thích — các chuỗi if-else kiểm tra phiên bản hệ điều hành, mẫu thiết bị hoặc sự sẵn có của tính năng. Khi có hơn 3-4 cờ, mã biến thành mì ống. Giải pháp là mẫu Strategy hoặc Feature Flags thông qua cấu hình.

Giải pháp tạm thời vs nợ kỹ thuật

Nhiều nhà phát triển nhầm lẫn giữa giải pháp tạm thời và nợ kỹ thuật. Sự khác biệt nằm ở quy mô và nhận thức. Giải pháp tạm thời là một giải pháp cục bộ, cụ thể (một phương thức, một lớp). Nợ kỹ thuật là một vấn đề hệ thống ảnh hưởng đến kiến trúc của một mô-đun hoặc toàn bộ ứng dụng.

Phép ẩn dụ của Ward Cunningham (người tạo ra thuật ngữ Nợ Kỹ thuật): nợ kỹ thuật giống như vay ngân hàng. Bạn lấy tiền ngay bây giờ để xây nhà nhanh hơn, nhưng sau đó phải trả lãi. Giải pháp tạm thời — giống như đóng đinh bằng búa thay vì súng bắn đinh: công việc được hoàn thành, nhưng kém hiệu quả hơn.

Một giải pháp tạm thời không tạo ra nợ kỹ thuật. Nhưng 50 giải pháp tạm thời trong một mô-đun = nợ kiến trúc. Do đó, nguyên tắc nhóm: mỗi giải pháp tạm thời được ghi lại trong quá trình đánh giá mã hoặc trình theo dõi tác vụ, và nhóm thường xuyên (mỗi sprint một lần) xem xét các giải pháp tạm thời tích lũy.

Theo Spotify Engineering (2023), các nhóm theo dõi các giải pháp tạm thời trong mã (thông qua nhãn TODO đặc biệt hoặc chú thích tùy chỉnh) giảm thời gian tái cấu trúc 30% — vì họ không mất hàng giờ để tìm kiếm những nơi có vấn đề.

Cách loại bỏ các giải pháp tạm thời

Bước đầu tiên là kiểm kê. Tìm kiếm trong cơ sở mã các từ khóa: TODO, FIXME, HACK, WORKAROUND, KLUDGE. Các IDE hiện đại làm nổi bật chúng bằng một màu riêng. GitHub cũng hiển thị TODO trong giao diện Pull Request. Lập danh sách tất cả các giải pháp tạm thời với mức ưu tiên.

Bước thứ hai là ưu tiên hóa. Không phải tất cả các giải pháp tạm thời đều cần được sửa ngay lập tức. Mức ưu tiên = tần suất thay đổi trong tệp × mức độ nghiêm trọng. Nếu một tệp thay đổi 2 lần một năm, giải pháp tạm thời có thể chờ đợi. Nếu một mô-đun được chạm đến trong mỗi sprint — giải pháp tạm thời cần được sửa trước.

Bước thứ ba là tái cấu trúc với kiểm thử. Không bao giờ tái cấu trúc một giải pháp tạm thời mà không có kiểm thử. Đầu tiên hãy viết một bài kiểm tra xác minh hành vi hiện tại (với giải pháp tạm thời), sau đó tái cấu trúc, sau đó đảm bảo bài kiểm tra vượt qua. Nếu không có điều này, việc tái cấu trúc một giải pháp tạm thời có thể phá vỡ chức năng mà nó được viết ra.

kotlin
// Before: URL workaround được hardcode
fun getApiUrl(): String {
    return "https://api.example.com/v2"
}

// After: cấu hình qua BuildConfig
fun getApiUrl(): String {
    return BuildConfig.API_BASE_URL
}

Bước thứ tư là tự động hóa. Thiết lập một trình linter ngăn chặn các mẫu giải pháp tạm thời nhất định. Ví dụ, Detekt cho Kotlin có thể kiểm tra sự vắng mặt của Thread.sleep() trong mã sản xuất, ESLint có thể cấm console.log trong dự án. Điều này ngăn chặn sự xuất hiện của các giải pháp tạm thời mới cùng loại.

Khi nào giải pháp tạm thời là hợp lý

Bất chấp hàm ý tiêu cực của thuật ngữ, một giải pháp tạm thời có thể là một giải pháp hợp lý. Điều kiện chính: giải pháp tạm thời là tạm thời, được đánh dấu rõ ràng và có kế hoạch thay thế. Trong mã sản xuất của mọi dự án lớn, có hàng trăm giải pháp tạm thời hợp lý.

Tình huống 1: bản vá nhanh trong sản xuất. Một lỗi nghiêm trọng ảnh hưởng đến tất cả người dùng. Nhóm cần sửa chữa trong vòng một giờ. Cách tiếp cận đúng: sửa lỗi bằng bất kỳ cách nào, triển khai bản vá nhanh. Sau đó, vào ngày hôm sau, viết giải pháp thích hợp và đóng vé. Một bản vá nhanh là giải pháp tạm thời hợp lý nếu nó tồn tại không quá 48 giờ.

Tình huống 2: chờ phiên bản thư viện mới. Một framework chứa lỗi đã được sửa trong master, nhưng bản phát hành sẽ ra mắt trong 2 tuần. Thay vì viết mã giải quyết phức tạp, nhóm thêm một giải pháp tạm thời với ghi chú “REMOVE after library 3.2.” Khi phiên bản 3.2 được phát hành, giải pháp tạm thời bị xóa.

Tình huống 3: đóng cửa startup hoặc MVP. Ở giai đoạn MVP, tốc độ quan trọng hơn kiến trúc. Các giải pháp tạm thời khi bắt đầu là bình thường. Vấn đề phát sinh khi startup không biến thành sản phẩm, nhưng các giải pháp tạm thời vẫn còn. Khuyến nghị: sau vòng gọi vốn, hãy phân bổ một sprint để trả hết nợ kỹ thuật nghiêm trọng.

Nguyên tắc chính: “Mã kế thừa là mã không có kiểm thử” (Michael Feathers). Nếu một giải pháp tạm thời được bao phủ bởi một bài kiểm thử và được ghi chép rõ ràng — nó có thể quản lý được. Nếu nó đã treo không có bình luận trong 2 năm trong một mô-đun bị lãng quên — đó không còn là giải pháp tạm thời nữa, mà là một vấn đề kiến trúc.

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

Giải pháp tạm thời khác với lỗi (bug) như thế nào?

Lỗi (bug) — mã không hoạt động như mong đợi. Giải pháp tạm thời — mã hoạt động nhưng được viết không tối ưu. Giải pháp tạm thời luôn là quyết định có ý thức của nhà phát triển; lỗi thường là sai lầm vô ý.

Làm thế nào để ghi chép giải pháp tạm thời trong mã?

Sử dụng // TODO: refactor — ... hoặc chú thích tùy chỉnh @Workaround với các trường: lý do, ngày tháng, người chịu trách nhiệm, thời hạn xóa. Tránh // HACK trần không giải thích.

Có nên tái cấu trúc các giải pháp tạm thời nếu mã hoạt động?

Nếu mô-đun không thay đổi và giải pháp tạm thời ổn định — không. Tái cấu trúc không có lý do làm tăng rủi ro hồi quy. Chỉ sửa những giải pháp tạm thời ngăn cản việc thêm chức năng mới.

Làm thế nào để giải thích với quản lý về sự cần thiết của việc tái cấu trúc giải pháp tạm thời?

So sánh thời gian: “Hiện tại chúng tôi dành 4 giờ cho kiểm thử thủ công vì các giải pháp tạm thời này. Tái cấu trúc sẽ mất 8 giờ và giảm thời gian xuống còn 30 phút. Hoàn vốn đầu tư — 2 sprint.” Hãy nói bằng ngôn ngữ tốc độ và tiền bạc, không phải kiến trúc sạch.

Làm thế nào để tìm các giải pháp tạm thời trong mã của người khác?

Tìm kiếm TODO, FIXME, HACK, WORKAROUND qua grep trong toàn bộ dự án. Phân tích các phương thức dài hơn 100 dòng và các lớp có hơn 5 phụ thuộc. Sử dụng linter với các quy tắc tùy chỉnh để phát hiện tự động.

Tổng kết

  • Giải pháp tạm thời — giải pháp tạm thời, không tối ưu hoạt động nhưng vi phạm các phương pháp tốt nhất.
  • Nguyên nhân chính: thời hạn, mã kế thừa, không tương thích API, thiếu kiểm thử.
  • Các loại phổ biến: hardcode, sao chép-dán, try-catch rỗng, sleep(), cờ tương thích.
  • Một giải pháp tạm thời — vấn đề cục bộ. 50 giải pháp tạm thời — nợ kỹ thuật cần giải pháp kiến trúc.
  • Để tái cấu trúc: kiểm kê → ưu tiên hóa → kiểm thử → tái cấu trúc → tự động hóa.
  • Giải pháp tạm thời hợp lý — bản vá nhanh (đến 48 giờ), chờ phiên bản thư viện mới, MVP.
  • Nguyên tắc chính: giải pháp tạm thời phải được đánh dấu rõ ràng và có kế hoạch loại bỏ.

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