07/09/2018, 10:18

Nguyên Lý DRY: Don't Repeat Yourself

Don't Repeat Yourself hay DRY là một nguyên lý cơ bản nhất của lập trình được đưa ra nhằm mục đích hạn chế tối thiểu việc viết các đoạn code lặp đi lặp lại nhiều lần chỉ để thực hiện các công việc giống nhau trong ứng dụng. Nguyên lý này được nhắc tới lần đầu trong cuốn sách The Pragmatic ...

Don't Repeat Yourself hay DRY là một nguyên lý cơ bản nhất của lập trình được đưa ra nhằm mục đích hạn chế tối thiểu việc viết các đoạn code lặp đi lặp lại nhiều lần chỉ để thực hiện các công việc giống nhau trong ứng dụng.

Nguyên lý này được nhắc tới lần đầu trong cuốn sách The Pragmatic Programmer viết bởi Andy HuntDave Thomas. Dennis Ritchie (tác giả của The C Programming Language) cũng tham gia vào việc cùng soạn thảo cuốn sách này.

Trong phần tiếp theo tôi sẽ giải thích tại sao chúng ta cần tuân thủ nguyên tắc DRY và khi nào bạn không nên.

Tại Sao Cần Tuân Thủ DRY

Trong một số trường hợp bạn sẽ cảm thấy việc tuân thủ nguyên tắc DRY trở lên tốn thời gian. Ví dụ khi bạn mới viết ứng dụng có một nhiệm vụ là X cần phải được thực hiện và bạn đã viết xong mã lệnh để thực hiện nhiệm vụ này trong ứng dụng. X có nội dung như sau:

Trên ứng dụng có 1 trang đặc biệt và chỉ có admin mới có thể truy cập được. Khi người dùng đăng nhập vào trang đặc biệt này hãy kiểm tra email của họ nếu khớp với địa chỉ email trong file cài đặt thì cho phép người dùng truy cập vào trang. Ngược lại từ chối quyền truy cập.

Được liệt kê vào danh sách những lập trình viên xuất sắc nhất của công ty. Chỉ 5 phút sau bạn đã hoàn thành xong task được giao. Trong trang admin.php bạn thêm vào phần mở đầu của file này đoạn mã sau:

// Lấy email của admin trong file cài đặt
$adminEmail = $config->getEmail();

// So sánh email của người dùng với email của admin
if ($user->email != $adminEmail) {
    die('Không được phép truy cập');
} else {
  // hiển thị thông tin mà admin cần dùng
}

Một tháng sau đó, yêu cầu thay đổi, lúc này không phải có 1 trang admin nữa mà là 2 trang admin và bạn cũng cần kiểm tra email của người dùng cho trang admin thứ 2. Và do nhiệm vụ lần này giống hệt với nhiệm vụ X đã làm trước đó, sếp giao cho bạn thực hiện lập trình phần này luôn.

Tuy nhiên, bạn nhận ra lúc này mã lệnh của ứng dụng đã nhiều hơn lúc trước và độ phức tạp của mã lệnh cũng tăng lên. Và bạn không nhớ và cũng lười không muốn kiếm lại đoạn mã thực hiện nhiệm vụ X trước đó. Bạn nhận thấy việc viết đoạn mã mới để hoàn tất công việc được giao sẽ nhanh hơn là việc lần lại mã lệnh trong ứng dụng để kiếm ra đoạn mã đã viết trước đó. Vậy là bạn quyết định viết thêm đoạn mã mới để hoàn tất công việc. Trong file admin2.php bạn cũng thêm vào phần đầu tiên đoạn mã:

// Lấy email của admin trong file cài đặt
$adminEmail = $config->getEmail();

// So sánh email của người dùng với email của admin
if ($user->email != $adminEmail) {
    die('Không được phép truy cập');
} else {
  // hiển thị thông tin mà admin cần dùng
}

Hai tuần sau sếp tiếp tục giao cho bạn công việc Z giống y chang công việc X và Y bạn đã làm. Lần này do chỉ có 2 tuần nên bạn nhớ ra được vị trí chính xác của đoạn mã lệnh bạn làm công việc Y 2 tuần trước đó. Bạn tìm trong ứng dụng cho đoạn mã này sau đó quyết định copy và dán nó vào vị trí của file khác nơi mà sẽ đảm nhận việc thực thi công việc Z.

Và theo một cách nào đó thì cách làm trên sẽ giúp bạn nhanh hơn trong việc hoàn tất công việc. Tuy nhiên...

Một tháng sau đó sếp quyết định thay đổi nội dung của công việc X một chút xíu và như vậy các công việc Y và Z cũng sẽ thay đổi theo. Thay vì chỉ kiểm tra địa chỉ email bạn cũng cần kiểm tra xem người dùng này được tạo ra lâu chưa. Nếu mới tạo ra trước đó 24 giờ thì ứng dụng cần từ chối quyền truy cập. Tất nhiên việc trên cũng không gây ra nhiều khó khăn cho bạn, 30 giây sau khi đọc xong yêu cầu bạn đã có câu trả lời:

if ( ($user->email != $adminEmail) && ($user->created_at < 24*60*60*60) ) {
    die('Không được phép truy cập');
} else {
  // hiển thị thông tin mà admin cần dùng
}

Oh nhưng mà bây giờ bạn nhận ra cơn ác mộng khi phải tìm lại vị trí của cả các vị trí trong ứng dụng nơi chứa các đoạn code thực thi các công việc X, Y và Z trên.

Ngoại Lệ

Tuy nhiên bạn cũng không nên nghĩ rằng phải tuyệt đối tuân theo nguyên tắc DRY. Trong lập trinh mọi nguyên tắc đều có ngoại lệ và trong một số trường hợp bạn có thể không tuân thủ nó.

Trở lại ví dụ chúng ta mới tìm hiểu ở trên. Nếu như bạn chắc chắn được rằng ứng dụng của bạn chỉ có 1 hoặc 2 trang admin và việc tìm lại vị trí của các đoạn mã thực hiện công việc X tốn quá nhiều thời gian trong khi hạn chót lại sắp tới gần bạn nên không tuân thủ DRY!

0