Re: Part 2; COM issues
From: H. S. Lahman (h.lahman_at_verizon.net)
Date: 08/13/04
- Next message: John Creighton: "Re: Superiorto('class name')"
- Previous message: Programmer Dude: "Re: Static vs. Dynamic typing (big advantage or not)---WAS: c.programming: OOP and memory management"
- In reply to: Mark Nicholls: "Re: Part 2; COM issues"
- Next in thread: Mark Nicholls: "Re: Part 2; COM issues"
- Reply: Mark Nicholls: "Re: Part 2; COM issues"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Fri, 13 Aug 2004 18:07:58 GMT
Responding to Nicholls...
>>>If the configuration data is part of the object implementation then so
>>>is the infrastructure the operating system, the hardware, who's using
>>>it, where it is, is it 240V or 120V.
>>
>>Not the same things. The COM configuration defines how the object
>>itself behaves.
>
>
> Yes but these differences are as you wanted, a seperate concern. In
> the same way as the hardware the operating system etc, it does not
> effect functional behaviour but non functional behaviour, the problem
> being that where the object actually does exist is of more importance.
If you believe that is always true, then I have a great bridge in
Brooklyn that I can sell you for a very low price. So long as that
implementation is incorporated in an application object with its own
problem space behaviors there is always a chance of behavior interaction.
The basic notion here is in no way unique to COM or OO development. The
first bug I remember in vivid detail because of the pain it caused was
with PL/I. I was trying to write output to a character screen using
PL/I's standard formatted output facility. I needed embedded control
characters to supplement PL/I's built-in formatting capabilities. The
screen refused to display correctly no matter what I did with the
formatting. I spent nearly a week beating my brains out trying until I
finally got someone in Tech Support who understood the problem.
It seems PL/I automatically stripped all control characters from the
text before applying any PL/I edit formatting (newlines, etc.) and it
was never mentioned in any of the PL/I documentation. So PL/I's support
of stream I/O was not independent of the problem functionality and the
only way one could format a character screen was by writing an Assembly
module for the I/O. I never did get a satisfactory answer for why they
would do such a thing but I'll bet COM has a whole passle of similar
imponderables.
In this case the problem was actually pretty easy to isolate (though it
didn't seem so back in those formative years) because the text string
was an argument to the PL/I facility. In effect, the concerns were
modularized because one accessed the PL/I facility explicitly. My point
in this context is that if COM does something bizarre and that interacts
with the functionality of the object, you would have no visibility into
that because there would be no separation of concerns -- you access
functional properties but the wrong thing happens.
>
> i.e. if you want to seperate concerns to the point where we can swap
> in and out network protocols and/or object location then it is not
> part of the functional implementation.
>
> i.e. it seesm that you
> want to seperate the concerns but don't like COM, and thus you don't
> seem to accept the the costs of the seperation are intrinsic, but
> somehow some sort of flaw in a COM implementation.
> I don't believe the concerns at this time can be seperated
> successfully to the degree that they historically have, and thus
> stateless SOA has been reinvented, and this can be seen in retrospect
> as something OO has not been very good at.
>
>
>>When I invoke an OS service that service belongs to
>>someone else and I am accessing it through an interface with a DbC
>>contract. Its implementation and behavior is quite independent from my
>>object that invokes the service.
>
>
> really?
>
> so if you send a message packet down a network then, if that network
> is implemented using carrier pidgeon or fibre optics is always
> irrelevant?
Yes. Caveat: remove "down a network". The application object just
sends a message to an interface and the sender has no clue what is on
the other side of that interface. (We use output interfaces for
subsystems to ensure that the interface the subsystem object always
"see" is fixed, no matter what the external context is.)
>
> it is irrelevant if we can make broad assumptions and generalisations
> about the non functional behaviour, but this, with hindsight, has not
> applied to OO middleware, it is not irrelevant whether an object is in
> my process space or in Japan, and this is not COM's fault, it is
> intrinsic, given the current level of technology.
I would be inclined to agree. However, I think that in large part that
is due to sloppy or non-OO design of the various technology
implementations. MS had never been very cognizant of OOA/D and that has
been demonstrated in a parade of product-out implementations starting
with the MFC wrapper around the Win32 library. [In part, witnessing
this parade of neo-OO crap has probably biased my views in the current
context -- if I don't have hands-on experience I still figure it is safe
to assume MS has made a mess of it.]
In addition, myopia over CRUD/USER processing has led to the domination
of one-dimensional layered models along with a penchant for pretending
that asynchronous behavior doesn't exist and a firm belief that the GUI
message loop runs the application. Finally, there has been a tendency
to mix & match paradigms that are fundamentally incompatible ("Wow, look
at this neat thing the FPLs do! Let's try doing that in OOPL code.").
>
>
>>However, the COM object combines both hidden infrastructure services and
>>problem semantics (getTime). It is that composition of behavior that I
>>have a problem with precisely because the object is monolithic and there
>>is no separation of implementation concerns.
>
>
> If it does it is completely and utterly abstracted away from the
> client code..and actually I do not believe that the infrastructure
> services are part of the objects implementation...because when I
> define the behaviour of the object I do not specify them.
That's true, but it is also the root of the problem. That abstraction
hides a monolithic, entwined mix of functional and infrastructure
implementation behind the scenes. For a trivial example note that any
hidden private state variables needed by the COM infrastructure will be
inserted into the object and that will modify <at least> the offset to
the virtual method jump table. So if you change anything you will at
least have to recompile. Those offsets will be transparent to your
program -- until you have to do something like writing your own
exception handler facility because the one provided with the OOPL is
brain dead.
When something goes wrong, it becomes difficult to isolate the culprit.
If there is a bug in the facility you will face a rather painful task
in trying to prove that to the satisfaction of the COM tech support
people. In addition, because the possible application space is
effectively infinite, there is always a chance that there will be an
interaction that the infrastructure designers never thought about that
will insert a defect.
But the real problem lies in changing the infrastructure. However
unlikely an infrastructure bug or implementation interaction might be in
the change, one cannot be sure. Since the problem solution and
infrastructure implementations are merged you have no choice but to
fully functionally test the entire application solution. If that
infrastructure were encapsulated in its own subsystem, one would only
need to functionally test that subsystem. One wouldn't even need to
recompile the problem solution.
[I think I mentioned that we did software that was used on multiple
platforms, had multiple UIs, interfaced with different networks, etc.
Our functional regression suite for the actual device driver took about
a week to execute because of things like hardware set-ups. So it was
simply infeasible to do a full functional test for every combination or
platform, UI, etc.]
>
>
>>>Do you consider the configuration data of an application to be part of
>>>it's implementation?
>>>
>>>The answer is surely no. It is not even the configuration data for the
>>>specific application, because this concern has, as you want, been
>>>completely seperated - I don't think you can have it both ways, it
>>>either is a seperate concern, in a seperate subsystem and not part of
>>>the implemention or it isn't.
>>
>>Actually, I do. Because we emphasize encoding invariants while
>>relegating detailed differences to external data, we use configuration
>>data to incorporate business rules and policies that would otherwise
>>have to be encoded. The application could not execute satisfactorily
>>without that data so that data is just as much a part of the problem
>>solution implementation as the code.
>
>
> no, it is part of a specific instance of the implementation. It's
> almost the implementation of an implementation.
>
> And if this is the case, all things that are part of that
> implementation (of the implementation!) are thus part of the
> implementation (!!!!!, I need a drink, we can go on to the set of
> indexes that don't contain themselves and then I'll need two drinks).
>
> so, hardware, OS, 240V, 120V, time of day, person operating it, the
> weather, a butterfly fapping it's wings in the amazonetc etc etc.
The difference is that the configuration data is application-specific.
That data has no relevance to other problems that one might solve. It
is also incorporated directly into the application solution via
attribute values and dynamic relationship instantiation. IOW, it is
intimately integrated into the problem solution.
However, the OS et al are generic implementations that support all
application problems being solved on the platform. They are also
deployed in separate modules and accessed through very disciplined
interfaces.
The COM implementation is a hybrid in that it is a generic service that
applies across applications but it is also application-specific because
it is carnally linked (tailored) to the application's objects by the
compiler.
>>>>>Yep I am defininately talking about a surogate to the point where the
>>>>>client code hasn't a clue whether it's talking to the real thing or a
>>>>>proxy.
>>>>
>>>>That's fine so long as it is an interface and doesn't implement any part
>>>>of the service. Then it is not part of the client; it is just an
>>>>interface to an external service. The fact that a networking service is
>>>>inserted in the middle between client and clock service becomes
>>>>transparent because all the client talks to is the same end of the pipe.
>>>>
>>>>However, my understanding of the COM infrastructure is that the
>>>>surrogate is not a simple external data transfer interface. Instead it
>>>>is a first class object on the client side that is transparently
>>>>provided with an implementation that allows it to communicate on an
>>>>object-to-object basis across the layer or distributed boundary (e.g.,
>>>>things like remote execution).
>>>
>>>
>>>I don't see the difference in these two.
>>
>>The difference lies in where the implementation lives. An interface can
>>be implemented in another DLL. (Outgoing subsystem interfaces almost
>>invariably are.) The COM component is defined, configured and
>>implemented /within/ the subsystem when it also has local semantics
>>(i.e., a GetTime knowledge responsibility).
>
>
> hmmm not sure....I will possbly do the first vb6 psuedo code this
> group has ever shuddered to look at....
>
> dim clock as clockService
> set clock = new clockService
> msgbox(clock.GetTime())
>
> are you all breaking out into a cold sweat?
No, because so far clockService is not a COM object. Except...
>
>
> to me this is the VB6 implementation (whether this is true in a C++
> implementation I don't know, but believe would be the same).
>
> Functionally it does not matter where clock is created, here, there or
> outer mongolia.
> 'new' is effectively an API call to an object factory, and in this
> case it's COM.
> All the configuration to do with where how and when it is created are
> completely encapsulated by this object factory.
>
> So is it part of my VB6 implementation?
>
> no.
Yes. That's because of the particular flavor of 'new' that is being
used. If you are creating COM objects by default, then that is part of
the object implementation because your "object factory" puts it there.
But in either case clockService will be instantiated in the application
process. All COM is adding is an infrastructure that allows it to talk
to a corresponding entity instantiated in some other process on an
object-to-object basis.
>>The main reason they are different is the one immediately above.
>>However, another spin on this lies in the nature of interfaces. An
>>implicit assumption I make about subsystem interfaces is that they are
>>pure message interfaces. Such interfaces need not be implemented with
>>objects or OOPLs; any handy buffer will do.
>>
>>However, insofar as interoperability in concerned, COM doesn't make that
>>assumption. Instead its model is direct object-to-object collaboration
>>regardless of the distributed environment. That collaboration involves
>>things like remote execution of behaviors and synchronous access of
>>remote state data. All that has to be somehow emulated in manner that
>>preserves data and referential integrity across the distributed boundary.
>>
>>That is just not possible for simple interfaces. One has to have a
>>concrete object implementation in the applications on /both/ sides of
>>the boundary. One can all them proxies, surrogates, smart Facades, or
>>whatever, but they are still first class objects that combine problem
>>solution semantics with intimate knowledge of networking in their
>>implementations.
>
>
> and so we are back to square 1.
>
> I agree, this was the point I made in my reply to the OP, but this has
> not been the case of mainstream OO middleware systems in general, your
> gripe is not with COM but the doctine that says locality is a always
> seperable concern. Its not, and your design approach only underlines
> that fact, otherwise you would not have to make subsystem interfaces a
> special case.
Interfaces aren't a special case; they simply represent encapsulation.
What I advocate is KISS -- using simple data transfer interfaces. The
COM distributed model is far more complicated than that.
The COM model is based upon magic. The idea is that one wants to push
on This object Over Here and see That object Over There move in a
totally transparent (magical) way. IOW, at an distributed COM demo, the
audience is supposed to go, "Ooooooo!".
The COM model does, indeed, remove some developer tedium in encoding and
decoding interface messages. In addition, constructing subsystems to
use pure data transfer interfaces properly requires some additional
design effort because there will be more explicit hand-shaking due to a
finer granularity in the message traffic. That, in turn, might lead to
-- horror of horrors! -- the developer having to think in terms of
asynchronous processing in some cases.
So the COM model for distributed processing protects the poor developer
from all that via magic -- everything is hidden in the infrastructure.
A few mystical incantations and -- voila! -- That object Over There
moves. Alas, the price is three-fold. The COM model entails orders of
magnitude more overhead than pure data transfer interfaces. There are
also hidden costs like defining the configurations separately from the
program logic.
But the most subtle and nastiest cost lies in the developer being forced
to construct the application around the COM way of doing things. That's
where one steps in the ka-ka because no matter how they implement that
model, it will make assumptions about the way software in general is
developed and the application will have to accommodate those
assumptions. (You have already indicated you think the magic hides
things too well so that sometimes you can't do what you want to do
because you can't tweak the hidden implementation.) It also leads to
glorifying paradigms like composition that are useful to COM itself but
may be fundamentally incompatible with some design approaches, like OOA/D.
Note that this argument is not anti-COM per se. It would apply to any
one-size-fits-all infrastructure that aspires to grandness by attempting
to do too many things for too many masters. [Though I am quite prepared
to believe that MS mucked it up worse than it needed to be for an OO
development environment based on their track record. B-)] For example,
I think it is a fundamental error to try to hide asynchronous processing
from developers. It's out there; deal with it.
>
>>
>>>>>The most significant difference between the COM implementation and the
>>>>>.net one is in this context is the existence of completely stateless
>>>>>objects as described above, where each method invocation invisibly
>>>>>creates uses and destroys an object.
>>>>
>>>>That's the normal implementation?!? Yech! Clearly the designers had a
>>>>lot of faith in Moore's Law.
>>>
>>>
>>>there are two, statefull and stateless, and its a configuraion issue.
>>>
>>>I don't understand the relavance of Moore's Law.
>>
>>I was referring here to creating/deleting a new instance for each method
>>invocation. Instantiation and deletion of objects are usually the most
>>expensive single behaviors associated with the object. And doing that
>>for an OS process like a network proxy would be orders of magnitude
>>worse. IOW, you need faith that by the time you get it working the
>>machines will be a lot faster. (Or that DB physical I/O will be such a
>>big bottleneck that nobody will notice.)
>
>
> but this is exacly what you're subsystem interfaces do, someone sends
> a message and then there is a flurry of activity, involving creating
> and destroying objects, but curerently the cost of this is less than
> the cost of maintaining remote references between objects and their
> clients.
I don't think so. Creating and deleting objects is an issue for
optimization strategy for the subsystem implementation during OOD/P. If
it is resolved during OOD, that may affect the message traffic /content/
but not the semantics (e.g., the stateless vs. stateful nature of objects).
My issue here is that if COM instantiates/deinstatiates a <business>
object for every method call (message), that just reflects a total lack
of optimization. It has nothing to do with the sorts of messages in the
interfaces; the interface just dispatches to objects that implement the
subsystem.
>>>>>>So there is a kind of Catch-22 here. It is easier to make WB than to
>>>>>>fix WA, but in an OO approach there wouldn't have been a WA in the first
>>>>>>place.
>>>>>
>>>>>
>>>>>I'm currently looking at this page in Google, it has text, buttons a
>>>>>scroll bar, they are all composed together in a page, if I want to
>>>>>change the behaviour of the page e.g. have a new button I can
>>>>>either...
>>>>>
>>>>>a) create a new page as a copy and add it.
>>>>>b) add it to the original.
>>>>>
>>>>>I prefer a) because I can then explicitly identify that version from
>>>>>the previous one. so....
>>>>
>>>>The problem with this analogy is that the page is not abstracted as a
>>>>monolithic entity in an OO context.
>>>
>>>
>>>I don't understand the above sentence.
>>
>>The page you are viewing is not a single composition object as you
>>describe -- if the application was developed in an OO manner. It is
>>actually constructed from multiple independent objects that abstract
>>quite different things and collaborate together by navigating
>>relationships between their classes.
>
>
> maybe, there are more than 1 way to skin a cat and more than 1 way to
> implement a page, button model.
>
> If I close the page, the buttons disappear...to me the model is
> composition, but not delegation.
Not if one is doing OOA/D where the paradigm is divide-and-conquer.
Besides, the REAL problem here is that your eyes are not sensitive
enough to see the individual elements being constructed and removed --
trying running the same UI on a machine with an 8080 processor and the
individual elements will become painfully obvious. B-))
>>>>>what has this to do with COM? (this page is html).
>>>>
>>>>With COM one could compose a monolithic Page1 component with embedded ON
>>>>and OFF buttons. One could also compose a monolithic Page2 component
>>>>with embedded ON, OFF, and MAYBE buttons. But it would be a different
>>>>thing than the first even though it was composed of almost identical
>>>>components.
>>>
>>>
>>>Yes....what would you do? subclass and inherit?.....I wouldn't.
>>
>>No, I would simply let Page and Button be separate objects:
>>
>> 1 controls for *
>>[Page] --------------------- [Button]
>>
>
>
> They are, but they are part of the page.
But as far as the problem in hand is concerned they are separate
entities. For example, the semantics of [Button] is pretty minimal in a
UI subsystem; it exists only in the value of a text string for the
label. So there is no reason why the same OFF button could not be
reused for another [Page] instance. (The relationship multiplicity just
says it can only be used for one Page at a time.)
While the Whole/Part relationship may exist from the perception of the
user, it is not critical to the software solution. In OO abstraction
one only abstracts those problem space properties that are necessary to
solve the problem in hand. In fact, nonfunctional requirements would
probably dictate that the Button be reused for different Pages. Since
the relationship path multiplicity through [Page] ensures that the OFF
semantics is interpreted in the right context, one can safely ignore the
Whole/Part and reuse the [Button] instance.
>
>
>>>>But in OO development one doesn't do that because it tends to
>>>>proliferate complex and rigid abstractions. So one has separate,
>>>>simpler notions for Page and Control and a flexible way to link them
>>>>together to yield arbitrary configurations.
>>>
>>>
>>>ah ha, now I possibly understand.
>>>
>>>Well in actual fact that is what is sort of happening, when you create
>>>a 'page' you really are creating a page factory, it simply captures
>>>the specific configuration.
>>>
>>>I agree it is presented to the programmer as a 'page' or form but it
>>>isn't, it's a form factory.
>>
>>I see that somewhat differently. The Factory just encapsulates the
>>rules and policies of instantiation:
>>
>> 1
>>[PageFactory] -------------------------+
>> | 1 |
>> | |
>> | |
>> | creates | creates
>> | * | *
>> [Page] ------------------------- [Button]
>> 1 controls for *
>
>
> that's what I said, a page factory.
>
> but the most intuitive way of designing a page factory is to visually
> design pages.
OK, you are talking about a process in the VB6 IDE. Instead of
designing and coding [PageFactory], you are using a WYSIWYG IDE facility
to write the code for you from a specification of the UI view. I was
talking about the OOA/D of the code itself, part of which is done by the
VB6 IDE.
*************
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
blog (under constr): http://pathfinderpeople.blogs.com/hslahman
(888)-OOA-PATH
- Next message: John Creighton: "Re: Superiorto('class name')"
- Previous message: Programmer Dude: "Re: Static vs. Dynamic typing (big advantage or not)---WAS: c.programming: OOP and memory management"
- In reply to: Mark Nicholls: "Re: Part 2; COM issues"
- Next in thread: Mark Nicholls: "Re: Part 2; COM issues"
- Reply: Mark Nicholls: "Re: Part 2; COM issues"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|