« November 2005 | Main | January 2006 »

December 2005 Archives

December 2, 2005

MulleEOF - Augmentation Style Programming II

Sorry for the delay, but I wasn't feeling well this week at all.

Let me come back to the entityName thing and ramble on that theme a bit more. An object store is expected to provide a finite number of objects (otherwise it would be an object factory). So with a qualifier you run a filter on the store to select a number of objects that match that criterion and with entityName you specify some other criterion that carves out a subset of those qualified objects. Because of the intermingling of entityName with EOClassDescription at the conceptual level of the object store you have a good idea that entityName is in some fairly direct way, related to a class.

The problem with this is, that looking at the dependencies of Structure and Progress you see, that MulleEOFoundation and MulleEOEntityConcept have no notion of an object store and no concept of EOClassDescription. What is an entityName is narrowed down by it's usage in EOClassDescription, that it has some relationship to the class system.

To belabor the point, lets look at EOModel and pick out some similarities with the entityName business. I think this will go to four installments...

An EOModel and it's constituent clases (EOEntity, EOAttribute...) serves two purposes. It is used to create EOClassDescriptions with its attributes and relationships (name based for key-value coding). It also maps the Foundation data types to an external representation. And that external representation is detailed in the constituent classes also. The semantics behind the external representation do not necessarily have to be defined by an EOAdaptor but in all likelihood will be. The link from the model to the adaptor is the adaptorName and doesn't that sound a little familiar, entityName, adaptorName ?

Progress is slow, but I promise this will get interesting next or the-one-after-that the latest :)

December 5, 2005

MulleEOF - Augmentation Style Programming III

As I tried to outline in my previous entries, it can be useful to layout your frameworks, so that a base framework supplies a class and base functionality and a frameworks that is loaded on top of that augments that class with the functionality it needs. A classic example in the original EOF would be that EOAccess adds the entity method to the class EOGenericRecord that is defined in EOControl. EOGenericRecord is an interesting topic by itself, but I am not gonna touch it :) So the original EOF already did augmentation a bit and MulleEOF with its finer granularity of frameworks uses it much more, but runs into problems.

Adding functionality using Categories is nothing new and usually unproblematic, except when you need to add a instance variable. In that case you have a problem, because the category can't add do that.

So if you take a look at the Structure and Progress and if you know that EOFetchSpecification is defined in MulleEOFoundation you can see a problem, because entityName as a concept isn't known in that framework. It is defined later in MulleEOEntityConcept . If I define NSString *_entityName; in the header of MulleEOFoundation, then I might as well code the accessors and methods for entityName and the whole raison d'etre of the MulleEOEntityConcept is gone.

  • I could do a workaround in declaring a special variable void *reserved; and try to pretend that I don't what it's going to be used for later, but I am not too fond of this make pretend programming style. Currently I have entityName declared in the heade for EOFetchSpecification but not the methods...

    There are two ways to look at this.

    One is to say: OK, the code is trying to tell me something! The framework MulleEOEntityConcept is a stupid idea and the idea of augmentation is fundamentally broken. There is a reason subclasses exist and I should be using them. This is just not very Foundation like though, which tries to minimize the number of class names one has to remember.

    From a different vantage point it would appear, that Objective-C is limited in that respect and could provide that functionality to not only augment methods but also instance variables to existing classes. And I will brainstorm on that a little bit in the final part.

  • December 24, 2005

    MulleEOF - Augmentation Style Programming IV

    The conclusion to the issue I verbosely circled around in the last three entries of this weblog.

    In the first three parts, I wanted to show how it would be nice for a library writer to have the possibility to extend a class with instance variables. The language Objective-C itself offers no support for that.

    A solution on the language level isn't easy, and the problem is somewhat similiar to that posed by multiple inheritance. How to order and access the instance variables ? As the category load order is determined at runtime, this can't be solved at compile time or link time at all. The compiler can only assume, that this category is the only category adding instance variables and compile for those instance variable offsets. Everything else has to be done and fixed at runtime. So the runtime linker would have to patch the different offsets into the compiled instructions. If the offset of an augmented instance variable 'x_' was known to be 32 at compile time and an intermediate category introduced two 32 bit instance variable augmentations, every load and store instruction accessing 'x_' would need to have their offsets patched by adding 8.

    That suffices only if the addressing is simple. Since you can do some fairly elaborate arithmetic with offset_of and the like, one would probably need to have an expression evaluator in the runtime linking stage (which brings back fond memories of my first assembler, linker which had just such a feature) ... a major operation, that is unlikely to happen.

    Then there is the problem of different sized instances. If you allocate an instance before an augmenting category is loaded in, its size will be less than of those instances allocated after the load. Access of such a smaller size instance by augmented category methods expecting their added instance variables is of course catastrophic. One could "finalize" a class after it's first alloc, but that restriction takes away from the attractiveness of augmentation. Thinking up some dynamic subclassing scheme is probably fruitless and defeats the idea of categories.

    A cheap alternative

    A cheap alternative to all that complicated runtime trickery is using a NSMutableDictionary either as a container to hold all the instance variables or as a designed-in possiblity to hold the augmented instance variables. Obviously this is a feature that must be thought of ahead of time for classes, that are to be shared - as library classes are wont to be. And predicting the needs of other people is impossible, so you would be tempted to put it in all classes...

    If you hold all instance variables in an NSMutableDictionary style storage scheme, you might enjoy the theoretical advantage of less storage needs, if the instance variables values are mostly nil. Then you would not need to store them in the dictionary at all. It could be tempting to subclass such classes from NSMutableDictionary directly, and why not.
    With the use of NSMutableDictionary I say theoretical, because the overhead of the key/value storage will negate that effect in all but the most unlikely circumstances. One can think of more complicated, yet efficient variations of the NSMutableDictionary method for holding the data (key storage "in" the class, storage in a malloced C-Array) that could actually make good of the promise of reduced storage requirements, but likely wont also.

    Or there could be a designated instance variable of type NSMutableDictionary that is used for the augmentation dictionary. A side effect of this is, that it divides the instance variables into first class and second class citizens. The augmented variables incur a speed penalty relative to the classed instance variables and that may or may not be acceptable.

    Why this doesn't work well

    The main stumbling block is now, that the instance variables can not be initialized during init (and released during dealloc, though when the dictionary goes down, the instance variables will also get their release, but no custom code will run). The problem of patching into init is equally difficult to the problem of adding an instance variable to the class. Overriding init in the category is so obviously a bad idea that I spare myself the pain of writing down the bad effects that would have. Calling an initXXX method from init would defeat the purpose of the augmenting category, as knowledge about that category should not exist in the class.

    So the only solution appears to me, that one would need some sort of NSMutableDictionary style infrastructure to register custom init methods (possibly during +load) of the categories somewhere in a class variable - and since those do not exist in static storage, maintained by some class methods -. Custom code in the init method would then have to call the various init functions. This is quite an elaborate setup. If I weren't in Marocco with no Mac in sight, I might code up an example but I leave that as an exercise to the reader :P

    I am currently as of today not doing any of this, because it feels like too much effort for one or two added instance variables in the whole MulleEOF project.

    Merry Christmas

    About December 2005

    This page contains all entries posted to Nat!'s Web Journal in December 2005. They are listed from oldest to newest.

    November 2005 is the previous archive.

    January 2006 is the next archive.

    Many more can be found on the main index page or by looking through the archives.

    Powered by
    Movable Type 3.34