【问题标题】:Coupling between public functions公共功能之间的耦合
【发布时间】:2011-10-07 14:17:58
【问题描述】:

假设我有一个名为 do3() 的函数 为了使该函数工作,我需要执行函数 do1() 和 do2()。

但是,do1() 和 do2() 也可能需要用于其他内容(可能用于 do4())

所有这些功能都是公共的(并且必须是公共的)。

问题,我应该如何实现代码?

选项 1:

function do3() {
    do2()
    do whatever is needed for do3
}

function do2() {
    do1()
    do whatever is needed for do2
}

function do1() {
    do whatever is needed for do1
}

所以如果我调用do3(),我相信一切都会完成,尽管会出现耦合

选项 2

function do3() {
    do whatever is needed for do3
}

function do2() {
    do whatever is needed for do2
}

function do2() {
    do whatever is needed for do1
}

所以当我想调用 do3() 时,我必须这样做

do1()
do2()
do3()

我觉得第二种选择更好,因为它的耦合更少,但是我无法解释为什么,它更像是一种感觉。我认为如果我使用选项一和一天我更改 do2() 我可能会遇到问题。

但是,对于选项 2,我必须确保每次我想使用 do3 时都调用 do1 和 do2。

如果有人有更好的想法(选项 3?)会很棒。

谢谢

【问题讨论】:

  • 我想你可能会找到一本书 (view it online) “基于事件的编程:将事件发挥到极致” 不要只看书名——第一章给出了深刻的描述和减少/转移耦合到较小形式的耦合行为的方法。

标签: oop architecture software-design coupling


【解决方案1】:

耦合是一个与类而不是函数相关的概念。 一个函数应该能够调用它所在的同一类的任何其他函数。 那里没有耦合问题。

你的第一个选项很好,do3调用do2和do2调用do1没有任何问题,只要它们都在同一个类中。

你不应该选择你的选项 2,因为它需要你在任何地方重复代码。

【讨论】:

  • 耦合就是耦合,当然它与类特别相关——但是如果你决定将函数重构为单独的类会发生什么?否则我同意你的看法。
  • 你好。我的错,“函数”实际上是对象中的方法(更具体的 php 对象)。问题是 do1() do2() 和 do3() 可能位于具有不同功能的不同包的不同类中。所以请记住它们属于不同的类,还要记住 do2() 可能被 do6() 和 do8() 调用。
【解决方案2】:

"假设我有一个名为 do3() 的函数 为了工作,我需要执行函数 do1() 和 do2()。 "

Juan:根据您的描述,do3() 依赖于 do1() 和 do2()。 依赖图是

    - ->do2()
do3()
    - ->do1() 

在这种情况下,您应该采用第二种方法。

如果你的依赖图是:

do3()- ->do2() - -> do1()

即

  • do3 依赖于 do2

  • do2 依赖于 do1

在这种情况下,您应该采用第一种方法。

--> : shows the dependency.

【讨论】:

    【解决方案3】:

    简短的回答是,如果 do3() 总是必须继续对 do2/do1 的调用,并且在调用者可能需要在这些调用之间执行某些操作时没有上下文,那么 do2 确实应该包含在 do3 中,依此类推.我还要断言,除非 doX 调用是 API 或其他难以更改的环境的一部分,否则明智的做法是避免将调用“以防万一”分开,以防将来出现需要拆分的情况(谨慎设计的原则)。

    更长的答案: 检验事物真相的一种方法是探索病态病例。将您的第二种选择发挥到极致,基本上需要完全分解功能组合,直至完全消除功能;毕竟,某些函数正在调用 do1() do2() do3() 并因此“耦合”到这些函数。

    [肥皂盒] 静态依赖(耦合)必然是一种恶习,这根本不是一个正确的命题,尽管这个概念现在很流行。静态依赖可能看起来不灵活,但它们也很容易理解、机器可验证和高度优化。为了说明这一点,请考虑以下假设代码:

    person = WebRequest('/GetPerson');
    if (person.Phone.AreaCode = '')
        person.Phone.AreaCode = GetAreaCodeFromZip(person.Zip);
    ...
    

    这样的逻辑可以而且经常被分解成可能的原因:

    requestService = CreationFactory(IRequest);
    requestService.Configure(ConfigurationService.GetConfiguration(requestService));
    requestService.SetEntityContext('Person');
    response = requestService.Invoke();
    entity = EntityService.ProcessEntity(response.Data);
    EntityService.RegisterEntityCorrectionService(entity, IAreaCorrectionService);
    ...
    interface IAreaCorrectionService
    ...
    class AreaCorrectionService : IAreaCorrectionService
    ...
    ServiceFactory.Register(AreaCorrectionService...
    

    我的观点很简单,就是在性能、可读性,甚至是对“解耦”的声明性降低方面都有成本。在考虑控制反转和其他框架时,很少明确考虑这一点。

    【讨论】:

      猜你喜欢
      • 2011-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-30
      • 2021-07-10
      • 2022-10-06
      • 2016-10-11
      相关资源
      最近更新 更多