在Objective-C中实现协议特定的方法

时间:2013-10-15 21:31:33

标签: objective-c

给定Objective-C类MyClass通过类Connection与API / Datalayer / external-something进行通信,MyClass应该(取决于周围的arch)接收和实例应该将构造函数中的ConnectionConnection的实例传递给需要连接的每个方法调用。这种方式MyClass可以封装应用程序逻辑,并且不知道连接细节。

要重用MyClass中不同外部组件的逻辑或单元测试MyClass,使用协议(ConnectionProtocol)代替类{{1}是合适的}。这样,只要实现Connection,就可以将不同的类(例如ConnectionHttp,ConnnectionAPI2,ConnectionTestingEmulateProxyIssue)与MyClass一起使用。

现在,假设开发人员有一个代码块,该代码块在ConnectionProtocolMyClass中重复,并使用MyOtherClass执行一系列操作。这违反了DRY原则,因此是不可接受的。

  1. 由于ConnectionProtocolMyClass,并且不共享公共基类(NSObject除外),开发人员不能简单地将functionallity合并到基类中。

    < / LI>
  2. MyOtherClass添加方法会再次违反DRY,因为在ConnectionProtocol的每个实施中都需要重复功能。

  3. 将该方法设为ConnectionProtocol的{​​{1}}成员仍然无效,因为

    • 该方法经常使用,需要在每个实现中实现
    • 方法逻辑特定于应用程序,而不是违反SoC的连接。
  4. 开发人员考虑向NSObject添加一个类别,该类别检查传递的对象是否实现了协议@optional,然后执行所需的操作。这有缺点:

    • NSObject的方法空间被污染了使用该类别的文件中的所有对象,
    • 错误地调用类别方法的错误会被捕获到运行时,并且开发人员选择强类型语言是出于某种原因
  5. ConnectionProtocol使用类别进行了扩展。这不违反DRY原则并尊重SoC。但它违反了Objective-C规范。

    ConnectionProtocol
  6. 如何在不违反DRY的情况下解决此问题,尊重SoC,并满足Objective-C的限制?

2 个答案:

答案 0 :(得分:2)

  

这违反了DRY原则,因此是不可接受的。

干旱不是无懈可击的自然法则。在美国大多数州,这甚至都不是重罪。这是一个有用的设计指南,应该与其他有用的设计指导进行权衡,例如简单性和避免SAAAD。我已经看到许多项目变得过于复杂,因为害怕重复几行琐碎的代码。清晰度比简洁更重要。魔术比WET更糟糕。

也就是说,DRY是一个有用的指导,我认为我们可以在这里适当地加入。

  

现在,假设开发人员有一个代码块,在MyClass,MyOtherClass中重复,并使用ConnectionProtocol执行一系列操作。

这表明有更高级别的操作独立于实际传输(“重复的代码块......并且使用ConnectionProtocol执行一系列操作”)。这表明你在错误的层面抽象。您有一个较低级别的传输(“HTTP”),并且您有一个更高级别的事物称为“连接”来管理该传输。因此,应该有一个具体的课程Connection,其中HAS-A <Transport>MyClass将是HAS-A Connection

那就是说,创建这个<Transport>协议我会很慢。我将从包含传输逻辑的Connection类开始。如果我必须解决的唯一问题是单元测试,我可能只是将Connection子类化为而不是注入复杂性。如果出现非测试问题,那么我会重构添加额外的层。过早地添加太多层是使代码库过度复杂化的常见方法,而复杂性是强大的敌人,而不是重复自己。

作为旁注:使用类方法打包公共代码的答案也是一种非常合理的方法,对于某些用途可能更简单。

答案 1 :(得分:0)

创建了一个“实用程序类”,ConnectionProtocolmyParam将被传递到该实用程序类中。

@implementation ConnectionProtocolAppLogicMethods

+(void)specialMethod:(NSObject*)myParam connection:(id<ConnectionProtocol>)connection
{
    // Do Stuff
}

@end