在创建松耦合设计上应该投入多少精力?


10

我目前正在学习设计模式。

我认为大多数人都同意这些模式是很好的工具,但应谨慎使用,而不是所有问题的答案。过多使用它们会使应用程序过于复杂,几乎没有好处。模式应仅在可能是最佳解决方案或有助于创建好的解决方案的地方使用(您同意吗?)。

考虑到这一点:

我正在阅读的书(Head First设计模式)经常强调松散耦合的重要性。这种松散耦合是通过遵循以下原则来实现的,例如“对接口编程,而不是实现”和“封装变化的内容”。

基本上,到目前为止,我学到的大多数模式都主要用于使设计能够松散耦合,从而更加灵活。

我了解松耦合的重要性和好处。

但是我的问题是,一个人应该实际投入多少精力来创建松耦合,灵活的设计?

那些反对设计模式的人说,使用这些模式的成本通常会超过收益。您需要花费大量时间来使用某种模式来创建松耦合的设计,而实际上-松耦合,“编程到接口而不是实现”以及所有这些原理实际上可能并不那么重要。

我想知道的是,我实际上应该在创建附加级别的抽象和设计上付出多少努力,才允许我的应用程序遵循OO原则,例如松散耦合,接口编程等,这真的值得吗?它?我应该为此付出多少努力?


有些人为此付出了一生,例如肯特·贝克(Kent Beck),欣赏它的人会看到您的努力。
Niing

Answers:


14

致命的答案:您做得越多,付出的努力就越少。

基本上,构建松耦合代码并不是很困难。另一方面,训练您的思维来考虑松散耦合。而且,我相信这是完全值得的。

假设您从事一项使用迭代方法进行软件开发的工作,这是过去20年中大多数人所推荐的。您构建的东西可以在迭代1中完美地工作。在迭代2中,您可以在其之上构建,添加一些新功能,并在不适合您的迭代1的情况下稍微弯曲一两个东西。 。现在是迭代3,您会发现需要重新思考基本体系结构的需求。您如何将您的代码拆开并重建,而不必回到第一位呢?

有时候是这样的。很多。它要么使项目运行太晚,要么使每个人都太害怕以至于无法在以后的迭代中完成需要做的事情。在最好的情况下,您会得到一个泥浆大球。松耦合和单责任原则之类的事情可以在很大程度上缓解这些问题。这就是吹捧SOLID原理的原因-它们确实可以提供帮助。

您会发现,在拥有一些松散耦合的设计之后,它就会自然而然地出现。模式是人们发现对他们有用的东西,因此他们记录了它们。它们是有用的工具,随着时间的流逝也自然而然地出现。


5

所需的努力并不总是能告诉您足够的;我认为更好的方法是付出比率。但是弄清楚收益可能并不总是直截了当且没有错误。

要增加灵活性的模式要牢记的一点是,投入这些模式需要付出一定的努力,除非您确切地知道需要它们的原因,否则最终可能会使代码复杂化,但永远不会使用它。如果灵活性从未得到体现,那么它可能就不存在了。

您应该始终做一件事(或尽可能合理地接近它):将软件的各个组件(用于OOP的对象,用于功能或过程编程的功能)放入黑盒。黑匣子是我们不了解或关心的内部(实现)的东西。

如果我们不知道或不关心它是如何工作的,那么我们将不尝试使用除接口之外的任何东西,因此,如果实现在不更改接口的情况下进行了更改,则只在黑匣子内部起作用,而在其外部则没有任何意义会受到影响。这也使对程序的思考变得更加容易,因为您不必将整个程序的每个细节都牢记在心。 您可以合理忘记的细节越多,脑海中就越有可能保留重要的细节。

我认为您误解了对设计模式的反对;我不喜欢它们,但是我非常喜欢松散耦合和对接口编程的原理。我对它们最强烈的反对意见是,将它们作为预包装的解决方案提供,它不鼓励理解它们背后的原理,而是鼓励记忆细节。我不建议您不要研究它们,但是当您这样做时,请记住,了解它们背​​后的原理比任何特定模式的细节都更为重要。

对设计模式的反对之一是它们“很明显”,或者“我在听说它们之前就在使用它们,只是没有用这个名字而已”。人们可以提出这些异议的原因,或者设计模式的发起者可以首先提出这些异议的原因是,他们了解其背后的原理。

使用黑匣子可以合理地组织代码,它们通常不会花费很多(如果有的话);到处使用它们。使用设计模式或其他增加抽象层或使事物复杂化的技术会产生成本。不要仅仅因为它们漂亮,整洁或聪明而使用它们;在适合问题时使用它们,并且值得付出成本才能获得收益。


4

您的问题似乎将松散耦合与设计模式等同起来,但它们实际上是独立的但相关的东西。

松耦合是编程中的基本问题。一旦我们脱离了机器代码,转而使用了符号语言,程序就与它们的执行变得松散耦合。等等。

OO本身基本上是用于创建松耦合组件的模型。封装使对象的内部与其他对象松散耦合。函数编程可能更是如此,因为在极端情况下,函数执行与其他函数的执行是松散耦合的。

几乎根据定义,您所做的任何设计都会涉及松散耦合。还有,你可以安排有东西在不经意间紧耦合的方式,但我只看到那里有人器实际上是一个系统的少数情况下紧密耦合。

(我时不时地与某个人合作,他们希望通过将静态引用嵌入到特定框架工件中来阻止将来的开发人员做出设计选择,从而迫使他们有意使用。但这确实是个例外。大多数设计围绕着为了模块化而分解事物。并在许多情况下重复使用。)


3

模式应仅在可能是最佳解决方案或有助于创建好的解决方案的地方使用(您同意吗?)。

我严格地将设计模式视为实现细节。如果将公共API和程序记录到该文档中,那么通常在哪里拥有设计模式都不会影响(或影响很大)。也就是说,您不要去“我这里有一个桥接模式,我将在它上面实现一个访问者”。相反,它是“此类将在各种操作系统上具有不同的实现,因此将使用桥接模式来实现”。然后,当您使用它时,您对于将其实现为桥接毫不关心-因为您查看的是公共API,而不是桥接模式。

一个人应该实际投入多少精力来创建松耦合,灵活的设计?

遵循简单的规则集即可实现松散耦合。如果您遵守这些原则,那么在编写代码时,您的代码将(或更多)松散地耦合在一起(即,任何工作都已经成为开发过程的一部分)。

规则中(并非详尽的列表):

  • 通过思考(或编写)客户端代码(如何使用该类)来定义接口,而不是通过类来做什么(即为接口设计,而不是实现)
  • “告诉,不要问”
  • 从已经创建的零件构造对象
  • 将要使用的实际对象传递给构造函数(不是成员的工厂,参数的工厂的参数或类似的东西)。
  • DRY(如果有两行在两个地方以相同的顺序出现,请将其提取到单独的函数中,依此类推)。
  • 如果对象的创建是一个更复杂的操作,则将中间部分的创建作为工厂方法/类来实现(即不在构造函数主体中)。
  • YAGNI(根据需要创建事物,而不是之前创建)。

遵循这些规则的方式有所不同,具体取决于语言,团队遵循的开发方法(例如TDD),时间预算约束等。

例如,在Java中,优良作法是将您的接口定义为,interface并在该接口上编写客户端代码(然后用实现类实例化该接口)。

另一方面,在C ++中,您没有接口,因此只能将接口编写为抽象基类。由于在C ++中,只有在对继承有很强的要求时才使用继承(因此避免了不必要的虚函数的开销),因此您可能不会单独定义接口,而仅定义类头。

那些反对设计模式的人说,使用这些模式的成本通常会超过收益。

我认为他们做错了。如果您编写的是松散耦合(和DRY)代码,则将设计模式集成到其中将花费最少的精力。否则,您将不得不修改代码以实现设计模式。

如果您必须进行大量更改才能实现设计模式,那么问题就不在于设计模式-它是您的代码库整体且紧密耦合。这是一个不良/次优的设计问题,而不是设计模式问题。

我想知道的是,我实际上应该在创建附加级别的抽象和设计上付出多少努力,才允许我的应用程序遵循OO原则,例如松散耦合,接口编程等,这真的值得吗?它?我应该为此付出多少努力?

您的问题做出了(未声明的)假设,即松耦合的唯一好处是能够轻松实现设计模式。它不是。

松耦合的优点包括:

  • 重构和重新设计的灵活性
  • 减少浪费的精力
  • 可测性
  • 重用代码的可能性增加
  • 设计简洁
  • 花费在调试器上的时间更少

...还有其他一些我现在不介意的东西。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.