Slide 1

Slide 1 text

REALM MODEL CLASSES THE PAST, PRESENT AND FUTURE Emanuele Zattin - Realm @emanuelez 20-02-2016 - Realm Meetup Tokyo

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

RULES ON THE NAME OF GETTERS AND SETTERS

Slide 4

Slide 4 text

Getters must me called: > get() > is() is allowed for boolean fields Setters must be called: > set()

Slide 5

Slide 5 text

This limitation usually goes unnoticed because the accessors generated by Android Studio follow such rules already!

Slide 6

Slide 6 text

WHY?

Slide 7

Slide 7 text

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.

Slide 8

Slide 8 text

ACCESSORS CANNOT CONTAIN ANY LOGIC

Slide 9

Slide 9 text

Want to validate user input? public void setName(String name) { if (name == null) { // handle the case } this.name = name; }

Slide 10

Slide 10 text

Want to convert or decorate data? public String getName() { return "Mr. " + name; }

Slide 11

Slide 11 text

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(); }

Slide 12

Slide 12 text

WHY?

Slide 13

Slide 13 text

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.

Slide 14

Slide 14 text

NO CUSTOM METHODS ALLOWED

Slide 15

Slide 15 text

Right now it's not possible to have a method such as this one: public String getFullName() { return this.lastName + " " + this.firstName; }

Slide 16

Slide 16 text

Once again the current workaround consists on static utility methods: public static String getFullName(Person person) { return person.getLastName() + " " + person.getFirstName(); }

Slide 17

Slide 17 text

WHY?

Slide 18

Slide 18 text

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.

Slide 19

Slide 19 text

NO INTERFACE IMPLEMENTATION ALLOWED

Slide 20

Slide 20 text

Currently on Realm model classes you cannot do this: public class Person extends RealmObject implements Parcelable { // ← ☹ // fields and accessors }

Slide 21

Slide 21 text

WHY?

Slide 22

Slide 22 text

This is of course a consequence of the lack of support for custom methods.

Slide 23

Slide 23 text

NO CUSTOM toString() equals() hashCode()

Slide 24

Slide 24 text

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" } }

Slide 25

Slide 25 text

WHY?

Slide 26

Slide 26 text

Again, we could allow this, but decided not to because the misuse would be too easy and provoke subtle bugs

Slide 27

Slide 27 text

THIS IS NOT GOOD ENOUGH!

Slide 28

Slide 28 text

THE PROBLEM: ANNOTATION PROCESSING IS NOT POWERFUL ENOUGH

Slide 29

Slide 29 text

THE SOLUTION

Slide 30

Slide 30 text

BYTECODE WEAVING

Slide 31

Slide 31 text

In the past few months we have been working on a project. Internally it's being called Better Objects

Slide 32

Slide 32 text

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$ > realmSet$

Slide 33

Slide 33 text

Public fields? No problem! public class Person extends RealmObject { public String name; public int age; }

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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; } }

Slide 36

Slide 36 text

Custom methods public class Person extends RealmObject { public String firstName; public int lastName; public String getFullName() { return this.firstName + " " + this.lastName; } }

Slide 37

Slide 37 text

Implement interfaces public class Person extends RealmObject implements Parcelable { private String name; private int age; // Tedious Parcelable API methods here }

Slide 38

Slide 38 text

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"; } }

Slide 39

Slide 39 text

!

Slide 40

Slide 40 text

WHEN???

Slide 41

Slide 41 text

Currently in the last stages of review. Soon to be merged to master and made available as SNAPSHOT

Slide 42

Slide 42 text

THE FUTURE

Slide 43

Slide 43 text

ͫΞ͜΀Ο RealmObject?

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

THANK YOU!