How to write the best level of data access using Realm

I use Realm in several small projects, and I really like it. I hope to switch to its use in large projects, and I am looking for the best structure for my level of data access.

I came across this similar question and tried to collect the information I found there. The approach discussed there is a DAO pattern, so I took a picture.

This is my model class.

class Chat: Object { dynamic var id: String = "" dynamic var createdAt: Date = Date() dynamic var creatorId: String = "" dynamic var title: String? let chatMessages = List<ChatMessage>() override static func primaryKey() -> String? { return "id" } convenience init(fromJSON json: JSON) { self.init() // ... } } 

Then I created a ChatDAOProtocol to store all the convenient helper methods.

 protocol ChatDAOProtocol { func addMessage(_ message: ChatMessage) func getChatThumbnail() -> UIImage func getParticipants(includingMe: Bool) -> [Participant]? static func getChat(fromId id: String) -> Chat? static func getChat(fromCreatorId id: String) -> Chat? } 

Finally, I created another class called ChatHelper that implemented all of these protocol methods.

 class ChatHelper: ChatDAOProtocol { func addMessage(_ message: ChatMessage) { } func getChatThumbnail() -> UIImage { return UIImage() } func getParticipants(includingMe: Bool) -> [Participant]? { return nil } static func getChat(fromId id: String) -> Chat? { return nil } static func getChat(fromCreatorId id: String) -> Chat? { return nil } } 

This already seems to be better than sprinkling all the database-related code throughout VC and the like. But I still have some doubts.

For example, let's say if I need to get all the chat participants, now I need to call the method in the ChatHelper class. And if I want to get just the chat name, I call the title property of the Chat object itself. Not like a very unified interface. Should I include getters and setters for all properties in the helper. Thus, a Chat object is never called directly (other than instantiation).

or

Should I make the Chat object itself conform to the ChatDAOProtocol protocol? So, are all the convenient methods, as well as properties, directly accessible from the Chat object?

Or is there a better way than both of these?

+5
source share
1 answer

This is a pretty tricky question, because it really depends on how much you want to escape from direct interaction with Realm and how much you want to compromise Realm's performance.

Personally, I think this is great if you abstract the request and write the logic, but still read directly from the objects of the Realm model. If you moved to another database based on objects (for example, main data), then when you reorganize the parent class, these objects belonged to something else (for example, from RLMObject to NSManagedObject ), then how your business logic reads these objects will not change.

One thing that you should definitely be careful about is to abstract the logic in such a way as to use the kingdom very inefficiently.

The main example of this I see in your getParticipants method, you return a standard Swift array. Converting a Realm Results object to this result will result in a search call to each object in memory (as opposed to lazy loading on demand), so you will lose many Realm performance benefits. But since Results objects behave like standard arrays, you won’t need to change your business logic if you return it right away.

Another consideration: if you update one property in an object package, you will be much better off guaranteeing that all objects will be updated in one write transaction, and not a helper class that opens a write transaction every time is called a helper method.

+2
source

Source: https://habr.com/ru/post/1263655/


All Articles