Re: What doesn't lend itself to OO?

From: H. S. Lahman (h.lahman_at_verizon.net)
Date: 07/26/04


Date: Mon, 26 Jul 2004 18:45:25 GMT

Responding to Nicholls...

>>That is quintessential OO because it is about using pure messages to
>>decouple implementations. The message itself is an object but it is a
>>dumb data holder that is constructed solely for the collaboration. It
>>has no semantics in terms of the problem in hand; just the semantics of
>>data transfer. That decoupling of semantics through the message is why
>>message and method are separated in OOA/D.
>>
>>Contrast that with the idea of passing object references or accessing
>>objects remotely. The semantic coupling is horrendous and one is
>>essentially exposing the client or service implementation. Even worse,
>>one is inviting the other process to modify the object or access it in a
>>completely open-ended and unpredictable fashion. Essentially one has
>>unlimited opportunity for foot-shooting.
>
>
> Don't get me wrong, but the vanilla (naive) OOA/D approach does not do
> this, and such issues are rarely if ever talked about in OOA/D books,
> and in fact is absent from most mainstream middleware packages until
> very recently, the mantra has been not to worry about where the
> objects exist because that has been abstracted away in a puff of OO
> magic, sadly the real world intervenes because the problems associated
> with interprocess/interapplication/intersystem communication don't sit
> well with the direct coupling of state and operation.

I submit that there are OOA/D authors today who boot strapped their
OOA/D from spending their formative years writing OOPL code where
compromises like eliminating the separation of message and method are
pervasive. Consequently they have mapped very procedural techniques
onto OO construction. These are the guys who converted to OO in the
'80s and '90s from a procedural background and are now writing books.

I also submit that even classic OOA/D authors tend to present A&D
methodologies in terms of How-To guidelines. IOW, they distill the
fundamentals into practical methodologies. So I agree one has to do a
lot of reading to between the lines to infer the fundamentals.

Even "Executable UML" by Mellor and Balcer is more interested in
defining an MDA profile than discussing Why one should use that profile
-- and it is the premier exposition of the methodology I espouse. So it
very explicitly separates message from method and separates knowledge
and behavior responsibilities in terms of synchronous access and
asynchronous access. Yet it doesn't actually /say/ that is what it is
doing. Instead it says one should use state machines to describe
behavior. Nor does it say anywhere that passing object references as
message data introduces horrendous coupling issues. Instead it says one
should employ event-based interfaces for object behaviors and subsystems.

As far as middleware packages and infrastructures are concerned, very
few of them are OO. Most of the OOness lies in marketing hype that
carries on the grand tradition of wrapping an OO Facade around a
function library that began with MFC.

However, I would point out that there is a big difference between
employing a paradigm to solve an specific problem and designing software
to implement that solution or designing the applications that access
that solution.

COM-like composition is a fine paradigm for creating very general
software infrastructures. But that is solving a very specific problem
with quite unique constraints. One can provide an OOA/D model that
implements the /solution/ paradigm without the model itself being
expressed with the paradigm. Similarly, client applications can access
a solution based on that paradigm without their construction being based
upon it.

For example, the world of RDBs is characterized by the RDM. One can
design a data base engine in an OO manner using objects like Schema,
Table, Field, Join, etc. But they are just vanilla OO abstractions of
the problem space. That DB engine design itself isn't using P/R to
construct the software. Similarly, the applications that access the DB
engine will abstract their problems in terms of Account, Customer, etc.
rather that Table, Tuple, etc. Those applications only need to
understand the semantics of the RDB paradigm in their application
interfaces, not the solution to their specific problem.

The analogy to COM/Middleware is similar:

DB engine => middleware infrastructure
RDM paradigm => composition paradigm
problem space abstraction => problem space abstraction
client => client.

<snip agreements>

>
>
>>In addition I would point out that the performance problem that dictates
>>stateless objects pretty much only exists on DB servers and middleware
>>where the main problem is processing large gobs of data rather than
>>solving business problems. The reason transaction processing lives on
>>despite the demise of batch processing is that it is a good paradigm for
>>data processing. So in those sorts of environments one already has to
>>live with that paradigm. So the issue of self-contained messages
>>becomes pretty academic.
>
>
> not so sure about this, If my GetTime() service was exposed as a
> service on the internet and simply accessed a clock, I wouldn't want
> it to be statefull.

OK, but I see that as pretty much the same problem. In practice, it is
a classic client/server situation with large numbers of clients and a
single, resource-limited server. And, in fact, most 'net applications
don't really do much except data entry checking; they just pass the data
through to a DB for later processing. In that sense they are not unlike
a middleware server.

[BTW, this is an example of why I get amused when people talk about how
unique 'net software is. That's pretty much a croc. Even the markup
and scripting languages are just rehashes of technology that was
abandoned in the '70s. Exactly the same things were done for decades
before the web. (It is sad how few developers realize that the internet
existed for decades before the W3 or that multi-client networking
applications also preceded the web by a couple of decades.) The only
thing that makes web applications "new and challenging" is the fact that
IT developers now have to explicitly think about issues like
concurrency, asynchronous processing, resources, bandwidth, and timeouts
that were all nicely serialized or hidden for them previously.]

Just out of curiosity, though, why shouldn't the clock service be
stateful? It isn't really a resource issue because there only needs to
be one instance.

>
> Though I do agree that the use of DB servers in most business apps
> makes the implementation of stateless services relatively easy except
> to say that I don't really consider them to be as stateless as client
> held state...the server application is maintaining state but via some
> sort of handle, client held state to me is much to be prefered because
> the server is not responsible for maintaining any state at all.
>
>
>>In other environments where the software is solving business problems
>>the collaborations will generally by more complex and will inherently
>>require some degree of persistence in the service between client
>>requests. The remote clock handling multiple time zones and calendar
>>synchronization is an example of that. In those situations it is almost
>>always better to provide the persistence in the service or in some
>>common repository like a DB or shared memory.
>
>
> If possible on the client BUT I accept there are a whole raft of
> scenarios where this is unreasonable and unwanted i.e. the raison
> d'etre (!) for the service is to supply some sort of persistence.

There's no free lunch; wherever state is maintained persistently there
is a downside. If it is in the server, then one has resource issues in
a multi-client environment. If it is in the DB, then one has the
performance hit of additional physical I/O access and one increases the
likelihood of needing deadlock resolution. If it is in the client, then
the client needs to know a lot about the persistence limitations and
there will be encoding/decoding overhead into generic formats like XML.
  (Not to mention that most of the client state will originally come
from the DB through the server anyway; all one is really doing is
optimizing the access.)

Essentially one has made every client responsible for also managing and
optimizing DB access in addition to solving the customer's problem.
That duplication fine if all the customer is doing is ad hoc reporting
and data entry because it can be largely reused as in RAD IDEs. But
when the applications are also solving significant problems, one has to
touch /all/ those solutions when something changes in DB-land. That's a
maintainability problem, which must be important because one is doing OO
in the first place.

So I would try to put state on the server or in the DB until that
downside was /demonstrated/ to be unacceptable. Fortunately for us
translationists the issue is largely academic; it's just a strategy
switch in the translation rules to move the state and one doesn't have
to maintain the code if it is put in the client. B-)).

>>>If I did this for all my code (and I do it more than most e.g. my
>>>likeing for dumb readonly shared composites and behaviour rich
>>>visitors) you would suggest I wasn't doing OO I think.
>>
>>How much of that is because you are dealing with "canned" layered model
>>infrastructures that exposes too much about the data layer? Sadly, most
>>of those infrastructures aren't very OO despite the marketing hype.
>>That's just another reason to isolate persistence and UI in application
>>subsystems whenever one is beyond CRUD/USER pipeline applications.
>
>
> I don't know, you wouldn't like my code - sometimes I don't - some of
> it has to do with working in an inherently multithreaded world where
> changing state is a nightmare...I usually just push everything into a
> single threaded queue.

Use state machines. B-) If the only problem is data consistency during
concurrent execution (as opposed to hard R-T constraints), then all one
needs to do is provide multiple instances of the event queue manager.
The event doesn't get on the queue until the data is consistent,
regardless of whether there are one or many queues, so data consistency
comes for free in just getting the asynchronous processing to work for
the object state machine interactions.

One can then allocate object state machines to event queue managers for
concurrency and put each event queue manager in its own thread. Simple
blocking constraints can even be supported via semaphores in the event
queue managers rather than invoking the <expensive> thread pausing
mechanisms.

[If blocking is necessary, it has to be managed somehow. Doing it by
pausing state machines, though, is more aspect-like (i.e., the code
looks the same everywhere) and is easier to manage because the scope is
at the state action (method) level and one can count on the FSM rules to
ensure that scope.]

>
>
>>>>Where the problem arises is when "canned" infrastructures designed to
>>>>hide the client/server boundary as an application layer define a layer
>>>>interface that exposes the server implementation model. That forces the
>>>>client application to employ the server implementation model. That is
>>>>bad OO.
>>>>
>>>
>>>hmm, you'll have to illustrate.
>>
>>Consider COM components. They utilize a very mixin-based composition
>>approach. That is great for providing highly general infrastructures
>>where one can't anticipate the final structure. But it is not a very OO
>>approach for individual applications because it trashes cohesion and
>>deviates from the problem space (e.g., Printable Sony Walkman). That
>>composition bias is very apparent because inheritance is the primary
>>vehicle for cobbling things together so it tends to foster that sort of
>>construction at the individual application level.
>
>
> hmmm I still don't understand and I don't think I agree.
>
> I personally think COM encourages composition over inheritance,
> because there is no temptation to use implementation inheritance to
> expose hooks. I don't believe a 'Printable Sony Walkman' is any more
> likely in COM than in C++, in fact probably less - you know I'm a COM
> fan. COM gets a bad rap because of VB, VB gets a bad rap because it's
> relatively easy to use - this is a good thing BUT you do tend to get
> the more bodge together mentality because more inexperienced people
> can use it - I am a big fan, there now appears to be a huge gap in the
> market for a simple but serious mainstream development tool in the
> market now MS are busy trying to out nerd the java world.

We seem to have different views of COM. B-) To me the primary
mechanism of COM composition is mixin-like inheritance. In one wants to
add a streaming facility to the component in hand, it is inherited from
Streamable (or whatever it is called -- it's been a long time since I
was exposed to COM and I wasn't paying much attention even then).

IME, once one opens Pandora's Box, one will start to get Printable Sony
Walkmans. I am also a strong believer that methodologies, languages,
and tools should /enforce/ good practices rather than simply supporting
them. Using getters/setters is neither convenient, obviously necessary
for a given attribute, nor even the most efficient technique in some
cases. But we still use them methodologically because that Good
Practice ensures we won't shoot ourselves in the foot in some situation
in the future. IOW, once the box is opened, one is in the position of
guessing which foot-shooting situations will arise; better to not have
to worry about it.

>
>
>>In contrast, individual applications are abstracted to a very particular
>>problem in hand. So if one routinely applies the COM composition
>>paradigm one ends up bypassing OO maintainability in favor of the view
>>that it is easier to cobble together a new component for a specific
>>change than to worry about modifying the existing application to be in
>>synch with the problem space. The result is enormous code bloat.
>>Worse, it leads to architectural drift in the applications away form the
>>problem space leading to a maintainability nightmare when the
>>application matures.
>>
>
>
> Bad implementation does not make a bad tool. COM may encourage this
> because it encourages composition over inheritance, there is less
> coupling within an application and so it becomes much easier to coble
> a bodge together than have to reengineer the system due to a new
> requirement.

And when one has collected together a flock of
almost-but-not-quite-the-same widgets and the requirements change, how
does one decide which widgets need to be modified or replaced? One can
guess that only a specific context is affected and modify that. Then
one must have a whole lot of faith in one's test suite.

Alternatively, one can go examine every context where each flock member
is used to see which widgets are affected by the requirements change.
That puts one knee deep in Spaghetti Code. B-).

But the real issue here is architectural drift. That increases the
chances that a relatively minor change in the problem space will trigger
a massive refactoring of the application. That sort of refactoring is
independent of whether COM techniques were used; is is a direct result
of the software structure not matching the problem space structure,
regardless of the construction techniques. My point is the the COM
composition paradigm strongly encourages architectural drift. IOW, it
may be somewhat more difficult now to implement an individual change
while preserving the problem space structure than doing so while
ignoring the problem space structure, but one will pay for it later.

*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com
(888)-OOA-PATH



Relevant Pages

  • Re: Creating a "toy" OO/AO language...
    ... The OO paradigm encourages mutable objects because the underlying entities in most customer spaces are inherently mutable; one repaints houses different colors, extends contract dates, modifies checking account balances, and whatnot quite regularly. ... Note that loading an FPL application with monads because one wanted persistent state one has in objects would be the same sort of construction methodology violation in the functional programming context. ... If the Client of the behavior ... I would use a closure ...
    (comp.object)
  • Re: Why use relational tables in OO (please just take a look inside)
    ... > I disagree because I disagree with your definition of OO paradigm. ... I am not arguing any construction principles ... One commonly extracts multiple tuples across multiple tables at the ... OOPLs make substantial compromises with the Turing/von Neumann ...
    (comp.object)
  • Re: Active Directory/HIPPA Question
    ... The client ... > roll out AD when their top priority this year is securing the applications ... Security is one of the biggest reasons. ... ESPECIALLY if you have 800 remote offices. ...
    (microsoft.public.win2000.general)
  • Re: C/C++ is dying... :-)
    ... For our own, in-house applications, we still very much prefer the ... traditional fat client, particularly for applications that need to automate ...
    (borland.public.delphi.non-technical)
  • Re: Software Development - Who owns the creative/resale rights?
    ... >I have developed a few software applications for a client in Visual ... Also, solicitors are expensive, you'll be lucky to find one that ... know of one case where the lead programmer of a software house left to ...
    (microsoft.public.vb.general.discussion)

Loading