REALM MODEL CLASSES THE PAST, PRESENT AND FUTURE

1fa9cb8c7997c8c4d3d251fb5e41f749?s=47 Realm
February 20, 2016

REALM MODEL CLASSES THE PAST, PRESENT AND FUTURE

Slides of talk by Emanuele Zattin on Realm meetup #12 in Japan.

1fa9cb8c7997c8c4d3d251fb5e41f749?s=128

Realm

February 20, 2016
Tweet

Transcript

  1. REALM MODEL CLASSES THE PAST, PRESENT AND FUTURE Emanuele Zattin

    - Realm @emanuelez 20-02-2016 - Realm Meetup Tokyo
  2. REALM MODEL CLASSES At the current stage Realm is imposing

    several limitations on how model classes are defined They are POJOs, but not quite, so let's see why
  3. RULES ON THE NAME OF GETTERS AND SETTERS

  4. Getters must me called: > get<FieldName>() > is<FieldName>() is allowed

    for boolean fields Setters must be called: > set<FieldName>()
  5. This limitation usually goes unnoticed because the accessors generated by

    Android Studio follow such rules already!
  6. WHY?

  7. The Java Annotation Processing API does not allow to introspect

    how methods are implemented. This means that right now Realm has to "guess" which methods are accessors for which fields.
  8. ACCESSORS CANNOT CONTAIN ANY LOGIC

  9. Want to validate user input? public void setName(String name) {

    if (name == null) { // handle the case } this.name = name; }
  10. Want to convert or decorate data? public String getName() {

    return "Mr. " + name; }
  11. Right now this is only possible using utility static methods.

    public static boolean isValidName(String name) { return name != null; } public static String getTitledName(Person person) { return "Mr. " + person.getName(); }
  12. WHY?

  13. Realm generates proxy classes for your model classes. > Person

    ⟶ PersonRealmProxy Because of the reason mentioned before Realm cannot replicate your logic in the proxied accessors. This will of course work fine for standalone objects.
  14. NO CUSTOM METHODS ALLOWED

  15. Right now it's not possible to have a method such

    as this one: public String getFullName() { return this.lastName + " " + this.firstName; }
  16. Once again the current workaround consists on static utility methods:

    public static String getFullName(Person person) { return person.getLastName() + " " + person.getFirstName(); }
  17. WHY?

  18. In theory this could be possible if we stated the

    rule that in such methods fields can only be accessed with accessors, but such rule would be hard to enforce and easy to forget, causing many subtle bugs so we decided to disallow it.
  19. NO INTERFACE IMPLEMENTATION ALLOWED

  20. Currently on Realm model classes you cannot do this: public

    class Person extends RealmObject implements Parcelable { // ← ☹ // fields and accessors }
  21. WHY?

  22. This is of course a consequence of the lack of

    support for custom methods.
  23. NO CUSTOM toString() equals() hashCode()

  24. Again, this is currently not possible. public class Person extends

    RealmObject { private String firstName; private int age; // getters & setters public void toString() { return firstName + " is " + age + " years old" } }
  25. WHY?

  26. Again, we could allow this, but decided not to because

    the misuse would be too easy and provoke subtle bugs
  27. THIS IS NOT GOOD ENOUGH!

  28. THE PROBLEM: ANNOTATION PROCESSING IS NOT POWERFUL ENOUGH

  29. THE SOLUTION

  30. BYTECODE WEAVING

  31. In the past few months we have been working on

    a project. Internally it's being called Better Objects
  32. WHAT DOES IT CONSIST OF? Use the Transform API to:

    > add custom accessors to model classes > replace field access with accessors The custom accessors are called: > realmGet$<fieldName> > realmSet$<fieldName>
  33. Public fields? No problem! public class Person extends RealmObject {

    public String name; public int age; }
  34. Accessors with custom names public class Person extends RealmObject {

    private String name; public String thisIsMyNameGetter() { return this.name; } }
  35. Accessors with custom logic public class Person extends RealmObject {

    private String name; public void setName(String name) { if (name == null || name.equals("")) { throw new GreatExceptionOfDoom(); } this.name = name; } }
  36. Custom methods public class Person extends RealmObject { public String

    firstName; public int lastName; public String getFullName() { return this.firstName + " " + this.lastName; } }
  37. Implement interfaces public class Person extends RealmObject implements Parcelable {

    private String name; private int age; // Tedious Parcelable API methods here }
  38. Custom Object methods public class Person extends RealmObject { public

    String name; public int age; public String toString() { return this.name + " is " + this.age + " years old"; } }
  39. !

  40. WHEN???

  41. Currently in the last stages of review. Soon to be

    merged to master and made available as SNAPSHOT
  42. THE FUTURE

  43. ͫΞ͜΀Ο RealmObject?

  44. Currently being discussed as Github issue 2296 github.com/realm/realm-java/pull/2296

  45. THANK YOU!