Hacker News new | past | comments | ask | show | jobs | submit login

KVO is akin to manual memory management - a lot of individual pieces to tweak and remember, and the outcome is very brittle and error-prone.

I prefe the approach where dependant values are expressed as functions, and then a caching layer is added where needs for performance.




How is it "brittle" and "error-prone"? You create your model object and KVO observe its properties from the controller. How much simpler and more decoupled could you get? If you're using MVC correctly, it seems to me that the pieces just naturally fall into place. You also get the benefit of being able to change your model from elsewhere in your program, or even swap it out completely, and have it automatically reflect in your view.

(On the other hand, if your app is not model-based, I can see how it could get unwieldily.)


The promise of simplicity does not match the reality. It's explained well here, this was linked in the article too: http://khanlou.com/2013/12/kvo-considered-harmful/


There are three ways in which it gets brittle:

1. Suppose we have a model object with 10 properties, which you want drawn on screen. Following KVO pattern you would set values for 10 labels during [viewWillAppear], then you would signup for KVO 10 times, then, in handling KVO notification, you would update one of the 10 labels (10 different update code paths), and then you would unsubscribe from KVO in [viewWillDisappear] and/or in [dealloc] also 10 times. Adding a new property, you have to add code in all of these place, and failing even one could have disastrous consequences - inconsistent data display or a crash.

That was a simple example. Now consider a more complex example:

2. Suppose we have a class Person with firstName and lastName. Now if you signup for KVO for both of these, and I perform a legal name change for that person from "Bill Smith" to "Jane Doe", you will receive two notifications. If you're sending out a welcome email, you will end up sending two emails, one of them for nonexistent person "Jane Smith". KVO notifications expose inconsistent data. You could rectify that problem by creating a method for changing both first and last name at the same time and managing notifications carefully, but then all the elegance went out of the window - you're doing your notifications manually.

Now for a really screwed up situation:

3. Suppose we have the Account class with a list of bank transactions. Separately, we have a Person where you display the person's total wealth as result of those transactions. Normally, I would start by computing the account balance each time on demand, but let's say that computing is expensive and we want to persist/cache the result for speed. To keep the Person.wealth up to date we sign up for KVO notifications for Account.transactions and recompute the balance. Now your UI component is hooked to KVO-observe both the list of transactions and the Person.wealth. I post new transaction, and you get two KVO notifications - one for Account.transactions, and one for Person.wealth. But you get them in random order! You might get the Person.wealth notification before transaction notification, or you may get them in the opposite order - exposing inconsistent data (transactions would show the transaction, but wealth will show the old balance because it didn't receive the notification yet). And unlike the example #2, there is nothing we can do to fix this, because the conflicting data is in different classes.


Caching has the reverse problem - needing to figure out when to invalidated the cached data. If only there was a way to ahem observe when the values of the keys the cache depends on change...


Doesn't caching has an equivalent set of pitfalls though?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: