【发布时间】:2016-10-26 20:36:24
【问题描述】:
我有一个复杂的业务操作,例如删除用户帐户。它包含多个连接的步骤,并且必须跟踪步骤之间的某些状态。编写此action 的更好方法是什么?
我看到更多functional 方法,如下所示。
function someAction(someParam, anotherParam, callback) {
async.waterfall([
step1,
step2,
step3,
step4
],callback
);
function step1(p,cb){/**use someParam and anotherParam here via closure*/}
function step2(p,cb){/**...*/}
function step3(p,cb){/**...*/}
function step4(p,cb){/**...*/}
};
someAction('value', 1241, (err)=>{/**...*/});
我不喜欢这种方法的一点是,所有内容都在单个函数的范围内定义(此处为 someAction)。
我找到了一种更object-oriented 的方式来更具可读性。状态和stepX 函数并不是真正私有的——有时它便于测试。
function SomeAction(someParam, anotherParam){
//private state
this._someParam = someParam;
this._anotherParam = anotherParam;
};
SomeAction.prototype._step1 = function(p, cb){
//use this._someParam and this._anotherParam
};
SomeAction.prototype._step2 = function(p, cb){
//use this._someParam and this._anotherParam
};
SomeAction.prototype._step3 = function(p, cb){
//use this._someParam and this._anotherParam
};
SomeAction.prototype._step4 = function(p, cb){
//use this._someParam and this._anotherParam
};
//public api
SomeAction.prototype.execute = function(callback) {
async.waterfall([
this._step1,
this._step2,
this._step3,
this._step4
],callback
)
};
new SomeAction('value', 1241).execute((err)=>{/**...*/})
它们之间有性能差异吗? Node.js 中推荐的方法是什么?每次我以功能方法调用someAction 时,是否真的 - 所有stepX 函数都必须从头开始定义?
【问题讨论】:
-
推荐的方法是对您来说更具可读性并且符合您的要求(可测试性)的方法。性能差异可以忽略不计。
-
最好的解决方案是使用 Promise。既是对象又是功能。
-
函数式并不意味着将整个逻辑放在一个函数中。这意味着设计每个具有单一目的的小功能,然后将这些功能组合成更复杂的功能。使用函数式范例,您不会获得封装,而是代码重用和由于没有副作用而提高了可维护性。
-
@LUH3417 感谢您的解释!我介绍的两种方法都由许多小函数组成(我喜欢这种风格——鲍勃叔叔推荐的)。问题是我应该如何在这些小函数之间传递数据 - 通过闭包或通过对象的属性。鲍勃叔叔认为,类是数据和操作它的方法的包。
-
现在我明白了。我很困惑,因为您在包装器内定义了
stepX函数(当然要关闭它们),因此不能再重用它们。您可以将不断变化的状态作为附加参数传递,并使用 state monad 将其抽象出来。如果共享状态没有改变,那么 reader monad 是一个替代方案。另一个问题是您是否使用不可变数据。最后,我认为这个问题太宽泛了。
标签: javascript node.js oop design-patterns functional-programming