12/08/2018, 17:06

RORO Pattern trong Javascript

Đây là kiểu pattern khi viết function trong javascript, function nhận input là 1 parameter kiểu object và ouput là trả về một object khác. Việc viết function theo pattern này có một số lợi ích nhất định sau: Named parameters Default parameters rõ ràng hơn Trả về giá trị phong phú hơn Hãy ...

Đây là kiểu pattern khi viết function trong javascript, function nhận input là 1 parameter kiểu object và ouput là trả về một object khác. Việc viết function theo pattern này có một số lợi ích nhất định sau:

  • Named parameters
  • Default parameters rõ ràng hơn
  • Trả về giá trị phong phú hơn

Hãy cùng phân tích cụ thể từng lợi ích đó nhé!

I. Named parameters

  • Giả sủ chúng ta có 1 function trả về 1 danh sách Users Theo quyền của họ, kèm theo đó là option lấy thêm thông tin liên lạc hoặc không và option lấy cả các user Inactive, khi đó chúng ta viết 1 function như sau
function findUsersByRole (
  role, 
  withContactInfo, 
  includeInactive
) {...}

Và khi ấy lời gọi function có thể sẽ là như sau:

findUsersByRole(
  'admin', 
  true, 
  true
)

Hãy nhìn vào 2 parameters cuối, "true, true" nói đến điều gì? Điều gì sẽ xảy ra nếu app của chúng ta hầu hết khi sử dụng function này đều không cần lấy ra contactInfo nhưng luôn cần Inactive user? Khi đó chúng ta sẽ cần nhập cả 3 tham số trong khi tham số thứ 2 là không cần thiết. Nói tóm lại, cách tiếp cận truyền thống nay sẽ gây nhiều điều khó hiểu và không rõ ràng trong code. Thay vào đó, chúng ta có thể truyền vào 1 parameter dạng object như sau:

function findUsersByRole ({
  role,
  withContactInfo, 
  includeInactive
}) {...}

Thay vì sử dụng 3 parameters như trước thì giờ đây function chỉ nhận vào object với 3 thuộc tính là role, withContactInfoincludeInactive

Và khi đó, đoạn code trên sẽ hoạt động dựa trên tính năng Destructuring của ES6, lúc này lời gọi function có thể được viết như sau:

findUsersByRole({
  role: 'admin', 
  withContactInfo: true, 
  includeInactive: true
})

Cách viết trên dễ đọc và dễ hiểu hơn rất nhiều. Hơn nữa, thứ tự params cũng không cần thiết nữa và chúng ta cũng có thể bỏ đi các params không cần thiết, ví dụ:

findUsersByRole({
  withContactInfo: true,
  role: 'admin', 
  includeInactive: true
})

Hay

findUsersByRole({
  role: 'admin', 
  includeInactive: true
})

Cả 2 lời gọi function trên đều sẽ hoạt động bình thường. Với cách viết function như trên thì việc bổ sung thêm parameter cho function cũng sẽ không gây ra bug. Tuy nhiên có 1 chú ý quan trọng đó là nếu chúng ta muốn tất cả parameters đều là optional, chúng ta cần set giá trị mặc định cho parameter object của mình, ví dụ:

function findUsersByRole ({
  role,
  withContactInfo, 
  includeInactive
} = {}) {...}

Việc sử dụng destructuring cho parameter object sẽ có lợi ích đó là đem lại tính bất biến cho nó. Khi chúng ta destructure object theo cách trên, chúng ta sẽ gán các thuộc tính của object vào các biến mới. Thay đổi trên các biến đó sẽ không làm thay đổi object ban đầu. Ví dụ trên đoạn code sau:

const options = {
  role: 'Admin',
  includeInactive: true
}
findUsersByRole(options)
function findUsersByRole ({
  role,
  withContactInfo, 
  includeInactive
} = {}) {
  role = role.toLowerCase()
  console.log(role) // 'admin'
  ...
}
console.log(options.role) // 'Admin'

Như vậy mặc dù có thay đổi giá trị của role thì giá trị của options.role vẫn không bị ảnh hưởng.

II. Cleaner Default Parameters

ES6 cung cấp tính năng Default parameters để chúng ta có thể khai báo các giá trị mặc định cho các tham số. Trong ví dụ trên chúng ta có sử dụng tính năng này với cú pháp = {} cho paramater object của hàm findUsersByRole. Với cách khai báo function truyền thống, việc khai báo default parameter sẽ có dạng:

function findUsersByRole (
  role, 
  withContactInfo = true, 
  includeInactive
) {...}

Nếu chúng ta muốn gán includeInactive thành true thì chúng ta cần truyền vào giá trị undefined cho tham số thứ 2 để giữ nguyên giá trị default của nó như sau:

findUsersByRole(
  'Admin', 
  undefined, 
  true
)

So sánh với cách khai báo function theo RORO pattern chúng ta sẽ thấy điểm khác biệt:

function findUsersByRole ({
  role,
  withContactInfo = true, 
  includeInactive
} = {}) {...}

Và gọi hàm:

findUsersByRole(
  role: 'Admin',
  includeInactive: true
)

Khi đó giá trị mặc định cho withContactInfo cũng vẫn được giữ nguyên

III. Richer Return Values

Function trong Javascript chỉ có thể trả về 1 giá trị. Và nếu giá trị đó là 1 object thì sẽ chứa đựng được nhiều thông tin hơn.

Nguồn

  • https://medium.freecodecamp.org/elegant-patterns-in-modern-javascript-roro-be01e7669cbd
0