2

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

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

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

然而,我觉得我从来没有真正听到过任何关于增加凝聚力的具体建议。有人可以提供吗?

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


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

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

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

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

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

4

4 回答 4

3

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

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

否则继续做好工作。

于 2009-09-10T15:39:37.693 回答
1

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.

于 2009-09-10T16:49:30.550 回答
1

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

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

于 2009-09-10T15:36:01.930 回答
1

想到的一件事是控制可见性。(我会用 Java 术语说话,但我猜这些概念会转移到其他语言)。什么可以“看到” OutgoingTransactionValidator?它在my.org.outgoing包之外可见是否合法?

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

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

于 2009-09-10T15:41:58.597 回答