给定Objective-C类MyClass
通过类Connection
与API / Datalayer / external-something进行通信,MyClass
应该(取决于周围的arch)接收和实例应该将构造函数中的Connection
或Connection
的实例传递给需要连接的每个方法调用。这种方式MyClass
可以封装应用程序逻辑,并且不知道连接细节。
要重用MyClass
中不同外部组件的逻辑或单元测试MyClass
,使用协议(ConnectionProtocol
)代替类{{1}是合适的}。这样,只要实现Connection
,就可以将不同的类(例如ConnectionHttp,ConnnectionAPI2,ConnectionTestingEmulateProxyIssue)与MyClass
一起使用。
现在,假设开发人员有一个代码块,该代码块在ConnectionProtocol
,MyClass
中重复,并使用MyOtherClass
执行一系列操作。这违反了DRY原则,因此是不可接受的。
由于ConnectionProtocol
,MyClass
,并且不共享公共基类(NSObject除外),开发人员不能简单地将functionallity合并到基类中。
向MyOtherClass
添加方法会再次违反DRY,因为在ConnectionProtocol
的每个实施中都需要重复功能。
将该方法设为ConnectionProtocol
的{{1}}成员仍然无效,因为
开发人员考虑向NSObject添加一个类别,该类别检查传递的对象是否实现了协议@optional
,然后执行所需的操作。这有缺点:
ConnectionProtocol
使用类别进行了扩展。这不违反DRY原则并尊重SoC。但它违反了Objective-C规范。
ConnectionProtocol
答案 0 :(得分:2)
干旱不是无懈可击的自然法则。在美国大多数州,这甚至都不是重罪。这是一个有用的设计指南,应该与其他有用的设计指导进行权衡,例如简单性和避免SAAAD。我已经看到许多项目变得过于复杂,因为害怕重复几行琐碎的代码。清晰度比简洁更重要。魔术比WET更糟糕。这违反了DRY原则,因此是不可接受的。
也就是说,DRY是一个有用的指导,我认为我们可以在这里适当地加入。
现在,假设开发人员有一个代码块,在MyClass,MyOtherClass中重复,并使用ConnectionProtocol执行一系列操作。
这表明有更高级别的操作独立于实际传输(“重复的代码块......并且使用ConnectionProtocol执行一系列操作”)。这表明你在错误的层面抽象。您有一个较低级别的传输(“HTTP”),并且您有一个更高级别的事物称为“连接”来管理该传输。因此,应该有一个具体的课程Connection
,其中HAS-A <Transport>
和MyClass
将是HAS-A Connection
。
那就是说,创建这个<Transport>
协议我会很慢。我将从包含传输逻辑的Connection
类开始。如果我必须解决的唯一问题是单元测试,我可能只是将Connection
子类化为而不是注入复杂性。如果出现非测试问题,那么我会重构添加额外的层。过早地添加太多层是使代码库过度复杂化的常见方法,而复杂性是强大的敌人,而不是重复自己。
作为旁注:使用类方法打包公共代码的答案也是一种非常合理的方法,对于某些用途可能更简单。
答案 1 :(得分:0)
创建了一个“实用程序类”,ConnectionProtocol
和myParam
将被传递到该实用程序类中。
@implementation ConnectionProtocolAppLogicMethods
+(void)specialMethod:(NSObject*)myParam connection:(id<ConnectionProtocol>)connection
{
// Do Stuff
}
@end