Last modified: 27 October 2011
method or @property?
If you're intending to add a new `property` to a Model (User, UserExercise, Exercise, etc) you should almost never make it a @property. If you're still thinking, "this feels like it should be a property, it's something that i want access to and i don't feel like using parens to get to it" then keep the following in mind:
properties should be fast. i.e. something trivial. if we had a model for an american oven that we were trying to internationalize:
do this! this is good; a property at its finest! it's a dumb transformation on the existing property. it happens quickly. it does math which takes no time at all. You could also have some ridiculous property like
Do this too! (if you really feel it's necessary, i mean, i don't know your life)
but if you're thinking
Then no! NO! red flag! no! NO!
And the reason is that whatever the hell magic is happening in Ovens.all() is likely non-trivial and it will take time. But you say "it doesn't take long when i run the query, i even @cached it. To which we respond: but, monsieur! each time a single Oven is serialized, it has to run that Ovens.all() query, or even hit memcached (if we're lucky). And as the number of ovens increases... that will take longer and longer.
And then you promptly remove the @property and we all go out and have an ambiguously alcoholic beverage (or not, i mean, i don't know if that's something you're into or not. at least not yet)
So why do i want a method there?
The reason is that methods only get run when called. They are like Lazy Properties at least as far as appengine is concerned. This means that unless you have some pressing need for the @property's value to be saved in the datastore, you can almost always make it a method call instead. If, for example, you had some api endpoint that relied on the value of the property, you could write some wrapper to cache the results of the property for whenever the endpoint uses it, but you almost never want to have that serialized in the object.
Here's a better example than the contrived oven. Suppose you have some Model which is called Fib(). Just remember this: Each time we serialize a Fib object, all the properties get evaluated.
In this example, having the @property fib_bignum() may seem like a good idea but what ends up happening is that each time we serialize a Fib object, fib_bignum gets evaluated which means that, even though it probably doesn't take that long it still takes non-constant time (especially since my implementation is probably naïve.) You should generally assume that numerical and most string operations take zero time but that things that run random queries and recursive magic take creepy amounts of time.