55

DRY principle

 5 years ago
source link: https://www.tuicool.com/articles/hit/IFZZ3uq
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Background

We want to have a function which checks whether an item in JS object representation is a commondity. An item is a commondity if it satisfies one of :

  • HAS a price attribute
  • HAS a barcode attribute

The following tests should pass:

isCommondity({price: 1}); //true
isCommondity({barcode: 'abc'}); //true
isCommondity({a: 'a'}); //false

Round one

It seems to be quite straightfordword to come out with the following solution:

function isCommondityV1(comd) {
  return !!comd.price || !!comd.barcode
}

The implementation is wrong under some circumstances. !!obj.prop is checking the truthy of the prop property of obj , instead of checking the existence of the prop property. E.g.

isCommondityV1({price: 0}); // false

while we expect isCommondityV1 to return true since {price: 0} does have the price property.

Round two

hasOwnProperty

function isCommondityV2(comd) {
  return comd.hasOwnProperty('price') || comd.hasOwnProperty('barcode')
}

isCommondityV2({price: 0}); //true

The solution works perfectly in line with the functionality requirement. However, it does suffer from the two problems:

  • Flexibility: if we add more checkings later on, we would have to update the implementation body. E.g. when the attribute set extends to be ['price', 'barcode', 'a', 'b'] .
function isCommondityV21(comd) {
  return comd.hasOwnProperty('price') || 
          comd.hasOwnProperty('barcode') || 
          comd.hasOwnProperty('a') || 
          comd.hasOwnProperty('b');
}
  • DRY: We're repeating the operation (i.e comd.hasOwnProperty ). We can be better off by seperating the variables and encapsulate the constants.

Round three

function isCommondityV3(comd) {
  return ['price', 'barcode'].some(Object.prototype.hasOwnProperty, comd);
}

With this implementation, we can easily deal with later change by updating the variables.

function isCommondityV31(comd) {
  return ['price', 'barcode', 'a', 'b'].some(Object.prototype.hasOwnProperty, comd);
}

Or we can even go one more step further by encapsulating the variables into config file. Futher requirement change will result in only changes in config file without touching the implementation body :-)

//config.js
export COMMONDITY_PROPS = ['price', 'barcode'];
//commondity.js
import { COMMONDITY_PROPS } from 'config.js'

function isCommondity(comd) {
  return COMMONDITY_PROPS.some(Object.prototype.hasOwnProperty, comd);
}

Notice

  • If you want to follow the latest news/articles for the series of my blogs, Please 「Watch」 to Subscribe.

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK