Please enable Javascript to view the contents

Javascript RORO 模式 ——编写更具可读性的函数

 ·  ☕ 3 分钟
  • 原文:https://www.tinyblog.dev/blog/2020-07-13-javascript-roro-pattern/
  • 翻译:码中人
  • 内容:以有关键字参数kwargs代替无关键字参数args

代码的可读性是非常重要的。开发人员花了很多时间阅读代码:别人的代码,自己的代码,未见过的代码等。以尽可能可读的方式编写代码,可以帮助你的团队中的每个人节省大量的时间。可读性有时会增加性能负担,但二者之间,我们更倾向于保证代码可读性。

我非常喜欢Javascript的一个模式是RORO模式,即接收一个对象,返回一个对象(Receive an Object, Return and Object)。该模式的要点如下:函数应该总是接受一个对象作为其参数,并且它们应该总是返回一个对象作为其结果。通过这种方式,我们将对输入参数和返回对象进行重构,将更好的描述函数内容。这是我在学习Python和获得**kwargs的经验后开始做的事情,我非常喜欢这样做,可以很容易知道函数需要什么参数。

考虑以下函数调用:

const item = await getItemFromCollection(54391, 'shop');

这是我试图规避的写法。这个函数有一个描述性足够强的函数,我们可以假设它会从一个集合中获取一个项目。但是,其余的信息呢?我们斗胆猜测; 54391看起来最像一个id,shop大概就是一个系列的名字。当然,又不能百分百确定,为了完全理解这个接口,我们必须在我们的代码库中找到函数定义。

async function getItemFromCollection(id, collectionName) {

好的,所以我们不得不翻阅代码库,找到了这个函数定义,但这花了一点时间。如果我们使用RORO模式来写这个函数,就没有这个麻烦。

async function getItemFromCollection({ id, collectionName }) {
// do something
};

const item = await getItemFromCollection({
id: 54391,
collectionName: 'shop',
});

在声明我们的函数时,通过解构赋值对函数参数进行重构,大部分的语法都是一样的。然而,以后调用函数时,我们可以传递命名的参数。仅仅通过阅读函数调用,我们就知道不同的参数应该是什么,不再需要去查找函数的声明位置来了解上下文。现在,参数是自描述的,这更具有可读性,而且可以减少在代码库/文档中的搜索。

我开始采用这种模式的另一个重要原因是,布尔值参数。如以下函数调用:

someFunctionCall(false);

这是啥?我非常讨厌传一个布尔值,这代表啥?你可能会这样修改:

const variableNameDescribingBooleansPurpose = false;
someFunctionCall(variableNameDescribingBooleansPurpose);

someFunctionCall(/* comment describing the booleans purpose*/ false)

最好的解决方案是传入一个对象能数并立即解构。将传递的内容的描述直接与函数调用本身联系起来,无需再做任何额外的事情来使您的代码可读。

someFunctionCall({ booleanPurpose: false });

RORO模式有两个部分。现在,我们了解了 Receive an Object 部分,接下来我们讨论 Return an Object。我们的函数将返回对象,同样通过解构以获得我们想要的数据。这样做的好处在于,它为我们的函数提供了某些语言具有但 Javascript 本身不支持的功能:单个返回包含多个项目。

async function runProcess({ processName }) {
// run process on your server
// maybe you decide to cache the results of this process running
return { result, wasCached };
};

// destructuring off the result we can now have multiple items return from our function
const { result, wasCached } = await runProcess({ processName });
if (wasCached) {
// run another process
}

我个人觉得接收一个对象参数的好处比返回一个对象参数得到的利好更多。返回多个内容,结合解构操作,也非常有用。

当然这里最有用的是命名参数。它使函数更容易阅读;特别是在处理多参数函数或接受布尔值的函数时。多个返回项也很好,偶尔非常实用。归根结底,这种模式是为了让我们的 Javascript 功能更加灵活。这是我在学习了 Python 和 Go之后,迁移到JavaScript的经验。

分享

码中人
作者
码中人
Web Developer