我正在调查pub / sub模式,因为我正在阅读一本高度提倡事件驱动架构的书,以便松散耦合。但我觉得松耦合只能通过牺牲可读性/透明度来实现。
我无法理解如何编写易于理解的发布/子代码。我目前编写代码的方式导致了很多一对一的通道,我觉得这样做是不好的做法。
我正在使用require.js AMD模块,这意味着我有许多较小尺寸的文件,因此我觉得有些人很难跟踪我的发布流程。
在下面的示例代码中,有三个不同的模块:
要点是用户提交文本,将其翻译成英文,然后存储到数据库中。此流程在自己的文件中分为三个模块。
// Main Controller Module
define(['pubSub'] function(pubSub) {
submitButton.onclick(function() {
var userText = textArea.val();
pubSub.publish("userSubmittedText", userText);
});
});
// Translator module
define(['pubSub'] function(pubSub) {
function toEnglish(text) {
// Do translation
pubSub.publish("translatedText", translatedText);
};
pubSub.subscribe("userSubmittedText", toEnglish);
});
// Database module
define(['pubSub'] function(pubSub) {
function store(text) {
// Store to database
};
pubSub.subscribe("translatedText", store);
});
为了让读者看到完整的流程,他必须在三个模块之间切换。但是,在看到第一个pubSub.publish("userSubmittedText", userText);
后,你将如何弄清楚读者的看法?
我觉得出版物就像一个悬崖挂架,读者想知道接下来会触发什么,但他必须去寻找具有订阅功能的模块。
我可以评论每次发布,解释哪些模块包含正在收听的功能,但这似乎不切实际。我不认为这是其他人正在做的事情。
此外,上面的代码使用一对一的渠道,我认为这是不好的风格,但我不确定。只有转换器模块的toEnglish()
函数才会订阅pubSub通道"userSubmittedText"
,但我必须为基本上单个函数调用创建新通道。虽然这样我的Controller模块不必将Translator作为依赖项,但它感觉不像真正的解耦。
缺乏功能流透明度对我来说很重要,因为我不知道如何阅读这些源代码的人会知道如何遵循。显然,我必须遗漏一些重要的东西。也许我没有使用有用的约定,或者我的发布事件名称可能不够描述?
只有牺牲流动透明度才能实现pub / sub的松散耦合?
答案 0 :(得分:1)
发布订阅模式的想法是,您不会对谁订阅某个主题或谁正在发布做出任何假设。来自维基百科(http://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern):
[...]相反,已发布的消息被分类为类, 不知道可能有什么订户(如果有的话)。 同样,订阅者表达对一个或多个类的兴趣,并且 只接收感兴趣的消息,而不知道什么, 如果有的话,那里有出版商。
如果您的运行代码没有做出任何假设,那么您的评论也不应该这样做。如果你想要一种更易读的模块通信方式,你可以使用requirejs的依赖注入,而你已经使用了pubsub模块。通过这种方式,您可以更轻松地读取代码(这会带来其他缺点)。这一切都取决于你想要达到的目标......