Showing posts with label polymorphism. Show all posts
Showing posts with label polymorphism. Show all posts

Thursday, February 7, 2008

Is there anything left after all the roles are stripped away?

While reading Looking at Philosophy[1], I came across its discussion of Kierkegaard saying that there is some existential being that is left when all the "roles" of that being are stripped away.  With my advocation in Existential Programming that "roles" be promoted over "is-a subclassing", it begs a deep question. If we have factored out all state and behavior from a class, moving them into various roles, when do we know that it is time to create a new instance of a "thing" to which roles will be attached?


For example, in a language like Javascript, one can create an empty object instance and dynamically add in attributes and methods later.  This capability can be used to implement "mixin" classes that each encapsulate the properties and behavior associated with some role.
While it is true that we can program the operations of instantiating an empty (i.e. essence-less) object and graft in the mixin classes for each role we expect to fulfill, the Philosophical question is, how could we know that a new blank instance is needed if we didn't have a particular "thing" in mind in the first place? I.E. doesn't a thing still have to start as a particular "kind" of thing in order to know when it is time to create a new one? 
In still other words, is there an actual case of a "thing" that consists only of roles? Are we sure that one of those roles isn't a thing itself?  Does the technology give us the capability to do something that makes no ontological sense?

[1] "Looking At Philosophy: The Unbearable Heaviness of Philosophy Made Lighter",2005, Palmer

Monday, June 11, 2007

Different orders of Polymorphism

When most computer science texts refer to polymorphism (in the context of object oriented programming) they are referring to either refining the implementation of a method via subclasses overriding that method, OR, by defining more than one behavior (method) with the same name. The former case (hopefully) preserves the semantics of the method name, the latter overloads multiple semantics on the same name. In either case, it is only the method that is multifaceted, not the entire object much less the class hierarchy.

With Existential Programming, a different order of polymorphism (i.e. "a single entity can take on multiple forms") is at work. Here a single entity in its entirety can take on multiple forms. Heck, it can take on multiple ontologies (aka class hierarchies). This means either supporting multiple (albeit, fundamentally similar) views/conceptions of an entity, OR, trying to knit together very different models where the object instance is in some sort of oscillating
Schrodinger's Cat-like state (except that we can look at it and not affect its state :-).

Friday, April 13, 2007

Don't confuse (OOP) Objects with Entities

AHA! (OOP language) Classes are too general to think of as synonymous with (Philosophical) Entities! OOP classes/objects can represent roles, or values of properties (e.g. Red), or PropertyTypes (e.g. Color), NONE OF WHICH are Entities. SO, the "isA" relationship between a superClass and its subClasses is not always analogous with the "isA" relationship between an Entity and the collection of Entities constituting an entityType.

"Red isA Color" is different than "Joe isA Human" or "Human isA Mammal".
 Red is not an entity, Joe is and a Human is. Why? Red is not countable and not distinguishable from another "instance" of red; Joe, humans, and mammals are. [Ed. note: this intuition will later be recognized as the problem of universals as the author reads more books. ;-) ]

With "domain objects" (aka "business objects") being roughly equivalent to philosophical entities, it is dawning on the IT industry (e.g. POJOs, "domain driven development") that there are at least 2 kinds of classes/objects: "domain" and "non-domain".  There are wildly different ideas of what "non-domain" classes are, but they generally are meant to include all that programming implementation logic kind of stuff rather than the direct modeling of the world.

The main point here (and the AHA moment), is recognizing that lots of confusion about how to divide a problem into programming language classes (along with what logic goes into their "equals" methods) boils down to a lack of understanding about first philosophy concepts of entities, universals, etc.  We programmers confuse the ability of programming languages to implement everything as a class/object with the idea that down deep everything is the same kind of thing.
Philosophy would say that red is fundamentally different than Fred, and both are fundamentally different than a "process" (i.e. an OO method) or an "event" (i.e. an OO "message").

Saturday, October 7, 2006

Post Facto Polymorphism

Post Facto Polymorphism ®☺ is the Existential Programming technique of mapping an abstraction (defined after the fact of creating actual object instances or relational database entities or semantic network relations) to multiple preexisting ontologies (i.e. class/type definitions).

For example, suppose that there were several data sources that held data (specifically names) about "people", and these data sources were culturally specific. A typical European ontology/DB-schema might define 3 fields: firstName, middleName, lastName. A Native American oriented database might define a single Name field. An Asian database might have a familyName and a childName field. Yet another ethnic database encoded names into the European schema but understood that
firstName was the "family name" for its data rather than lastName. If we wish to consolidate these data sources and define (after the fact) a new abstraction to work with all of them, we can use the external abstraction technique to adapt each of these apples and oranges to all be "fruit".

An AbstractName interface could be defined, and adapters defined for each "concrete class" that implement the mapping between that class' name-related properties and the
properties of AbstractName. By having objects be "existential", thus allowing mixin adapter code to be dynamically added, the objects can all be accessed via the getFamilyName() and getTheNamePeopleCallMe() methods defined by AbstractName.

Of course, all this support for "cleaning up" data via external abstraction should not lessen the pressure to clean up the source data as much as possible (by which I mean cleaning up the schema and entity definitions more than the data itself). Otherwise, multiple "bad" data sources, each having their own classes/interfaces/source-of-record IDs/"package IDs", would need to be specified when referencing data in order to disambiguate which data source is desired. By cleaning up the schemas (to make the semantics more well-defined), fewer explicit "package ID" references are required
, and one's code is much simpler/cleaner.

External Abstractions, Existential Classes, Object Views

Traditionally, object oriented modeling proceeds "top down" in that classes/interfaces are defined first and then instances (i.e. "objects") are created. Essence Precedes Existence. The objects consist of the class-defined attribute set, the whole class-defined attribute set, and nothing but the class-defined attribute set!

In Existential Programming, the developer can define "bottom up" classes/interfaces where, after the fact, attributes can be chosen from existing ones, or new "computed" attributes can be added. Existence Precedes Essence. This is very similar to the database concept of "view" where some subset of columns can be dealt with as if they were their own table/entity. These views can also add "computed" or "joined" columns thus supporting the philosophy that there is a fine (or non-existent) line between "behavior" and "data". They are all just properties, and it is inside the black box that the details exist of what was required to get or set that property (using Java-speak).

A difference between this object view idea and normal interfaces is that the interface declaring a method has to be defined before the class that implements it is defined, which in turn is before an object (based on that class definition) is created. With a view, an object could be "cast" to some defined-after-object-creation interface, as long as that object had the methods/properties that the view expected. Otherwise, potentially a cast-exception could be thrown (or, it could just let you work with any methods that *did* match). Of course, with Existential Programming, all "interfaces" and "classes" are the same as "views". There is no single "real" version of an object/entity with other versions just "views". This is different from database views where down deep there IS a "real" table (or several if the view was really a "join"). With Existential Programming's strategy of using EAV structure for persistence, all entity definitions / classes / interfaces are "views".

This sort of thing is done with dynamic languages like JavaScript and is called "duck typing". This name reflects 2 puns simultaneously:
  1. "quacks-like-a-duck" typing (vs strong or weak typing)
  2. duct taping (which is what all weakly typed programming is in the opinion of many)
In the same way database views can use logic to calculate attributes and join tables, existential classes/ontologies should be able to map/calculate each attribute via references to the attributes in other classes/ontologies. These ideas resonate with the "rules" in logic-programming languages like Prolog.

External Abstraction ®☺

A related idea I've had is that of the "external abstraction" where, instead of merely views, whole hierarchies of super-classes, subclasses, and interfaces are defined after the fact. ["Internal" abstractions would be those normal OO abstractions where the super-classes and interfaces supported by an object were those that were defined when the object instance was created (i.e. its essence).]

The point of "external" abstractions is that someone "external" (i.e. other than the ontology creator and object instantiator) can decide (after an object has been created) that some aspect of the object is overly specific to one point of view and needs to support other points of view. For example, the "name" attribute of "person" classes is often broken into first name, middle name, last name which is very culturally biased. So, support needs to be added for other cultures where "last name" is not synonymous with "family name", and there is no "Christian name", and not everyone has three names.
Is Dances with Wolves' middle name "with"?

Normally, if one were refactoring that class hierarchy to better handle names, one would convert the 3 string fields representing the name into a reference to a new Name interface and define classes that implement various permutations of name. The interface could have methods like getFamilyName() which determined the value based on the particular cultural variant name class instantiated. This is all nice when one can do this beforehand such that is it all compiled and ready for the code to use before the person object is instantiated. With External Abstraction, the developer can do this refactoring and apply it to an entity that has already been created and exists as an object or persisted to some data store. By adding in a newly created "
mixin" interface/class to the preexisting object, the 3 name fields can be reinterpreted and mapped to other ontologies supporting other cultures.