今天原本想美美地完成UI层与Core层通过消息总线实现博客发布的功能。一切都很顺利,直到我重构到
PublishBlog
方法,准备为ApplicationService
写事件处理逻辑时,不然发现不对劲——“不兑!等等,我该怎么把发布结果信息传回给ApplicationService
呢?” 就是这么一个看似简单的问题,让我一脸懵逼。。。
一、 项目背景与问题起源
先简单介绍下我的项目:这是一个.NET Winform
博客一键发布工具。架构上做了清晰的分层(自己突然想出来写着玩的):
-
UI层:负责界面交互,它不关心核心逻辑,只通过消息总线向Core层发送指令(比如“发布博客”)。
-
Core层:负责所有核心业务。其中有一个关键的
ApplicationService
,它就像是Core层的“总指挥部”,所有消息的接收和发布都由它一手包办。当它收到UI层的指令后,会去调用像BlogPublishService
这样的具体“业务部门”来干活。
这种设计的好处是解耦:UI层和Core层互相不认识,只通过消息沟通,非常清爽。在后续开发我甚至打算使用更加精美与符合现代审美WPF项目来作为UI层,所以如此设计打有好处。(得意叉腰)
问题就出在这里:我的 BlogPublishService.PublishBlog
方法,以前干完活是自己直接“大喊一声”(发布事件)通知UI层。但现在规矩变了,所有“喊话”的权力都收归 ApplicationService
了。这下好了,PublishBlog
方法变成了一个“哑巴”,它活干得怎么样,ApplicationService
完全不知道,自然也就没法向上汇报了。
所以,核心问题变成了:如何让“哑巴”开口,把它工作的结果告诉“总指挥部”?
二、 思路博弈:返回值 vs 输出参数
首先得确定沟通方式。脑子里蹦出两个选项:
-
返回值 (Return Value):最直接,像函数式编程,
输入 -> 处理 -> 输出
,符合直觉。 -
输出参数 (out Parameters):感觉更“高级”一点,但用在这里有点别扭。
我琢磨了一下,PublishBlog
这个方法非常纯粹:给它配置和内容,它就去发布,最后给你一个结果。这简直就是为返回值量身定做的场景。用 out
参数的话,代码会显得很拧巴,所以果断选择了返回值方案。
// 返回值方式:清晰,像在问一个问题并得到一个答案var result = await blogPublishService.PublishBlog(configs, blogInfo);// 输出参数方式:有点绕,像在操作一个机器blogPublishService.PublishBlog(configs, blogInfo, out var result);
三、 命名的纠结:与AI的“头脑风暴”
确定了用返回值,下一个头疼的事来了:返回什么类型?方法内部主要有两种信息要传递:一个是所有平台的发布详情 (List<PublishResult>
),另一个是可能出现的业务错误 (List<string>
)。
直接返回元组 (List<PublishResult>, List<string>)
太丑了,过于冗长,不够优雅,Item1
和 Item2
过几天自己都看不懂。返回事件类型又会造成层与层之间的耦合。所以,定义一个新类型是唯一优雅的选择。
但取什么名字呢?我犯了难,于是求助了AI。AI给了我几个方案:
-
PublishOperationResult
(发布操作结果) -
PublishSummaryResult
(发布摘要结果) -
PublishAggregateResult
(发布聚合结果)
我盯着这几个名字看了好久。OperationResult
太泛了,什么操作都能用;SummaryResult
强调摘要,感觉有点轻量。最后我选择了 PublishAggregateResult
。
为什么? 因为这个词精准地描述了这个类的本质:它不是一个简单的结果,而是由多个PublishResult
聚合而成的。Aggregate
(聚合)这个词在DDD(领域驱动设计)里很常见,它暗示了这是一个整体,能很好地表达“总和”的概念。就这么定了!
// 最终,方法签名变得非常清晰public async Task<PublishAggregateResult> PublishBlog(...){// ... 内部逻辑return new PublishAggregateResult {PublishResults = res,FailReasons = failedReasons};}
四、 总结与心得
这次重构让我深刻体会到,软件设计就是在不断地做权衡。从最初的架构选择(消息总线),到具体的技术方案(返回值),再到最后的命名细节,每一步都是一个决策点。
-
分层与解耦是基础:清晰的分层让问题暴露得更早,解决起来方向也更明确。
-
返回值是直觉之选:对于纯计算或纯业务逻辑,返回值通常是最直接、最清晰的通信方式。
-
命名是设计的延伸:一个好名字能准确传达类的职责,
PublishAggregateResult
无疑比Item1
和Item2
要好懂得多。