DRY - don't repeat yourself

Công nghệ - 12/04/2025 08:32:00

ChatGPT đã nói:
🚀 Clean code không phải chuyện xa xỉ mà là sống còn khi xây framework cho hàng nghìn dev. Bài viết bóc tách nguyên tắc DRY qua ví dụ thực tế, liên hệ SRP, YAGNI, KISS – đủ khiến bạn phải xem ngay!

Tôi có cơ hội khi nằm trong một công ty framework, mà đối tượng khách hàng là hàng nghìn senior developers đối tác, một điểm tôi nhận thấy trong khi làm việc là sự quan trọng của các nguyên tắc phát triển phần mềm trong việc tạo ra mã nguồn sạch, dễ bảo trì và hiệu quả.

Trong bài viết này, chúng ta sẽ cùng khám phá nguyên tắc DRY (Don't Repeat Yourself), một trong những nền tảng giúp lập trình viên viết mã sạch, dễ bảo trì và hiệu quả hơn. Tôi sẽ giải thích DRY là gì, phân tích ưu nhược điểm, và liên hệ với các nguyên tắc lập trình khác.

Chúng ta bắt đầu nhé.


Nguyên tắc DRY là gì?

DRY, viết tắt của "Don't Repeat Yourself", có nghĩa là "Đừng lặp lại chính mình". Nguyên tắc này khuyến khích rằng mỗi phần logic hoặc thông tin trong hệ thống phần mềm nên chỉ được biểu diễn một lần duy nhất, ở một nơi duy nhất. Điều này áp dụng không chỉ cho source code mà còn cho configuration, document, hoặc business logic.

Ngược lại với DRY là tình trạng WET (Write Everything Twice hoặc We Enjoy Typing), tức là lặp lại mã hoặc logic ở nhiều nơi, dẫn đến khó khăn trong việc bảo trì, dễ xảy ra lỗi, và làm tăng độ phức tạp của dự án. Ví dụ, nếu bạn sao chép logic kiểm tra đầu vào ở ba phương thức khác nhau, bạn sẽ phải sửa cả ba nơi nếu logic đó thay đổi – một cơn ác mộng thực sự!

Trong C# và các ngôn ngữ lập trình hướng đối tượng, DRY thường được áp dụng thông qua các kỹ thuật như trích xuất phương thức, sử dụng giao diện, kế thừa, hoặc các mẫu thiết kế (design patterns).

Hãy cùng xem xét một vài ví dụ cụ thể:

  • Pha Trà và Cà phê: Trích xuất logic chung (đun nước, thêm đường hay thêm sữa) thành phương thức riêng, gọi lại trong cả hai quy trình. - tôi rất thích hướng dẫn các bạn cách pha trà cho sếp - nịnh sếp :)
  • Animals - bài tập OOP kinh điển: con chó kêu gâu gâu, con mèo kêu meo meo, gà gáy ối zời ơi... Tất cả các con đều biết kêu, vậy cho nó thành một cái interface IAnimal với method talk - đứa nào cũng phải kêu :)
  • Hay lưu Khách hàng và Nhân viên: Tách logic xác thực thành phương thức chung, áp dụng cho cả hai đối tượng.
  • ...

     


    Ví dụ code C# minh họa DRY

    Ví dụ 1: Pha Trà và Cà phê

    Hãy tưởng tượng bạn đang viết mã để mô phỏng việc pha trà và cà phê. Ban đầu, bạn có thể viết mã như sau (vi phạm DRY):

    Nội dung bài viết

    Vấn đề: Logic "đun nước" và "thêm đường" được lặp lại ở cả hai phương thức. Nếu bạn cần thay đổi cách đun nước (ví dụ, thêm kiểm tra nhiệt độ), bạn phải sửa cả hai nơi.

    Áp dụng DRY: Trích xuất logic chung thành các phương thức riêng:

    Nội dung bài viết

    Lợi ích:

  • Logic chung (BoilWater, AddSugar, PourIntoCup) chỉ được định nghĩa một lần.
  • Nếu cần thay đổi (ví dụ, thêm kiểm tra nhiệt độ trong BoilWater), bạn chỉ sửa một nơi.
  • Mã dễ bảo trì và mở rộng (có thể thêm MakeHotChocolate mà không lặp lại logic).

... ủa, mà sao phải code nhiều hơn nhỉ :D cùng thử vài ví dụ khác nữa nhé.


Ví dụ 2: Lưu Khách hàng và Nhân viên

Giả sử bạn cần lưu thông tin khách hàng và nhân viên vào cơ sở dữ liệu, với yêu cầu xác thực tên và email. Mã ban đầu có thể như sau:

Nội dung bài viết

Vấn đề: Logic xác thực tên và email được lặp lại hoàn toàn ở cả hai phương thức. Nếu bạn muốn thêm kiểm tra mới (ví dụ, độ dài tối đa của tên), bạn phải sửa cả hai nơi.

Áp dụng DRY: Trích xuất logic xác thực thành một phương thức chung:

Nội dung bài viết

Lợi ích:

  • Logic xác thực được tập trung vào ValidatePerson, chỉ cần sửa một nơi nếu có thay đổi.
  • Mã ngắn gọn hơn, dễ bảo trì và mở rộng (có thể thêm SaveVendor mà không lặp lại xác thực).
  • Dễ kiểm thử, vì bạn chỉ cần viết unit test cho ValidatePerson một lần.

Cách sử dụng:

Nội dung bài viết

Ví dụ 3: (Nâng cao) Template Method Pattern

Để minh họa cách áp dụng DRY ở mức cao hơn, hãy xem xét mẫu thiết kế Template Method. Giả sử bạn cần xử lý các tài liệu ở định dạng khác nhau (PDF, Word, txt,...), nhưng quy trình xử lý có các bước chung.

Trước DRY:

Nội dung bài viết

Vấn đề: Các bước "mở file", "xác thực nội dung", "lưu thay đổi", và "đóng file" được lặp lại.

Áp dụng DRY với Template Method:

Nội dung bài viết

Lợi ích:

  • Các bước chung được định nghĩa một lần trong lớp cơ sở DocumentProcessor.
  • Chỉ cần triển khai bước khác biệt (ParseContent) trong các lớp con.
  • Dễ mở rộng cho các định dạng mới (ví dụ, Excel) mà không lặp lại logic.

Cách sử dụng:

Nội dung bài viết

Đơn giản hơn nhiều phải không :)


Ví dụ khác

Bạn hãy thử thực hành với bài tập động vật kêu IAnimal hay tính điện tích hình IShape (Hình chữ nhật, hình vuông, hình tròn,...) nhé.


Quay lại câu chuyện viết code dài hơn, không phải DRY không có nhược điểm, chúng ta cùng xem xét ưu nhược điểm của nguyên tắc này nhé

Ưu điểm và Nhược điểm của DRY

Ưu điểm

1. Dễ bảo trì:Khi logic chỉ xuất hiện một lần, bạn chỉ cần sửa ở một nơi khi có thay đổi, giảm nguy cơ bỏ sót hoặc không đồng bộ.

2. Ít lỗi hơn:Tránh được các lỗi do sao chép mã không nhất quán, đặc biệt khi sửa lỗi hoặc nâng cấp tính năng.

3. Mã sạch và gọn gàng: Loại bỏ mã lặp lại giúp codebase dễ đọc, dễ hiểu, đặc biệt trong các dự án lớn.

4. Dễ mở rộng: Các thành phần tái sử dụng có thể được áp dụng cho các tính năng mới mà không cần viết lại mã.

Nhược điểm

1. Trừu tượng hóa quá mức:Cố gắng làm mã quá DRY có thể dẫn đến các lớp hoặc phương thức phức tạp, khó hiểu, đặc biệt với lập trình viên mới.

2. Chi phí ban đầu:Việc thiết kế các thành phần tái sử dụng có thể mất nhiều thời gian hơn so với sao chép mã đơn giản, đặc biệt trong các dự án nhỏ.

3. Hiệu suất (hiếm gặp): Trong một số trường hợp, việc gọi phương thức tái sử dụng có thể chậm hơn một chút so với mã inline, nhưng điều này thường không đáng kể.

 

Các Nguyên tắc Lập trình liên quan

DRY không hoạt động đơn lẻ mà thường liên kết với các nguyên tắc khác trong phát triển phần mềm. Dưới đây là một số nguyên tắc liên quan:

1. Single Responsibility Principle (SRP):Mỗi lớp hoặc phương thức chỉ nên có một lý do để thay đổi. Ví dụ, trong DataSaver, phương thức ValidatePerson chỉ chịu trách nhiệm xác thực, không làm nhiệm vụ lưu dữ liệu. SRP bổ sung cho DRY bằng cách giữ mã tập trung và dễ tái sử dụng.

2. YAGNI (You Ain’t Gonna Need It):Tránh thêm mã hoặc tính năng mà bạn nghĩ sẽ cần trong tương lai. Nếu bạn tạo quá nhiều lớp hoặc phương thức tái sử dụng không được dùng đến, bạn có thể vi phạm YAGNI, làm tăng độ phức tạp không cần thiết.

3. KISS (Keep It Simple, Stupid):Giữ mã đơn giản nhất có thể. Đôi khi, chấp nhận một chút lặp lại (ví dụ, hai phương thức ngắn với logic tương tự) có thể dễ hiểu hơn so với một hệ thống trừu tượng phức tạp.

4. SOLID Principles: DRY thường liên quan chặt chẽ với các nguyên tắc SOLID, đặc biệt là SRP và OCP (Open/Closed Principle). Ví dụ, trong ShapeCalculator, giao diện IShape giúp mã mở rộng mà không cần sửa đổi, đồng thời tránh lặp lại logic.

 

Lưu ý khi Áp dụng DRY

  • Để áp dụng DRY hiệu quả, hãy cân nhắc những điều sau:
  • Nhận diện lặp lại: Tìm các đoạn mã có logic giống nhau, như kiểm tra đầu vào, tính toán, hoặc xuất dữ liệu.
  • Đừng lạm dụng: Tránh tạo ra các lớp hoặc phương thức quá chung chung, vì điều này có thể làm mã khó hiểu. Ví dụ, không nên gộp logic xác thực của khách hàng và nhân viên nếu chúng có các yêu cầu khác biệt lớn.
  • Tài liệu rõ ràng: Các thành phần tái sử dụng nên được đặt tên rõ ràng và có chú thích nếu cần, để đội ngũ dễ hiểu và sử dụng.
  • Cân bằng với KISS và YAGNI: Trong các dự án nhỏ, đôi khi sao chép mã đơn giản có thể chấp nhận được nếu việc trừu tượng hóa mất quá nhiều thời gian.

Kết luận

Nguyên tắc DRY là một công cụ mạnh mẽ giúp lập trình viên C# nói riêng và các ngôn ngữ lập trình OOP nói chung viết mã sạch, dễ bảo trì và mở rộng. Qua các ví dụ như pha trà/cà phê, lưu khách hàng/nhân viên, và xử lý tài liệu, chúng ta thấy rằng việc trích xuất logic chung thành phương thức, giao diện, hoặc mẫu thiết kế có thể giảm đáng kể sự lặp lại và cải thiện chất lượng mã.

Tuy nhiên, DRY không phải là Silver Bullet. Bạn cần áp dụng nó một cách thông minh, tránh trừu tượng hóa quá mức, và kết hợp với các nguyên tắc như SRP, YAGNI, và KISS để đạt hiệu quả tối ưu.

Hy vọng bài viết này đáp ứng yêu cầu của bạn với các đoạn mã cụ thể và phân tích chi tiết.

Tài liệu tham khảo

Bạn có thường xuyên áp dụng DRY trong công việc? Hãy chia sẻ kinh nghiệm hoặc câu hỏi của bạn trong phần bình luận, tôi rất sẵn lòng thảo luận thêm!

 

/Son Do - believe in basic

 

#SoftwareDesign #DRY #CleanCode #DotNet #OOP #CSharp #SoftwareEngineering #DevLife #CodingBestPractices #CodeRefactoring #SOLIDPrinciples

#wecommit100xshare #1percentbetter

Công nghệ - 19/08/2025 21:13:07

Tìm hiểu cách xây dựng hệ thống phát hiện ngôn ngữ ký hiệu theo thời gian thực bằng AI, sử dụng DETR để tăng cường khả năng tiếp cận và đổi mới. Kết nối lời nói và cử chỉ.

Công nghệ - 18/08/2025 13:38:25

Tối ưu hóa các hệ thống RAG bằng cách tận dụng siêu dữ liệu để truy xuất thông tin chính xác và nhanh chóng hơn, giải quyết các thách thức về dữ liệu dư thừa hoặc lỗi thời với công cụ LangExtract nguồn mở. Khám phá cách LangExtract sử dụng các mô hình ngôn ngữ tiên tiến để trích xuất và cấu trúc siêu dữ liệu, tạo ra một quy trình truy xuất hợp lý và hiệu quả.

Công nghệ - 01/08/2025 07:00:00

Gỡ lỗi LLM rất quan trọng vì quy trình làm việc của chúng phức tạp và liên quan đến nhiều phần như chuỗi, lời nhắc, API, công cụ, trình truy xuất, v.v.

Công nghệ - 19/06/2025 03:05:09

Code xong chạy được là chưa đủ – phải biết khi nào nó "chết" nữa chứ 😅

Bạn đang triển khai ứng dụng trên Kubernetes, Docker hay môi trường production nào? Và bạn từng "toát mồ hôi" vì service chết mà không ai báo?

Công nghệ - 16/07/2025 13:41:17

Bạn có bao giờ tự hỏi tại sao trang web của mình tải chậm, đặc biệt là trên các thiết bị di động? Rất có thể, thủ phạm chính là những hình ảnh chưa được tối ưu. May mắn thay, có một công cụ miễn phí và cực kỳ hữu ích có thể giúp bạn giải quyết vấn đề này: Responsive Image Linter – một tiện ích mở rộng trên Chrome. Video này sẽ giới thiệu chi tiết về công cụ này, giúp bạn xác định và tối ưu hóa các hình ảnh gây tốn hiệu năng trên trang web của mình.

Công nghệ - 27/06/2025 03:15:44

⏳ Chậm 3 giây – Mất 50% người dùng. Đó không còn là lý thuyết, đó là thực tế.

Công nghệ - 11/12/2025 15:05:29

[Góc chuyện nghề] bán account game để đi học nghệ - bạn dám không?

Làm nghề 20 năm, gặp nhiều sinh viên, nhưng chiều qua tôi khá bất ngờ với một cậu em tên Quang. Em Quang muốn theo nghề BA và mong muốn lương 20 triệu sau khi làm việc 1.5 năm tới 2 năm trong nghề.

Công nghệ - 22/09/2025 08:59:20

Dừng ngay việc dùng DateTime.Now trong APIs, đó là ổ lỗi tiềm ẩn trong hệ thống của bạn

⏱️ Tôi từng nghĩ DateTime.Now là một thứ vô hại, đơn giản và tiện lợi, cho đến khi gặp những vấn đề về múi giờ. Những lỗi "tưởng chừng nhỏ" này lại chính là nguồn cơn của sự thất vọng và tốn kém thời gian cho nhiều đội ngũ phát triển.

Công nghệ - 14/03/2025 04:30:32

💡Bạn muốn tăng tốc tìm kiếm toàn văn nhưng hạ tầng hạn chế? Lucene có thể là giải pháp bất ngờ! Bài viết tiết lộ cách nó vượt trội hơn SQL Server, tối ưu truy vấn và những ứng dụng thực tế đáng khám phá.