DRY principle trong lập trình - Làm thế nào để biết code của bạn DRY hay WET ?

Nhìn ảnh chắc chúng ta cũng đã hiểu, điều gì xảy ra nếu có quá nhiều đoạn code giống nhau trong chương trình của bạn. Có phải khi một yêu cầu nào đó thay đổi, bạn sẽ phải sửa lại hết toàn bộ những đoạn code giống nhau đó hay không. Vậy làm thế nào để giữ nguyên tắc DRY principle trong lập trình, ví dụ và tác hại của nó, các bạn hãy xem bài viết này nhé.

Ví dụ đơn giản

Bạn Tín muốn kiểm tra quyền của user hiện tại xem nó có phải admin hay không, nếu phải thì bạn ấy mới cho người này quyền Create, Edit và Delete trên hệ thống.

Thế là bạn có nước đi rất hay là viết hẳn 3 đoạn code như sau để kiểm tra permission mỗi khi người dùng thực thi thao tác được chỉ định (THÊM / SỬA / XÓA).

function whenCreate(){
 int role = myServer.getSessionRole();

 if (role == 0){
     createStudent();
 }
}

function whenEdit(){
 int role = myServer.getSessionRole();

 if (role == 0){
     editStudent();
 }
}

function whenDelete(){
 int role = myServer.getSessionRole();

 if (role == 0){
     deleteStudent();
 }
}

Nhìn qua thì những bạn mới học lập trình cũng sẽ làm tương tự, và không nhận ra điều bất thường trong đoạn code trên, nhưng thực tế thì đoạn code của bạn Tín đã vi phạm nguyên tắc DRY trong lập trình.

 

Phát hiện những đoạn code trùng lặp (WET)

Có thể thấy rằng cả ba hàm trên điều có những đoạn code , block code sau

 int role = myServer.getSessionRole();

 if (role == 0){
     //Do the action user trigger before
 }

Tác hại của điều này là gì ?

 

Bạn Tín đưa chương trình cho sếp, sếp đẻ thêm 2 yêu cầu:

💥Sếp muốn thêm vào chương trình của mình, ngoài Create, Edit hay Delete một số hàm nữa như Read, DeleteAll, History,.... Thì bạn ấy phải copy lại hàm cũ rồi chỉnh sửa cho phù hợp

💥Sếp muốn rằng thay vì role=0 thì cấp quyền, anh ấy muốn role=1 mới cấp quyền. Rồi xong, bạn Tín phải sửa lại hết cái đống if-else đó, thay role == 0 thành role == 1

 

Vậy làm sao để phát hiện một đoạn code, một tính năng của chương trình nói riêng và cả chương trình nói chung có dính WET không. Câu trả lời là mình cũng không biết, nhưng mình có thể bày các bạn cách để ngăn chặn nó

Hiểu nguyên lí sau: nếu mình không tạo ra nó, thì mình không phải tìm nó - WET code cũng vậy.

 

Theo như wiki nói, để áp dụng DRY, ta cần phải

Every piece of knowledge must have a single, unambiguous, authoritative representation within a system

"Piece of knowledge" nghĩa là một tính năng, một business, một thuật toán hay là một hàm trong chương trình của bạn.

Ta phải đảm bảo rằng nó là duy nhất, nó đảm nhiệm chức năng duy nhất, rõ ràng và mạch lạc

 

Và lưu ý rằng, nếu chương trình của bạn không có bất kỳ đoạn code nào giống nhau, bạn cũng không thể kết luận rằng mình đã tuân theo 100% DRY principles

 

Hãy tạm dừng lại và tìm cách giải quyết cho bài toán của bạn Tín bên trên - nếu bạn có thể làm đúng theo nguyên tắc DRY, bạn quả là một dev thực thụ =)))

 

Lợi ích của DRY

Giải pháp

Như ta đã biết thì gần phải đảm bảo rằng một function chỉ đảm nhiệm đúng tính năng của nó thôi, whenDelete thì chỉ nên Delete, hay whenCreate thì chỉ nên Create, đại loại vậy.

Vậy tại sao ta lại phải getPermission  int role = myServer.getSessionRole(); hay checkPermission if role == 0 trong đoạn code ở phần đầu ?

Việc nào liên quan tới permission nên để function permission lo nhỉ

function verifyPermission(){
  int role = myServer.getSessionRole();
  if (role == 0){
     return true;
  }
  return false;
}

Như vậy chỉ cần gọi hàm verifyPermission này mỗi khi có user muốn trigger bất kì action nào cần kiểm tra quyền hạn

function whenCreate(){
 if (verifyPermission()){
     createStudent();
 }
}

Đoạn code này sẽ giải quyết vấn đề sếp đưa ra bên trên, giúp chúng ta bảo trì và nâng cấp hệ thống nhanh hơn.

 

Khả năng bảo trì

Lợi ích lớn nhất của việc sử dụng DRY là khả năng bảo trì. Như ví dụ trên, nếu logic của việc kiểm tra quyền được lặp lại, thì việc khắc phục các vấn đề phát sinh sẽ trở nên khó khăn.

Khi bạn khắc phục sự cố trong một lần, bạn có thể dễ dàng quên khắc phục sự cố trong những lần khác.

Ngoài ra, nếu bạn phải sửa đổi logic, bạn phải copy khắp nơi. Nhưng nếu áp dụng DRY, bạn chỉ phải duy trì mã ở một nơi duy nhất.

 

Thu gọn - Dễ đọc

Rõ ràng là việc tiêu trừ các đoạn code trùng nhau sẽ giúp chương trình nhìn gọn hơn và dễ hiểu hơn.

Hãy thường xuyên kiểm tra WET nếu cảm thấy đoạn code đó đột nhiên hơi phình ra, đừng để nó trở thành đống SHIT khổng lồ rồi mới loay xoay chỉnh sửa.

 

Tái sử dụng

Có thể thấy rằng tách riêng function để kiểm tra quyền của user sẽ giúp chúng ta dễ dàng dùng tiếp hàm này cho các action khác về sau.

Nếu sếp bạn muốn thêm 100 function cần kiểm tra quyền cũng chả là vấn đề nữa, ta chỉ cần gọi hàm verifyPermission() trong hàm chính để kiểm tra.

 

Lợi ích thời gian

Có thể DRY sẽ tốn thời gian cho bạn đọc, nhưng tiết kiệm khá nhiều thời gian cho bạn code

Hãy ngừng sao chép bản thân, ngay cả khi Copy - Paste tuy thuận tiện và nhanh, nhưng bạn không thể nào cứ copy như vậy trong dự án có hàng ngàn function được, đúng không 😀.

 

Ví dụ tập luyện

Mình hơi nhát, nên đưa 2 ví dụ thôi nhỉ, cộng cả với cái trên thì đây là ví dụ 2

Ví dụ 1: Sếp của Tín

xem bên trên

 

Ví dụ 2: SHIP hàng tới cảng Tiên Sa

Bạn được sếp giao cho nhiệm vụ viết chương trình ghi nhận đơn hàng và chuyển nó tới cảng Tiên Sa, tuy nhiên có một logic khá là thú vị.

Khi ship hàng tới cảng Tiên Sa, giám đốc cảng yêu cầu mỗi mặt hàng phải được thông qua 1 bước kiểm tra chất lượng.

Đợt làm ăn này khấm khá, nên có tận 97000 mặt hàng khác nhau lận, và mỗi mặt hàng sau khi kiểm tra chất lượng xong sẽ có một số logic riêng biệt không giống nhau

Và đương nhiên là kiểm tra bằng code, ai rảnh mà đi check

Bạn sẽ code như thế nào?

A : Dùng một lệnh if-else ngay trong hàm shipMilk() để kiểm tra, sau đó copy nó ra 96999 mặt hàng còn lại, bao gồm: shipCookie, shipWater, shipPhone, shipFood, shipCat, shipDog, shipShip,... đm nhiều vãi lol (and >96k more nhé)

B: Viết hàm checkChatLuong, sau đó sử dụng nó trong các mặt hàng này

C: Một thứ gì đó cao siêu mà nhân loại chưa từng nghĩ tới

D: Đốt cảng

 

Đáp án đúng là đáp án A, nhưng chỉ đúng khi bạn ship tới cảng Tiên Sa thôi

Mọi chuyện sẽ bình thường nếu ngày đẹp trời sếp không ngứa tay bảo "anh đổi ý rồi, anh muốn ship tới Hoa Kỳ cơ, em sửa lại chương trình giúp anh nhé"

Ời anh, Hoa Kỳ rõ ràng là nó khác với Tiên Sa, nên logic kiểm tra chất lượng của nó cũng khác, thôi thì anh đợi em tầm 5-6 tháng để em viết lại cái hàm, rồi em copy nó ra nhé anh

Nói đến đây chắc bạn cũng đã biết đáp an, nếu vẫn không biết đáp án thì rõ là bạn chưa nắm DRY principle đâu, tìm hiểu thêm nhé, bye bye 😀


  RATE: 4.6 

  2554 VIEW


none
 GUEST 2021-07-20 12:04:27.0
ửbwr
none
 MOD 2021-08-31 13:36:22.0
Lô cc
none
 GUEST 2021-08-03 02:15:19.0
https://teams.microsoft.com/l/meetup-join/19%3ar9wAfk-0l0p9qi3igWKIWCbAyAOgFOjZtcj8EgONo6E1%40thread.tacv2/1627613350993?context=%7b%22Tid%22%3a%22912568cf-726e-421b-b907-7f8034164baf%22%2c%22Oid%22%3a%22ee88b76d-fe88-48ee-8797-90282159f08d%22%7d
none
 GUEST 2021-08-10 09:52:27.0
https://drive.google.com/drive/folders/18ZaF_VOx2Sm8q2ji9o-IxMSkcWUOWICb?usp=sharing
BÀI VIẾT LIÊN QUAN
DRY principle trong lập trình - Làm thế nào để biết code của bạn DRY hay WET ?

Nhìn ảnh chắc chúng ta cũng đã hiểu, điều gì xảy ra nếu có quá nhiều đoạn code giống nhau trong chương trình của bạn. Có phải khi một yêu cầu nào đó thay đổi, bạn sẽ phải sửa lại hết toàn bộ những đoạn code giống nhau đó hay không. Vậy làm thế nào để giữ nguyên tắc DRY principle trong lập trình, ví dụ và tác hại của nó, các bạn hãy xem bài viết này nhé.

BÀI VIẾT LIÊN QUAN
Code Game 2D Dodge Block Bằng Unity (Phần 2)

Hiện có rất nhiều phần mềm Engine hỗ trợ việc lập trình game từ di động đến desktop, như Game Maker Studio, Unreal Engine 4, … trong đó có Unity. Nhìn sơ qua thì Unity có thể là một nền tảng khá khó cho người mới học, họ dễ bị sốc kiến thức khi lần đầu tiếp cận unity vì nó cung cấp 1 lượng lớn thư viện hỗ trợ gồm các thư viện Asset đồ sộ, các model, được dựng sẵn.

BÀI VIẾT LIÊN QUAN
Code Game 2D Dodge Block Bằng Unity (Phần 1)

Hiện có rất nhiều phần mềm Engine hỗ trợ việc lập trình game từ di động đến desktop, như Game Maker Studio, Unreal Engine 4, … trong đó có Unity. Nhìn sơ qua thì Unity có thể là một nền tảng khá khó cho người mới học, họ dễ bị sốc kiến thức khi lần đầu tiếp cận unity vì nó cung cấp 1 lượng lớn thư viện hỗ trợ gồm các thư viện Asset đồ sộ, các model, được dựng sẵn.