有哪些技术可以在保持松散耦合的同时增加内聚力?

发布于 2024-08-04 13:41:18 字数 1118 浏览 12 评论 0原文

松耦合,高内聚 可维护的应用程序

这是我一遍又一遍听到的战斗口号。关于如何松散耦合组件有很多建议。

  • 基于接口并注入所有依赖项
  • 使用事件
  • 使用服务总线
  • 等。

但是,我觉得我从未真正听到过任何增加内聚力的具体建议。有人可以提供吗?

你可以从那里开始回答,但我有一个具体的情况,我也想得到建议。


我有一个相当松散耦合的 C# Windows Forms MVP 应用程序,它的许多组件都基于接口,通过构造函数注入它们,并使用控制反转容器 (Castle Windsor) 将它们组装在一起。

我想说它的架构非常好 - 它已经经历了几次重大的变更请求并且很容易处理它们。总的来说,我对它非常满意,但我无法摆脱一个挥之不去的怀疑,即它不是特别有凝聚力。作为唯一的开发人员,这对我来说不是问题,但我担心第一次进入该应用程序的人可能会感到非常困惑。

让我举个例子 - A 公司使用该应用程序来填充和处理出库卡车的产品。这意味着有一个 OutgoingTransactionInfo 对象、一个 OutgoingTransactionInfoControl (用于实际输入所述信息)、OutgoingTransactionValidatorOutgoingTransactionPersister >。随着应用程序投入生产,我们也收到了处理传入交易的请求 - 这些交易会附加不同的信息、不同的验证以及不同的持久化方式。然后,B 公司也想使用该应用程序进行事务处理,其想法是相似的,但同样,信息、验证、持久性以及其他一些组件可能有所不同。

因为我的应用程序有一个很好的测试套件并且很宽松,所以我能够很容易地满足这些请求。但是我认识到很容易意外地将其配置为无效状态。例如,您可以将其连接为使用 OutgoingTransactionInfo 对象,同时使用 IncomingTransactionValidator 进行验证。如果差异很细微,错误甚至可能在一段时间内未被发现。

您对我有什么建议吗?您使用哪些技术来降低此类风险?

Loose coupling, high cohesion for a
maintainable application

This is the battle-cry that I hear over and over. There is plenty of advice on how to loosely couple components.

  • Base on interfaces and inject all dependencies
  • Use events
  • Use a service bus
  • etc.

However, I feel like I've never really heard any specific suggestions for increasing cohesion. Does anyone have any to offer?

You can start answering there but I have as specific situation in mind that I would like advice on also.


I have a fairly loosely coupled C# Windows Forms MVP application that bases many of its components off of interfaces, injects them through constructors and uses an Inversion of Control container (Castle Windsor) to assemble it all together.

I would say its quite well architected - it has undergone several big change requests already and handled them quite easily. I am overall quite satisfied with it but I just can't let go of a nagging doubt that it's not particularly cohesive. This is not a problem for me as the sole developer but I fear it can get quite confusing for someone that comes into the application for the first time.

Let me give you an example - the application is used by Company A to fill and process outgoing trucks with product. This means that there is an OutgoingTransactionInfo object, an OutgoingTransactionInfoControl (for actually entering said information), OutgoingTransactionValidator, and OutgoingTransactionPersister. With the app in production, we got a request to handle incoming transactions as well - these get different information attached, different validation, and a different way of persisting them. Then Company B wanted to use the application for their transaction processing too, the idea is the similar but again, info, validations, persistence, and maybe a few other components differ.

Because my application has a good testing suite and is loose I've been able to accommodate these requests quite easily. However I recognize that it is all too easy to accidentally configure it in an invalid state. For example, you can wire it to use OutgoingTransactionInfo objects while validating with an IncomingTransactionValidator. If the differences are subtle the error might even go undetected for some time.

Do you have any suggestions for me? What techniques have you use to mitigate such risk?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

明媚如初 2024-08-11 13:41:18

内聚意味着您不会将不相关的东西放在一个模块(类,...)中。从你的描述来看,你似乎做得很好。适当的测试(你似乎也在做)应该可以控制风险。

您可能可以使用类型系统(泛型/模板)来确保信息及其验证器能够组合在一起,并可能节省一些代码/使其更加统一(不过,请确保增加的复杂性是值得的)。

否则继续做好工作。

Cohesion means that you don't put unrelated stuff together in a module (class, ...). From your description you seem to do this nicely. Proper testing (which you seem to do as well) should keep the risks in check.

You could probably use the type system (generics / templates) to make sure that info and its validator fit together and possibly save some code / make it more uniform (make sure the added complexity is worth it, though).

Otherwise keep up the good work.

罪#恶を代价 2024-08-11 13:41:18

当系统的每个组件都专注于一项职责时,您就获得了一个高度内聚的系统。俗话说“做一件事,就把它做好”。当您觉得一个类开始做“太多”的事情时,您可以将其重构为两个或多个类,每个类负责一件事。这导致松散耦合:因为每个职责都被本地化到一个特定的类,所以这些类之间更有可能具有非常离散的交互。

针对您的接线问题的快速建议:您的 OutgoingAbc 类不能检查以确保它在连接在一起时收到 OutgoingXyz 并在类型错误时抛出异常吗?

You achieve a highly cohesive system when each component of the system is focused on one responsibility. As the saying goes, "Do one thing and do it well." When you feel like a class is starting to do "too much" you can refactor it into two or more classes, each of which is responsible for one thing. This leads to loose coupling: because the responsibilities have each been localized to a particular class, the classes are more likely to have very discrete interactions with one another.

Quick suggestion for your wiring problem: couldn't your OutgoingAbc class check to ensure that it's receiving a OutgoingXyz when wired together and throw an exception if it's of the wrong type?

水溶 2024-08-11 13:41:18

我想到的一件事是控制可见性。 (我将用 Java 术语进行讨论,但我猜这些概念也适用于其他语言)。什么可以“看到”OutgoingTransactionValidator?它在 my.org.outgoing 包之外可见是否合法?

因此,可以通过不公开某些内容来控制错误接线。

将这个概念更进一步,OSGi 允许您显式声明捆绑包导出哪些包以及捆绑包使用哪些包,因此依赖关系变得更加明确和受控。

One thing that comes to mind is to control visibility. (I'll speak in Java terms, but I guess that the concepts tranfer to other languages). What can "see" OutgoingTransactionValidator? Is it legitimate for it to be visible outside the my.org.outgoing package?

So miswiring can be controlled by not declaring something public.

Taking this concept a stage further OSGi allows you to explicitly declare which packages a bundle exports and which packages a bundle uses, so the dependencies become much more explicit, and controlled.

我很OK 2024-08-11 13:41:18

这是一个有趣的 Jim Weirich 在 2009 年 Mountain West Ruby 会议上从 Ruby 的角度进行的关于耦合和内聚问题的演讲。处理不同的程度以及它们何时可能合适或不合适。

Here's an interesting presentation by Jim Weirich on the issues of coupling and cohesion from a Ruby point of view from the 2009 Mountain West Ruby Conference. Deals with the various degrees and when they may or may not be appropriate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文