语义耦合(Semantic Coupling)

本文探讨了语义耦合的概念,指出它不同于常规耦合,即使在静态代码分析中看似解耦,但通过交换隐含意义的数据、假设对方完成工作或暗示执行预期代码等方式,仍存在依赖。语义耦合可能导致隐藏的BUG、不利于单元测试和设计上的问题。解决方案包括明确接口、预判状态和避免暗示执行。
摘要由CSDN通过智能技术生成

跟小伙伴一起重构一段 UI,试图将用户界面和业务代码分离的时候,小伙伴试图在业务代码中直接调用 UI。我们当然都知道这会产生耦合,于是小伙伴试图定义一些属性、变量或接口来解决这个耦合。虽然在代码的静态分析中,这一的耦合消失了,但我始终觉得不妥。觉得耦合依然存在,只是不再能被静态分析了。

我想到一个词——“语义耦合(Semantic Coupling)”,搜索发现也有很多小伙伴在关心这个问题。而且,从他们的文章和讨论中,我也了解到更多关于语义耦合的种类和危害。


什么是语义耦合

这是区别于常规意义上的“耦合”而言的。

即类 Foo 依赖于类 Bar,即是常规意义上的耦合。静态代码分析工具就可以为我们发现这种耦合。如果将 Bar 拆开成两个部分,一是类 Bar 的实现本身,另一个是接口 IBar;现在 Foo 依赖的是接口 IBar,那么 Foo 就没有依赖类 Bar了。在静态代码分析工具中就会发现这样的依赖就解除了。

在静态代码分析工具认为没有耦合的情况之下,如果两个类之间还交换带有隐含意义的数据假设对方已为自己完成了某种工作暗示对方执行期望的代码,那么这两个类在语义上还存在着耦合。

我们说耦合的危害是修改一个类的时候,另一个类也需要做对应的修改。显式耦合有工具帮我们做重构时的解耦,而语义上的耦合却很难有准确帮助我们的工具。一些变态的工具(例如 ReSharper)能够帮助我们解决一部分。

哪些代码算作语义耦合

按照上面的定义,语义耦合的概念依然模糊,但都有一个统一的核心——在实现细节上存在依赖,而不是在调用上存在依赖。

交换带有隐含意义的数据

在这段代码中,Bar 依赖于 Foo,他们都依赖于 FooInfo。至少静态代码分析工具是这么认为的。

public class Foo
{
    public void Do(object arg)
    {
        var info = (FooInfo) arg;
        // 后续代码。
    }
}

public 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值