首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >方法将命令委托给其他方法。

方法将命令委托给其他方法。
EN

Code Review用户
提问于 2020-09-26 09:29:29
回答 6查看 1.2K关注 0票数 10

因为我是一个人在这方面工作,我希望有人能看一看,并指出任何错误或事情,我可以做得更好。

我的问题:

  1. 如何改进这个大开关语句?

当命令是适度命令时,executeModeration是我调用的方法。command.parameters[0]包含需要执行的逗号参数。

代码语言:javascript
复制
const executeModeration = async (command, channel) => {
  switch (command.command)  {
    case "ban":
      if(command.parameters[0])
        await moderation.ban(channel, command.parameters[0], command.parameters[1] !== undefined ? command.parameters[1] : '');
      break;
    case "unban":
      if(command.parameters[0])
        await moderation.unban(channel, command.parameters[0]);
      break;
    case "timeout":
      if(command.parameters[0])
        await moderation.timeout(channel, command.parameters[0], command.parameters[1] !== undefined ? command.parameters[1] : 300, command.parameters[2] !== undefined ? command.parameters[2] : '');
      break;
    case "emoteonly":
      await moderation.emoteonly(channel);
      break;
    case "emoteonlyoff":
      await moderation.emoteonlyoff(channel);
      break;
    case "followersonly":
      await moderation.followersonly(channel,command.parameters[0] !== undefined ? command.parameters[0] : 30);
      break;
    case "followersonlyoff":
      await moderation.followersonlyoff(channel);
      break;
    case "r9kbeta":
      await moderation.r9kbeta(channel);
      break;
    case "r9kbetaoff":
      await moderation.r9kbetaoff(channel);
      break;
    case "slow":
      await moderation.slow(channel, command.parameters[0] !== undefined ? command.parameters[0] : 30);
      break;
    case "slowoff":
      await moderation.slowoff(channel);
      break;
    case "subscribers":
      await moderation.subscribers(channel);
      break;
    case  "subscribersoff":
      await moderation.subscribersoff(channel);
      break;
    case  "mod":
      if(command.parameters[0])
        await moderation.mod(channel, command.parameters[0]);
      break;
    case  "unmod":
      if(command.parameters[0])
        await moderation.unmod(channel, command.parameters[0]);
      break;
    case  "vip":
      if(command.parameters[0])
        await moderation.vip(channel, command.parameters[0]);
      break;
    case  "unvip":
      if(command.parameters[0])
        await moderation.unvip(channel, command.parameters[0]);
      break;
    case  "clear":
      await moderation.clear(channel);
      break;
    case  "host":
      if(command.parameters[0])
        await moderation.host(channel, command.parameters[0]);
      break;
    case  "unhost":
      await moderation.unhost(channel);
      break;
    case  "commercial":
      if(command.parameters[0])
        await moderation.commercial(channel, command.parameters[0]);
      break;
  }
EN

回答 6

Code Review用户

发布于 2020-09-26 16:14:13

Spread类似于Mohammed的答案,但没有变异,而且使用like语法(我发现这种语法比.apply更容易阅读),您可以这样做:

代码语言:javascript
复制
const executeModeration = async (command, channel) => {
    await moderation[command.command](...command.parameters);
}

默认参数

在调用函数时使用许多条件运算符,例如:

代码语言:javascript
复制
.ban(
    channel,
    command.parameters[0],
    command.parameters[1] !== undefined ? command.parameters[1] : ''
);
代码语言:javascript
复制
.timeout(
    channel,
    command.parameters[0],
    command.parameters[1] !== undefined ? command.parameters[1] : 300,
    command.parameters[2] !== undefined ? command.parameters[2] : ''
);

如果可能的话,最好是定义这些方法,以便它们分配默认参数,而不是从上面传递默认值。例如,对于timeout方法,可以定义如下:

代码语言:javascript
复制
timeout(arg1, arg2 = 300, arg3 = '') {
}

然后,在从问题中的脚本调用parameters时,只需传递timeout,默认参数将处理其余参数。

如果您不能修改moderation对象的方法,那么创建这些默认参数的一种方法是通过命令索引对象,其值是需要默认参数的函数,并调用moderation方法。例如,对于.ban.timeout

代码语言:javascript
复制
const executeModeration = ({ command, parameters }, channel) => {
    const fnsWithDefaultParams = {
        ban(arg1, arg2 = '') {
            return moderation.ban(channel, arg1, arg2);
        },
        timeout(arg1, arg2 = 300, arg3 = '') {
            return moderation.timeout(channel, arg1, arg2, arg3);
        },
        // ...
    };
    return fnsWithDefaultParams[command]
        ? fnsWithDefaultParams[command](...parameters)
        : moderation[command](...parameters)
};

注意,如果函数显式返回承诺,现在就不需要async函数了,如上面所示。

票数 9
EN

Code Review用户

发布于 2020-09-26 12:03:44

我不是JavaScipt程序员,所以我的建议是有限的

有什么明显的初学者缺陷吗?

使用这样的大型case语句是初学者的一个缺陷,因为它很难维护(扩展和收缩很难),性能也可以改进。在C++中,我将使用函数的关键字映射,并在C语言或其他语言中执行类似的操作。索引到数组或其他一些表查找机制比开关/案例逻辑更快,并且更容易将关键字函数对添加到数据结构中。

票数 8
EN

Code Review用户

发布于 2020-09-26 21:10:15

我的回答将包括几个步骤。在最后的答案中,有些步骤将不再存在,但我提到它们,因为在其他情况下,您可能会发现关注这些步骤很有趣。

对command.parameters0、command.parameters1、.

的相同引用的多次使用

你在任何地方都在使用command.parameters[0]。如果你正在写的东西看起来像重复,那是一个很好的提示,那就是有一些东西需要分解。

所以让我们从移除它开始。

代码语言:javascript
复制
const executeModeration = async (command, channel) => {
    const [param0, param1, param2] = command.parameters;
    switch (command.command) {
        case "ban":
            if (param0)
                await moderation.ban(channel, param0, param1 !== undefined ? param1 : '');
            break;
        case "unban":
            if (param0)
                await moderation.unban(channel, param0);
            break;
        case "timeout":
            if (param0)
                await moderation.timeout(channel, param0, param1 !== undefined ? param1 : 300, param2 !== undefined ? param2 : '');
            break;
        case "emoteonly":
            await moderation.emoteonly(channel);
            break;
        case "emoteonlyoff":
            await moderation.emoteonlyoff(channel);
            break;
        case "followersonly":
            await moderation.followersonly(channel, param0 !== undefined ? param0 : 30);
            break;
        case "followersonlyoff":
            await moderation.followersonlyoff(channel);
            break;
        case "r9kbeta":
            await moderation.r9kbeta(channel);
            break;
        case "r9kbetaoff":
            await moderation.r9kbetaoff(channel);
            break;
        case "slow":
            await moderation.slow(channel, param0 !== undefined ? param0 : 30);
            break;
        case "slowoff":
            await moderation.slowoff(channel);
            break;
        case "subscribers":
            await moderation.subscribers(channel);
            break;
        case "subscribersoff":
            await moderation.subscribersoff(channel);
            break;
        case "mod":
            if (param0)
                await moderation.mod(channel, param0);
            break;
        case "unmod":
            if (param0)
                await moderation.unmod(channel, param0);
            break;
        case "vip":
            if (param0)
                await moderation.vip(channel, param0);
            break;
        case "unvip":
            if (param0)
                await moderation.unvip(channel, param0);
            break;
        case "clear":
            await moderation.clear(channel);
            break;
        case "host":
            if (param0)
                await moderation.host(channel, param0);
            break;
        case "unhost":
            await moderation.unhost(channel);
            break;
        case "commercial":
            if (param0)
                await moderation.commercial(channel, param0);
            break;
    }
}

模式变量的

重复!==未定义?变量:值

还有另一种重复:

variable !== undefined ? variable : value,特别是variable !== undefined ? variable : ''也在任何地方使用..。

让我们骑上那辆车。

代码语言:javascript
复制
const getOrDefault = (element, def) => element !== undefined ? element : def;
const getOrEmpty = (element) => getOrDefault(element, '');

const executeModeration = async (command, channel) => {
    const [param0, param1, param2] = command.parameters;
    switch (command.command) {
        case "ban":
            if (param0)
                await moderation.ban(channel, param0, getOrEmpty(param1));
            break;
        case "unban":
            if (param0)
                await moderation.unban(channel, param0);
            break;
        case "timeout":
            if (param0)
                await moderation.timeout(channel, param0, getOrDefault(param1,300), getOrEmpty(param2));
            break;
        case "emoteonly":
            await moderation.emoteonly(channel);
            break;
        case "emoteonlyoff":
            await moderation.emoteonlyoff(channel);
            break;
        case "followersonly":
            await moderation.followersonly(channel, getOrDefault(param0, 30));
            break;
        case "followersonlyoff":
            await moderation.followersonlyoff(channel);
            break;
        case "r9kbeta":
            await moderation.r9kbeta(channel);
            break;
        case "r9kbetaoff":
            await moderation.r9kbetaoff(channel);
            break;
        case "slow":
            await moderation.slow(channel, getOrDefault(param0, 30));
            break;
        case "slowoff":
            await moderation.slowoff(channel);
            break;
        case "subscribers":
            await moderation.subscribers(channel);
            break;
        case "subscribersoff":
            await moderation.subscribersoff(channel);
            break;
        case "mod":
            if (param0)
                await moderation.mod(channel, param0);
            break;
        case "unmod":
            if (param0)
                await moderation.unmod(channel, param0);
            break;
        case "vip":
            if (param0)
                await moderation.vip(channel, param0);
            break;
        case "unvip":
            if (param0)
                await moderation.unvip(channel, param0);
            break;
        case "clear":
            await moderation.clear(channel);
            break;
        case "host":
            if (param0)
                await moderation.host(channel, param0);
            break;
        case "unhost":
            await moderation.unhost(channel);
            break;
        case "commercial":
            if (param0)
                await moderation.commercial(channel, param0);
            break;
    }
}

请注意,虽然仍然有开关/大小写,但超时行似乎更易读。

,让我们骑上开关/箱子

我们现在可以用操作对象替换开关/情况。

代码语言:javascript
复制
const getOrDefault = (element, def) => element !== undefined ? element : def;
const getOrEmpty = (element) => getOrDefault(element, '');

const moderationCommandActions = {
    ban: async (channel, nick, param2) => {
        if (nick) {
            await moderation.ban(channel, nick, getOrEmpty(param2))
        }
    },
    unban: async (channel, nick) => {
        if (nick) {
            await moderation.unban(channel, nick);
        }
    },
    timeout: async (channel, nick, value, param2) => {
        if (nick) {
            await moderation.timeout(channel, nick, getOrDefault(value, 300), getOrEmpty(param2));
        }
    },
    emoteonly: async (channel) => await moderation.emoteonly(channel),
    emoteonlyoff: async (channel) => await moderation.emoteonlyoff(channel),
    [...],
};

const executeModeration = async (command, channel) => {
    const action = moderationCommandActions[command.command];
    if (action) {
        await action(channel, ...command.parameters);
    }
}

请注意,这允许我把一些像nick这样的名字,而不是param0 (但我不知道您的API,我不确定它是否正确的含义)。这里最好的方法是使用paramX名称并使用描述性名称。

最后,getOrEmptygetOrDefault现在只用于检查操作参数,因此可以用函数声明中的默认params替换。

取代getOrEmpty和getOrDefault

代码语言:javascript
复制
const moderationCommandActions = {
    ban: async (channel, nick, param2='') => {
        if (nick) {
            await moderation.ban(channel, nick, param2)
        }
    },
    unban: async (channel, nick) => {
        if (nick) {
            await moderation.unban(channel, nick);
        }
    },
    timeout: async (channel, nick, value=300, param2='') => {
        if (nick) {
            await moderation.timeout(channel, nick, value, (param2));
        }
    },
    emoteonly: async (channel) => await moderation.emoteonly(channel),
    emoteonlyoff: async (channel) => await moderation.emoteonlyoff(channel),
    [...],
};

const executeModeration = async (command, channel) => {
    const action = moderationCommandActions[command.command];
    if (action) {
        await action(channel, ...command.parameters);
    }
}

请注意,超时实现现在比原来的实现更具可读性。

使用析构分配的

您最终可以替换:

代码语言:javascript
复制
const executeModeration = async (command, channel) => {
    const action = moderationCommandActions[command.command];
    if (action) {
        await action(channel, ...command.parameters);
    }
}

通过

代码语言:javascript
复制
const executeModeration = async ({ command, parameters }, channel) => {
    const action = moderationCommandActions[command];
    if (action) {
        await action(channel, ...parameters);
    }
}

但是,如果需要检查函数的第一个参数是否为null,则不能这样做,因此必须执行以下操作:

代码语言:javascript
复制
const executeModeration = async (command, channel) => {
    if (command) {
        const action = moderationCommandActions[command.command];
        if (action) {
            await action(channel, ...command.parameters);
        }
    }
}
票数 8
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/249873

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档