Ray Racine
Posts: 1
Nickname: rpr
Registered: Nov, 2009
|
|
Re: The DCI Architecture: A New Vision of Object-Oriented Programming
|
Posted: Nov 29, 2009 12:46 PM
|
|
The OO Problem
From a high level DCI et al is an effort to "fix" what is broken in the OO model from an OO perspective.
The brokenness manifests itself with standard OO Analysis and Design. Parse the domain into classes, assign responsibilities to said classes ,and execute Use Cases via collaboration of runtime object instances of said classes.
The failure is the inability to pigeon-hole a clear unit of capability/responsibility solely to a single class. It all becomes a forced, shoe horning of capabilities into classes, the opposite, a thin scattering across classes losing all cohesiveness. OO says you _have_ to "put it" somewhere.
And your told if you can't figure out where to put it, you're OO chops are just not up to snuff or your OO model is flawed. Throw it out and start over until you can assign each capability/responsibility to its appropriate OO owner. The fact that this is not possible is ignored by OO.
One camp says the problem is your classes are just too domain anemic, that Order class needs to be beefed up for example. But it becomes a blackhole. More capability, entails and entrains more capability. The Order class soon becomes the Ordering class, a massive God Object that IS the program.
At which point the other camp chimes in no, no, no, "do one thing and one thing only" in your classes. Then all your devouring blackhole God objects go Nova, exploding into a scintilla of ever more anaemic single purpose classes., devolving towards simple state wrappers and manipulators, increasingly orphaning the "do stuff" aspects of your program with nowhere to "put" it.
As all the Noun classes rapidly devolve into simple Data Encapsulators a myriad of -e/or classes explode onto the scene to stitch things together. These are the artificial Class constructs sprung straight from the forehead to act as places to attach all the orphaned "do stuff" code. The Transact-or, the Book-er, the Price-r, the Submit-or, the ... Do'er. But it's all wrong, wrong, wrong, it ain't OO, and you HAVE to be OO. So you take all those zillions of teeny tiny classes do'er and state wrappers that lack any sort of coherence and start merging and combining things back into Nouns classes. Carefully assigning capabilities strictly and solely to each one. Blackholes God classes re-emerge sucking in responsibilities, demanding attachment, until ...
While BigBang followed by Collapse and re-Bang in an endless cycle may be a fine way to run a universe, it is not necessarily so for running the design of a program.
Fixing OO Can't Be Done Via OO
I think the "ideas" to fix OO are and have been out there for quite awhile. The failure is the repeated attempts to apply the fixes in the context of OO in tortured OO terms.
A entirely new and different vocabulary is necessary. Instead of trying to stretch OO concept semantics to "bend" in new concepts why not just properly label the new concepts and retain OO terms and concepts for OO.
For example, in DCI, objects tend to degenerate into "dumb" simplistic state encapsulators barely smart enough to manipulate their enclosed state. The canonical DCI Account classes encapsulate an amount value and token manipulator methods of this value. Yet is is still discussed as an OO class with OO instances. But it's not. Its no longer a robust domain driven Account stuffed with transactive capability for example. Its just a state wrapper and manipulator. Its closer to a simple structure with associated procedures with an implicit self parameter than full-blown OO object.
The point of all the above is to say that fixing the conceptual flaws of OO-ness by constraining solutions to be OO-centric in nature does not appear to be working very well. The solutions appear well known but fail to translate and for the life of me I don't understand why the translation is necessary! OO must be subsumed by a new solution; it cannot be the solution, only an aspect of it.
To be clear I certainly don't know enough to state the solution. What I am saying is it appears some really smart people appear to know the answers but fail to materialize them in translation. The self imposed OO-only constraints completely obstuficate what were originally rather straight forward solutions.
Attempts to demonstrate new multiparadigm higher level design approaches that sit above OO design become a morass with repeated attempts to reifiy the solutions within OO boundaries.
Watch for example the Account with Funds Transfer problem degenerate into exercises in tortured C++ templates or pushing anaemic, kindergarten Java to do things via ever more clever contortions.
What Must Be Done
Stop trying to shoehorn multiparadigm solutions within a legacy context OO paradigm context. Stop defining solution paradigms a top of ancient languages such as C++, Java or SmallTalk. Total waste of time. They cannot be fixed. Enough with exotic, boilerplate, effusive "Patterns" over these substrates. We need a better substrate.
OO must be subsumed or at minimum become a peer paradigm NOT the central tenant. Why continue to discuss a new paradigm such as DCI in OO terms within an OO constrained language, when a priori your objects are not objects, often just dumb data manipulators, and just-in-time role casting is necessary?
The answer is obviously a multi-paradigm / hybrid one. I'd go as far to claim at a minimum one which combines Functional with OO.
One must start with a multi paradigm / hybrid language to properly demonstrate new design and implementation solutions. Lets use Scala for the rest of the discussion. Why? Its multiparadigm (OO, Functional, Actor, Pattern, Algebraic) in design AND clean enough that there is a good chance missing paradigms could be added cleanly as smooth extensions of the language or properly as libraries.
For the hell of, imagine if the current semantics of Scala was _not_ modified one iota, however the following term syntax aliasing was allowed.
object -> module package object -> package module trait -> trait, class -> structure.
To get a gist of the impact of these simple term substitutions let's examine a couple of them.
Module over object encourages people to "think" conceptually different. Its a gathering spot for those procedural, algorithmic things. It is a place where "functional" things can be defined cleanly. These is no dissonance in concieving the below in a "module". But it's a mental hurdle to view it both as a singleton "object", and as the natural container for such constructs.
type T = ...
val c = ...
val f[A,B,C]: (g: (A, B) => C) (x: A, y: B) => g (y, x) val h (x: Int, ..) => ... def k (..) = ...
It is the proper place in Scala land of course, but it seems forced. Of course the Scala folks know this. So why Object and not Module. Because we keep trying to defined new concepts as tortured OO concepts otherwise the Java folks won't grok it. People don't know what a Module is anymore therefore the most intuitive way to add modules conceptually is as singleton object.
Aside: Imagine, giving a talk to COBOL, VB, PL1, RPG, PLSQL and Java developers, its the folks with only the "modern OO" language experience you have to slow down for to explain what modules, procedures and functions are. Ironic.
Object implies Class instance and hence a sort of domain mapping (for me) and the reification of some domain "thing". But it's simply a cohesive grouping of procedural code, functions and algorithms that "do stuff". Where is the "object" I ask you? Sure one can hand wave and claim scala Object is isomorphic to a Module, but damn it it's a module first and a clever means singleton object construction second.
Class -> Struct. (SML structure, not C) Again the idea here is to move away from the OO relentless domain mapping of objects and things and allow one to think in a guilt free manner of constructions whose primary purpose is to encapsulate and manipulate state without OO burden.
I want to be guilt free to think of these things as simply encapsulated data, with associated functions with an implicit self parameter without a receiving a citation from the OO police for an Anaemic Object violation.
By simply aliasing 5 or 6 key terms in the Scala language, without changing any of the semantics of the language, one gets a "whole" new language in the sense that the "way" a single individual would write a program to solve a problem would radically shift.
Same problem, same programmer, same language. Alias five terms and one would gets a more functional code base with appropriate and prevalent state encapsulation. Same semantics just different labelling, say Structures/Instances instead of Classes/Objects.
Leave the current syntax labelling in place one would get a OO centric code base with modest migration of procedure code and algo out of Classes. It all depends on how much the developer can soar above the OOness of the Scala's bias to use non-OO paradigm constructions with peer OO constructions to solve the problem.
One variation of Scala supports DCI and other solutions with less dissonance, the other implies a straining to achieve DCI, a continued uphill struggle to break free beyond just OO in the solution space. In less capable languages such as C++ or Java the strain becomes an all out war against the language limitations itself.
|
|