使用node.js我正在创建一个函数,通过在列表中附加一个新元素来更新包含JSON列表的文件。更新的列表将重写回文件。如果文件不存在,我创建它。
下面,__list_append(..)
会追加列表和文件更新。
我的问题是,是否(并且应该)我可以重构此代码,而不是两次调用__list_append
。我对node.js有点新意,并且对异步策略没有好感。
function list_append(filename, doc) {
fs.exists(filename, function(exists) {
if (exists) {
fs.readFile(filename, function(err, data) {
if (err)
throw err;
__list_append(filename, JSON.parse(data), doc);
});
} else
__list_append(filename, [], doc);
});
}
答案 0 :(得分:2)
很容易对“最佳实践”有点迂腐,但是当我编写代码并且我感到有些东西不正确或者某些东西可能被改变时,我会回顾一些众所周知的最佳实践和尝试看看我写的代码是否符合他们的要求。 SOLID虽然是面向对象编程的原则,但在其他环境中思考可能很有用。在这种情况下,在我看来该函数违反了Single Responsibility Principle:
良好设计的最基本原则之一是:
将出于同样原因而改变的事物聚集在一起,并将那些因不同原因而改变的事物分开。
这一原则通常被称为单一责任原则或SRP。简而言之,它表示子系统,模块,类或甚至函数不应有多个原因需要改变。
(对于这个例子,这或许可以换成Separation of Concerns或其他类似的原则,但概念是相同的。)
在这种情况下,该功能有两个职责:(1)获取与文件名相关联的当前(或默认)列表,以及(2)将数据附加到所述列表。分离这些问题的第一步可能看起来像这样:
function get_current_list(filename, callback) {
fs.exists(filename, function(exists) {
if (exists) {
fs.readFile(filename, function(err, data) {
if (err)
return callback(err);
callback(null, JSON.parse(data));
});
} else
callback(null, []);
});
}
function list_append(filename, doc) {
get_current_list(filename, function(err, list) {
if(err) throw err;
__list_append(filename, list, doc);
});
}
现在,get_current_list
仅负责获取文件中的当前列表(如果没有文件,则为空数组),__list_append
是(假设为只有 负责追加; list_append
现在是这两个函数之间的简单集成点。这些函数可以重复使用,也可以更容易地进行测试(另外,测试优先或TDD编程方法可以帮助您预先注意到这些事情)。此外,在callback
中重复get_current_list
比重复__list_append
更加通用;如果您需要将__list_append
更改为其他内容,现在只能在一个地方调用它。
答案 1 :(得分:0)
这种情况总是令我感到不满意因为是的,你必须在两个分支上重复调用__list_append
,因为只有一个分支是同步的。
答案 2 :(得分:0)
我喜欢和投票给布兰登的答案,但这也有效:
function list_append(filename, doc) {
fs.exists(filename, function(exists) {
var data = [];
if (exists) {
data = fs.readFileSync(filename, "utf8");
}
__list_append(filename, data, doc);
});
}