First, a few thought:
- I made it in a way that I should fairy easy change the Realm db to any other. Because of that this is not the simplest architecht.
- I like to use the Result framework [https://github.com/antitypical/Result], so its heavily build on using that, however its not necessery. I wrap a data and an error object with it, and make that as a result.
- All of the realm operations will go on a dedicated Realm thread.
- The communication between Factorys <-> Managers <-> UI made with callbacks, because of the thread switch. I am not happy with that.
I have a main RealmManager class with static functions. These functions are connected closely to realm, like user registration, login, logout, creating the realm, migrating, connect to the server etc [its not 100% true, because i have connection handlers too but it doesnt matter it this case].
Most of the apps has a user, so lets take that as an example.
I will have a RealmUser model to store the data and a User struct to use it on the UI.
The User can be mapped to RealmUser and RealmUser can be mapped to User too.
I will have a RealmUserFactory: this contains all the CRUD actions, queries etc. Also, in this class i’m switching to the dedicated realm thread too. You can access it, just only in the managers.
I will have a UserManager: this is the class that you can use everywhere. It calls the UserFactory methods, gets the result in a callback then map the data to the stuct and passes back to the caller.
When you call a manager like this, you need to decide if you need to switch to main thread or not - i dont want to go every call result into the main thread, but if i want i will put it here. This result a better code on the UI-s.
So the calls like this:
UI button: getUserByEmail() -> UserManager.getUserByEmail() -> RealmUserFactory.getUserByEmail() -> RealmManager.getCurrentRealm() return Realm() -> RealmUserFactory Query(), returning RealmUser -> UserManager return Map(from: RealmUser, to: User) -> UI writes userdata on screen