29

当我查看 ASP.NET MVC 项目时,我每次都会看到松散耦合架构。

为什么我需要在 Web 架构中进行松散耦合(如果我不进行单元测试)?

这有什么优点缺点

解耦层/类的主要原因是什么?

例如,如果我不想更改我的 DAL 怎么办?我的意思是我什么时候应该改变我的整个 DAL?!所以我可以将我的 DAL 耦合到 UI。这有什么不好?

4

13 回答 13

32

松散耦合允许您在应用程序的一个区域进行更改而不影响其他区域。从理论上讲,它允许您在不重建业务或 UI 层的情况下进行更改数据访问层之类的操作。

它确实使您的应用程序更灵活、更善于更改并且更易于维护(因为您不必担心应用程序的一个区域的更改会破坏另一个区域)。

于 2010-05-19T19:17:42.760 回答
22

对于任何不小的项目,它将为您节省大量时间,我将非常小的定义为少于几千行代码(取决于语言)。

原因是一旦你通过了超级小项目,每次更改或更新都会变得更难,因为它耦合得越紧密。松散耦合使您能够继续前进,添加功能,修复错误等。

在某种程度上,我认为任何程序都成为维护、更新和添加的噩梦。设计越松散耦合,该点被延迟得越远。如果它是紧密耦合的,可能在大约 10,000 行代码之后它变得无法维护,如果不从头开始重写,添加一些功能变得不可能。

松散耦合允许它增长到 1,000,000 - 10,000,000 行代码,同时仍然能够在合理的时间内进行更改和添加新功能。

这些数字并不是从字面上理解的,因为它们只是虚构的,而是为了让人们了解它在哪里变得有用。

如果您从不需要更新程序并且它相当简单,那么可以肯定,紧密耦合是可以的。以这种方式开始甚至是可以的,但知道什么时候应该将东西分开,但是您仍然需要编写松散耦合代码的经验才能知道它在什么时候变得有益。

Enterprise Fizzbuzz是一个故意幽默的例子,它说明了过度工程是如何过度设计的,而且并不是每个项目都需要相同级别的解耦。

MVC 通常被认为是一个很好的起点,因为大多数项目都会变得足够大,以至于它会有所帮助。当项目变得更大时,这种程度的解耦是不够的,M 部分需要自己拆分成几个层,等等。没有万能的,但 MVC 对大多数项目来说是一个很好的解耦。

于 2011-06-28T20:14:57.590 回答
12

在纸面上,松散耦合有很多优点,但在实践中,恕我直言,很难做到正确。以下是一些优点:

  • 系统可以在生命周期方面独立发展。

  • 系统可以用不同的语言编写,并最终在不同的操作系统上运行。

  • 系统可以(并且应该)由不同的团队构建。您可以外包系统的开发。事实上,这几乎是扩展软件开发组织的唯一途径。

不过,这里有一些缺点:

  • 一开始是比较辛苦的,如果做的不好,可能永远也看不到它的好处。

  • 定义 API/合约非常困难,需要非常有经验的开发人员。最初做起来很容易,但从长远来看很难。

  • 松散耦合的泛化实际上会导致到处都是松散类型。除了使用明确定义的有意义的对象外,您可能会观察到“对象”参数或返回类型的使用增加,泛型类型添加到每个类或接口。这样做的坏影响是普通开发人员可能会到处添加狂野的演员操作,假设类型在所谓的松散耦合系统的两侧。

  • 一些松散耦合技术基于接口定义的泛化,目的是避免直接依赖。请记住,一旦定义和发布,界面就应该是一成不变的。现在,这并不是我所说的松散耦合。.NET 类,利用 JIT 和方法重载等技术可以成为更好的松散耦合工具。因此,这些接口和工厂无处不在的问题在于,它将导致类型、程序集、测试用例等的倍增……以及更多的工作和复杂性。与其简化事物,不如构建一个系统,而是构建多个系统。“N 层系统是 N 倍的工作” :-)

  • 松耦合以某种方式绕过了有史以来最强大的工具之一:编译器(C# 或其他)。这实际上就是它的全部目的,但它肯定有一些缺点,因为编译器所做的所有基础工作(类型检查等)都需要在其他地方(测试)完成,这将产生成本。

  • 许多开箱即用的工具可能不再起作用。您将无法使用诸如 Visual Studio“转到定义”或“查找所有引用”之类的东西。

于 2011-06-28T21:45:52.817 回答
8

当您的应用程序需要更改或增长时,松散耦合架构将为您提供帮助。任何非平凡的应用程序最终都需要改变或增长。

如果您使用松散耦合的架构进行设计,那么当需求发生变化时,应该只会影响应用程序的一小部分。对于过于紧密耦合的架构,许多部分都需要更改,并且很难准确地确定哪些部分会受到影响。

在我看来,TDD 的主要好处之一是有助于促进松散耦合的架构。

于 2010-05-19T19:20:42.910 回答
5

我认为其他答案中解释了“正确”的方式。但我现在会根据我自己的经验来写。

在决定架构时,您必须考虑几件事情。

一种。客户

您是否有足够的时间让一切都以“正确”的方式进行(伟大的架构、测试等)?有时客户希望快速看到结果。我们可以抱怨时间短,产品不会达到最高标准,但归根结底是我们的问题。在这种情况下,我们向客户解释他会得到什么,并编写我们都知道的意大利面条代码。

客户的要求是什么(在可靠性、可扩展性、可扩展性、速度方面)?我认为这是不言自明的。有时客户会规定“正确”的方式。我们可以为客户提供“正确”的方式,但最终客户会做出决定(当然取决于时间和金钱)。

系统开发完成后谁来支持?我想支持一个很好的解耦代码。因此,当我编写代码时,我会尽力使其“正确”。有时我可能会将视图和控制器结合起来,或者结合一些服务并对此感到满意。知道我自己的代码很容易支持它。

湾。项目

项目的规模是多少?有些项目非常小,以至于任何复杂的架构都没有必要。

该软件未来是否有机会快速增长(更多功能)?这是最大的挑战之一。但是,如果软件发展壮大,就意味着它是成功的。您可能会有更多的资源可以使用。重构代码并使其“正确”相对容易。

该项目是否可能存在可扩展性问题?就用户和数据而言,有些项目永远不会增长。我见过一些项目试图通过使用 Oracle RAC 数据库设置来看起来很严肃,而一个简单的嵌入式数据库就可以正常工作!

您是开始该项目还是从其他开发人员那里接手?这是由谁将支持该软件以及该软件将发展的问题的组合。您可能会从其他开发人员那里获得意大利面条代码。你会有时间和资源让它“正确”吗?

C。开发小组

团队是否有足够的经验来正确解耦?当我经验不足时,我尝试编写“正确”的代码。而我失败了。关键是要真正了解您的开发团队、他们的技能和知识。不要小看这个问题。当与经验不足的开发人员一起工作时,我通常会在架构上做出一些牺牲。将做出的牺牲是我所拥有的最有根据的猜测。架构中有一些点是可以牺牲的,而有些点是不能牺牲的。通常你之前做出的一个或多个牺牲会回来咬你。

开发人员是否有编写自动测试的经验?仅有自动测试是不够的。它们应该是完整的(尽可能)并且做得正确。如果您的测试很弱,那么您最好根本没有它们。你不会想靠在满是洞的墙上。

结论

我知道我们都想成为专业人士。作为专业人士,我们必须考虑所有事情。我们不能把时间和精力浪费在以“正确”的方式做事上。有时我们必须考虑其他因素(现实)并做出选择。最重要的是忍受它。

于 2011-07-05T09:04:54.960 回答
4

好处:

  • 可扩展性 - 允许您扩展数据库访问层
  • 可交换性 - 例如电子邮件提供商代码
  • 可维护性 - 只需在一处更改代码
  • 易于设置单元测试 - 您可以像数据库一样模拟对象

缺点:

  • 几行额外的代码可能
  • 一些额外的接口类
于 2010-05-19T19:38:47.500 回答
3

首先,您应该编写单元测试;)

假设您最终需要更改底层数据库。如果您的数据访问代码与您的业务逻辑紧密耦合,那么这可能是一项巨大的工作。使用松散耦合的代码,您的业务逻辑将不受影响。

如果您决定要编写一些利用后端组件的命令行实用程序怎么办?使用松散耦合的代码更容易为您的系统提供多个入口点。

于 2010-05-19T19:22:25.400 回答
3

它将为您提供可扩展性。例如,如果您后面有服务层,则可以将其分隔在多个服务器中。此外,您将拥有更少的依赖关系,并且修改会更容易。代码支持也会更容易。

在这里你可以看到有趣的小文章:SOA - Loosely Coupled...What?

不久它说:

松耦合系统提供了许多优势,包括在运行时支持后期或动态绑定到其他组件,并且可以调解组件结构、安全模型、协议和语义方面的差异,从而抽象出易变性......

于 2010-05-19T19:24:01.410 回答
2

因为即使不与基于浏览器的 HTTP Web UI 通信,后面的内容也可能有用。因此,您希望能够将其与该特定 UI 断开连接。

于 2010-05-19T19:18:35.290 回答
2

耦合和解耦合类的主要原因是为了可扩展性。一个人的改变不应该影响另一个人。

如果您构建的应用程序当前正在使用 MYSql 数据库来存储数据。现在我们有了新的要求,将数据存储在 MSSQL 作为他的后端系统。如果您构建与 MYSQL 库更集成的系统,您还剩下什么解决方案。为 MSSQL 重写整个应用程序。现在怎么样 我们基于 MSSQL 构建一个新的 DAL 并将 Dal 插入系统而不对系统 (UI) 进行任何更改。

应用程序正在调用基于接口的例程,并且接口没有实现。

尝试阅读 Unity 或 MEF 这些主题将为您提供很好的见解

于 2011-07-02T21:19:22.147 回答
2

这一切都取决于制作应用程序的意图以及商业利益。如果业务热衷于扩展它并且涉及足够的燃料(读取语料库),这会为架构师提供足够的思考以使应用程序获得长期利益。

所以优点是:-

1)如果您使用第三方控件/代码:始终编写“包装器/适配器层”,以便无论出于何种原因,如果它不可用,您可以获得其他东西并更改适配器层而不会干扰您的应用程序存储库代码。

2)将特定的复杂功能封装在可能需要也可能不需要数据库请求的“服务层”中:这是有益的,因为请求和响应保持不变(它肯定也会随着时间而变化),您始终可以提高性能在不更改输出的情况下使用该特定代码。有了单元案例,我们还可以衡量代码的性能。

3)让特定的角色编写特定的代码:如果我们创建了很多角色,团队中的人更容易专注于他们的特定存储库,而不是迷失在一堆不相关的代码中。

4)专注的质量保证:如果我们有分层架构,它总是有助于改善质量保证作为其重点。

5)查找/解决错误:使用分层架构并假设您有良好的日志记录,它总是可以节省查找错误和解决问题的时间。

缺点是:-

1) 使用这种框架设置应用程序需要额外的时间。所以“上市”会被推迟。

2)如果你太热衷于技术,它可能会以过度杀戮而告终。

3)额外的事务延迟:当数据通过各个层时,每个事务中都会增加额外的延迟。

关于更改 DAL:-

当然,会有一段时间,性能优先于功能,那时您将不得不开始考虑您的数据提供者导致 DAL 发生变化。

如果将 DAL 与 UI 耦合,则每次更改 DAL(如果有的话,如果有的话)总是需要在生产环境中重新发布整个二进制文件。哪个有自己的问题(我回避在这里解释,如果你需要我可以随时包括在内)

这就是原因,最初最好花时间并得出应用程序何时会发生“自毁”的结论。我的意思是应用程序的生命是什么,如果回答得好,那么一切都会到位。

于 2011-07-05T07:15:38.063 回答
1

分工,这是人类的关注点分离等价物。您的 HTML 大师应该能够独立于您的 SQL 女神工作。

前端的巨大变化应该能够在不破坏后端的情况下进行,反之亦然。换句话说,你应该只雇用一个人而不是两个人。

于 2010-05-20T01:05:28.290 回答
0

以别人没有讨论过的角度回应;时间解耦。可以通过以下几种方式完成:

使用上述方法时(除了 async monad),您通常会显式处理消息而不是方法调用。这导致了与消息传递如何工作相关的思考(处理它们的幂等性、用于在传输中存储它们的队列、附加到它们的信封的安全数据、处理程序而不是请求程序中的重试逻辑......)。

通过转向时间上解耦的面向消息的架构,您可以更轻松地扩展应用程序 - 特别是如果您主要进行发布-订阅(另请参阅事件驱动架构) - 任何事情都可以监听事件并对它们做出反应,而您不要将集成器的实现绑定到初始调用站点。

将工作推送到队列的网站通常响应速度更快,因为它们不会让工作线程等待 IO 发生。从长远来看,它们的维护成本通常也更低。

对于不同类型的编译类型耦合(和其他指标),请浏览http://www.ndepend.com/Metrics.aspx并自己阅读一些内容。

于 2011-07-05T17:19:47.490 回答