简体   繁体   中英

How to make the if conditions look cleaner?

Is there a way to make this if conditions look cleaner and easily to add more Query search in the future as in Open–closed principle?

For example:

if (event.queryParameters["name"]) {
    result = await getResultByName(event.queryParameters["name"]);
} else if (event.queryParameters["emailAddress"]) {
    result = await getResultByEmail(event.queryParameters["emailAddress"]);
} else if (event.queryParameters["param1"]) {
    result = await getResultByParam1(event.queryParameters["param1"]);
} else if (event.queryParameters["something1"] && event.queryParameters["something2"]) {
    result = await getResultBySomething(event.queryParameters["something1"], event.queryParameters["something2"]);
}

As you can see it look really messy.

Make a table of entries and use Array.prototype.find() :

const lut = [
  { keys: ['name'], getResultBy: getResultByName },
  { keys: ['emailAddress'], getResultBy: getResultByEmail },
  { keys: ['param1'], getResultBy: getResultByParam1 },
  { keys: ['something1', 'something2'], getResultBy: getResultBySomething }
]

const params = event.queryParameters
const entry = lut.find(
  ({ keys }) => keys.every(key => key in params)
)

if (entry) {
  const { keys, getResultBy } = entry
  const result = await getResultBy(...keys.map(key => params[key]))
  ...
}

The problem with the original code is that it isn't DRY, and so any incremental modification will inevitably repeat what was already written.

Compare the following two incremental changes:

...
{ keys: ['fizz', 'buzz', 'fizzbuzz'], getResultBy: getResultByFizzBuzz }
...
else if (params.fizz && params.buzz && params.fizzbuzz) {
  result = await getResultByFizzBuzz(params.fizz, params.buzz, params.fizzbuzz);
}

And tell me which one you'd rather be typing every time you go back and add a new function.

Since values are different and functions are different, there's not much place for improvement.

There's no necessity for bracket notation and there's no reason to reference event object every time.

It could be written as:

const { queryParameters } = event;

if (queryParameters.name) {
    result = await getResultByName(queryParameters.name);
} else if ...

No other improvements can be made, unless the same case occurs in several places and could be DRYed up:

const paramHandlers = [
  { handler: getResultByName, paramNames: ['name'] },
  ...
];

Then paramHandlers can be iterated to check if paramNames match event.queryParameters properties.

So what you have looks perfectly readable, simple, and clean. You could create an event handler list if you need more flexibility:

eventHandlers = [nameHandler, emailHandler, ...];
var result;
for (var handler of eventHandlers) {
    if (result = handler(event)) break;
}

In this example, the event handlers are functions that return a result if the event was consumed and processing should end. In your case your result can be a Promise or any arbitrary value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM