21

I'm new to the world of iOS and Swift and am working on a new app which I want to use Realm for persistence. I have Entities in my code already which my Services access and populate for an HTTP API endpoint.

Now I want to persist certain Entities and wanted advice as to whether I should create new Realm specific Models for each of my entities to read and write from Realm. Or should I convert all my existing plain Swift Entities to Realm Entities. At first this felt wrong as I would be passing Realm Entities al around my app instead of just in the persistence layer.

However, the alternative is that every time I read/write entities to Realm I need to convert them back and forth from Entities to Realm Entities.

Any advice on the best approach to this?

Thanks

Rob212
  • 315
  • 2
  • 13
  • I would choose those entities that I really want to persist, and make them Realm objects. It is OK and highly desirable to have just realm objects for storing or passing between controllers, etc. – Shripada Jan 22 '16 at 10:33

2 Answers2

38

Both strategies are fine and have their own advantages and disadvantages.

Value Objects + Realm Objects

  • ✅ Value objects are thread-safe
  • ✅ Value objects can be mutated anywhere, without worrying about side-effects
  • ✅ Value objects can be arbitrary defined and allow to use the full possibilities of the language, which allows to workaround constraints given by object persistence mapping
  • ❗️ No lazily-loading, which means the full object hierarchy has to be loaded into memory
  • ❗️ Can't express cycles
  • ❗️ Requires to maintain your model definitions twice
  • ❗️ Needs logic to map from transport encoding (e.g. JSON) to Swift Structs and from those to Realm Objects

Using only Realm Objects

  • ✅ Zero-copy, which means reading from them is less expensive
  • ✅ Live, which means their data is always up to date
  • ✅ Lazily loaded from the database: fewer disk reads
  • ✅ Can express cycles and arbitrary object hierarchies
  • ✅ Define your model in one place
  • ✅ If you can control the transport encoding and you can share naming conventions, you could rely mostly on Realm's integrated Foundation value type mapping logic used by create(_:update:_) and its friends.
  • ✅ Supports KVO, which allow easy integration with some reactive programming frameworks
  • ❗️ Adds constraints to the way how you define your model objects (Some language constructs are not directly supported as enums and require workarounds for now)
  • ❗️ Reference types need more care for mutations to avoid undesirable side-effects, in addition modifications are only possible within write transactions (which should be batched to be as large as possible)
  • ❗️ Realm Objects are not thread-safe

TL;DR

You lose many Realm features when opting out of Realm Objects and will have a hard-time to re-implement them yourselves. Depending on how much you need these and how your use-case looks like, you would buy thread-safety for a high cost.

In the long-term we're working on making Realm objects even easier to use and try to eliminate their disadvantages, so long being aware what those are will be helpful for making a well-informed decision.

marius
  • 7,766
  • 18
  • 30
  • 1
    Thanks for the detailed and very informative response @marius. I'm very keen on having model layer not having any knowledge of the persistence layer therefor I am going to opt for having seperate Realm and model entities. Despite having duplicate models I think this will work best for my current needs. Looking forward to working with Realm. – Rob212 Jan 23 '16 at 12:15
  • 8
    This answer is missing the most critical differences between using Realm objects directly, or via indirect manipulation through value types/proxies. 1) Realm objects are lazily loaded from the database, which means fewer disk reads & less memory copying. 2) Realm objects are zero-copy, which means reading from them is less expensive. 3) Realm objects are "live", which means their data is always up to date. 4) Realm objects have a rich object graph, which would be difficult & expensive to duplicate in memory. tl;dr; you lose many Realm features when opting out of Realm objects – jpsim Apr 18 '16 at 14:22
  • 1
    I think these are some really good points, so I've updated my answer to include them. – marius Apr 18 '16 at 16:25
  • You can use Structify which will automatically convert your structs to ObjectiveC classes: https://github.com/arturdev/Structify – arturdev Feb 11 '19 at 20:57
5

From my point of view, all persistence interaction should be in classes called Store/Repository. If you want to change your database it will affect only Store/Repository classes. I think framework independency for application is more valuable than performance. You can use realm objects in case of performance problems, but i think the case of this situations is very rare.

Mark
  • 701
  • 6
  • 12
  • 1
    Agreed 100%, the last thing you want to do is to let a 3rd party library/dependency to creep into your application domain. I know, for example, that Realm notifications might sound appealing, but then it gets so tightly coupled, that you can hardly change the database. – imilakovic Mar 13 '20 at 09:08
  • 1
    I agree completely. I am maintaining an (Android) app where Realm is so coupled to the business logic that we're taking at least twice the time to develop new features. It takes time, because Realm's "reactiveness" just keeps breaking existing features. Furthermore, in order to truly benefit from Realm, you end up not only coupling entities (extending from Realm Object), but query results too (RealmResults) and even view controllers like RecyclerView adapters (RealmAdapters). If we wanted to swap Realm for another DBMS, it would cost us less to rewrite the entire app. – necavit Mar 25 '20 at 08:56