Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!snorkelwacker.mit.edu!bloom-beacon!eru!hagbard!sunic!mcsun!ukc!pyrltd!tetrauk!rick From: rick@tetrauk.UUCP (Rick Jones) Newsgroups: comp.software-eng Subject: Re: Object-oriented system startup Message-ID: <1126@tetrauk.UUCP> Date: 3 Apr 91 16:07:40 GMT References: <12479@pt.cs.cmu.edu> Reply-To: rick@tetrauk.UUCP (Rick Jones) Organization: Tetra Ltd., Maidenhead, UK Lines: 82 In article <12479@pt.cs.cmu.edu> tgl@g.gp.cs.cmu.edu (Tom Lane) writes: >[I got no response to this in comp.object; maybe somebody here can help.] I must have missed it in comp.object! - here are some ideas: >I've run into a system structuring issue that seems like it ought to be >a standard problem with standard solutions in O-O programming. >However, I've never heard anybody address it in my (limited) exposure to >the field. Pointers would be appreciated. > > [ deleted: outline of problem & underlying difficulty in selecting > which object to instantiate ] > >Now here's my problem: how do I set up the initial method-selection >phase so as to preserve modularity? I don't want to have a central >chunk of code that knows the real name of every method in the system >and the conditions for its use; that would be big, ugly, buggy, and a >total failure of modularity. The only other thing I can think of is to >have a list of applicability-test functions, each of which decides >whether its associated method is applicable. This has its own faults, >the main one being that the order in which the functions are tried >could create unexpected interactions. Polymorphism is a wonderful thing, but this is the classic catch - somewhere you have to write the decision code on which of a variety of possible sub-classes to instantiate, and you are likely to end up with a lot of if-then-else stuff or complex switches which doesn't look in the least bit object oriented. I have run into this myself, and the essential things to keep in mind are (a) write only one decision routine for one set of criteria, and (b) encapsulate it. To achieve this, you need an abstract definition of each of the modules for which there will be multiple classes. In a good OOPL - my work is all done in Eiffel - you can define an abstract class which captures the common elements of each module's interface. Most of the routines probably won't be implemented, but some can be, in terms of the deferred, unimplemented ones. The code which uses these modules is all written in terms of the abstract classes. In order to select which version you are going to use, the cleanest approach is to write one or more object-generator classes. These contain functions which will take parameters on which the decisions will be made, and will instantiate the correct sub-type, returning a reference to the created object back to the calling routine. The declared type of the return value is the abstract type, so the routine requesting the object never needs to know what actual type was created. From then on, you just use the object via its abstract interface, and dynamic binding takes care of the rest. By encapsulating the decision code in one place, the whole system is readily extendable. If you need to add another compression routine, you just need a new module for the appropriate method, and another branch in the decision routine in order to create it. >Like I said, this seems like it must be a standard problem: any time you >instantiate particular objects from a large O-O class hierarchy, you have >the question of which subclass to instantiate and where do you put the >decision-making code. Any advice? Well, that's my advice - I hope it helps. >(In case it matters, this will all be coded in vanilla C for portability >reasons. So the "objects" will just be C structs containing function >pointers. I'm not really concerned with hiding representational details >about the image data, only in having a cheap and transparent way of >selecting one of N similar routines at runtime. But I'm not averse to >hearing about solutions that depend on features of real O-O languages; >maybe I can adapt their ideas.) I assume it's clear how you transform this idea into C using structs for the function pointers - you seem to know what you're doing. If portability is an issue, do look at Eiffel. The compiler will generate a highly optimised C source suite for the entire program, complete with run-time support (in source), and a makefile. You can then transfer the package to anything with a C compiler and re-build it. You don't need an Eiffel compiler or any run-time license for the target system. If you wan't to go into more details that would be inappropriate for public discussion, feel free to drop me some email. -- Rick Jones, Tetra Ltd. Maidenhead, Berks, UK rick@tetrauk.uucp Any fool can provide a solution - the problem is to understand the problem