0
0
Lập trình
TT

Cách Lập Trình Thông Minh: Ngừng Sao Chép, Bắt Đầu Tái Sử Dụng

Đăng vào 3 giờ trước

• 6 phút đọc

Giới thiệu

Trong quá trình phát triển phần mềm, đôi khi chúng ta dễ bị cuốn vào việc sao chép và dán mã từ file này sang file khác. Việc này có thể giúp bạn tiết kiệm thời gian nhất thời, nhưng về lâu dài, nó sẽ tạo ra một đống nợ kỹ thuật. Việc viết mã tái sử dụng không chỉ là tạo ra mã sạch mà còn là một cách đầu tư cho tương lai của bạn và đồng đội.

Bài viết này sẽ giải thích lý do tại sao việc tái sử dụng mã lại quan trọng, cách thực hiện nó và cung cấp cho bạn những ví dụ có thể áp dụng ngay lập tức.

Tại sao nên tái sử dụng mã thay vì sao chép?

Khi bạn sao chép mã:

  • 🧩 Nhân đôi lỗi: Việc sửa một lỗi sẽ khó khăn hơn gấp ba lần, vì bạn phải sửa ở nhiều nơi khác nhau.
  • ⏳ Thời gian lãng phí: Thay đổi mã sẽ mất nhiều thời gian hơn khi mã nguồn của bạn lớn lên.
  • 🔄 Không nhất quán: Một phiên bản mã được cập nhật nhưng những phiên bản khác thì không, dẫn đến hành vi khác nhau trong các khu vực khác nhau của mã.

Khi bạn viết mã tái sử dụng:

  • ✅ Nguồn gốc duy nhất: Bạn chỉ cần sửa ở một nơi và mọi nơi khác sẽ được cập nhật.
  • ⚡ Tốc độ phát triển nhanh hơn: Ít mã mẫu để sửa đổi và duy trì.
  • 🚀 Kiến trúc có khả năng mở rộng: Dễ dàng hơn để đào tạo các lập trình viên mới.

Mã tái sử dụng của bạn là một khoản đầu tư: Nó có thể tốn kém một chút thời gian ban đầu khi bạn viết mã, nhưng sức mạnh của nó sẽ được đền đáp theo cấp số nhân.

Nguyên tắc cơ bản của việc viết mã tái sử dụng

Để thoát khỏi thói quen sao chép/dán, bạn cần tuân thủ một số nguyên tắc. Dưới đây là những nguyên tắc chính:

1. DRY (Don't Repeat Yourself)

Nguyên tắc này rất quan trọng. Bất cứ khi nào bạn nhận thấy mình đang viết cùng một logic ở nhiều nơi, hãy tách nó ra.

Ví dụ xấu:

javascript Copy
// Sao chép và dán xác thực
function isValidEmail(email) {
  return /\S+@\S+\.\S+/.test(email);
}

function isValidUsername(username) {
  return username.length > 3 && username.length < 20;
}

// Tệp khác...
function isValidPassword(password) {
  return password.length >= 8;
}

Ví dụ tốt:

javascript Copy
// Tiện ích xác thực tái sử dụng
export const validators = {
  email: (email) => /\S+@\S+\.\S+/.test(email),
  username: (username) => username.length > 3 && username.length < 20,
  password: (password) => password.length >= 8,
};

// Cách sử dụng
if (validators.email(userInput)) {
  // Tiếp tục
}

2. Nguyên tắc trách nhiệm đơn lẻ (SRP)

Mỗi hàm, lớp hoặc thành phần nên thực hiện một nhiệm vụ duy nhất.

Ví dụ, một thành phần nút trong React nên chỉ đơn giản là render một nút, không nên chịu trách nhiệm thực hiện xác thực biểu mẫu. Việc tách biệt trách nhiệm sẽ giúp mã dễ tái sử dụng hơn.

3. Tham số hóa

Thay vì tạo ra nhiều phiên bản khác nhau của cùng một logic, hãy làm cho các hàm có thể cấu hình để dễ dàng quản lý.

Ví dụ xấu:

python Copy
# Thay vì viết các hàm sắp xếp riêng biệt
def sort_asc(items):
    return sorted(items)

def sort_desc(items):
    return sorted(items, reverse=True)

Ví dụ tốt:

python Copy
# Cách tiếp cận tái sử dụng
def sort_items(items, reverse=False):
    return sorted(items, reverse=reverse)

# Cách sử dụng
print(sort_items([3, 1, 2]))          # Tăng dần
print(sort_items([3, 1, 2], True))    # Giảm dần

Ví dụ thực tế về mã tái sử dụng

🖼️ Ví dụ 1: Các thành phần React tái sử dụng

Thay vì sao chép và dán kiểu nút trong toàn bộ ứng dụng của bạn:

javascript Copy
// Xấu: Nhân đôi nút khắp nơi
<button className="bg-blue-500 text-white px-4 py-2 rounded">
  Gửi
</button>
<button className="bg-blue-500 text-white px-4 py-2 rounded">
  Hủy
</button>

Tạo thành phần tái sử dụng:

javascript Copy
// Button.jsx
export default function Button({ children, onClick }) {
  return (
    <button
      onClick={onClick}
      className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
    >
      {children}
    </button>
  );
}

// Cách sử dụng
<Button onClick={handleSubmit}>Gửi</Button>
<Button onClick={handleCancel}>Hủy</Button>

Khi bạn cập nhật kiểu dáng một lần trong Button.jsx, toàn bộ ứng dụng sẽ được cập nhật, giúp bạn dễ dàng quản lý hơn.

⚙️ Ví dụ 2: Tiện ích Backend

Thay vì viết lại các hàm xử lý phản hồi API trong mỗi endpoint:

javascript Copy
// Xấu: Lặp lại xử lý lỗi
app.get("/users", (req, res) => {
  try {
    // logic
  } catch (err) {
    res.status(500).json({ error: "Có gì đó không ổn" });
  }
});

app.get("/posts", (req, res) => {
  try {
    // logic
  } catch (err) {
    res.status(500).json({ error: "Có gì đó không ổn" });
  }
});

Sử dụng cách tiếp cận middleware tái sử dụng:

javascript Copy
function asyncHandler(fn) {
  return (req, res, next) => {
    Promise.resolve(fn(req, res, next)).catch(next);
  };
}

// Cách sử dụng
app.get("/users", asyncHandler(async (req, res) => {
  const users = await User.find();
  res.json(users);
}));

app.get("/posts", asyncHandler(async (req, res) => {
  const posts = await Post.find();
  res.json(posts);
}));

Giờ đây, việc xử lý lỗi đã được tập trung hóa và tuân thủ nguyên tắc DRY.

Những gợi ý hữu ích cho người mới bắt đầu viết mã tái sử dụng

  • Nhận diện sự lặp lại sớm: Nếu bạn sao chép và dán mã hai lần, hãy nghĩ đến việc tái cấu trúc.
  • Cẩn thận khi trừu tượng hóa: Đừng làm cho mã trở nên phức tạp hơn mức cần thiết. Tái sử dụng nên giải quyết một vấn đề thực sự và không nên làm cho mã trở nên khó đọc hơn.
  • Suy nghĩ theo mô-đun: Hãy suy nghĩ về các phương pháp cho "các khối xây dựng tái sử dụng" (ví dụ: dịch vụ, tiện ích, thành phần).
  • Tài liệu và đặt tên mã của bạn tốt: Không ai sẽ tái sử dụng mã của bạn nếu họ không biết cách sử dụng nó.
  • Sử dụng thư viện: Đôi khi, tái sử dụng có nghĩa là không cần phải phát minh lại bánh xe. Nhiều gói và thư viện đã được chứng minh, bền vững và được duy trì tốt.

Tái sử dụng không có nghĩa là làm phức tạp hóa

Một cạm bẫy cần lưu ý: Không phải tất cả mã đều cần phải là một thư viện chung. Thực tế, thường thì tốt hơn nên chờ đợi cho đến khi bạn có một tình huống thực sự lặp lại trước khi trừu tượng hóa. Hãy tìm kiếm một điểm giữa giữa sự đơn giản hôm nay và trừu tượng ngày mai.

Kết luận

Việc sao chép và dán mã có thể trông có vẻ hiệu quả, nhưng nó thực sự là một vụ nổ chậm. Việc thúc đẩy tái sử dụng giúp dự án của bạn trở thành một hệ thống có khả năng mở rộng và dễ bảo trì hơn. Bạn sẽ sửa lỗi một lần duy nhất, loại bỏ các mã mẫu và dễ dàng hơn trong việc đào tạo các thành viên trong nhóm.

Lần tới khi bạn chuẩn bị sao chép và dán, hãy suy nghĩ:
👉 Tôi có thể trừu tượng hóa điều này thành một hàm, thành phần hoặc mô-đun tái sử dụng không?

Tương lai của bạn (và đồng đội của bạn) sẽ cảm ơn bạn.

💡 Chia sẻ: Bạn đã gặp phải lỗi “sao chép/dán” đau đớn nào trong các dự án của mình? Hãy để lại ý kiến của bạn trong phần bình luận - hãy cùng nhau học hỏi!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào