我们有一个类,它既侦听套接字,又根据它读取套接字的内容为自己设置值。我相信这符合SRP。
为了坚持ISP,我们为套接字创建了一个接口(例如。StartListening,StopListening)和另一个接口,它包含从套接字读取的值的只读字段,并修改了我们的类以实现两者。
我们的想法是将ISocketStuff (不是它的真名)传递给需要启动/停止侦听的代码,并将ISocketValues传递到需要知道值的位置。
我在审查一位同事的守则,他有这样的想法:
public interface ISocketStuffAndValues : ISocketStuff, ISocketValues {};
他把它传递给了一个构造师。
这感觉不对,但我想不出有什么理由不这么做。这是为了解决一个棘手的设计问题,他本可以通过ISocketValues的,但他想这么做,我不能告诉他为什么这是一个糟糕的选择。
那么,这是一个糟糕的选择吗?我能给出什么理由来传递ISocketValues而不创建ISocketStuffAndValues呢?
发布于 2013-05-30 16:15:16
您的同事试图减少另一种代码气味;在方法调用中有许多和/或多余的参数。如果您坚持ISP、SRP和DIP,允许将两个接口的不同实现传递到一个需要每个接口的实现的方法中,但是您有一个实现两个接口的类,那么当您调用该方法时,您将传递相同的实例两次,一次作为ISocketStuff,一次作为ISocketValues。你的同事认为这闻起来很难闻(而且他是对的),并对其进行了重构,以便允许一次传递的引用。
它总是一个好主意,而不是盲目地遵循坚实的规则,提醒自己为什么这些规则存在,它们的目的是什么?在ISP的情况下,规则的目的是防止对不消耗正在更改的接口的特定方法的接口的使用者进行更改。但是,如果所有的使用都需要所有的方法,这就清楚地证明了接口的方法是一致的,至少就您的系统而言是这样,并且它们不需要被分割。
因此,对您的问题的正确答案取决于对这个问题的回答: ISocketStuff实现的所有使用者也需要ISocketValues吗?
如果是这样的话,那么您关于这些接口必须是独立接口的断言是没有根据的。如果一个接口的每个实现都实现了另一个,而其中一个的每个使用者同时使用了两个接口,那么如果接口发生变化,那么两个接口的所有实现和使用都会发生变化,因此您在隔离它们时将一无所获。两个接口的成员在单个接口中都具有高度的凝聚力。将两个接口重新连接到实现和使用者使用的子接口中的代码气味是您的红旗,考虑到您的系统需要,您已经过度隔离了它,ISocketStuff应该简单地公开ISocketValues的成员。
如果没有,那么你还有其他的问题。对于一个对象来说,实现多个接口本身并不坏;这是接口存在的原因之一,也是为什么语言规范首先允许实现许多接口的原因之一。但是,在这种情况下,具有单独的套接字侦听责任的对象和负责存储状态/数据值的对象是具有两种责任的两个对象,不应该有单一的共享实现。相反,考虑将ISocketValues的实现变成一个“瘦”数据类( DTO),这个类是由ISocketStuff公开的方法生成的。
ISocketValues可以是廉价的和一次性的,当您需要更新时就可以得到它,然后将它扔掉,或者ISocketValues的实例可以更长时间,并从ISocketStuff接收“实时”更新。哪个更好取决于您喜欢如何使用这两个接口,以及您希望其他对象了解哪些接口。如果大多数或所有使用者都需要基于更新控制侦听器,那么他们需要ISocketStuff;使ISocketValues的实现成为DTO,公开一个工厂方法来生成它们,并将ISocketStuff传递给可以根据需要生成ISocketValues实例的使用者。如果您的使用者只需要数据/状态信息,那么ISocketStuff就太强大了;将这些依赖项注入调用者的ISocketStuff所有者应该生成并将“实时更新”ISocketValues实现传递给消费者,消费者将不再需要知道ISocketStuff的存在。
https://softwareengineering.stackexchange.com/questions/199933
复制相似问题