松耦合与信息隐藏和易于更改

发布于 2024-07-10 00:38:06 字数 1449 浏览 5 评论 0原文

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

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

发布评论

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

评论(10

烟─花易冷 2024-07-17 00:38:06

我在你的参数 2 中看到的问题是

  1. 你假设每个需要的值都来自 Employee 实例。 这绝不总是正确的。 例如,假设您必须考虑公司的财务状况来计算给予任何员工多少“奖金假期”。 您是否会将财务状态信息添加到员工类别中以避免更改签名?

  2. 更改签名不一定“更难”,尤其是在当今的工具中,单击按钮即可突出显示每个调用位置。

你的第一个论点的主要问题是它并没有像其他人所说的那样破坏封装。 您正在展示什么,而不是如何,这就是封装的意义所在。

The problems I see with your argument number 2 are

  1. you are assuming every needed value comes from an Employee instance. This is by no means always true. For example, say you have to consider the financial state of the company to calculate how much 'bonus holiday' give to any employee. Would you add financial state information to the employee class to avoid changing the signature?

  2. changing a signature is not necessarily "harder", especially so in these days of tools that will highlight every calling place at the click of a button.

And the main problem with your argument number 1 is that it just doesn't break encapsulation as everyone else has said. You are showing the what, not the how, which is what encapsulation is about.

最丧也最甜 2024-07-17 00:38:06

最终松散的耦合获胜。 从高耦合到低耦合,有各种不同的耦合类别:

  1. 内容耦合(高):一个模块修改或依赖于
    另一个模块的内部运作
  2. 公共耦合:两个模块共享相同的全局数据(例如全局数据)
    多变的)。 更改共享
    资源意味着改变所有
    使用它的模块。
  3. 外部耦合:两个模块共享外部施加的数据
    格式、通信协议或
    设备接口。
  4. 控制耦合:一个模块控制另一个模块的逻辑,通过
    向其传递有关做什么的信息
    (例如传递“做什么”标志)。
  5. 邮票耦合(数据结构耦合):当模块共享复合数据结构并使用时
    只是其中的一部分,可能是
    不同的部分(例如传递一个整体
    记录到一个只需要的函数
    其中一个字段)。
  6. 数据耦合:模块通过参数等方式共享数据。
    每个数据都是一个基本部分,并且
    这些是唯一的数据
    共享(例如将整数传递给
    计算平方的函数
    根)。
  7. 消息耦合(低):模块之间不相互依赖
    其他,相反,他们使用公共
    无参数交换接口
    消息(或事件,请参阅 消息
    通过
    )。
  8. 无耦合:模块之间根本不通信。

传入Employee是Stamp耦合,比Data耦合耦合性更强。 如果您真正考虑修改的方便性,那么低耦合会更好,因为您不必担心不需要的副作用。 假设您要更改Employee 类的结构。 您现在必须检查假期函数的实际实现,以确保它不会破坏数学。

最好的解耦方法是定义一个接口 IHolidayable,但这对于这种情况来说有点过分了。

Ultimately loose coupling wins. From high coupling to low, there are various classes of coupling:

  1. Content coupling (high): One module modifies or relies on the
    internal workings of another module
  2. Common coupling: two modules share the same global data (e.g. a global
    variable). Changing the shared
    resource implies changing all the
    modules using it.
  3. External coupling: two modules share an externally imposed data
    format, communication protocol, or
    device interface.
  4. Control coupling: one module controlling the logic of another, by
    passing it information on what to do
    (e.g. passing a what-to-do flag).
  5. Stamp coupling (Data-structured coupling): when modules share a composite data structure and use
    only a part of it, possibly a
    different part (e.g. passing a whole
    record to a function which only needs
    one field of it).
  6. Data coupling: when modules share data through, for example, parameters.
    Each datum is an elementary piece, and
    these are the only data which are
    shared (e.g. passing an integer to a
    function which computes a square
    root).
  7. Message coupling (low): Modules are not dependent on each
    other, instead they use a public
    interface to exchange parameter-less
    messages (or events, see Message
    passing
    ).
  8. No coupling: Modules do not communicate at all with one another.

Passing in Employee is Stamp coupling, which is more coupled than Data coupling. If you really think about the ease of modification, low coupling is better because you have less to worry about the unwanted side effects. Suppose you want to change the structure of the Employee class. You now have to check the actual implementation of the holidays function to make sure that it doesn't break the math.

The best most decoupled way is to define an interface IHolidayable, but that's an overkill for this situation.

一腔孤↑勇 2024-07-17 00:38:06

对我来说,“正确”的答案归结为您在创建此函数时是定义高级 API 还是低级 API。 对于任何特定情况,低级 API 将灵活性置于便利性之上,并支持 intholidays(Date entryDate, Number sales)
。 高级 API 旨在为客户提供尽可能多的便利,做好一件事。 这支持 intholidays(Employee emp),因为它在调用者方面需要较少的样板文件(从 Employee 类中提取日期和销售额)并且不那么冗长。

To me the "right" answer boils down to whether you're defining a high-level or low-level API when creating this function. A low-level API puts flexibility above convenience for any particular case and argues for int holidays(Date entryDate, Number sales)
. A high-level API is designed to do one thing well with as much convenience as possible for the client. This argues for int holidays(Employee emp) because it requires less boilerplate on the caller's part (extracting the date and sales from the Employee class) and is less verbose.

隔纱相望 2024-07-17 00:38:06

1)提供参数不会破坏封装。 它只是说明这些参数是用来计算假期的。 “如何”仍然隐藏在方法内部。

2) Holiday 方法不应该是 Employee 类的一部分。

1) Providing parameters doesn't break encapsulation. It just shows that these parameters are used to calculate holidays. The "HOW" is still hidden inside the method.

2) Holiday method should not be a part of Employee class.

九命猫 2024-07-17 00:38:06
int holidays(Employee emp)

在这种情况下,只有员工可以使用相关功能......

int holidays(Employee emp)

In this case only an employee can use the function in question...

森罗 2024-07-17 00:38:06
  1. 这并没有破坏封装。 打破封装将揭示它用来计算假期的内部方法。 提供启动参数就是定义 API 的内容。

  2. 可以改进 API 以允许此类更改 - 但是,大多数方法建议您应该进行设计以满足当前的要求,而不是针对不可预见的更改进行过度设计(为更改而设计,但不要尝试预测更改) 。 最好现在实现您需要的内容,并在必要时进行重构。

    可以

在我看来,最好通过尽可能多的解耦和封装来规划变更,以便尽可能轻松地进行重构。 试图提前预测每种可能的情况最终会导致系统设计过度臃肿。

  1. This is not breaking encapsulation. Breaking encapsulation would be revealing the internal methods it uses to calculate the holidays. Providing the starting parameters is what defines the API.

  2. The API could be improved to allow such changes - however, most approaches suggest that you should design to meet the requirements have currently and not to over design for unforeseen changes (design for change, but do not try to predict the change). It's better to implement what you need now and refactor later if necessary.

In my opinion it's best to plan for change by decoupling and encapsulating as much as possible so that refactoring could be done as easily as possible. Attempting to predict ahead of time every possible scenario ends up with a bloated over-designed system.

好听的两个字的网名 2024-07-17 00:38:06

我想说松耦合的主要好处之一是易于更改。 松散耦合的类型可以彼此独立地改变,所以我不明白你在问题中的“vs”。

此外,我不会说您通过为方法提供参数来破坏封装。 您可以随意实现 Sum(int a, int b) - 但您必须告诉我(作为用户)您期望两个数字。

I would say that one of the major benefits of loose coupling is the ease of change. Loosely coupled types can change independently of each other so I don't understand your "vs" in the question.

Additionally, I would not say that you break encapsulation by providing parameters for the method. You can implement a Sum(int a, int b) anyway you want - but you have to tell me (as the user) that you expect two numbers.

初与友歌 2024-07-17 00:38:06

与其他一些帖子不同,我同意你的观点,这打破了封装。 不是类的封装,而是计算假期概念的封装。 如果您想在将来更改此计算的工作方式,并且仍然避免紧密耦合,我建议将 Employee 设为一个接口。 如果这仍然与 Employee 耦合太紧密,因为您认为可能需要为其他事情计算假期,那么您可以拥有一个 Employee 继承的 GetsHolidays 接口。

当然,您选择的解决方案的复杂程度应该取决于您认为耦合和封装问题的严重程度。 我认为这两种原始解决方案在许多情况下都是可以接受的,如果可能的话保持简单。

Unlike some other posts i agree with you that this breaks encapsulation. Not the encapsulation of a class, but of the concept of calculating holidays. If you want to change how this calculation works in the future, and still avoid tight coupling, i would suggest making Employee an interface. If this is still too tightly coupled to Employee because you think holidays might need to be calculated for other things, then you could have a GetsHolidays interface from which Employee inherits.

Of course, how involved the solution you choose is should depend on how serious you consider the coupling and encapsulation problems to be. I would consider both the original solutions to be acceptable in many situations, keep it simple if possible.

烟酉 2024-07-17 00:38:06

最好的解耦方式是定义一个接口IHolidayable

这种笼统的声明真的让我很恼火。 仅仅因为您使用接口并不意味着您会自动解耦任何东西。 如果您的员工类实现了一个计算假期的接口,则任何调用该方法的代码仍然会调用相同的方法。 在最坏的情况下,调用代码将通过直接访问雇员对象而不是 IHolidayable 接口引用来实现这一点,在这种情况下,您只会使情况变得更糟(因为现在接口和任何类之间存在更微妙的耦合)实施它)。

接口确实可以帮助解耦,但它们不会自动这样做,即使它们这样做,它们也不一定是比抽象(或其他祖先)类更好的解决方案。

The best most decoupled way is to define an interface IHolidayable

This sort of blanket statement really annoys me. Just because you use an interface does NOT mean you automatically decouple anything. If your employee class implements an interface to calculate holidays, any code that calls the method, still calls the same method. At worst, the calling code will do that by direct access to an employee object, not an IHolidayable interface reference, in which case you have only made the situation worse (because there is now also a more subtle coupling between the interface and any classes which implement it).

Interfaces can indeed help with decoupling, but they do not automatically do so, and even when they do, they are not necessarily a better solution than an abstract (or some other ancestor) class.

云胡 2024-07-17 00:38:06
int holidays (IHolidayInfo obj)

可能是一种方法。 在这种情况下,任何实现 IHolidayInfo 的对象都可以使用“holidays”函数。 只是一个替代方案。

int holidays (IHolidayInfo obj)

Is might be a way. In this case, any object that implements IHolidayInfo would able to use "holidays" function. Just an alternative.

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