这是在Cocoa Touch Framework中使用令人惊叹的Realm数据库时的代码模式/设计问题。具体来说,一个框架将作为cocoapod分发。
假设我在构建的框架中有一些领域对象
public class Dog: Object {
@objc public private(set) dynamic var name: String?
public let age = RealmOptional<Int>()
public private(set) var owner: Person?
}
public class Person: Object {
@objc public private(set) dynamic var name: String?
public private(set) var dogs = LinkingObjects(fromType: Dog.self, property: "owner")
}
现在,我希望我的框架的使用者能够与这些对象进行交互。我不想用MVVM模式来抽象它们,因为我希望我的框架用户能够利用一些很棒的Realm东西,比如查询,排序,最重要的是,Realm更改通知。
所以,第一个问题。我应该让我的框架用户直接初始化对象吗?他们已经将这些选项与Realm初始化程序一起使用,如果他们选择使用它们,则他们对它们负责。但是,我喜欢使用静态方法来使用工厂模式。像这样:
extension Dog {
public static func retreiveManagedDog() throws -> Dog {
let dog = Dog()
do{
let realm = try Realm()
realm.beginWrite()
realm.add(dog)
try realm.commitWrite()
}catch{
throw error
}
return dog
}
}
这个用例是一个很好的设计模式吗?
其次,下一个问题是更新对象。由于所有Realm对象都必须在写入事务中更新,因此我不希望我的框架用户必须编写一堆样板代码才能更改名称。所以,我写这样的函数:
//MARK: Extension that has functions to update properties
extension Dog {
public func updateName(_ name: String?) throws {
do{
let realm = try Realm()
realm.beginWrite()
self.name = name
try realm.commitWrite()
}catch{
throw error
}
}
}
请注意,我的对象定义仅为此private(set)
。它将有助于强制我的框架用户使用我的setter方法。
总的来说,我试图用这种方式包裹Realm是疯了吗?其他持久存在的优秀框架通常包含所有SQL Lite / Core Data逻辑。我也想提出改善这种模式的建议。
答案 0 :(得分:2)
幸运的是,我认为你的问题没有任何快速正确的答案。这实际上取决于你想要做什么。
首先,不要篡改默认Realm或默认Realm配置,这是个好主意,因为任何直接使用Realm的应用程序都可能会操纵它们。您还需要确保为模型类型命名空间并将其从默认模式中排除。 (同样,您可能只想使用内部定义的模型的模式打开框架的领域。)
至于你的API,它看起来将取决于你想在框架的上下文中使用Realm的内容。
如果Realm是一个实现细节,那么控制用户如何通过API(如上所述的API)与基于Realm的对象进行交互是有意义的。通过这种方式,您可以准确控制用户可以对模型对象执行的操作,并确保不会对其状态变为无效(如果这是一个问题)进行修改。
例如,您可能希望通过您提供的API指定用户在Realm对象上注册和取消注册观察器块,该API指定了自己的前提条件和要求。如果应该观察对象的时间段应该与框架中某个其他对象或系统一致或受其控制,这可能很有用:而不是告诉用户如何存储他们的通知令牌以及何时适当的时间是处理它们,你可以在幕后处理所有这些细节,并确保用户不能在你的框架环境中滥用Realm。
您甚至可以将这种情况发挥到极致,并通过将您的Realm类型与某些协议相符并使您的API消耗并销售该协议类型,从而使Realm对您的用户不可见。这样,您的用户就无法判断您的对象是Realm对象,并且不会想要将它们粘贴在自己的领域,复制它们等等。
但是,如果您希望用户知道您在API中为他们提供Realm对象,甚至可能将他们与他们自己使用的Realm一起使用(例如将它们放在他们自己的Realm中),那么明确地将它们作为Realm对象出售是有意义的,也许使用辅助API,就像你为了方便起见而严格描述的那样。在这种情况下,您想要考虑您的框架对Realm的使用如何避免干扰您的消费者对Realm的使用。