使用字符串作为参数来控制函数结果是否是反模式?

时间:2018-08-22 18:36:55

标签: javascript

我正在尝试确定编写可以执行多个动作的函数时的最佳实践。我当前的解决方案是使用一个字符串参数来告诉函数该做什么(例如,updateTasks('complete selected', data);)。

我意识到我可以将此功能拆分为多个功能,但是我会以这种方式重复很多次。我的另一种选择是以布尔语句的形式使用更多参数,但我读到了use fewer arguments

目标

  • 参数很少
  • 保持干燥,或拆分成多个功能

数据集

let data = {
  selectedTasks:[1,3],
  tasks: [
    {
      id: 1,
      title: 'get milk',
      complete: false,
    },
    {
      id: 2,
      title: 'feed cat',
      complete: true,
    },
    {
      id: 3,
      title: 'exercise',
      complete: false,
    }
  ]
};

功能

根据lealceldeiro的建议进行了更新

updateTasks = (action, data) => {
  const taskChanges = data.tasks.map(task => {

    const isSelected = data.selectedTasks.indexOf(task.id) > -1;

    if ((action === 'complete selected' && isSelected) || 
    (action === 'complete nonselected' && !isSelected) || 
    (action === 'complete all')) 
      return Object.assign({}, task, {complete: true}); 

    if ((action === 'uncomplete selected' && isSelected) ||
    (action === 'uncomplete nonselected' && !isSelected) ||
    (action === 'uncomplete all')) 
      return Object.assign({}, task, {complete: false}); 

    return task; // keep as is
  });
  return taskChanges;
};

用法示例

updateTasks('complete selected', data);

这是最佳实践,还是最好将功能拆分?我希望我的代码尽可能干燥且清晰易读。

1 个答案:

答案 0 :(得分:1)

我不知道有任何反模式。实际上有一个command pattern。但是,与其传递一个字符串,不如传递一个函数以返回完整状态。

const completeAllAction = () => true; //prev, isSelected parms ignored
const uncompleteAllAction = () => false;
const compleSelectedAction = (prev, isSelected ) =>  isSelected ? true : prev; 
const compleNonSelectedAction = (prev, isSelected ) =>  !isSelected ? true : prev; 
const uncompleSelectedAction = (prev, isSelected ) =>  isSelected ? false : prev; 
const uncompleNonSelectedAction = (prev, isSelected ) =>  !isSelected ? false : prev; 

const updateTasks = (action, data) => {
  const taskChanges = data.tasks.map(task => {
    const isSelected = data.selectedTasks.indexOf(task.id) > -1;
    const newComplete = action(task.complete, isSelected);
    return Object.assign({}, task, {complete: newComplete});
  });
  return taskChanges;
};


updateTasks(completeAllAction, data);

我强烈建议您不要在if语句后省略{bloc}。有关详细信息,请参见Crockford的JavaScript the good parts

您还可以使用function composition来减少参数数量并保持代码干燥。

const getUpdateTasksFunction = action => {
    //return a function that takes the data object
    return (data) => {
        return data.tasks.map(task => {
            const isSelected = data.selectedTasks.indexOf(task.id) > -1;
            const newComplete = action(task.complete, isSelected);
            return Object.assign({}, task, {complete: newComplete});
        });
    }
}

const uncompleteAll = getUpdateTasksFunction(uncompleteAllAction);
const compleNonSelected = getUpdateTasksFunction(compleNonSelectedAction);
 //  ... continue for each action

//usage with only one param
const newData = uncompleteAll(data);