Immediacy and the Web and our Toughtful Bad Habits
Yesterday while working on a project, I found myself in a muddle. I had been operating under a self imposed constraint to use classical inheritance for everything in the system. The reason for this constraint was largely one of ease of understanding for the people who I need to impress with the demo. I was already walking on dangerous ground, cooking up a "feast for thought", and didn't want to confuse the issue further. This self imposed constraint meant that:
- a prototype object (née class) must be created for each kind of thing
- a class must be pluggable enough so that different instances can do different things
- instances must be created for each element & initialized with the correct behavior
Ostensibly the purpose of this system is "reuse", but the real goal of this system is classification. If things that shared behavior have a common base class, the theory goes, we can reason about those two entities as being equivalent for a certain domain. Two images, a jpg and a png, are equivalent, as long as we limit our reasoning to all actions common to all images. This in a specific academic sense turns into a very powerful tool for unlocking all sorts of categorical logic.
Now in reality in the project I'm building, there is only 1 instance of 1 class in any 1 context. Additionally, there is only one class that is ever instantiated twice, and it is so hooked with per instance overrides that that class might as well be two different ones (the code would be 20% smaller!). So since the objects in the interface have a 1-1 correspondence with the unique behaviors of the system, and each object has infinite extent (within the context of the running application). Classical inheritance provides no tangible benefit, and produces a more fragile system.
This last claim can be understood in terms of the number of overridden behaviors and the number of points that must be corrected when a change occurs to the structure ofthe system. Since each class method depends upon state information embodied in the instance to negotiate any instance specific behavior, the class object must understand and modify the instance object's structure. Now normally modifying an object's internal state would break encapsulation, but a special exception is made for class objects and called inheritance. This is really what we are saying when we say "extends", we really means "allows full access to". This generally works fine as long as you always build behavior up from the base class, never modify a base class, and never depend on anything other than class methods for behavior. If an object is based on a class with many hooks, each of the delegation points provide opportunities for runtime extension of behavior, and by extension run time permission grants to arbitrary code.