The magic of Key Value Coding and Key Value Observing

  • Key Value Coding and Key Value Observing seem just a
    little too magical to me, and I think I understand how
    it all works.  I have been using these techniques for
    a year now, and I find myself using them less and
    less.

    The underlying implementation of Key Value Observing
    uses "isa swizzling".  This is a clever trick enabled
    by the Objective-C runtime.

    Key Value Coding uses Objective-C runtime
    introspection to access instance variables and expands
    on the approach previously/also used to connect
    outlets when loading nib files.

    There is no doubt that KVO and KVC are cleaver.  They
    can be used well for rapid application prototyping.
    They can eliminate many lines of code, and they
    support the larger concepts of "bindings."  They just
    aren't obvious.  Like connections made in Interface
    Builder, there is no intention revealing source code
    that communicates the implementation to other/future
    programmers.  I obviously use connections in Interface
    Builder, and I firmly believe that less code is
    better.  I just can't articulate why I am
    uncomfortable with KVC and KVO when I am comfortable
    with connections in IB.

    I look forward to language support for "properties."
    and hope that they will communicate intention in a way
    that I think is missing from current KVC and KVO.
  • On Aug 30, 2007, at 9:29 PM, Erik Buck wrote:

    > The underlying implementation of Key Value Observing
    > uses "isa swizzling".  This is a clever trick enabled
    > by the Objective-C runtime.
    >
    Well, this is an implementation detail to support "*automatic* KVO".
    All this does is insert invocations of {will,did}ChangeValueForKey
    {before,after} your set accessor method implementation to save you
    having to do so yourself.  If you want the "magic-free" version, then
    just implement manual notification as described in <http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueObserving
    /Concepts/AutoVsManual.html
    >.

    > I just can't articulate why I am uncomfortable with KVC and KVO when
    > I am comfortable with connections in IB.
    >
    Being uncomfortable with KVC is a puzzler.  It's simply providing a
    further level of abstraction.  Would it help if you thought of it in
    terms of using the key to get a selector (NSSelectorFromString --
    (@"key") for valueForKey: and (@"setKey:") for setValue:forKey:)[*]
    which is then used to invoke the corresponding accessor with an
    argument if appropriate?

    I can understand a little more the discomfit KVO might give, since
    it's allowing a loose relationship between objects.  But again there's
    a venerable existing pattern in Cocoa that provides similar
    functionality -- notifications.  With notifications, you simply let
    anyone who's registered an interest know that what they're interested
    in has happened.  And if you're interested in an event, you ask the
    notification centre to let you know if/when it happens.  With KVO,
    it's much the same except that rather than asking a notification
    centre to mediate, you get in touch with the objects directly.  I'm
    sure you're comfortable enough with using notifications... I hope that
    might help?

    > I look forward to language support for "properties."
    > and hope that they will communicate intention in a way
    > that I think is missing from current KVC and KVO.
    >
    The declared properties feature (as described at <http://developer.apple.com/leopard/overview/tools.html>) is orthogonal to KVC.  It is possible to use KVC to access
    properties, and to use properties without ever using KVC.

    A major design goal, however, is precisely to communicate intent (see
    for example the 'readonly' keyword).

    mmalc

    [*] Obviously it's a little more complicated than that, but if it
    helps you sleep at night... :-)
  • > On Aug 30, 2007, at 9:29 PM, Erik Buck wrote:
    >>
    >> I just can't articulate why I am uncomfortable with KVC and KVO
    >> when I am comfortable with connections in IB.
    On Aug 30, 2007, at 10:28 PM, mmalc crawford wrote:
    > Being uncomfortable with KVC is a puzzler.
    >
    ... at least for the reasons you seem to be suggesting.  A common
    complaint is that use of KVC can lead to runtime debugging -- you only
    find out when you launch your app that you misspelled a key.  Some
    people use constants for key names to avoid this issue...

    mmalc
  • On Aug 30, 2007, at 9:29 PM, Erik Buck wrote:

    > I just can't articulate why I am
    > uncomfortable with KVC and KVO when I am comfortable
    > with connections in IB.

    Maybe Alan can help?

    From "The Early History of Smalltalk", by Alan Kay:

    "Object-oriented" Style
    This is probably a good place to comment on the difference between
    what we thought of as OOP-style and the superficial encapsulation
    called "abstact data types" that was just starting to be investigated
    in academic circles. Our early "LISP-pair" definition is an example of
    an abstract data type because it preserves the "field access" and
    "field rebinding" that is the hallmark of a data structure.
    Considerable work in the 60s was concerned with generalizing such
    strcutures [DSP *]. The "official" computer science world started to
    regard Simula as a possible vehicle for defining abstract data types
    (even by one of its inventors [Dahl 1970]), and it formed much of the
    later backbone of ADA. This led to the ubiquitous stack data-type
    example in hundreds of papers. To put it mildly, we were quite amazed
    at this, since to us, what Simula had whispered was something much
    stringer than simply reimplementing a weak and ad hoc idea. What I got
    from Simula was that you could now replace bindings and assignment
    with goals. The last thing you wanted any programmer to do is mess
    with internal state even if presented figuratively. Instead, the
    objects should be presented as site of higher level behaviors more
    appropriate for use as dynamic components.

    Even the way we taught children (cf. ahead) reflected this way of
    looking at objects. Not too surprisingly this approach has
    considerable bearing on the ease of programming, the size of the code
    needed, the integrity of the design, etc. It is unfortunate that much
    of what is called "object-oriented programming" today is simply old
    style programming with fancier constructs. Many programs are loaded
    with "assignment-style" operations now done by more expensive attached
    procedures.

    Where does the special efficiency of object-oriented design come from?
    This is a good question given that it can be viewed as a slightly
    different way to apply procedures to data-structures. Part of the
    effect comes from a much clearer way to represent a complex system.
    Here, the constraints are as useful as the generalities. Four
    techniques used together--persistent state, polymorphism,
    instantiation, and methods-as-goals for the object--account for much
    of the power. None of these require an "object-oriented language" to
    be employed--ALGOL 68 can almost be turned to this style--and OOPL
    merely focuses the designer's mind in a particular fruitful direction.
    However, doing encapsulation right is a commitment not just to
    abstraction of state, but to eliminate state oriented metaphors from
    programming.

    Perhaps the most important principle--again derived from operating
    system architectures--is that when you give someone a structure,
    rarely do you want them to have unlimited priviledges with it. Just
    doing type-matching isn't even close to what's needed. Nor is it
    terribly useful to have some objects protected and others not. Make
    them all first class citizens and protect all.

    I believe that the much smaller size of a good OOP system comes not
    just by being gently forced to come up with a more thought out design.
    I think it also has to do with the "bang per line of code" you can get
    with OOP. The object carries with it a lot of significance and
    intention, its methods suggest the strongest kinds of goals it can
    carry out, its superclasses can add up to much more code-
    frunctionality being invoked than most procedures-on-data-structures.
    Assignment statements--even abstract ones--express very low-level
    goals, and more of them will be needed to get anything done.
    Generally, we don't want the programmer to be messing around with
    state, whether simulated or not. The ability to instantiate an object
    has a considerable effect on code size as well. Another way to think
    of all this is: though the late-binding of automatic storage
    allocations doesn't do anything a programmer can't do, its presence
    leads both to simpler and more powerful code. OOP is a late binding
    strategy for many things and all of them together hold off fragility
    and size explosion much longer than the older methodologies. In other
    words, human programmers aren't Turing machines--and the lesss their
    programming systems require Turing machine techniques the better.
previous month august 2007 next month
MTWTFSS
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
Go to today