Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

creaping coupling......

11 views
Skip to first unread message

Mark Nicholls

unread,
Feb 24, 2005, 5:27:04 AM2/24/05
to
Is it me, I am being stupid, I keep coming across this problem......


interface IB has a parameter of type IA.

class B implements IB

and class C instantiates an B....

so (in .net though I expect this happens in a lot of strongly typed
languages).

C has to know about how to instantiate a B.....fair enough.
C has to know that about IB.......damn.....why?
C has to know about IA then......disaster......why?
etc etc etc

Soon C has to reference all sorts of stuff it not interested in.

it seems to me that all C should need to know is that some method
(constuctor) returns something labelled B.....what you can actually do with
B is incidental.

Is there a way around this? (OK I could return 'object's and cast in the
code that accesses the interfaces....but uuuuggghhhh)


Mark Nicholls

unread,
Feb 24, 2005, 6:45:12 AM2/24/05
to

"Mark Nicholls" <nichol...@mtvne.com> wrote in message
news:385oe0F...@individual.net...

> Is it me, I am being stupid, I keep coming across this problem......
>
>
>
>
> interface IB has a parameter of type IA.
>
> class B implements IB
>
> and class C instantiates an B....
>
> so (in .net though I expect this happens in a lot of strongly typed
> languages).
>
> C has to know about how to instantiate a B.....fair enough.
> C has to know that about IB.......damn.....why?

ok, well, actually if C ever wants to do anything with B (assuming the class
interface B is empty), then C would need to know about IB.....but C would
not need to know the details of IB, just that B implements IB.

> C has to know about IA then......disaster......why?
> etc etc etc
>
> Soon C has to reference all sorts of stuff it not interested in.
>
> it seems to me that all C should need to know is that some method
> (constuctor) returns something labelled B.....what you can actually do
with
> B is incidental.
>
> Is there a way around this? (OK I could return 'object's and cast in the
> code that accesses the interfaces....but uuuuggghhhh)
>
>

so let me mildly rephrase.....

C has to know about how to instantiate a B.....fair enough.

C has to know that about the existence of IB and that B implements
it.....fair enough.
C has to know the details of the methods of IB......!....no.....but my
compiler seems to reckon it does.
C thus has to know the interfaces of all parameters in the methods of
IB....!!......no.....but my compiler seems to reckon it does.
recursively....!!!!......C has to know the complete tree of interfaces
stemming from B.....!!!......disaster.


Dmitry A. Kazakov

unread,
Feb 24, 2005, 8:25:50 AM2/24/05
to
On Thu, 24 Feb 2005 11:45:12 -0000, Mark Nicholls wrote:

> "Mark Nicholls" <nichol...@mtvne.com> wrote in message
> news:385oe0F...@individual.net...
>> Is it me, I am being stupid, I keep coming across this problem......
>>
>> interface IB has a parameter of type IA.
>>
>> class B implements IB
>>
>> and class C instantiates an B....

Does it B or IB?

>> so (in .net though I expect this happens in a lot of strongly typed
>> languages).
>>
>> C has to know about how to instantiate a B.....fair enough.
>> C has to know that about IB.......damn.....why?
>
> ok, well, actually if C ever wants to do anything with B (assuming the class
> interface B is empty), then C would need to know about IB.....but C would
> not need to know the details of IB, just that B implements IB.

If you know B => you know its interface => you also know IB, because the
interface of B contains (=B implements) the interface IB.

>> C has to know about IA then......disaster......why?
>> etc etc etc
>>
>> Soon C has to reference all sorts of stuff it not interested in.
>>
>> it seems to me that all C should need to know is that some method
>> (constuctor) returns something labelled B.....what you can actually do with
>> B is incidental.
>>
>> Is there a way around this? (OK I could return 'object's and cast in the
>> code that accesses the interfaces....but uuuuggghhhh)
>>
> so let me mildly rephrase.....
>
> C has to know about how to instantiate a B.....fair enough.
> C has to know that about the existence of IB and that B implements
> it.....fair enough.
> C has to know the details of the methods of IB......!....no.....but my
> compiler seems to reckon it does.

The methods of IB = all existence of IB. Without its methods IB is just a
text: "IB".

> C thus has to know the interfaces of all parameters in the methods of
> IB....!!......no.....but my compiler seems to reckon it does.

Clearly it should! The interfaces of the parameters mentioned in an
interface is a part of that interface.

> recursively....!!!!......C has to know the complete tree of interfaces
> stemming from B.....!!!......disaster.

Why so? It should know the [sub]tree of all ancestors of B. It need not to
know any of its successors, siblings or ancestor's siblings as well as
their successors.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Mark Nicholls

unread,
Feb 24, 2005, 9:10:15 AM2/24/05
to
we meet again......

"Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
news:xl2m948rh45h.16pt6a4mj108b$.dlg@40tude.net...


> On Thu, 24 Feb 2005 11:45:12 -0000, Mark Nicholls wrote:
>
> > "Mark Nicholls" <nichol...@mtvne.com> wrote in message
> > news:385oe0F...@individual.net...
> >> Is it me, I am being stupid, I keep coming across this problem......
> >>
> >> interface IB has a parameter of type IA.
> >>
> >> class B implements IB
> >>
> >> and class C instantiates an B....
>
> Does it B or IB?

OK, the whole thing about 'classes' I find confusing, as we need to
distinguish whether we are talking about the class interface, the constuctor
or the implementation........

so lets decouple C from B, and simply make it dependent on IB.

C instantiates an object that implements IB

i.e. so there exists an interface

interface IB
{
void DoSomething(IA a);
}

IB CreateB()
{
}


and C looks something like

...
IB b = CreateB();
....

now in my book, if this is all that C does, then it needs to know the
existence of IB, but not the specifics of it.....my compiler disagrees, very
irritatingly.


>
> >> so (in .net though I expect this happens in a lot of strongly typed
> >> languages).
> >>
> >> C has to know about how to instantiate a B.....fair enough.
> >> C has to know that about IB.......damn.....why?
> >
> > ok, well, actually if C ever wants to do anything with B (assuming the
class
> > interface B is empty), then C would need to know about IB.....but C
would
> > not need to know the details of IB, just that B implements IB.
>
> If you know B => you know its interface => you also know IB, because the
> interface of B contains (=B implements) the interface IB.

but I do not need to know what the interface contains.....I have an object
that implements IB....what IB actually does is neither here nor there.

e.g. in COM I can have an object that implements all sorts of interfaces, I
do not need to know what those interfaces are to handle a pointer to that
object.

interestingly in .net you can 'explicitly' implement an interface.....which
means it is implemented 'privately', i.e. it's method signatures do not
appear in the class interface......this is very good......but unfortunately
in order to instantiate such an object the compiler insists I know of the
interface it implements, even when I may have no interest in that interest.


>
> >> C has to know about IA then......disaster......why?
> >> etc etc etc
> >>
> >> Soon C has to reference all sorts of stuff it not interested in.
> >>
> >> it seems to me that all C should need to know is that some method
> >> (constuctor) returns something labelled B.....what you can actually do
with
> >> B is incidental.
> >>
> >> Is there a way around this? (OK I could return 'object's and cast in
the
> >> code that accesses the interfaces....but uuuuggghhhh)
> >>
> > so let me mildly rephrase.....
> >
> > C has to know about how to instantiate a B.....fair enough.
> > C has to know that about the existence of IB and that B implements
> > it.....fair enough.
> > C has to know the details of the methods of IB......!....no.....but my
> > compiler seems to reckon it does.
>
> The methods of IB = all existence of IB. Without its methods IB is just a
> text: "IB".

and that's all I want.

I want to go

IB b = CreateB();

ID d = CreateD();

d.DoSomethingWithB(b);


now the knowledge of what's in IB is isolated in D.....good.
DoSomethingWithB expects an IB object, so the client caller of it needs to
know of the existence of IB in order to be able to pass an object that
implements it.

but my compiler will force the class that contains the above code to know of
the inticasies of all the parameters in the methods of IB......that's a real
headache......and seems completely incidental to what I want to do.


>
> > C thus has to know the interfaces of all parameters in the methods of
> > IB....!!......no.....but my compiler seems to reckon it does.
>
> Clearly it should! The interfaces of the parameters mentioned in an
> interface is a part of that interface.
>
> > recursively....!!!!......C has to know the complete tree of interfaces
> > stemming from B.....!!!......disaster.
>
> Why so? It should know the [sub]tree of all ancestors of B.

but why does it need to?

> It need not to
> know any of its successors, siblings or ancestor's siblings as well as
> their successors.

correct, but I do not see why it needs intimate knowledge of the methods of
the interface when it, itself never accesses them.

OK, I can cast my way out of this, but I soon end in a completely untypesafe
world.

Mark Nicholls

unread,
Feb 24, 2005, 9:15:13 AM2/24/05
to
> e.g. in COM I can have an object that implements all sorts of interfaces,
I
> do not need to know what those interfaces are to handle a pointer to that
> object.
>
should read

e.g. in COM I can have an object that implements all sorts of interfaces, I

do not need to know what those interfaces *instantiate* that
object....I think....maybe.


Thomas Gagne

unread,
Feb 24, 2005, 9:34:29 AM2/24/05
to
It's problem like your's that give object oriented programming a bad
reputation. Better to post struggles like this in comp.lang.java.programmer
than comp.object. The OO naysayers don't hang out there and problems like
this only give them more fodder.

The only naysayers in c.l.j.p and c.l.j.a are those protesting against static
languages (which would also make your life easier).

Mark Nicholls

unread,
Feb 24, 2005, 9:35:59 AM2/24/05
to
Actually I've done this before....you can solve it in a dodgy complex ugly
way.....the crux is that you are explicitly seperating instantiation from
operation in the server class.


So

// promises to navigate to an object implementing IA, but without explicit
type information to free the client from incidental coupling.
interface IARole
{
object AsIA();
}

// the interface itself
interface IA
{
void Boom(IZ z);
}

// class implements both the promise to navigate to an interface and the
interface itself.....
// there are other ways of doing this but this is the simplest
class A : IARole,IA
{

object AsIA()
{
return this; // !!! return an untyped version of this....i.e. an
object that implements IA as an 'object'.
}

void Boom(IZ z)
{
z.Bang();
}
}


class AFactory
{
IARole CreateNewA()
{
return new A();
}
}

----------------------------------------------------------------------------
--------

we have an operating client, it has knowledge of Z,IZ,IA and IARole

class OperatingClientOfA
{
void InvokeBang(IARole aRole)
{
// !!!!! cast to IA.....but it's pretty safe, as long as the promise is
kept.....and invoke Boom via this interface.
(IA)(aRole.AsIA()).Boom(new Z());
}
}


----------------------------------------------------------------------------
---------

we have an instantiating client....that has knowledge of IARole,AFactory and
OperatingClientOfA *only*


class InstantiatingClientOfA
{
void DoSomething()
{
AFactory factory = new AFactory();
IARole iaRole = factory.CreateNewA();
OperatingClientOfA operatingClient = new OperatingClientOfA();
operatingClient.InvokeBang(iaRole );
}
}
----------------------------------------------------------------------------
-----------

what I'm asking is.........is all this really necessary in order to isolate
InstantiatingClientOfA from all the other stuff..........it is possible,
because the above code is correct, works, and removes incidental
coupling......it is guarenteed to work as long as the programmer makes sure
an IXXXRole object actually does implement the corresponding
interface......but.............uuuuuuuuuuggggggggggghhhhhhhhhhhhh...........
.I suspect I'm not the first person to be irritated in this way......or the
last.


Mark Nicholls

unread,
Feb 24, 2005, 9:43:36 AM2/24/05
to
"Thomas Gagne" <tga...@wide-open-west.com> wrote in message
news:FZSdnf3r3cp...@wideopenwest.com...

> It's problem like your's that give object oriented programming a bad
> reputation.

if its a genuine problem....and endemic (I don't think it's inherent), then
OOP tools deserve a bad rap, even if OO itself doesn't.

> Better to post struggles like this in comp.lang.java.programmer

maybe......its not a java question though....it applies to C#....and
probably java....and probably C++, and probably, VB6, delphi.....pick any
strongly typed lanuage.....it probably applies.....

> than comp.object. The OO naysayers don't hang out there and problems like
> this only give them more fodder.
>
> The only naysayers in c.l.j.p and c.l.j.a are those protesting against
static
> languages (which would also make your life easier).

The problem is fundamental in most strongly typed OO languages.....and here
in this group.....people (including those that design OOP's) continuously
intertwine class and interface, instantiation and operation and create an OO
mess and potentially give OO a bad rap........it is a serious OO
implementation problem.....unless I'm being stupid and there is a simple way
out.

What is the point of partitioning a system, if the tools we use force each
partitioned subsystem to know about the internal interfaces of all
others....what it doesn't have to.

It is not inherent in strongly typed languages, only in those (which may be
all), that for the owner of a typed object to know the intricacies of it's
interface methods.....


Mark Nicholls

unread,
Feb 24, 2005, 9:58:26 AM2/24/05
to

"Mark Nicholls" <nichol...@mtvne.com> wrote in message
news:38670nF...@individual.net...

actually you can take the method

AsXXXRole out, and simply use the interface as a marker that states.....

<Interface>Role => I can be case to <Interface>.....


but it's still pretty horrible.


Laurent Bossavit

unread,
Feb 24, 2005, 10:03:22 AM2/24/05
to
Mark,

> C has to know about IA then......disaster......why?

What do you mean by "know about" ? In practical terms, how does the
problem - "disaster" - manifest itself ?

Laurent

Mark Nicholls

unread,
Feb 24, 2005, 10:16:47 AM2/24/05
to
"Laurent Bossavit" <lau...@dontspambossavit.com> wrote in message
news:MPG.1c880afce...@news.noos.fr...

> Mark,
>
> > C has to know about IA then......disaster......why?
>
> What do you mean by "know about" ?

it needs to reference those 'modules' that contain all the parameter types
of the methods and recursively all the parameters types of those methods etc
etc etc.....


> In practical terms, how does the
> problem - "disaster" - manifest itself ?

it manifests itself by a module containing 3 lines of code

IA a = CreateNewA();
IB b = CreateNewB();
b.DoSomethingToA(a);

having to recursively reference all modules containing all the parameters of
methods.......when it actually doesn't need to.....as my other post
demonstrates...if you deliberately loose the type information and cast on
the other side to regain it.....the instantiating client shouldn't give a
monkeys about the details of IA or IB, simply that the objects returned from
the factory methods implement those interfaces......

it's encapsulation of the method signatures inside the interface I
suppose.......I my OOP doesn't do it.....and I expect yours doesn't either.


Mark Nicholls

unread,
Feb 24, 2005, 10:30:04 AM2/24/05
to

"Mark Nicholls" <nichol...@mtvne.com> wrote in message
news:3869d8F...@individual.net...

It's like the invention of money......

before you may give me a bag of rice if I give you a chicken......but rather
than me having to carry around loads of chickens, pigs, goats, tofu burgers,
I carry around money....I don't care what you actually do with the money or
even comprehend....we just need to agree to deal in terms of something that
can be transformed into what you actually want.


Shayne Wissler

unread,
Feb 24, 2005, 10:46:54 AM2/24/05
to

"Laurent Bossavit" <lau...@dontspambossavit.com> wrote in message
news:MPG.1c880afce...@news.noos.fr...

That's what I was thinking.

In C++ I think the potential "disaster" is that you might have long compile
times or need to recompile often (which really could be bad depending), but
there's no design disaster that I'm seeing here.


Shayne Wissler
http://www.thoughtsonsoftware.com


Mark Nicholls

unread,
Feb 24, 2005, 11:21:59 AM2/24/05
to

"Shayne Wissler" <thalesN...@yahoo.com> wrote in message
news:37idncipuqB...@comcast.com...

The 'disaster' is that you cannot hide incidental information.....this is
surely the raison d'etre for OO.

We can argue that encapsulation and data hiding are not necessary to write
well defined and structured software, but to abandon, encapsulation and data
hiding would surely be a disaster........they are fundemental enablers of
good software.

what I am pointing out is that the implementation of objects are not the
only source of incidental coupling, interfaces themselves and how they are
dealt with by, at least my OOP tool, is completely unencapsulated.....

The ramifications may well be mildly disasterous for inter system
communication....I've often wondered at the failing of object rich
intersystem communication....we seemed to have failed to deliver it, to the
point now where such interfaces seem to usually be designed in primitive
types.....yet the coupling caused by using bespoke interfaces would seem to
completely inhibit anything but using primitive types, because the
incidental coupling would permeate through any two or more subsystems in the
manner described.....is that bad enough?

To me anything that inhibits, decoupling, isolating and encapsulating
subsystems and modules is.......a disaster.....or at least a major problem.


Dmitry A. Kazakov

unread,
Feb 24, 2005, 11:32:21 AM2/24/05
to
On Thu, 24 Feb 2005 14:10:15 -0000, Mark Nicholls wrote:

> we meet again......

Yep

> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
> news:xl2m948rh45h.16pt6a4mj108b$.dlg@40tude.net...
>> On Thu, 24 Feb 2005 11:45:12 -0000, Mark Nicholls wrote:
>>
>>> "Mark Nicholls" <nichol...@mtvne.com> wrote in message
>>> news:385oe0F...@individual.net...
>>>> Is it me, I am being stupid, I keep coming across this problem......
>>>>
>>>> interface IB has a parameter of type IA.
>>>>
>>>> class B implements IB
>>>>
>>>> and class C instantiates an B....
>>
>> Does it B or IB?
>
> OK, the whole thing about 'classes' I find confusing, as we need to
> distinguish whether we are talking about the class interface, the constuctor
> or the implementation........

Right, but isn't that complicated. It is

T - the type
T'Class - the class

function Foo (...) return T; -- type-constructor function
function Bar (...) return T'Class; -- class-constructor function (factory)

> so lets decouple C from B, and simply make it dependent on IB.

> C instantiates an object that implements IB
>
> i.e. so there exists an interface
>
> interface IB
> {
> void DoSomething(IA a);
> }
>
> IB CreateB()
> {
> }
>
>
> and C looks something like
>
> ...
> IB b = CreateB();
> ....
>
> now in my book, if this is all that C does, then it needs to know the
> existence of IB, but not the specifics of it.....my compiler disagrees, very
> irritatingly.

OK, but CreateB is of B, you have not decoupled it yet. If it were of IB,
like in the factory pattern, then you would need not to know of any
concrete B:

package IB_Things is
type IB is abstract ...; -- The interface
function Factory (...) return IB'Class;
-- This does not depend on any B, though its body probably will
...
end IB_Things;

use IB_Things; -- B definitely knows its interface (and IB a part of it)
package B_Thing;
type B is new IB with ...; -- This implements IB
...
end B_Thing;

use IB_Things; -- We don't use B_Thing here, only IB_Things
package C_Thing is
type C is ...; -- This can't use B

Now B's interface is decoupled from C's one. The implementation could still
be coupled directly or indirectly.

>>>> so (in .net though I expect this happens in a lot of strongly typed
>>>> languages).
>>>>
>>>> C has to know about how to instantiate a B.....fair enough.
>>>> C has to know that about IB.......damn.....why?
>>>
>>> ok, well, actually if C ever wants to do anything with B (assuming the class
>>> interface B is empty), then C would need to know about IB.....but C would
>>> not need to know the details of IB, just that B implements IB.
>>
>> If you know B => you know its interface => you also know IB, because the
>> interface of B contains (=B implements) the interface IB.
>
> but I do not need to know what the interface contains.....I have an object
> that implements IB....what IB actually does is neither here nor there.
>
> e.g. in COM I can have an object that implements all sorts of interfaces, I
> do not need to know what those interfaces are to handle a pointer to that
> object.

The question is whether the object implements the interfaces publicly or
privately. If it does that publicly, then this is the contract of the
object. This contract has to be known for each and every instance. So if
Integer publicly implements Numeric, then yes you have to know that there
are things like "+".

> interestingly in .net you can 'explicitly' implement an interface.....which
> means it is implemented 'privately', i.e. it's method signatures do not
> appear in the class interface......this is very good......but unfortunately
> in order to instantiate such an object the compiler insists I know of the
> interface it implements, even when I may have no interest in that interest.

OK, but that is rather an implementation issue. I.e. whether private
interfaces could be implemented privately. It is sometimes possible, but in
general it is rather not. The reason is that in some cases it could make
the compiler very complicated and the code very inefficient. Though it is
clearly the trend.

>>>> C has to know about IA then......disaster......why?
>>>> etc etc etc
>>>>
>>>> Soon C has to reference all sorts of stuff it not interested in.
>>>>
>>>> it seems to me that all C should need to know is that some method
>>>> (constuctor) returns something labelled B.....what you can actually do with
>>>> B is incidental.
>>>>
>>>> Is there a way around this? (OK I could return 'object's and cast in the
>>>> code that accesses the interfaces....but uuuuggghhhh)
>>>>
>>> so let me mildly rephrase.....
>>>
>>> C has to know about how to instantiate a B.....fair enough.
>>> C has to know that about the existence of IB and that B implements
>>> it.....fair enough.
>>> C has to know the details of the methods of IB......!....no.....but my
>>> compiler seems to reckon it does.
>>
>> The methods of IB = all existence of IB. Without its methods IB is just a
>> text: "IB".
>
> and that's all I want.
>
> I want to go
>
> IB b = CreateB();
>
> ID d = CreateD();
>
> d.DoSomethingWithB(b);

If IB is just a name, then it should be not IB, but Any:

Object_B : Any'Class := Factory_Of_Everything ("That should be B");
Object_D : D'Class := Factory_Of_Ds ();

D_does_something_with_anything (Object_D, Object_B);

> now the knowledge of what's in IB is isolated in D.....good.
> DoSomethingWithB expects an IB object, so the client caller of it needs to
> know of the existence of IB in order to be able to pass an object that
> implements it.

OK, then it should be:

Object_B : IB'Class := Factory_Of_IB ("That should be my precious B");
Object_D : D'Class := Factory_Of_Ds ();

D_does_something_with_IB (Object_D, Object_B);

> but my compiler will force the class that contains the above code to know of
> the inticasies of all the parameters in the methods of IB......that's a real
> headache......and seems completely incidental to what I want to do.

It should force the *body* (implementation) of this class to know IB
(IB'Class). Clearly it should know it because you create an object of
IB'Class there. But the interface of the class need not to know anything
about B if the interface does not refer to the interface of B (B'Class).

>>> C thus has to know the interfaces of all parameters in the methods of
>>> IB....!!......no.....but my compiler seems to reckon it does.
>>
>> Clearly it should! The interfaces of the parameters mentioned in an
>> interface is a part of that interface.
>>
>>> recursively....!!!!......C has to know the complete tree of interfaces
>>> stemming from B.....!!!......disaster.
>>
>> Why so? It should know the [sub]tree of all ancestors of B.
>
> but why does it need to?

Because its interface refers to the interface of B. It is a closure.

To be boringly formal: the "use" relation is transitive.

>> It need not to
>> know any of its successors, siblings or ancestor's siblings as well as
>> their successors.
>
> correct, but I do not see why it needs intimate knowledge of the methods of
> the interface when it, itself never accesses them.

But that's the essence of OO (or ADT)! No floating procedures. When you
refer to a type (=its interface) you take everything with, and thus you are
ready to use it. This is the *contract* model. It seems that you rather
want to have that awful way of how C++ templates work. That would be real
coupling. Because for a template the contract is not what is stated but
only what is actually used. And because the implementation may vary, you,
in fact, have no any contract at all. And furthermore, you couple that to
the implementation. Do you really want this?

> OK, I can cast my way out of this, but I soon end in a completely untypesafe
> world.

Casting is bad. If you need it then there must something wrong with the
design. Perhaps you have to re-partition the type space. [Of course, there
might be pathological cases when the type hierarchy is not a tree. But they
are rather rare.]

Mark Nicholls

unread,
Feb 24, 2005, 12:00:31 PM2/24/05
to
>
> > "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
> > news:xl2m948rh45h.16pt6a4mj108b$.dlg@40tude.net...
> >> On Thu, 24 Feb 2005 11:45:12 -0000, Mark Nicholls wrote:
> >>
> >>> "Mark Nicholls" <nichol...@mtvne.com> wrote in message
> >>> news:385oe0F...@individual.net...
> >>>> Is it me, I am being stupid, I keep coming across this problem......
> >>>>
> >>>> interface IB has a parameter of type IA.
> >>>>
> >>>> class B implements IB
> >>>>
> >>>> and class C instantiates an B....
> >>
> >> Does it B or IB?
> >
> > OK, the whole thing about 'classes' I find confusing, as we need to
> > distinguish whether we are talking about the class interface, the
constuctor
> > or the implementation........
>
> Right, but isn't that complicated. It is
>
> T - the type
> T'Class - the class
>
> function Foo (...) return T; -- type-constructor function
> function Bar (...) return T'Class; -- class-constructor function (factory)

oh god it's T and T'class again.....not your fault I just can never remember
which is which....and I tend to live in a interface based world.

>
> > so lets decouple C from B, and simply make it dependent on IB.
>
> > C instantiates an object that implements IB
> >
> > i.e. so there exists an interface
> >
> > interface IB
> > {
> > void DoSomething(IA a);
> > }
> >
> > IB CreateB()
> > {
> > }
> >
> >
> > and C looks something like
> >
> > ...
> > IB b = CreateB();
> > ....
> >
> > now in my book, if this is all that C does, then it needs to know the
> > existence of IB, but not the specifics of it.....my compiler disagrees,
very
> > irritatingly.
>
> OK, but CreateB is of B, you have not decoupled it yet. If it were of IB,
> like in the factory pattern, then you would need not to know of any
> concrete B:

I don't CreateB returns something that implements IB.

>
> package IB_Things is
> type IB is abstract ...; -- The interface
> function Factory (...) return IB'Class;
> -- This does not depend on any B, though its body probably will
> ...
> end IB_Things;

yes.

>
> use IB_Things; -- B definitely knows its interface (and IB a part of it)
> package B_Thing;
> type B is new IB with ...; -- This implements IB
> ...
> end B_Thing;
>
> use IB_Things; -- We don't use B_Thing here, only IB_Things
> package C_Thing is
> type C is ...; -- This can't use B

I'm not following this....it's too un C like.

>
> Now B's interface is decoupled from C's one. The implementation could
still
> be coupled directly or indirectly.

can we javaesque psuedo code?

bit there is a difference from saying

"I am capable of implementing things via interface XYZ"

and

"I am capable of implementing things via interface XYZ i.e.
XYZ.Boom(IA a);
XYZ.Boom(IB b);"

the second statement is what my compiler wants.....my code only needs the
1st statement.....so my code then has to reference all the information it
requires to validate that the second statement is true.......this is bad in
isolation....but recursively it seriously inhibits and decoupling.

>
> > interestingly in .net you can 'explicitly' implement an
interface.....which
> > means it is implemented 'privately', i.e. it's method signatures do not
> > appear in the class interface......this is very good......but
unfortunately
> > in order to instantiate such an object the compiler insists I know of
the
> > interface it implements, even when I may have no interest in that
interest.
>
> OK, but that is rather an implementation issue. I.e. whether private
> interfaces could be implemented privately. It is sometimes possible, but
in
> general it is rather not. The reason is that in some cases it could make
> the compiler very complicated and the code very inefficient. Though it is
> clearly the trend.

I cannot see why it should make the compiler slower....it would be more
complicated because it would validate the contents of the interface if the
client code actually operated on it.......it would just JIT it.

It would actually make it quicker in most cases.

It would have no effect on the compiled code, the coupling is
incidental....i.e. there is no actual need to know the valididty of the
interface itself, its not its business to do this.

it is more that Any...becuase it promises that it can *potentially* be used
to invoke methods on this interface.

but if no actual invocations occur in this code, there is no need to
consider IB as anthing more that the promise of potentiallity.

>
> Object_B : Any'Class := Factory_Of_Everything ("That should be B");
> Object_D : D'Class := Factory_Of_Ds ();
>
> D_does_something_with_anything (Object_D, Object_B);
>
> > now the knowledge of what's in IB is isolated in D.....good.
> > DoSomethingWithB expects an IB object, so the client caller of it needs
to
> > know of the existence of IB in order to be able to pass an object that
> > implements it.
>
> OK, then it should be:
>
> Object_B : IB'Class := Factory_Of_IB ("That should be my precious B");
> Object_D : D'Class := Factory_Of_Ds ();
>
> D_does_something_with_IB (Object_D, Object_B);

I don't understand this, your OOP tool may well be more capable than mine,
or I may not be able to see the equivalent C# code.

>
> > but my compiler will force the class that contains the above code to
know of
> > the inticasies of all the parameters in the methods of IB......that's a
real
> > headache......and seems completely incidental to what I want to do.
>
> It should force the *body* (implementation) of this class to know IB
> (IB'Class).

yes

> Clearly it should know it because you create an object of
> IB'Class there. But the interface of the class need not to know anything
> about B if the interface does not refer to the interface of B (B'Class).

yes

>
> >>> C thus has to know the interfaces of all parameters in the methods of
> >>> IB....!!......no.....but my compiler seems to reckon it does.
> >>
> >> Clearly it should! The interfaces of the parameters mentioned in an
> >> interface is a part of that interface.
> >>
> >>> recursively....!!!!......C has to know the complete tree of interfaces
> >>> stemming from B.....!!!......disaster.
> >>
> >> Why so? It should know the [sub]tree of all ancestors of B.
> >
> > but why does it need to?
>
> Because its interface refers to the interface of B. It is a closure.

but the closure is not required.....

>
> To be boringly formal: the "use" relation is transitive.

but the relation is not required.....in this context.

thus the closure with this relation is overkill and incidental.

>
> >> It need not to
> >> know any of its successors, siblings or ancestor's siblings as well as
> >> their successors.
> >
> > correct, but I do not see why it needs intimate knowledge of the methods
of
> > the interface when it, itself never accesses them.
>
> But that's the essence of OO (or ADT)!

then it's wrong !.......it's too strong....it's incidental....it is not
required.

> No floating procedures. When you
> refer to a type (=its interface) you take everything with

even when you don't need any of it except the promise that something can
operate via that interface.

> , and thus you are
> ready to use it.

but this code does not want to.....thus it does not need this
information...and thus the information is incidental and should be hidden.

> This is the *contract* model.

I have no problem with the contract, but I want 2.....

one that say's.

contract 1: "I promise I can obey contract 2"
contract 2: "I promise if you satisfy ABC, I'll do XYZ"

I only need 1......but my OOP insists that if I have 1.....I must know what
2 contains.


> It seems that you rather
> want to have that awful way of how C++ templates work.

maybe.....I don't know how they work.

>That would be real
> coupling. Because for a template the contract is not what is stated but
> only what is actually used. And because the implementation may vary, you,
> in fact, have no any contract at all. And furthermore, you couple that to
> the implementation. Do you really want this?

I do not know how that works.

I simply want my code to depend on contract 1......the constructor satisfies
this contract...it supplies a IB...
The delegate requires contract 1 as part of it's preconditions.....and I
know it's satisfied......but the compiler insists on sticking it's nose
in......

>
> > OK, I can cast my way out of this, but I soon end in a completely
untypesafe
> > world.
>
> Casting is bad. If you need it then there must something wrong with the
> design. Perhaps you have to re-partition the type space. [Of course, there
> might be pathological cases when the type hierarchy is not a tree. But
they
> are rather rare.]
>


Think of a pipe.....

pipe implements IPipeReadable and IPipeWritable.

I have a PipeReader that reads via IPipeReadable.....yet my OOP will insist
that it actually has to be coupled to IPipeWriteable as well....because it
takes the closure........that to me is bad, and recursively.....very
bad......it's analogous to making all private fields public.


Dmitry A. Kazakov

unread,
Feb 24, 2005, 2:37:14 PM2/24/05
to
On Thu, 24 Feb 2005 17:00:31 -0000, Mark Nicholls wrote:

>>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
>>> news:xl2m948rh45h.16pt6a4mj108b$.dlg@40tude.net...

>> OK, but CreateB is of B, you have not decoupled it yet. If it were of IB,


>> like in the factory pattern, then you would need not to know of any
>> concrete B:
>
> I don't CreateB returns something that implements IB.

Yes, but its name assumes that it creates either B or B'Class. Any of these
indeed implement IB, but it is a more strict contract than required. If you
want to decouple then the contract has to be as weak as possible. Take
CreateIB, known of only that it creates an IB'Class. [It cannot create IB,
because IB is abstract (=interface).]

>> package IB_Things is
>> type IB is abstract ...; -- The interface
>> function Factory (...) return IB'Class;
>> -- This does not depend on any B, though its body probably will
>> ...
>> end IB_Things;
>
> yes.
>
>> use IB_Things; -- B definitely knows its interface (and IB a part of it)
>> package B_Thing;
>> type B is new IB with ...; -- This implements IB
>> ...
>> end B_Thing;
>>
>> use IB_Things; -- We don't use B_Thing here, only IB_Things
>> package C_Thing is
>> type C is ...; -- This can't use B
>
> I'm not following this....it's too un C like.

The package, namespace, file, where C is declared does not refer to
B_Thing.

>> Now B's interface is decoupled from C's one. The implementation could still
>> be coupled directly or indirectly.
>
> can we javaesque psuedo code?

In C++:

----- file IB.h -----------
class IB
{
private :
IB () {} // Enforce no objects
};
IB * Factory (...); // Need pointers because of C++ deficiency

-------- file B.h ----------
#include "IB.h"
class B : public IB
{
public :
B (); // This is a concrete type
};

------ file C.h ----------
// Do not include B.h!
#include "IB.h"
class C
{
public :
// Whatsoever here cannot depend on B
};

But the first implies the second. You cannot claim to be a bird but refuse
to lay eggs.

>>> interestingly in .net you can 'explicitly' implement an interface.....which
>>> means it is implemented 'privately', i.e. it's method signatures do not
>>> appear in the class interface......this is very good......but unfortunately
>>> in order to instantiate such an object the compiler insists I know of the
>>> interface it implements, even when I may have no interest in that interest.
>>
>> OK, but that is rather an implementation issue. I.e. whether private
>> interfaces could be implemented privately. It is sometimes possible, but in
>> general it is rather not. The reason is that in some cases it could make
>> the compiler very complicated and the code very inefficient. Though it is
>> clearly the trend.
>
> I cannot see why it should make the compiler slower....it would be more
> complicated because it would validate the contents of the interface if the
> client code actually operated on it.......it would just JIT it.
>
> It would actually make it quicker in most cases.
>
> It would have no effect on the compiled code, the coupling is
> incidental....i.e. there is no actual need to know the valididty of the
> interface itself, its not its business to do this.

The major problem with opaque type implementations is that to produce
efficient code the compiler should know the size of the objects in advance.
If it does not, then the object have to be allocated in the heap. It is a
performance hit in order of magnitude. For massively parallel systems with
shared memory it would be a disaster. Of course, the compiler might look
into implementations, but that would couple implementation. So you will
have lots of nasty problems with shared libraries, separate compilation,
switching implementations etc.

If this code has no invocations of IB then why do you declare the object as
IB? It is your code that creates unnecessary coupling!

>> Object_B : Any'Class := Factory_Of_Everything ("That should be B");
>> Object_D : D'Class := Factory_Of_Ds ();
>>
>> D_does_something_with_anything (Object_D, Object_B);
>>
>>> now the knowledge of what's in IB is isolated in D.....good.
>>> DoSomethingWithB expects an IB object, so the client caller of it needs to
>>> know of the existence of IB in order to be able to pass an object that
>>> implements it.
>>
>> OK, then it should be:
>>
>> Object_B : IB'Class := Factory_Of_IB ("That should be my precious B");
>> Object_D : D'Class := Factory_Of_Ds ();
>>
>> D_does_something_with_IB (Object_D, Object_B);
>
> I don't understand this, your OOP tool may well be more capable than mine,
> or I may not be able to see the equivalent C# code.

You have just to ask yourself what is the precondition of the code that
requires that Object_B?

If D_does_something_with... requires IB'Class then Object_B *must* be in
that class. You cannot then claim that you do not need each and every
method of IB'Class in your code because you don't know what
D_does_something... uses, and you call it!

Alternatively, if D_does_something... works with any object, then there is
absolutely no need to create an IB for it.

Also I see nothing wrong with OO here.

>>>>> C thus has to know the interfaces of all parameters in the methods of
>>>>> IB....!!......no.....but my compiler seems to reckon it does.
>>>>
>>>> Clearly it should! The interfaces of the parameters mentioned in an
>>>> interface is a part of that interface.
>>>>
>>>>> recursively....!!!!......C has to know the complete tree of interfaces
>>>>> stemming from B.....!!!......disaster.
>>>>
>>>> Why so? It should know the [sub]tree of all ancestors of B.
>>>
>>> but why does it need to?
>>
>> Because its interface refers to the interface of B. It is a closure.
>
> but the closure is not required.....

It is required because we want to decouple interface and implementation.
Once they are decoupled, you cannot tell which subset of the interface
would be required in an implementation based on the interface.

A poultry farm that sells broilers might need no egg laying, nevertheless
broilers are hatched out of eggs.

>> To be boringly formal: the "use" relation is transitive.
>
> but the relation is not required.....in this context.
>
> thus the closure with this relation is overkill and incidental.

Not at all. The whole essence of interface is that its properties do not
depend on the context you might wish to use it. You can rely on it in any
context.

You might also look at this in other way: the set of all contexts where
something can be used in some definite way constitutes an interface.

Nothing here is incidental. If it appears so, then you have a design
problem: fat classes.

>>>> It need not to
>>>> know any of its successors, siblings or ancestor's siblings as well as
>>>> their successors.
>>>
>>> correct, but I do not see why it needs intimate knowledge of the methods of
>>> the interface when it, itself never accesses them.
>>
>> But that's the essence of OO (or ADT)!
>
> then it's wrong !.......it's too strong....it's incidental....it is not
> required.

Refactor, re-partition.

>> No floating procedures. When you
>> refer to a type (=its interface) you take everything with
>
> even when you don't need any of it except the promise that something can
> operate via that interface.

Yes. Next day you might change your mind and use something from the
interface. If you 100% sure that you will never ever do it, then it is a
design problem: you over-specify.

>> , and thus you are
>> ready to use it.
>
> but this code does not want to.....thus it does not need this
> information...and thus the information is incidental and should be hidden.
>
>> This is the *contract* model.
>
> I have no problem with the contract, but I want 2.....
>
> one that say's.
>
> contract 1: "I promise I can obey contract 2"
> contract 2: "I promise if you satisfy ABC, I'll do XYZ"
>
> I only need 1......but my OOP insists that if I have 1.....I must know what
> 2 contains.

Yes. You'll never sign any contract without looking into it. Would you?

DMCA:

contract 1: By buying DVD I sign to the contract 2
contract 2: I can be jailed if I try to play on my Linux box

> I simply want my code to depend on contract 1......the constructor satisfies
> this contract...it supplies a IB...

Stop,

1. "the constructor supplies an IB"
2. "the constructor supplies a B"

are two different contracts!

> The delegate requires contract 1 as part of it's preconditions.....and I
> know it's satisfied......but the compiler insists on sticking it's nose
> in......

Abstract factory seems what you need.

>>> OK, I can cast my way out of this, but I soon end in a completely untypesafe
>>> world.
>>
>> Casting is bad. If you need it then there must something wrong with the
>> design. Perhaps you have to re-partition the type space. [Of course, there
>> might be pathological cases when the type hierarchy is not a tree. But they
>> are rather rare.]
>
> Think of a pipe.....
>
> pipe implements IPipeReadable and IPipeWritable.
>
> I have a PipeReader that reads via IPipeReadable.....yet my OOP will insist
> that it actually has to be coupled to IPipeWriteable as well....because it
> takes the closure........that to me is bad, and recursively.....very
> bad......it's analogous to making all private fields public.

class Readable
{
public :
virtual Element Read () = 0;
};

class Writable
{
public :
virtual void Write (const Element& Item) = 0;
};

class InPipe : public Readable
{
public :
Element Read ();
};

class OutPipe : public Writable
{
public :
void Write (const Element& Item) = 0;
};

class Socket : public Readable, public Writable
{
public :
Element Read ();
void Write (const Element& Item) = 0;
};

H. S. Lahman

unread,
Feb 24, 2005, 4:22:01 PM2/24/05
to
Responding to Nicholls...

> Is it me, I am being stupid, I keep coming across this problem......

It's not you. The basic problem you describe can be summarized as:
physical coupling. The OOPLs do a great job on minimizing logical
coupling between program units but they do a terrible job on physical
coupling.

What it comes down to is that the language defines both the logical
structure and the implementation in the same place (e.g., a header
file). In addition, at the 3GL level the logical structure is tied to
the implementation because things like ADTs must be mapped into physical
storage, etc.. So...

> interface IB has a parameter of type IA.
>
> class B implements IB
>
> and class C instantiates an B....
>
> so (in .net though I expect this happens in a lot of strongly typed
> languages).
>
> C has to know about how to instantiate a B.....fair enough.
> C has to know that about IB.......damn.....why?

The compiler needs to know how to build B and access it. Part of that
information depends on things like name mangling and signatures in IB.

> C has to know about IA then......disaster......why?

The compiler needs to know how the parameter is mapped (i.e., what its
implementation is) so that the parameter can be accessed. So it needs
to "walk" IA back to the parameter class implementation.

John Lakos has a good discussion of these sorts of physical coupling
problems in "Large Scale C++ Software Design". Though C++ is probably
the worst offender, the general ideas apply to most other statically
typed OOPLs and, to a lesser extent, to dynamically typed OOPLs. IOW,
it has a lot to do with the use of type systems at the 3GL level and the
way they are implemented.

> etc etc etc
>
> Soon C has to reference all sorts of stuff it not interested in.
>
> it seems to me that all C should need to know is that some method
> (constuctor) returns something labelled B.....what you can actually do with
> B is incidental.
>
> Is there a way around this? (OK I could return 'object's and cast in the
> code that accesses the interfaces....but uuuuggghhhh)

Yes, but not entirely. One can minimize it with dependency management.
For example, one can at least ensure that the dependency graph between
classes forms a DAG so everything is going in only one direction. In
fact, minimizing physical coupling is pretty much what dependency
management refactoring at the OOP level is all about.

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

H. S. Lahman
h...@pathfindermda.com
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com
blog (under constr): http://pathfinderpeople.blogs.com/hslahman
(888)-OOA-PATH

Daniel T.

unread,
Feb 24, 2005, 4:29:52 PM2/24/05
to
"Mark Nicholls" <nichol...@mtvne.com> wrote:

I don't know about C#, but in C++ the problem with the above is that in
order to compile C, the system needs to know the size of B, IB, and IA...

class IA { };

class IB { IA itsA; };

class B : public IB { };

class C { B itsB; };

Anytime any of the 4 classes change, C must be recompiled because the
size of a "B" object may have changed.

Change the parameter in IB to a pointer and the latter classes (B and C)
no longer need to recompile just because IA changes (unless they use IA
objects directly of course.)

kirkk

unread,
Feb 24, 2005, 5:38:32 PM2/24/05
to
I see little wrong with the initial design, aside from the fact that C
is coupled to B. Make C coupled to IB, which also indirectly couples it
to IA. But C is decoupled from all the B's and A's in the world. It can
be compiled separate from them, tested separate from them, and used
only with those you desire.

And if you place IB and IA in the same package or physical unit as C,
but separate the implementations, you'll gain even more flexibility.
Put your interfaces close to the classes that use them. Separate your
interfaces from the classes that implement them.

Kirk Knoernschild
www.kirkk.com
www.extensiblejava.com

Robert C. Martin

unread,
Feb 24, 2005, 9:01:01 PM2/24/05
to

Welcome to the world of statically typed languages. In languages like
C++, Java, and C# the instantiator of an object must know about the
transitive closure of all classes depending on the class of that
object. C++ allows us to escape some of this through a mechanism
known as forward declaration. But even C++ is succumbs to the
strength of the inheritance relationship.

In statically typed language, inheritance is *very* strong. If class
D inherits from class B, then class D knows about everything that
class B knows about. There is no escape from this.

However, there are design patterns that can make life easier. You can
use the Abstract Factory pattern to break the dependence of the
instantiator of B upon B. Consider:

interface BFactory
{
public IB makeB();
}

class BFactoryImplementation implements BFactory
{
public IB makeB() {return new B();}
}

Now in class C:

static BFactory bfactory;
// set by main to an instance of BFactoryImplementation

IB ib = bFactory.makeB();

Now C knows about IB, but does not know about B!

This is the real power of OO in statically typed languages. We don't
have to worry too much about the fact that instantiators know about
the transitive closure of the classes they instantiate, because we can
hide that instantiation in a factory, and because we can pass around
the *TOP* of the inheritance hierarchy, rather than the bottom.

See "The Dependency Inversion Principle"
http://www.objectmentor.com/resources/articles/dip.pdf

-----
Robert C. Martin (Uncle Bob) | email: uncl...@objectmentor.com
Object Mentor Inc. | blog: www.butunclebob.com
The Agile Transition Experts | web: www.objectmentor.com
800-338-6716


"The aim of science is not to open the door to infinite wisdom,
but to set a limit to infinite error."
-- Bertolt Brecht, Life of Galileo

Robert C. Martin

unread,
Feb 24, 2005, 9:05:17 PM2/24/05
to

The potential disaster is that C depends upon B even though all the
methods of B are declared in IB. This means that if B changes, C must
be recompiled.

This might not be bad. On the other hand, if B and C are in separate
jar files that are meant to be deployed independently, then it's a
disaster. And an avoidable one.

Robert C. Martin

unread,
Feb 24, 2005, 9:08:31 PM2/24/05
to
On Thu, 24 Feb 2005 16:21:59 -0000, "Mark Nicholls"
<nichol...@mtvne.com> wrote:

>The 'disaster' is that you cannot hide incidental information.....this is
>surely the raison d'etre for OO.

When you make these arguments you have to get concrete. You are
right, but you aren't telling people the concrete bad things that will
happen. In Java and .NET the concrete bad thing that happens is that
you *might* couple two components that were meant to be independently
deployed.

Why would you want to independently deploy components? Lots of
reasons. You may wish to only ship the minimum set of changed
components. You may wish to charge extra for some components. You
may wish to configure the system based upon which components are
present. Etc. etc.

Robert C. Martin

unread,
Feb 24, 2005, 9:13:42 PM2/24/05
to
On Thu, 24 Feb 2005 21:22:01 GMT, "H. S. Lahman"
<h.la...@verizon.net> wrote:

>It's not you. The basic problem you describe can be summarized as:
>physical coupling. The OOPLs do a great job on minimizing logical
>coupling between program units but they do a terrible job on physical
>coupling.

No. A statically typed OOPL does a better job at minimizing physical
couplings than a statically typed non-OOPL. A dynamically typed OOPL
(like smalltalk, phython, or Ruby) does a *tremendous* job of
minimizing physical couplings. It reduces them to near zero.

Even in statically typed OOPLS the problem is not that bad. With a
good knowledge of OO design principles and design patterns, a designer
can reduce physical coupling in C++, Java, and C# to very low levels.
Indeed, *THAT* is the reason that OO language, and OO design
principles and patterns, are beneficial to the software industry.

Dmitry A. Kazakov

unread,
Feb 25, 2005, 4:28:26 AM2/25/05
to
On Thu, 24 Feb 2005 20:01:01 -0600, Robert C. Martin wrote:

> Welcome to the world of statically typed languages. In languages like
> C++, Java, and C# the instantiator of an object must know about the
> transitive closure of all classes depending on the class of that
> object. C++ allows us to escape some of this through a mechanism
> known as forward declaration. But even C++ is succumbs to the
> strength of the inheritance relationship.
>
> In statically typed language, inheritance is *very* strong. If class
> D inherits from class B, then class D knows about everything that
> class B knows about. There is no escape from this.

Not quite. There is also separation between public and private interfaces
which can be utilized for further decoupling. When a type privately
inherits from another, their public interface are formally decoupled. Yes,
it is required that both private and public parts be declared in physically
same module. But it is not always necessary that they also be *defined*
there. Not in C++, but in Ada there are opaque types which can hide the
definition in the module body. This could be used to break the chain of
dependencies. Clearly it is very limited, but it is possible. The pattern
is:

package A is
type X is ...; -- Some type to inherit from
end A;

package B is
type Y is private; -- This "inherits" from X, but privately
... -- Whatever public methods of Y, user cannot see
... -- that Y is related to X.
private
type Y_Impl; -- The implementation of Y, it is opaque
type Y is access Y_Impl; -- Pointer to the implementation
end B;

Now in the body of the package B we will provide full implementation of
Y_Impl:

package body B is
type Y_Impl is new X with ...; -- It is a descendant of X
...
end B;

Here Y is coupled to X only in the body. This pattern also works in C++ but
it would require casting.

Mark Nicholls

unread,
Feb 25, 2005, 6:33:52 AM2/25/05
to

"Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
news:1adglflng2htt$.1wj8496rkoktq.dlg@40tude.net...

> On Thu, 24 Feb 2005 17:00:31 -0000, Mark Nicholls wrote:
>
> >>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
> >>> news:xl2m948rh45h.16pt6a4mj108b$.dlg@40tude.net...
>
> >> OK, but CreateB is of B, you have not decoupled it yet. If it were of
IB,
> >> like in the factory pattern, then you would need not to know of any
> >> concrete B:
> >
> > I don't CreateB returns something that implements IB.
>
> Yes, but its name assumes that it creates either B or B'Class. Any of
these
> indeed implement IB, but it is a more strict contract than required. If
you
> want to decouple then the contract has to be as weak as possible. Take
> CreateIB, known of only that it creates an IB'Class. [It cannot create IB,
> because IB is abstract (=interface).]

OK call it CreateIB()

>
> >> package IB_Things is
> >> type IB is abstract ...; -- The interface
> >> function Factory (...) return IB'Class;
> >> -- This does not depend on any B, though its body probably will
> >> ...
> >> end IB_Things;
> >
> > yes.
> >
> >> use IB_Things; -- B definitely knows its interface (and IB a part of
it)
> >> package B_Thing;
> >> type B is new IB with ...; -- This implements IB
> >> ...
> >> end B_Thing;
> >>
> >> use IB_Things; -- We don't use B_Thing here, only IB_Things
> >> package C_Thing is
> >> type C is ...; -- This can't use B
> >
> > I'm not following this....it's too un C like.
>
> The package, namespace, file, where C is declared does not refer to
> B_Thing.

no, but it's implementation has to....

>
> >> Now B's interface is decoupled from C's one. The implementation could
still
> >> be coupled directly or indirectly.
> >
> > can we javaesque psuedo code?
>
> In C++:
>
> ----- file IB.h -----------
> class IB
> {
> private :
> IB () {} // Enforce no objects
> };
> IB * Factory (...); // Need pointers because of C++ deficiency
>
> -------- file B.h ----------
> #include "IB.h"
> class B : public IB
> {
> public :
> B (); // This is a concrete type
> };
>
> ------ file C.h ----------
> // Do not include B.h!
> #include "IB.h"
> class C
> {
> public :
> // Whatsoever here cannot depend on B
> };

OK, but in my example IB contains a method that uses another type, IZ....

class IB
{
public:
void DoSomething(IZ z);


private :
IB () {} // Enforce no objects
};

so IB.h requires knowledge of IZ.h

and this makes C.h coupled to IZ.h.....when it doesn't need to be.

no it doesn't.

Oh dear this is reminiscent of the probablity thing.

You need to define your universe.....

we have A,B,C

and A->B

how can we get to A-->C......?...we can't

if we have B-->C then we can.

i.e. are the statements

"I am capable of implementing things via interface XYZ"

and

"I am capable of implementing things via interface XYZ i.e.
XYZ.Boom(IA a);
XYZ.Boom(IB b);"

equivalent?

only if you know that all things that implement XYZ implement Boom.......but
if you don't know that, they aren't.

My code does not need to know wether the object implements specific methods,
only that it promises to implement any methods declared in a named
interface.

consider specifically that we compile, deploy and then we delete a method to
XYZ.....code that only instatiates and then passes an object on should still
work (bizarrely in .net I think this can be done, even though the compiler
demands closure, the runtime doesn't....which further undermines the value
of the demand).....if it does work, then why does your compiler demand
closure.....and if it doesn't, why logically shouldn't it....because no real
promises have been broken.


> You cannot claim to be a bird but refuse
> to lay eggs.

I can, if the definition of bird does not demand it.

yet I believe the runtime actually does not demand this...so at least in the
case of .net, this would/should not be a problem.


> If it does not, then the object have to be allocated in the heap. It is a
> performance hit in order of magnitude. For massively parallel systems with
> shared memory it would be a disaster.

I am not operating in this context, I don't believe my OOP tool is capable
of this.

I like the use of the word disaster....I believe it is proportionate.

> Of course, the compiler might look
> into implementations, but that would couple implementation. So you will
> have lots of nasty problems with shared libraries, separate compilation,
> switching implementations etc.

OK, I believe you, but this is not my or my compilers context, it would be
simply solved by having a compiler switch

app = windows app
app = console app
app = massively parallel app!

because the code that actually does do the invocation needs the promise..

i.e.

IWriteable pipe = new Pipe();
IPipeWriter writer = new PipeWriter(pipe);
writer.Write("hello");

it is perfectly reasonable for PipeWriter to demand IWriteable......it is
unnecessary for this code to know anything about the intricacies of the
IWriteable interface.....that is a private matter between PipeWriter and
Pipe.

If you can give me a better way of doing the above, please do, I do not
exclude ignorance/idiocy on my part.


>
> >> Object_B : Any'Class := Factory_Of_Everything ("That should be B");
> >> Object_D : D'Class := Factory_Of_Ds ();
> >>
> >> D_does_something_with_anything (Object_D, Object_B);
> >>
> >>> now the knowledge of what's in IB is isolated in D.....good.
> >>> DoSomethingWithB expects an IB object, so the client caller of it
needs to
> >>> know of the existence of IB in order to be able to pass an object that
> >>> implements it.
> >>
> >> OK, then it should be:
> >>
> >> Object_B : IB'Class := Factory_Of_IB ("That should be my precious B");
> >> Object_D : D'Class := Factory_Of_Ds ();
> >>
> >> D_does_something_with_IB (Object_D, Object_B);
> >
> > I don't understand this, your OOP tool may well be more capable than
mine,
> > or I may not be able to see the equivalent C# code.
>
> You have just to ask yourself what is the precondition of the code that
> requires that Object_B?

The procondition of the operating class is that the passed object implements
an inteface....no more, the specifics of that interface are a wholely
private matter between operating client and server class, the instantiating
client has absolutely no interest.

>
> If D_does_something_with... requires IB'Class then Object_B *must* be in
> that class. You cannot then claim that you do not need each and every
> method of IB'Class in your code because you don't know what
> D_does_something... uses, and you call it!
>
> Alternatively, if D_does_something... works with any object, then there is
> absolutely no need to create an IB for it.
>
> Also I see nothing wrong with OO here.

I see nothing wrong with OO principle, rather than OO practive.....though I
have long claimed that OO theory should better seperate the concepts of
operation from instantiation (and object passing), and that the
coupling/overloading of class with interface is also a cause of significant
confusion.

>
> >>>>> C thus has to know the interfaces of all parameters in the methods
of
> >>>>> IB....!!......no.....but my compiler seems to reckon it does.
> >>>>
> >>>> Clearly it should! The interfaces of the parameters mentioned in an
> >>>> interface is a part of that interface.
> >>>>
> >>>>> recursively....!!!!......C has to know the complete tree of
interfaces
> >>>>> stemming from B.....!!!......disaster.
> >>>>
> >>>> Why so? It should know the [sub]tree of all ancestors of B.
> >>>
> >>> but why does it need to?
> >>
> >> Because its interface refers to the interface of B. It is a closure.
> >
> > but the closure is not required.....
>
> It is required because we want to decouple interface and implementation.
> Once they are decoupled, you cannot tell which subset of the interface
> would be required in an implementation based on the interface.

In the exampes given closure is not required.

I can theoretically typesafely create (or recieve and send) objects till I
am blue in the face.....I need not know any specific methods.

As I said in a parallel post......it's like money.....

If I go to the shop, I ask how much for the newspaper....he say "50
cents".......it makes life much easier than saying...."half a chicken and a
packet of chips" one day and "a bag of rice and a popadom" the next........

I need not know what the shopkeeper wants with my my money, just that he
need the potential to get what he wants.

My instantiating client does not need to know what or how another is going
to do it's job, just that it is, and that I have given it the potential to
do so by satisfying the precondition...."does it implement XYZ".


>
> A poultry farm that sells broilers might need no egg laying, nevertheless
> broilers are hatched out of eggs.

? thats self referential....my examples aren't....
What came first....the broiler or the egg?

Maybe the farmer simply buys broilers in, and sells them on at a profit, he
may be amazed when you tell him broilers can lay eggs and that eggs exists,
and that chickens come out of eggs.

To me there is a principle that you should only include the minimal
information that you need, this would seem to be the basis of
taxonomy.....and this the basis of OO, yet my compiler insists on complete
knowledge of stuff that is none of it's business.

>
> >> To be boringly formal: the "use" relation is transitive.
> >
> > but the relation is not required.....in this context.
> >
> > thus the closure with this relation is overkill and incidental.
>
> Not at all. The whole essence of interface is that its properties do not
> depend on the context you might wish to use it. You can rely on it in any
> context.

and I am not breaking that.......I am simply saying the promise to implement
an inteface is weaker than the promise to implement named methods of an
interface.

for examlpe, changing the names of the methods, breaks one promise but not
the other......yet if the code does not require any specific invocations,
then it only requires the weaker promise.

>
> You might also look at this in other way: the set of all contexts where
> something can be used in some definite way constitutes an interface.

I see no contradiction.

>
> Nothing here is incidental. If it appears so, then you have a design
> problem: fat classes.

then solve the problem

inteface IWriteable
{
void Write(string);
void Write(IStream);
}


client code.

IWriteable pipe = new Pipe();
IPipeWriter writer = new PipeWriter(pipe);
writer.Write("hello");


client code needs to reference the module containing IStream......why?

you could claim that IWriteable is fat ?!?.....but that way really leads to
1 method interfaces.....

i.e.
inteface IStringWriteable
{
void Write(string);
}

inteface IStreamWriteable
{
void Write(IStream);
}

and

interface IStreamWriter
interface IStringWriter

oh and 'new' is has to be removed.....because the class implements both
interfaces so....

some factory

class CStreamPipeFactory
class CStringPipeFactory

but even now, recursively, if Pipe implements ...IStreamWriter and
IStringWriter, CStreamPipeFactory needs to know about IStringWriter......and
it doesn't need to.....OK so maybe we need StreamPipe and
StringPipe.......but now I cannot write Streams and strings into the same
pipe......

The same thing would apply to IStreamReadable and
IStreamWritable......eventually if you remove all incidental coupling you
recursively would have to seperate the concrete classes.......but that would
mean any pipe I write to, I can't read from........thats pretty
limiting.....some would say it renders pipes completely useless.....because
it does.

>
> >>>> It need not to
> >>>> know any of its successors, siblings or ancestor's siblings as well
as
> >>>> their successors.
> >>>
> >>> correct, but I do not see why it needs intimate knowledge of the
methods of
> >>> the interface when it, itself never accesses them.
> >>
> >> But that's the essence of OO (or ADT)!
> >
> > then it's wrong !.......it's too strong....it's incidental....it is not
> > required.
>
> Refactor, re-partition.

show me how to write Pipe, and PipeReader....in such a way that no object
knows about intefaces that it never accesses.

>
> >> No floating procedures. When you
> >> refer to a type (=its interface) you take everything with
> >
> > even when you don't need any of it except the promise that something can
> > operate via that interface.
>
> Yes. Next day you might change your mind and use something from the
> interface. If you 100% sure that you will never ever do it, then it is a
> design problem: you over-specify.

recursively this makes the whole code a huge blob of coupling...and forces
you to use primitive types for subsystem interfaces.

>
> >> , and thus you are
> >> ready to use it.
> >
> > but this code does not want to.....thus it does not need this
> > information...and thus the information is incidental and should be
hidden.
> >
> >> This is the *contract* model.
> >
> > I have no problem with the contract, but I want 2.....
> >
> > one that say's.
> >
> > contract 1: "I promise I can obey contract 2"
> > contract 2: "I promise if you satisfy ABC, I'll do XYZ"
> >
> > I only need 1......but my OOP insists that if I have 1.....I must know
what
> > 2 contains.
>
> Yes. You'll never sign any contract without looking into it. Would you?

yes, it's called money.....

I promise to do work for money.....my employer does not need to know what I
do with that money....I may just put it under my mattress.

Imagine the cost and paperwork involved if my contract of employment
stipulated what I did with my money and recursively what all other parties I
could pass money to could do with it..

All contracts then become coupled...

>
> DMCA:
>
> contract 1: By buying DVD I sign to the contract 2
> contract 2: I can be jailed if I try to play on my Linux box
>
> > I simply want my code to depend on contract 1......the constructor
satisfies
> > this contract...it supplies a IB...
>
> Stop,
>
> 1. "the constructor supplies an IB"
> 2. "the constructor supplies a B"
>
> are two different contracts!

I am using 'constructor' loosely......some method that returns an object of
a given type/interface.

>
> > The delegate requires contract 1 as part of it's preconditions.....and I
> > know it's satisfied......but the compiler insists on sticking it's nose
> > in......
>
> Abstract factory seems what you need.

nope....it doesn't break contract 1 from 2.

any types in methods in the interface returned will automatically have to be
referenced....even if no methods are actually invoked.

now write some client code that creates an object that implements Writable
and passes it to another object that actually writes something.

do so such that the client code does not have to reference the module
containing the definition for Element......for it doesn't need to know it.


As I say the irony here is that I can actually write code in .net that does
this...

write an empty interface.
write the factory with an empty implementation
write an empty pipe writer
write a the client to create an object from the factory and pass it to the
pipewiter.
compile
deploy
reversion, compile and deploy the interface with the correct methods.
write the pipe implementation, compile and deploy
reversion, compile and deploy the factory to create the concrete pipe.
reversion, compile and deploy the writer to write to the pipe.

I now have a piece of deployed code that executes and works, typesafely.

recompile whole project........BOOOOMMMM.......client does not reference
'Element'.........


Mark Nicholls

unread,
Feb 25, 2005, 6:41:08 AM2/25/05
to

"kirkk" <ki...@kirkk.com> wrote in message
news:1109284712.5...@g14g2000cwa.googlegroups.com...

> I see little wrong with the initial design, aside from the fact that C
> is coupled to B. Make C coupled to IB, which also indirectly couples it
> to IA. But C is decoupled from all the B's and A's in the world. It can
> be compiled separate from them, tested separate from them, and used
> only with those you desire.

now change something in IA.........you should logically only have to change
code that accesses a method in IA......but your tool will force you to
compile all references to IA......bad....incidental coupling.......I think
we all agree incidental coupling is the root of much evil.....

now deploy C.....oh dear you need to deply IA with C.....even though C never
uses it....

do this recursively....the example I have given is deliberately
trivial....real world system are several orders more complex.

>
> And if you place IB and IA in the same package or physical unit as C,

I don't do this, I have never done this.....I always deploy in a seperate
package to both client and server....the interface 'belongs' to noone.

It still applies.

> but separate the implementations, you'll gain even more flexibility.
> Put your interfaces close to the classes that use them. Separate your
> interfaces from the classes that implement them.
>

I do...and from the classes that use them......not to do so limits
you.........I don't want to revisit DIP, it doesn't apply.....(and I believe
it is at best suboptimal).


Mark Nicholls

unread,
Feb 25, 2005, 9:24:36 AM2/25/05
to
> But the first implies the second. You cannot claim to be a bird but refuse
> to lay eggs.
>

As an aside.....if I'm a male bird I would be most upset if people demanded
I started to lay eggs......it would be an affront to my masculinity.


Mark Nicholls

unread,
Feb 25, 2005, 11:08:45 AM2/25/05
to
Mr Martin states what I am trying to get at.....

"Clients should not be forced to depend upon interfaces they do not *use*"

(I know ISP is really getting at a slightly different problem, but still I
think the above stands in general).

yet.....this thread is all about how OOP tools *force* clients to depend on
interfaces they do not use.

I agree with Mr Martin......but can someone show me how to achieve this in
this context in a mainstream OOP (preferably C#) the simple example give.


interface IWriteable
{
void Write(IElement element);
}

class CPipe : IWriteable
{
...
}

class CPipeWriter
{
public CPipeWriter(IWriteable writeable)
{
...
}

void WriteABC()
{
writeable.write(new Element("ABC"));
}
...
}

client code

IWriteable pipe = new CPipe();
CPipeWriter writer = new CPipeWriter(pipe);
writer.WriteABC();

but my compiler insists this code needs to know what an IElement is because
it appears in a method in IWriteable......can someone show me how to get
around this? or is it endemic in all strongly typed languages....or am I
just talking nonsense.

"Mark Nicholls" <nichol...@mtvne.com> wrote in message
news:385oe0F...@individual.net...

> Is it me, I am being stupid, I keep coming across this problem......
>
>
>
>
> interface IB has a parameter of type IA.
>
> class B implements IB
>
> and class C instantiates an B....
>

> so (in .net though I expect this happens in a lot of strongly typed
> languages).
>
> C has to know about how to instantiate a B.....fair enough.
> C has to know that about IB.......damn.....why?

Mark Nicholls

unread,
Feb 25, 2005, 11:22:44 AM2/25/05
to
sorry I missed this, and then posted something about ISP in order to trigger
a response.....

"Robert C. Martin" <uncl...@objectmentor.com> wrote in message
news:581t11ph6um0550ms...@4ax.com...


> On Thu, 24 Feb 2005 10:27:04 -0000, "Mark Nicholls"
> <nichol...@mtvne.com> wrote:
>
> >Is it me, I am being stupid, I keep coming across this problem......
> >
> >
> >
> >
> >interface IB has a parameter of type IA.
> >
> >class B implements IB
> >
> >and class C instantiates an B....
> >
> >so (in .net though I expect this happens in a lot of strongly typed
> >languages).
> >
> >C has to know about how to instantiate a B.....fair enough.
> >C has to know that about IB.......damn.....why?
> >C has to know about IA then......disaster......why?
> >etc etc etc
> >
> >Soon C has to reference all sorts of stuff it not interested in.
> >
> >it seems to me that all C should need to know is that some method
> >(constuctor) returns something labelled B.....what you can actually do
with
> >B is incidental.
> >
> >Is there a way around this? (OK I could return 'object's and cast in the
> >code that accesses the interfaces....but uuuuggghhhh)
>
> Welcome to the world of statically typed languages. In languages like
> C++, Java, and C# the instantiator of an object must know about the
> transitive closure of all classes depending on the class of that
> object.

yet.....the runtime I don't believe has the same stipulation......and there
seems no logical reason why it should.

> C++ allows us to escape some of this through a mechanism
> known as forward declaration. But even C++ is succumbs to the
> strength of the inheritance relationship.
>
> In statically typed language, inheritance is *very* strong. If class
> D inherits from class B, then class D knows about everything that
> class B knows about. There is no escape from this.

that is fine.......ish

my example is much weaker, not only does it need to know about the
inheritance tree....but seemingly all the parameters and then recursively
onwards......

>
> However, there are design patterns that can make life easier. You can
> use the Abstract Factory pattern to break the dependence of the
> instantiator of B upon B. Consider:
>
> interface BFactory
> {
> public IB makeB();
> }
>
> class BFactoryImplementation implements BFactory
> {
> public IB makeB() {return new B();}
> }
>
> Now in class C:
>
> static BFactory bfactory;
> // set by main to an instance of BFactoryImplementation
>
> IB ib = bFactory.makeB();
>
> Now C knows about IB, but does not know about B!

I know but that is not the problem given.....the problem given is not about
closure of the inheritance tree, but closure via the method parameters.

>
> This is the real power of OO in statically typed languages. We don't
> have to worry too much about the fact that instantiators know about
> the transitive closure of the classes they instantiate, because we can
> hide that instantiation in a factory, and because we can pass around
> the *TOP* of the inheritance hierarchy, rather than the bottom.
>

OK, but thats not the problem....


Mark Nicholls

unread,
Feb 25, 2005, 11:28:16 AM2/25/05
to

"Robert C. Martin" <uncl...@objectmentor.com> wrote in message
news:9v1t115d0ep58u0sp...@4ax.com...

> On Thu, 24 Feb 2005 16:21:59 -0000, "Mark Nicholls"
> <nichol...@mtvne.com> wrote:
>
> >The 'disaster' is that you cannot hide incidental information.....this is
> >surely the raison d'etre for OO.
>
> When you make these arguments you have to get concrete. You are
> right, but you aren't telling people the concrete bad things that will
> happen. In Java and .NET the concrete bad thing that happens is that
> you *might* couple two components that were meant to be independently
> deployed.
>
> Why would you want to independently deploy components? Lots of
> reasons. You may wish to only ship the minimum set of changed
> components. You may wish to charge extra for some components. You
> may wish to configure the system based upon which components are
> present. Etc. etc.
>

maybe, but I don't think I need to get concrete to claim that incidental
coupling is bad.


Mark Nicholls

unread,
Feb 25, 2005, 11:31:51 AM2/25/05
to

"Robert C. Martin" <uncl...@objectmentor.com> wrote in message
news:5t1t11d613g7uhqi1...@4ax.com...

> On Thu, 24 Feb 2005 08:46:54 -0700, "Shayne Wissler"
> <thalesN...@yahoo.com> wrote:
>
> >
> >"Laurent Bossavit" <lau...@dontspambossavit.com> wrote in message
> >news:MPG.1c880afce...@news.noos.fr...
> >> Mark,
> >>
> >>> C has to know about IA then......disaster......why?
> >>
> >> What do you mean by "know about" ? In practical terms, how does the
> >> problem - "disaster" - manifest itself ?
> >
> >That's what I was thinking.
> >
> >In C++ I think the potential "disaster" is that you might have long
compile
> >times or need to recompile often (which really could be bad depending),
but
> >there's no design disaster that I'm seeing here.
>
> The potential disaster is that C depends upon B even though all the
> methods of B are declared in IB. This means that if B changes, C must
> be recompiled.
>
> This might not be bad. On the other hand, if B and C are in separate
> jar files that are meant to be deployed independently, then it's a
> disaster. And an avoidable one.
>
Careful

I am not talking about closure of the inheritance tree.....I know how to get
around that.

I am talking about closure via the method declarations, when a client
accesses no methods........thus it is incidental coupling.

The symptoms are the same though.....apart from the complexity of
deployment, there is complexity of development...and 'noise'.....90% of the
types my client code can see, it actually doesn't need to.....from a
programmers point of view that is bad, because I may start believeing this
coupling is 'real' and inherent, and then start entwining subject
areas/concerns that should be kept seperate.


Mark Nicholls

unread,
Feb 25, 2005, 11:39:09 AM2/25/05
to

"H. S. Lahman" <h.la...@verizon.net> wrote in message
news:ZzrTd.31229$ya6.27504@trndny01...

> Responding to Nicholls...
>
> > Is it me, I am being stupid, I keep coming across this problem......
>
> It's not you. The basic problem you describe can be summarized as:
> physical coupling. The OOPLs do a great job on minimizing logical
> coupling between program units but they do a terrible job on physical
> coupling.

OK, I'm not going completely mad then.

>
> What it comes down to is that the language defines both the logical
> structure and the implementation in the same place (e.g., a header
> file). In addition, at the 3GL level the logical structure is tied to
> the implementation because things like ADTs must be mapped into physical
> storage, etc.. So...

As I have said elsewhere....I'm not sure I completely buy this.....I believe
I can create a workable .net module that is not coupled in two ways.

i) by creating empty server classes compiling, deploying, and then
reversioning them
ii) casting.

both are unpleasant.

>
> > interface IB has a parameter of type IA.
> >
> > class B implements IB
> >
> > and class C instantiates an B....
> >
> > so (in .net though I expect this happens in a lot of strongly typed
> > languages).
> >
> > C has to know about how to instantiate a B.....fair enough.
> > C has to know that about IB.......damn.....why?
>
> The compiler needs to know how to build B and access it.

yet this code does not access it.....and the instuctions for building is
held (i.e. type information) in a seperate assembly......so I don't really
see the problem.

> Part of that
> information depends on things like name mangling and signatures in IB.
>
> > C has to know about IA then......disaster......why?
>
> The compiler needs to know how the parameter is mapped (i.e., what its
> implementation is) so that the parameter can be accessed. So it needs
> to "walk" IA back to the parameter class implementation.

but the client never actually accesses any method.....so this knowledge is
incidental and redundant.

>
> John Lakos has a good discussion of these sorts of physical coupling
> problems in "Large Scale C++ Software Design". Though C++ is probably
> the worst offender, the general ideas apply to most other statically
> typed OOPLs and, to a lesser extent, to dynamically typed OOPLs. IOW,
> it has a lot to do with the use of type systems at the 3GL level and the
> way they are implemented.

The fix is easy.....you just simply make the compiler walk the method
dependencies if anything accesses a method.....if not....don't.

>
> > etc etc etc
> >
> > Soon C has to reference all sorts of stuff it not interested in.
> >
> > it seems to me that all C should need to know is that some method
> > (constuctor) returns something labelled B.....what you can actually do
with
> > B is incidental.
> >
> > Is there a way around this? (OK I could return 'object's and cast in the
> > code that accesses the interfaces....but uuuuggghhhh)
>
> Yes, but not entirely. One can minimize it with dependency management.
> For example, one can at least ensure that the dependency graph between
> classes forms a DAG so everything is going in only one direction.

Ok, I have this already.....it's par for the course.

> In
> fact, minimizing physical coupling is pretty much what dependency
> management refactoring at the OOP level is all about.
>

Yet this seems a huge thorn in my side......any subsystems that communicate
with non primitive types then pollute all other subsystem
communications.....thats bad.


Mark Nicholls

unread,
Feb 25, 2005, 11:41:14 AM2/25/05
to

"Robert C. Martin" <uncl...@objectmentor.com> wrote in message
news:g52t1158vejh1dk89...@4ax.com...

> On Thu, 24 Feb 2005 21:22:01 GMT, "H. S. Lahman"
> <h.la...@verizon.net> wrote:
>
> >It's not you. The basic problem you describe can be summarized as:
> >physical coupling. The OOPLs do a great job on minimizing logical
> >coupling between program units but they do a terrible job on physical
> >coupling.
>
> No. A statically typed OOPL does a better job at minimizing physical
> couplings than a statically typed non-OOPL. A dynamically typed OOPL
> (like smalltalk, phython, or Ruby) does a *tremendous* job of
> minimizing physical couplings. It reduces them to near zero.
>
> Even in statically typed OOPLS the problem is not that bad. With a
> good knowledge of OO design principles and design patterns, a designer
> can reduce physical coupling in C++, Java, and C# to very low levels.
> Indeed, *THAT* is the reason that OO language, and OO design
> principles and patterns, are beneficial to the software industry.
>

You need to demonstrate how to solve the following trivial problem, before I
will believe that claim.

Mark Nicholls

unread,
Feb 25, 2005, 11:59:19 AM2/25/05
to

"Daniel T." <a@b.c> wrote in message
news:a-51652C.16...@news1.east.earthlink.net...

That is the equivalent of my 'versioning' solution....i.e. you create the
code with no methods, and then reversion them in.....unfortunately you then
find that the whole system will not compile, even though the software
works.......I think.


Laurent Bossavit

unread,
Feb 25, 2005, 12:44:29 PM2/25/05
to
Mark,

> but my compiler insists this code needs to know what an IElement is because
> it appears in a method in IWriteable......can someone show me how to get
> around this? or is it endemic in all strongly typed languages....or am I
> just talking nonsense.

I'm still not getting, in operational terms, what "knows about" or
"knows what is" entails.

Suppose I type in your example as Java code. I'd have one Java file per
class, plus one class - call it "Main" - to hold your sample of client
code.

On the first pass at least, if I ask the compiler to compile Main, it's
going to compile all the other classes that Main depends on, directly or
indirectly. It's going to complain until I have given the details of all
the classes, including Element and IElement (which you didn't provide).
Is this what you see as a problem ? That the Java compiler cannot
compile Main until after it has compiled everything it depends on ? It
seems like a reasonable limitation to me - type-safety depends on it.

It's what happens after the first pass that's interesting. Experimenting
with the Java compiler will reveal that if you make some trivial change
to the client code in Main, and ask the compiler to recompile *just*
Main.java, the corresponding source file, then the compiler will read
the compiled bytecode for IWriteable, CPipe, and CPipeWriter, which Main
*directly* depends on. (It will also recompile these classes if it
doesn't find the bytecode for them.) But the Java compiler will *not*
access, at all, the files for IElement and Element. Changes do not
propagate unnecessarily in Java - there isn't the physical coupling
problem that happens in C++ unless you take steps to prevent it.

So, if your discussion is about what happens after the initial
compilation, then either a) Java does not have the problem you're
talking about - I don't know if that's true of C# or any .Net language,
though - or b) I'm still not getting what you mean by "references" or
"knows about", and you'll have to translate that for me in terms of the
compiler accessing file X during operation Y.

Laurent

Falk Tannhäuser

unread,
Feb 25, 2005, 12:57:21 PM2/25/05
to
Mark Nicholls wrote:
> I agree with Mr Martin......but can someone show me how to achieve this in
> this context in a mainstream OOP (preferably C#) the simple example give.
>
> interface IWriteable
> {
> void Write(IElement element);
> }
>
> class CPipe : IWriteable
> {
> ...
> }
>
> class CPipeWriter
> {
> public CPipeWriter(IWriteable writeable)
> {
> ...
> }
>
> void WriteABC()
> {
> writeable.write(new Element("ABC"));
> }
> ...
> }
>
> client code
>
> IWriteable pipe = new CPipe();
> CPipeWriter writer = new CPipeWriter(pipe);
> writer.WriteABC();
>
> but my compiler insists this code needs to know what an IElement is because
> it appears in a method in IWriteable......can someone show me how to get
> around this? or is it endemic in all strongly typed languages....or am I
> just talking nonsense.

in C++, it would be sufficient to declare (without defining) the class
IElement before the definition of the class IWriteable containing the
declaration of Write().
The cutting into source files could look like this:

___________ file: IElement.h ______________

class IElement
{
...
};

__________ file: IWriteable.h _____________

class IElement; // declared but not defined
// no need to #include "IElement.h"

class IWriteable
{
public:
virtual void Write(IElement& element) = 0;
// Declaration of IElement is sufficient here
};

_________ file: CPipe.h ____________________

#include "IWritable.h"

class CPipe : public IWritable
{
public:
virtual void Write(IElement& element);
};

_________ file: CPipe.cxx ___________________

#include "CPipe.h"
#include "IElement.h"

void CPipe::Write(IElement& element)
{
...
// Here, we need to know the definition of IElement
}

_________ file: CPipeWriter.h _______________

#include "IWritable.h"

class CPipeWriter
{
IWriteable& writable;
public:
CPipeWriter(IWriteable& wr) : writable(wr)
{
...
}

void WriteABC();
...
};
_________ file: CPipeWriter.cxx _____________

#include "CPipeWriter.h"
#include "IElement.h"

void CPipeWriter::WriteABC()
{
writeable.write(new IElement("ABC"));
// Here we need to know the definition of IElement to instantiate it
}

____________ file: ClientCode.cxx _____________

#include "CPipe.h"
#include "CPipeWriter.h"

void foo()
{


IWriteable pipe = new CPipe();
CPipeWriter writer = new CPipeWriter(pipe);
writer.WriteABC();
}

_______________________________________________


As you can see, the file ClientCode.cxx does not include IElement.h,
neither directly nor indirectly. Only CPipe.cxx and CPipeWriter.cxx
do. Thus, if the definition of class IElement changes, only the two
latter .cxx files have to be recompiled.
(Of course, in real code you would still have to add include include
guards to the header files and virtual destructors to most classes,
delete the objects created with 'new' when you are finished with them
and the like...

I don't know how such separation through separate compilation could
be achieved in Java or C#.

Falk

Mark Nicholls

unread,
Feb 25, 2005, 1:08:32 PM2/25/05
to
Actually I may be talking complete bollocks, at least about C#......I now
have something that does compile, even when it does not reference all the
subprojects.....I'll tell you on Monday.....


"Laurent Bossavit" <lau...@dontspambossavit.com> wrote in message

news:MPG.1c89823b6...@news.noos.fr...

H. S. Lahman

unread,
Feb 25, 2005, 1:08:46 PM2/25/05
to

> No. A statically typed OOPL does a better job at minimizing physical
> couplings than a statically typed non-OOPL. A dynamically typed OOPL
> (like smalltalk, phython, or Ruby) does a *tremendous* job of
> minimizing physical couplings. It reduces them to near zero.

Wasn't it you who has characterized polymorphism as being about jump
tables? B-)

As soon as one introduces jump tables for virtual access any client
access through those jump tables is done by relative offset. If the
table is relocated (due to adding attributes) or the offsets change (due
to adding behaviors), then every accessing client needs to be
recompiled. Even the dynamically typed languages have offset tables.

You are correct that interpreted, dynamically bound OOPLs have less of a
problem than compiled, statically bound OOPLs, but I mentioned that
explicitly. However, the physical coupling is still there; they just
pay for it in a different way (performance).

>
> Even in statically typed OOPLS the problem is not that bad. With a
> good knowledge of OO design principles and design patterns, a designer
> can reduce physical coupling in C++, Java, and C# to very low levels.
> Indeed, *THAT* is the reason that OO language, and OO design
> principles and patterns, are beneficial to the software industry.

Wasn't it you who characterized dependency management as minimizing what
objects need to know about one another? B-))

Those "design principles" are mostly dependency management, which is the
main reason one does refactoring in XP. That dependency management
would be largely unnecessary if it weren't for the physical coupling.
(Such refactoring (after correctness is achieved) is never done in OOA/D
models.) That's because physical coupling in the OOPLs ties the
client's logical access to the service's physical implementation. IOW,
the compiler needs to know too much about the service to implement the
access and the developer must artificially modify the software structure
to minimize that knowledge _after one has a correct solution_.

So the problem is not whether the designer /can/ reduce physical
coupling to low levels, it is about the fact that physical coupling
exists so that the developer /must/ deal with it. There is also the
problem of the performance hit. Lakos measured up to 3 orders of
magnitude performance hits when reducing physical coupling to near zero.

H. S. Lahman

unread,
Feb 25, 2005, 1:34:04 PM2/25/05
to
Responding to Nicholls...

>>What it comes down to is that the language defines both the logical
>>structure and the implementation in the same place (e.g., a header
>>file). In addition, at the 3GL level the logical structure is tied to
>>the implementation because things like ADTs must be mapped into physical
>>storage, etc.. So...
>
>
> As I have said elsewhere....I'm not sure I completely buy this.....I believe
> I can create a workable .net module that is not coupled in two ways.
>
> i) by creating empty server classes compiling, deploying, and then
> reversioning them
> ii) casting.
>
> both are unpleasant.

Actually, there are lots of techniques for minimizing the effects of
physical coupling. The Lakos book I mentioned is devoted to such
techniques in C++ but the ideas are readily transferable to other OOPLs.
Martin's Dependency Management Principles define another suite of such
techniques. So does much of Fowler's "Refactoring" book.

Alas, there is no free lunch. Dealing with OOPL physical coupling
requires additional work on the part of the OOP developer beyond
providing a correct solution. That notion of 'extra work' is most clear
in the agile OOP-based processes where one does militant refactoring but
it is done /after/ a correct solution is achieved.

>>>C has to know about IA then......disaster......why?
>>
>>The compiler needs to know how the parameter is mapped (i.e., what its
>>implementation is) so that the parameter can be accessed. So it needs
>>to "walk" IA back to the parameter class implementation.
>
>
> but the client never actually accesses any method.....so this knowledge is
> incidental and redundant.

But the compiler has to provide code for the method and that code
accesses the parameter. IOW, the problem lies in compiling the
/implementation/ of B.

>>John Lakos has a good discussion of these sorts of physical coupling
>>problems in "Large Scale C++ Software Design". Though C++ is probably
>>the worst offender, the general ideas apply to most other statically
>>typed OOPLs and, to a lesser extent, to dynamically typed OOPLs. IOW,
>>it has a lot to do with the use of type systems at the 3GL level and the
>>way they are implemented.
>
>
> The fix is easy.....you just simply make the compiler walk the method
> dependencies if anything accesses a method.....if not....don't.

You are right, in principle there is no reason why the compiler can't
figure out whether the implementation change /actually/ affects the code
in hand. But there are two problems. The first is that attribute and
method access is often done via relative offset. In one adds/removes
attributes or methods it can screw up access for all the rest. This is
pretty common and there is not much one can do about it.

The second is a basic trade-off for the language IDE. Determining
whether a specific code fragment that implements class A is actually
accessing a changed element of class Z is nontrivial because of things
like aliasing. It is further complicated by the need for time stamping
individual changes so one can compare to the last time A was compiled.
To make that efficient would probably require a lot more information in
a "compiled" header that would bulk things up. It would also lengthen
compile time to execute the checking algorithms. So I suspect the
language designers have already decided that make files and simply
recompiling clients is the best overall size/performance trade-off.

Dmitry A. Kazakov

unread,
Feb 25, 2005, 2:00:47 PM2/25/05
to

It is not clear what you exactly object. So I'll try to consider possible
interpretations:

1. Element is in fact Any, but there are predefined types which aren't Any.

You need ad-hoc supertypes here. Workaround: wrapper types.

--- Streams.h ---------------------
class Element {...};
class Stream
{
public :
void Write (Element& Item);
};
Stream * Factory (...);
--- StringStreams.h ------------------
#include "Streams.h"
class StringAdapter : public Element
{
public :
StringAdapter (const String& From);
};
--- Pipes.h -----------------------------
#include "Streams.h"
class Pipe : public Stream {...};
--- StringClient.cpp --------------------------
#include "Streams.h"
#include "StreamStrings.h"
...
Stream X = Factory ("I want a pipe");
X->Write (StringAdapter ("Hello"));

You can write a client that knows neither StringAdapter nor Pipe:

#include "Streams.h"
...
Stream X = Factory ("I want a pipe");
WriteString (X, "Hello"); // This is implemented somewhere else

Because Element and Stream are abstract you are coupled to nothing.

2. Element is an implementation detail of Stream, I don't want to see it
because all objects of derived types have interfaces of their own. Well, it
is just bad design. What do the descendants share? Empty interface? Then in
your example, you have to remove Write (Element); That's it. You can mix
(1) and (2) by creating an empty parent for Stream:

--- VoidStreams.h ---------------------
class VoidStream
{
public :
};
VoidStream * Factory (...);
--- Streams.h ---------------------
class Stream : public VoidStream
{
public :
void Write (Element& Item);
};
--- Pipes.h -----------------------------
#include "VoidStreams.h"
class Pipe : public VoidStream
{
public :
Pipe (...);
void Write (String& Item);
void WriteOpaque ();
private :
void * Implementation; // Points to Streams (implemented in Pipes.cpp)
};
--- client.cpp --------------------------
#include "Pipes.h"
...
Pipe X (...);

Pipe->Write ("Hello");
Pipe->WriteOpaque ();

3. I want to write a generic writer capable to deal with all possible
Streams and all possible Elements.

Here you need double dispatch to implement this in a right way. It is a
classical example of double dispatch. In the languages which do not have MD
there is no good solution. [ In Ada 95, there is hard-wired double-dispatch
implemented by the attributes 'Input / 'Output specially for this concrete
case. ]

In general you need:

type Stream is ...;
type Element is ...;
procedure Write (Where : in out Stream; What : Element) is abstract;

Now:

String implements Element
Pipe implements Stream

Pipe and String are completely decoupled. You are free to write clients
that use any, both or none of them.

In the client you could do:

Write (My_Pipe, "Hello");

Once you wrote that, the compiler have to check if there is an
implementation of Write for Pipe and String. I have no idea how to ensure
that. This is a great problem with implementation of MD in statically typed
languages. In a dynamically typed one it is on the programmer's shoulders:
"method not understood, leave me alone...".

Workarounds are known. You emulate MD via cascaded single dispatch. Then
you have another problem: who is responsible for the second dispatch.
Because String is predefined there is little choice, but Stream. That in
turn explodes in the interface of Stream because all potential examples of
Element need to be mentioned there. Though you can still manage it by
creating specialized abstract streams.

Dmitry A. Kazakov

unread,
Feb 25, 2005, 2:01:09 PM2/25/05
to

Well, if I remember correctly male's eggs are sperms.

Dmitry A. Kazakov

unread,
Feb 25, 2005, 2:02:53 PM2/25/05
to
On Fri, 25 Feb 2005 11:33:52 -0000, Mark Nicholls wrote:

> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
> news:1adglflng2htt$.1wj8496rkoktq.dlg@40tude.net...
>> On Thu, 24 Feb 2005 17:00:31 -0000, Mark Nicholls wrote:
>>
>>>>> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
>>>>> news:xl2m948rh45h.16pt6a4mj108b$.dlg@40tude.net...
>>
>>>> OK, but CreateB is of B, you have not decoupled it yet. If it were of IB,
>>>> like in the factory pattern, then you would need not to know of any
>>>> concrete B:
>>>
>>> I don't CreateB returns something that implements IB.
>>
>> Yes, but its name assumes that it creates either B or B'Class. Any of these
>> indeed implement IB, but it is a more strict contract than required. If you
>> want to decouple then the contract has to be as weak as possible. Take
>> CreateIB, known of only that it creates an IB'Class. [It cannot create IB,
>> because IB is abstract (=interface).]
>
> OK call it CreateIB()

Then its interface becomes decoupled from B's interface.

>> The package, namespace, file, where C is declared does not refer to
>> B_Thing.
>
> no, but it's implementation has to....

Of course, to create B you have to refer to it, directly or indirectly.

It has to be because it uses IB which uses IZ. It is transitive. This is
why changing interfaces is an expensive thing. This is why design is worth
its weight in gold.

If from the domain point of view it makes a lot of sense to have many
different Cs which are independent on IZ, then IB is a design fault. You
should have rather:

class IIB
{ // This one does not refer to IZ
public:

private :
IIB () {} // Enforce no objects
};
IIB * Factory (...); // Abstract factory of things using no IZ
-----------------------
class IB : public IB


{
public:
void DoSomething(IZ z);
private :
IB () {} // Enforce no objects
};

IB * Factory (...); // Abstract factory of thigs using IZ

>>> bit there is a difference from saying
>>>
>>> "I am capable of implementing things via interface XYZ"
>>>
>>> and
>>>
>>> "I am capable of implementing things via interface XYZ i.e.
>>> XYZ.Boom(IA a);
>>> XYZ.Boom(IB b);"
>>>
>>> the second statement is what my compiler wants.....my code only needs the
>>> 1st statement.....so my code then has to reference all the information it
>>> requires to validate that the second statement is true.......this is bad in
>>> isolation....but recursively it seriously inhibits and decoupling.
>>
>> But the first implies the second.
>
> no it doesn't.
>
> Oh dear this is reminiscent of the probablity thing.

(:-))

> You need to define your universe.....
>
> we have A,B,C
>
> and A->B
>
> how can we get to A-->C......?...we can't
>
> if we have B-->C then we can.
>
> i.e. are the statements
>
> "I am capable of implementing things via interface XYZ"
>
> and
>
> "I am capable of implementing things via interface XYZ i.e.
> XYZ.Boom(IA a);
> XYZ.Boom(IB b);"
>
> equivalent?

Yes.

> only if you know that all things that implement XYZ implement Boom.......but
> if you don't know that, they aren't.
>
> My code does not need to know wether the object implements specific methods,
> only that it promises to implement any methods declared in a named
> interface.

How does it differ? Isn't "named interface" = "interface"?

> consider specifically that we compile, deploy and then we delete a method to
> XYZ.....code that only instatiates and then passes an object on should still
> work (bizarrely in .net I think this can be done, even though the compiler
> demands closure, the runtime doesn't....which further undermines the value
> of the demand).....if it does work, then why does your compiler demand
> closure.....and if it doesn't, why logically shouldn't it....because no real
> promises have been broken.

No problem. The class of objects that are only known to be instantiatable
is *not* XYZ'Class. It is Any'Class. You are using wrong class.

>> You cannot claim to be a bird but refuse
>> to lay eggs.
>
> I can, if the definition of bird does not demand it.

Yes, but either God or Darwin have defined birds this way. If you disagree
with them, you have an opportunity to re-design. It is not a disaster, but
might be too expensive in this particualr case... (:-))

>>>>> interestingly in .net you can 'explicitly' implement an interface.....which
>>>>> means it is implemented 'privately', i.e. it's method signatures do not
>>>>> appear in the class interface......this is very good......but unfortunately
>>>>> in order to instantiate such an object the compiler insists I know of the
>>>>> interface it implements, even when I may have no interest in that interest.
>>>>
>>>> OK, but that is rather an implementation issue. I.e. whether private
>>>> interfaces could be implemented privately. It is sometimes possible, but in
>>>> general it is rather not. The reason is that in some cases it could make
>>>> the compiler very complicated and the code very inefficient. Though it is
>>>> clearly the trend.
>>>
>>> I cannot see why it should make the compiler slower....it would be more
>>> complicated because it would validate the contents of the interface if the
>>> client code actually operated on it.......it would just JIT it.
>>>
>>> It would actually make it quicker in most cases.
>>>
>>> It would have no effect on the compiled code, the coupling is
>>> incidental....i.e. there is no actual need to know the valididty of the
>>> interface itself, its not its business to do this.
>>
>> The major problem with opaque type implementations is that to produce
>> efficient code the compiler should know the size of the objects in advance.
>
> yet I believe the runtime actually does not demand this...so at least in the
> case of .net, this would/should not be a problem.

If you want to allocate things on the stack you need to know the size. I
cannot tell for .NET, but presumably it is already far too slow and uses
by-reference semantics anyway.

>> Of course, the compiler might look
>> into implementations, but that would couple implementation. So you will
>> have lots of nasty problems with shared libraries, separate compilation,
>> switching implementations etc.
>
> OK, I believe you, but this is not my or my compilers context, it would be
> simply solved by having a compiler switch
>
> app = windows app
> app = console app
> app = massively parallel app!

This is what I hate most in MS compilers, these 2**10 different targets:
Multithreaded/Not x DLL/Static x Debug/Release x ... This is the real
disaster. It is unmaintable if you have 10 interdependent projects for 3-4
platforms. How would you test it? You start to weep being asked to
recompile once. How about recompiling 2**10 times? In our case to compile
one C++ target is about 4 hours. Then somebody have to reformat the hard
drive, re-install the platform and test that. 2**10 times, rememeber!

>>> it is more that Any...becuase it promises that it can *potentially* be used
>>> to invoke methods on this interface.
>>>
>>> but if no actual invocations occur in this code, there is no need to
>>> consider IB as anthing more that the promise of potentiallity.
>>
>> If this code has no invocations of IB then why do you declare the object as
>> IB? It is your code that creates unnecessary coupling!
>
> because the code that actually does do the invocation needs the promise..
>
> i.e.
>
> IWriteable pipe = new Pipe();
> IPipeWriter writer = new PipeWriter(pipe);
> writer.Write("hello");
>
> it is perfectly reasonable for PipeWriter to demand IWriteable......it is
> unnecessary for this code to know anything about the intricacies of the
> IWriteable interface.....that is a private matter between PipeWriter and
> Pipe.

It is a design problem to me. Your client need not to know that there are
pipes and writers. It needs an object where it can put its string. That
object might create a pipe and a writer, but it is not interesting to your
client.

>>> I don't understand this, your OOP tool may well be more capable than mine,
>>> or I may not be able to see the equivalent C# code.
>>
>> You have just to ask yourself what is the precondition of the code that
>> requires that Object_B?
>
> The procondition of the operating class is that the passed object implements
> an inteface....no more, the specifics of that interface are a wholely
> private matter between operating client and server class, the instantiating
> client has absolutely no interest.

Interface has no specifics. It is indivisible. To have "specifics" you need
to split the interface into two and use only one of them.

>> If D_does_something_with... requires IB'Class then Object_B *must* be in
>> that class. You cannot then claim that you do not need each and every
>> method of IB'Class in your code because you don't know what
>> D_does_something... uses, and you call it!
>>
>> Alternatively, if D_does_something... works with any object, then there is
>> absolutely no need to create an IB for it.
>>
>> Also I see nothing wrong with OO here.
>
> I see nothing wrong with OO principle, rather than OO practive.....though I
> have long claimed that OO theory should better seperate the concepts of
> operation from instantiation (and object passing),

It is already separated. You can have a type specific constructing function
(returns T) and a class-wide constructing function (returns T'Class). When
S is a descendant of T and you have a T'Class constructing function
(=abstract factory), then you can create S knowing nothing about the
methods specific to S. You will see only the methods of T'Class.

> and that the
> coupling/overloading of class with interface is also a cause of significant
> confusion.

Overloading is wrong, but coupling is OK. Any type implements several
interfaces, including one of its own. I see no reason to decouple these.

>> It is required because we want to decouple interface and implementation.
>> Once they are decoupled, you cannot tell which subset of the interface
>> would be required in an implementation based on the interface.
>
> In the exampes given closure is not required.
>
> I can theoretically typesafely create (or recieve and send) objects till I
> am blue in the face.....I need not know any specific methods.

But you need to know what you are sending. The receiver's contract limits
you in that respect. To fulfil the contract you have to know what's it
about. That's the interface.

> As I said in a parallel post......it's like money.....
>
> If I go to the shop, I ask how much for the newspaper....he say "50
> cents".......it makes life much easier than saying...."half a chicken and a
> packet of chips" one day and "a bag of rice and a popadom" the next........
>
> I need not know what the shopkeeper wants with my my money, just that he
> need the potential to get what he wants.

It is a good example. The interface of a cent tells nothing about chicken.
Neither one of chicken does something about cents. It is the shop's
interface that binds those together. So the shop has to know that chickens
are sold for cents.

It would be interesting to research the issue together with multiple
dispatch assuming that all subroutines are methods of their arguments. In
the shop chickens need to get a method "sell", but not earlier. So I think
that your arguments have a rationale. We cannot foresee all interfaces
chicken might need to implement. We need ad-hoc supertypes created and
deleted on the fly.

>> A poultry farm that sells broilers might need no egg laying, nevertheless
>> broilers are hatched out of eggs.
>
> ? thats self referential....my examples aren't....
> What came first....the broiler or the egg?
>
> Maybe the farmer simply buys broilers in, and sells them on at a profit, he
> may be amazed when you tell him broilers can lay eggs and that eggs exists,
> and that chickens come out of eggs.

Exactly. But that does not influence the chicken-egg relation.

> To me there is a principle that you should only include the minimal
> information that you need, this would seem to be the basis of
> taxonomy.....and this the basis of OO, yet my compiler insists on complete
> knowledge of stuff that is none of it's business.

The universe shall know how to run chickens. The farmer doesn't need to,
but he can educate himself... It becomes a philosophical dispute: does a
chicken exist while nobody looks at it? (:-))

> any types in methods in the interface returned will automatically have to be
> referenced....even if no methods are actually invoked.

That's OK to me. I would try to make interfaces finer if that becomes a
problem. With exception of MD it is possible to do. For MD there are
patterns provided that not all possible combinations of the parameter types
need to be implemented. Otherwise, well, then you are in trouble...

> now write some client code that creates an object that implements Writable
> and passes it to another object that actually writes something.
>
> do so such that the client code does not have to reference the module
> containing the definition for Element......for it doesn't need to know it.

"Object that implements Writable" implies that there should be something
writable. It is a contract. This contract contains definiton of what is to
write. You cannot just write, you write something somewhere. Something is
Element, somewhere is Writable. They are equivalent from any point of view
except for semantcis of Write, which is no matter anyway. So if you want to
decouple from Element you have to have another contract: "[any] object that
can be passed".

Again I see here rather a design problem. Why somebody who creates Writable
should know nothing about what will be written? What for does he create
this?

Mark Nicholls

unread,
Feb 26, 2005, 3:15:26 AM2/26/05
to
My apologies.....what I want from the .net compiler, it actually does
do....it doesn't do the closure via method calls, but only via the
inheritance tree.

So I've rather led you up the garden path....I will attempt to bow out
gracefully.....

<snip>

> >>> isolation....but recursively it seriously inhibits and decoupling.
> >>
> >> But the first implies the second.
> >
> > no it doesn't.
> >
> > Oh dear this is reminiscent of the probablity thing.
>
> (:-))
>
> > You need to define your universe.....
> >
> > we have A,B,C
> >
> > and A->B
> >
> > how can we get to A-->C......?...we can't
> >
> > if we have B-->C then we can.
> >
> > i.e. are the statements
> >
> > "I am capable of implementing things via interface XYZ"
> >
> > and
> >
> > "I am capable of implementing things via interface XYZ i.e.
> > XYZ.Boom(IA a);
> > XYZ.Boom(IB b);"
> >
> > equivalent?
>
> Yes.

oh dear.. :-)

>
> > only if you know that all things that implement XYZ implement Boom.......but
> > if you don't know that, they aren't.
> >
> > My code does not need to know wether the object implements specific methods,
> > only that it promises to implement any methods declared in a named
> > interface.
>
> How does it differ? Isn't "named interface" = "interface"?

If we allow defintions to change, without changing labels (as we have
discussed), then claiming to be a member of a set by label is
different from claiming to have the characteristics of a set at a
given point in time.

<snip>

>
> >> You cannot claim to be a bird but refuse
> >> to lay eggs.
> >
> > I can, if the definition of bird does not demand it.
>
> Yes, but either God or Darwin have defined birds this way. If you disagree
> with them, you have an opportunity to re-design. It is not a disaster, but
> might be too expensive in this particualr case... (:-))

yes but the defintion may change but not the labels (in programming).

<snip>

>
> If you want to allocate things on the stack you need to know the size. I
> cannot tell for .NET, but presumably it is already far too slow and uses
> by-reference semantics anyway.

yes I mislead you.....my apologies....both the runtime and the
compiler are capable of handling this....my brain was stuck in C
mode....

>
> >> Of course, the compiler might look
> >> into implementations, but that would couple implementation. So you will
> >> have lots of nasty problems with shared libraries, separate compilation,
> >> switching implementations etc.
> >
> > OK, I believe you, but this is not my or my compilers context, it would be
> > simply solved by having a compiler switch
> >
> > app = windows app
> > app = console app
> > app = massively parallel app!
>
> This is what I hate most in MS compilers, these 2**10 different targets:
> Multithreaded/Not x DLL/Static x Debug/Release x ... This is the real
> disaster. It is unmaintable if you have 10 interdependent projects for 3-4
> platforms. How would you test it? You start to weep being asked to
> recompile once. How about recompiling 2**10 times? In our case to compile
> one C++ target is about 4 hours. Then somebody have to reformat the hard
> drive, re-install the platform and test that. 2**10 times, rememeber!

You may be right, what I do is create the 99% code in a non specific
way...and then 'host' it in a specific application type.

<snip>

I am sorry to have mislead you.....I think I must have had a base
class that was poluting my client...my brain was stuck in C mode...or
similar and jumped to a conclusion that was false.

The compiler indeed only demands knowledge on use.

Mark Nicholls

unread,
Feb 26, 2005, 3:17:36 AM2/26/05
to
"Mark Nicholls" <nichol...@mtvne.com> wrote in message news:<3891v7F...@individual.net>...

yet my example is vapourware.....so ignore me.....I was going mad after all.

Mark Nicholls

unread,
Feb 26, 2005, 3:19:21 AM2/26/05
to
"Mark Nicholls" <nichol...@mtvne.com> wrote in message news:<38925uF...@individual.net>...

> "Robert C. Martin" <uncl...@objectmentor.com> wrote in message
> news:5t1t11d613g7uhqi1...@4ax.com...
> > On Thu, 24 Feb 2005 08:46:54 -0700, "Shayne Wissler"
> > <thalesN...@yahoo.com> wrote:
> >
> > >
> > >"Laurent Bossavit" <lau...@dontspambossavit.com> wrote in message
> > >news:MPG.1c880afce...@news.noos.fr...
> > >> Mark,
> > >>
> > >>> C has to know about IA then......disaster......why?
> > >>
> > >> What do you mean by "know about" ? In practical terms, how does the
> > >> problem - "disaster" - manifest itself ?
> > >
> > >That's what I was thinking.
> > >
> > >In C++ I think the potential "disaster" is that you might have long
> compile
> > >times or need to recompile often (which really could be bad depending),
> but
> > >there's no design disaster that I'm seeing here.
> >
> > The potential disaster is that C depends upon B even though all the
> > methods of B are declared in IB. This means that if B changes, C must
> > be recompiled.
> >
> > This might not be bad. On the other hand, if B and C are in separate
> > jar files that are meant to be deployed independently, then it's a
> > disaster. And an avoidable one.
> >
> Careful

!!!! ironic !!!!!

>
> I am not talking about closure of the inheritance tree.....I know how to get
> around that.
>
> I am talking about closure via the method declarations, when a client
> accesses no methods........thus it is incidental coupling.

and it's not a problem in .net so ignore........

>
> The symptoms are the same though.....apart from the complexity of
> deployment, there is complexity of development...and 'noise'.....90% of the
> types my client code can see, it actually doesn't need to.....from a
> programmers point of view that is bad, because I may start believeing this
> coupling is 'real' and inherent, and then start entwining subject
> areas/concerns that should be kept seperate.

Then I should make sure I know how the compiler works before making
assumptions about what the client does/does not need to know.

Mark Nicholls

unread,
Feb 26, 2005, 3:21:22 AM2/26/05
to
"Mark Nicholls" <nichol...@mtvne.com> wrote in message news:<3897r8F...@individual.net>...

> Actually I may be talking complete bollocks, at least about C#......I now
> have something that does compile, even when it does not reference all the
> subprojects.....I'll tell you on Monday.....

Well spotted me.....

I am (and often do) talk complete and utter rubbish....

my apologies for wasting everyone's time with a wild goose chase....

If your OOP demands closure via method parameter types then I suggest
you throw it in the bin and get .net.

Mark Nicholls

unread,
Feb 26, 2005, 3:26:20 AM2/26/05
to
"H. S. Lahman" <h.la...@verizon.net> wrote in message news:<wcKTd.34818$f%5.9258@trndny03>...
> Responding to Nicholls...

>
>
> You are right, in principle there is no reason why the compiler can't
> figure out whether the implementation change /actually/ affects the code
> in hand. But there are two problems. The first is that attribute and
> method access is often done via relative offset. In one adds/removes
> attributes or methods it can screw up access for all the rest. This is
> pretty common and there is not much one can do about it.

and you are right.....

but I was originally wrong.....the compiler does indeed do this.....I
have wasted your time....I am sorry....I shall go away and boil my
head.

Mark Nicholls

unread,
Feb 26, 2005, 3:28:02 AM2/26/05
to
"Mark Nicholls" <nichol...@mtvne.com> wrote in message news:<3891ksF...@individual.net>...

> sorry I missed this, and then posted something about ISP in order to trigger
> a response.....
>
> "Robert C. Martin" <uncl...@objectmentor.com> wrote in message
> news:581t11ph6um0550ms...@4ax.com...
> > On Thu, 24 Feb 2005 10:27:04 -0000, "Mark Nicholls"
> > <nichol...@mtvne.com> wrote:
> >
> > >Is it me, I am being stupid, I keep coming across this problem......
> > >
> > >

Yes I am stupid.....

>
> I know but that is not the problem given.....the problem given is not about
> closure of the inheritance tree, but closure via the method parameters.

and there is no problem.


>
> >
> > This is the real power of OO in statically typed languages. We don't
> > have to worry too much about the fact that instantiators know about
> > the transitive closure of the classes they instantiate, because we can
> > hide that instantiation in a factory, and because we can pass around
> > the *TOP* of the inheritance hierarchy, rather than the bottom.
> >
> OK, but thats not the problem....

there isn't one....sorry......

Mark Nicholls

unread,
Feb 26, 2005, 3:29:41 AM2/26/05
to
"Mark Nicholls" <nichol...@mtvne.com> wrote in message news:<3892nhF...@individual.net>...

> "Robert C. Martin" <uncl...@objectmentor.com> wrote in message
> news:g52t1158vejh1dk89...@4ax.com...
> > On Thu, 24 Feb 2005 21:22:01 GMT, "H. S. Lahman"
> > <h.la...@verizon.net> wrote:
> >
> > >It's not you. The basic problem you describe can be summarized as:
> > >physical coupling. The OOPLs do a great job on minimizing logical
> > >coupling between program units but they do a terrible job on physical
> > >coupling.
> >
> > No. A statically typed OOPL does a better job at minimizing physical
> > couplings than a statically typed non-OOPL. A dynamically typed OOPL
> > (like smalltalk, phython, or Ruby) does a *tremendous* job of
> > minimizing physical couplings. It reduces them to near zero.
> >
> > Even in statically typed OOPLS the problem is not that bad. With a
> > good knowledge of OO design principles and design patterns, a designer
> > can reduce physical coupling in C++, Java, and C# to very low levels.
> > Indeed, *THAT* is the reason that OO language, and OO design
> > principles and patterns, are beneficial to the software industry.
> >
>
> You need to demonstrate how to solve the following trivial problem, before I
> will believe that claim.

you just type the damn thing in and press compile.......solved.....sorry....

Dmitry A. Kazakov

unread,
Feb 26, 2005, 4:22:39 AM2/26/05
to
On 26 Feb 2005 00:15:26 -0800, Mark Nicholls wrote:

>>> My code does not need to know wether the object implements specific methods,
>>> only that it promises to implement any methods declared in a named
>>> interface.
>>
>> How does it differ? Isn't "named interface" = "interface"?
>
> If we allow defintions to change, without changing labels (as we have
> discussed), then claiming to be a member of a set by label is
> different from claiming to have the characteristics of a set at a
> given point in time.

It is not about labels, it is about the membership function. If you define
the membership function of a set as: X in A = true if X fulfills the
contract attached to A. Then to make X a member would require
implementation of the contract. If you define the membership function as X
in A = true if X is named "A". Then you are free to make any X member of A
just by labeling it.

The question is not in how you define the membership function. The question
is what this or that definition may bring to you.

The first definition gives: X in A => X implements A. This is what type
systems about.

The second is: X in A => X has label 'A'. This is trivially implemented by
a map container.

>>>> You cannot claim to be a bird but refuse
>>>> to lay eggs.
>>>
>>> I can, if the definition of bird does not demand it.
>>
>> Yes, but either God or Darwin have defined birds this way. If you disagree
>> with them, you have an opportunity to re-design. It is not a disaster, but
>> might be too expensive in this particualr case... (:-))
>
> yes but the defintion may change but not the labels (in programming).

Don't even try to get me into a philosophical dispute about mind and
matter! (:-))

>> This is what I hate most in MS compilers, these 2**10 different targets:
>> Multithreaded/Not x DLL/Static x Debug/Release x ... This is the real
>> disaster. It is unmaintable if you have 10 interdependent projects for 3-4
>> platforms. How would you test it? You start to weep being asked to
>> recompile once. How about recompiling 2**10 times? In our case to compile
>> one C++ target is about 4 hours. Then somebody have to reformat the hard
>> drive, re-install the platform and test that. 2**10 times, rememeber!
>
> You may be right, what I do is create the 99% code in a non specific
> way...and then 'host' it in a specific application type.

Yes. The problem is that the compiler forces you to vary settings which
have global effect and cannot be insulated. For example, single vs.
multithreaded is a global choice all parts have to be conform to.

Robert C. Martin

unread,
Feb 27, 2005, 9:40:52 AM2/27/05
to
On Fri, 25 Feb 2005 16:41:14 -0000, "Mark Nicholls"
<nichol...@mtvne.com> wrote:

>
>"Robert C. Martin" <uncl...@objectmentor.com> wrote in message
>news:g52t1158vejh1dk89...@4ax.com...
>> On Thu, 24 Feb 2005 21:22:01 GMT, "H. S. Lahman"
>> <h.la...@verizon.net> wrote:
>>
>> >It's not you. The basic problem you describe can be summarized as:
>> >physical coupling. The OOPLs do a great job on minimizing logical
>> >coupling between program units but they do a terrible job on physical
>> >coupling.
>>
>> No. A statically typed OOPL does a better job at minimizing physical
>> couplings than a statically typed non-OOPL. A dynamically typed OOPL
>> (like smalltalk, phython, or Ruby) does a *tremendous* job of
>> minimizing physical couplings. It reduces them to near zero.
>>
>> Even in statically typed OOPLS the problem is not that bad. With a
>> good knowledge of OO design principles and design patterns, a designer
>> can reduce physical coupling in C++, Java, and C# to very low levels.
>> Indeed, *THAT* is the reason that OO language, and OO design
>> principles and patterns, are beneficial to the software industry.
>>
>
>You need to demonstrate how to solve the following trivial problem, before I
>will believe that claim.

In C++ it would be trivial to break that source code dependency, as
follows
>
------IWriteable.h-------
>class IElement;
>class IWriteable
>{
> public: virtual void Write(IElement* element) = 0;
>}

-----CPipe.h-------
#include IWriteable.h
>class CPipe : public IWriteable
>{
>...
>}

-----CPipeWriter.h-------
#include IWriteable.h
>class CPipeWriter
>{
> public: void CPipeWriter(IWriteable* writeable)
> {
> ...
> }
>
> void WriteABC();
> ...
>}

----CPipeWriter.cpp----
#include CPipeWriter.h
#include CElement.h
> void CPipeWriter::WriteABC()
> {
> writeable.write(new Element("ABC"));
> }
>
-----main.cpp-----
#include IWriteable.h
#include CPipe.h
#include CPipeWriter.h
>
>IWriteable* pipe = new CPipe();
>CPipeWriter* writer = new CPipeWriter(pipe);
>writer->WriteABC();

In this case main.cpp does not #include IElement.h. In fact the only
source file to #include IElement.h is CPipeWriter.cpp. This breaks
the source code dependency that you were worried about. That's one of
the benefits of the .h/.cpp file division in C++.

In Java and C# you can't do this. The reason is that neither compiler
depends solely on source code. When you compile a .java module, it
tries to find declarations from the .class files that it depends upon.
This means that there is a mixed source and binary dependency. So in
your example above there is no way to keep the source code of
IWriteable from depending on the binary code of IElement.

To be fair, the C++ system also depends on the binary of IElement
since it won't run without it. But in C++ that dependency is not
asserted at compile time. It's only asserted at link time (or runtime
in the case of dlls.). In Java and C# it's asserted at compile time.

The advantage of the C# and Java system is *much* faster compile
times. In C++, compile times cannot get better than O(nlogn) and even
a little carelessness will make them O(n^2). In java and c# compile
times are much closer to O(n) simply because there is no #include tree
to load for each module. So the small extra coupling is probably
worth the benefit.

If you *really* want to get rid of that coupling of IElement to the
main program, you can do it by using reflection. But I doubt it would
be worth it in most cases.

-----
Robert C. Martin (Uncle Bob) | email: uncl...@objectmentor.com
Object Mentor Inc. | blog: www.butunclebob.com
The Agile Transition Experts | web: www.objectmentor.com
800-338-6716


"The aim of science is not to open the door to infinite wisdom,
but to set a limit to infinite error."
-- Bertolt Brecht, Life of Galileo

Robert C. Martin

unread,
Feb 27, 2005, 9:50:31 AM2/27/05
to
On 26 Feb 2005 00:21:22 -0800, Nichol...@mtvne.com (Mark Nicholls)
wrote:

>"Mark Nicholls" <nichol...@mtvne.com> wrote in message news:<3897r8F...@individual.net>...
>> Actually I may be talking complete bollocks, at least about C#......I now
>> have something that does compile, even when it does not reference all the
>> subprojects.....I'll tell you on Monday.....
>
>Well spotted me.....
>
>I am (and often do) talk complete and utter rubbish....
>
>my apologies for wasting everyone's time with a wild goose chase....
>
>If your OOP demands closure via method parameter types then I suggest
>you throw it in the bin and get .net.

You may be getting fooled by the presence of assemblies that have
already been compiled, and that are accessible to the compiler.

Robert C. Martin

unread,
Feb 27, 2005, 9:48:44 AM2/27/05
to
On Fri, 25 Feb 2005 18:44:29 +0100, Laurent Bossavit
<lau...@dontspambossavit.com> wrote:


>It's what happens after the first pass that's interesting. Experimenting
>with the Java compiler will reveal that if you make some trivial change
>to the client code in Main, and ask the compiler to recompile *just*
>Main.java, the corresponding source file, then the compiler will read
>the compiled bytecode for IWriteable, CPipe, and CPipeWriter, which Main
>*directly* depends on. (It will also recompile these classes if it
>doesn't find the bytecode for them.) But the Java compiler will *not*
>access, at all, the files for IElement and Element. Changes do not
>propagate unnecessarily in Java - there isn't the physical coupling
>problem that happens in C++ unless you take steps to prevent it.

Isn't it interesting that either IElement.java or IElement.class
*must* be present when you compile main; and yet in the C++ version
IElement.h need not be present to compile main.cpp. In that sense,
C++ has managed to decouple more than Java.

Of course once you compile main in java, it's ready to run. Compiling
main.cpp in C++ does not make it ready to run because you haven't
linked it. Linking it *will* require that IElement be compiled.

So the issue is a temporal one. The java compiler needs IElement
source (or binary) code a bit sooner than C++ does. I suppose that
difference in temporal coupling could make a difference in some cases.
On the other hand, the efficiency of java compilation is probably
worth it.

Dmitry A. Kazakov

unread,
Feb 27, 2005, 11:00:25 AM2/27/05
to
On Sun, 27 Feb 2005 09:04:32 -0600, Robert C. Martin wrote:

> On Fri, 25 Feb 2005 18:08:46 GMT, "H. S. Lahman"
> <h.la...@verizon.net> wrote:
>
>>So the problem is not whether the designer /can/ reduce physical
>>coupling to low levels, it is about the fact that physical coupling
>>exists so that the developer /must/ deal with it. There is also the
>>problem of the performance hit. Lakos measured up to 3 orders of
>>magnitude performance hits when reducing physical coupling to near zero.
>

> In dynamic languages the developer does not have to deal with physical
> couplings. They are all resolved at runtime.

Disagree. There is nobody at run time who can do it. I think that the point
is that the programmer should foresee the potential problem and that must
happen before run time. If the compiler cannot not help here, but rather
moves the issue of binding to run time makes things only worse. In my view,
a late binding is acceptable if and only if it may not fail at run time.

>There is a performance hit, but nowadays it's very small.

It is difficult to judge. To me it is essential whether decoupling violates
the principle of never failing bindings or not. Dynamically polymorphic
subroutines don't violate it. Downcasting does. The first is good, the
second is bad.

As for the question what does it cost to decouple, it is far from trivial.
I wonder how the figure 3 mentioned by Lahman was obtained. It looks like
that sort of figures telling us how much someone could prolong his life by
drinking one glass of red wine per day.

Robert C. Martin

unread,
Feb 27, 2005, 10:04:32 AM2/27/05
to
On Fri, 25 Feb 2005 18:08:46 GMT, "H. S. Lahman"
<h.la...@verizon.net> wrote:

>So the problem is not whether the designer /can/ reduce physical
>coupling to low levels, it is about the fact that physical coupling
>exists so that the developer /must/ deal with it. There is also the
>problem of the performance hit. Lakos measured up to 3 orders of
>magnitude performance hits when reducing physical coupling to near zero.

In dynamic languages the developer does not have to deal with physical
couplings. They are all resolved at runtime. There is a performance


hit, but nowadays it's very small.

Developers in statically typed OO languages do have to deal with
physical coupling. Fortunately, since they are OO languages, they
have the facilities for dealing with those couplings. It is the
OO-ness of those languages that provides the ability to manage
dependencies well. Also, modern compilers (java, c#) have softened
those physical dependencies by taking tricks from the dynamic camp.
They are nowhere near as sensitive to physical changes as C++ is.

So, OO languages do not do a "terrible job at physical coupling".
They give us the tools to deal with that coupling better than most
languages do.

Robert C. Martin

unread,
Feb 27, 2005, 1:35:43 PM2/27/05
to
On Sun, 27 Feb 2005 17:00:25 +0100, "Dmitry A. Kazakov"
<mai...@dmitry-kazakov.de> wrote:

>On Sun, 27 Feb 2005 09:04:32 -0600, Robert C. Martin wrote:
>
>> In dynamic languages the developer does not have to deal with physical
>> couplings. They are all resolved at runtime.
>
>Disagree. There is nobody at run time who can do it.

Disagree. The names of methods and classes are initially looked up at
runtime.

H. S. Lahman

unread,
Feb 27, 2005, 2:24:28 PM2/27/05
to
Responding to Martin...

>>So the problem is not whether the designer /can/ reduce physical
>>coupling to low levels, it is about the fact that physical coupling
>>exists so that the developer /must/ deal with it. There is also the
>>problem of the performance hit. Lakos measured up to 3 orders of
>>magnitude performance hits when reducing physical coupling to near zero.
>
>
> In dynamic languages the developer does not have to deal with physical
> couplings. They are all resolved at runtime. There is a performance
> hit, but nowadays it's very small.

Are you saying that you do not need to practice your Principles for
dependency management when you program in Smalltalk? As I recall, a lot
of your original examples on your web site were from Smalltalk.

Whether the binding is static or dynamic, it is still bound to the
implementation in the OOPLs (e.g., dispatch tables are still accessed by
relative offset). What you seem to be saying is that physical coupling
magically goes away when a language is interpreted just because the type
mapping to the implementation is done "on the fly". It doesn't; you
just pay for it in a different way (e.g., performance vs.
compile-the-world).


>
> Developers in statically typed OO languages do have to deal with
> physical coupling. Fortunately, since they are OO languages, they
> have the facilities for dealing with those couplings. It is the
> OO-ness of those languages that provides the ability to manage
> dependencies well. Also, modern compilers (java, c#) have softened
> those physical dependencies by taking tricks from the dynamic camp.
> They are nowhere near as sensitive to physical changes as C++ is.

Note that in my original post I specifically said that C++ was the worst
offender and that is was less of a problem for dynamically bound OOPLs
than for statically bound ones. But...

> So, OO languages do not do a "terrible job at physical coupling".
> They give us the tools to deal with that coupling better than most
> languages do.

All of the OOPLs are still worse than most procedural languages because
of higher levels of abstraction, subclassing, polymorphic access, etc.
IOW, the OOPL type systems are much more sophisticated.

Dmitry A. Kazakov

unread,
Feb 27, 2005, 3:38:02 PM2/27/05
to
On Sun, 27 Feb 2005 12:35:43 -0600, Robert C. Martin wrote:

> On Sun, 27 Feb 2005 17:00:25 +0100, "Dmitry A. Kazakov"
> <mai...@dmitry-kazakov.de> wrote:
>
>>On Sun, 27 Feb 2005 09:04:32 -0600, Robert C. Martin wrote:
>>
>>> In dynamic languages the developer does not have to deal with physical
>>> couplings. They are all resolved at runtime.
>>
>>Disagree. There is nobody at run time who can do it.
>
> Disagree. The names of methods and classes are initially looked up at
> runtime.

So? When the target is not found, there is no other way to deal with that
than to throw an exception. Either you let that exception propagating to
kill the program or you have to handle it. That is to write a handler, and
this has to happen *before* run time. The handler need to be written.

The bottom line is, that the coupling cannot be resolved at run time. This
or that way the programmer has to deal with it before the program starts.
It is much better when coupling errors are manifested as compile errors,
much worse when they do as link errors (C++ is infamous for that) and for
all, run time exceptions is the worst possible case.

I agree with H. S. Lahman that coupling does not disappear, it is only
re-shaped into this or that form, and among them, coupling through
exception is the worst.

Mark Nicholls

unread,
Feb 28, 2005, 4:48:05 AM2/28/05
to
>
> If you *really* want to get rid of that coupling of IElement to the
> main program, you can do it by using reflection. But I doubt it would
> be worth it in most cases.
>

My head has been well an truly boiled now.....as I say, it's all a red
herring.....C# does not traverse the parameter dependency....unless you
reference it.............thanks anyway....next time I'll check my
facts......then again probably not.....


Robert C. Martin

unread,
Feb 28, 2005, 3:28:41 PM2/28/05
to
On Sun, 27 Feb 2005 21:38:02 +0100, "Dmitry A. Kazakov"
<mai...@dmitry-kazakov.de> wrote:

>On Sun, 27 Feb 2005 12:35:43 -0600, Robert C. Martin wrote:
>
>> On Sun, 27 Feb 2005 17:00:25 +0100, "Dmitry A. Kazakov"
>> <mai...@dmitry-kazakov.de> wrote:
>>
>>>On Sun, 27 Feb 2005 09:04:32 -0600, Robert C. Martin wrote:
>>>
>>>> In dynamic languages the developer does not have to deal with physical
>>>> couplings. They are all resolved at runtime.
>>>
>>>Disagree. There is nobody at run time who can do it.
>>
>> Disagree. The names of methods and classes are initially looked up at
>> runtime.
>
>So? When the target is not found, there is no other way to deal with that
>than to throw an exception.

In the case where all the couplings are resolved, they are resolved at
runtime. The compiler does not resolve them. This means that each
source code module is independent of all others; and no change to one
module can physically force a change to another.

>I agree with H. S. Lahman that coupling does not disappear,

True, but it moves. And moving it to runtime makes for *much* more
flexible source code. (Not to mention much faster build times).

Robert C. Martin

unread,
Feb 28, 2005, 4:42:44 PM2/28/05
to
On Sun, 27 Feb 2005 19:24:28 GMT, "H. S. Lahman"
<h.la...@verizon.net> wrote:

>Responding to Martin...
>
>>>So the problem is not whether the designer /can/ reduce physical
>>>coupling to low levels, it is about the fact that physical coupling
>>>exists so that the developer /must/ deal with it. There is also the
>>>problem of the performance hit. Lakos measured up to 3 orders of
>>>magnitude performance hits when reducing physical coupling to near zero.
>>
>>
>> In dynamic languages the developer does not have to deal with physical
>> couplings. They are all resolved at runtime. There is a performance
>> hit, but nowadays it's very small.
>
>Are you saying that you do not need to practice your Principles for
>dependency management when you program in Smalltalk? As I recall, a lot
>of your original examples on your web site were from Smalltalk.

None of the examples I have written have been in Smalltalk. I've
never written more than 1000 lines of Smalltalk. I've written more
Phython and Ruby than Smalltalk; but haven't written any articles with
examples in those languages either.

To answer your question, many of the principles I talk about are for
statically typed languages; and have either no application, or a very
altered application, in dynamically typed languages.

For example, the Interface Segregation Principle (ISP) is a strategy
for limiting the incidental or accidental dependence of clients upon
method that they don't call, but that are declared in service objects.
This is a large issue in statically typed language, but a complete
non-issue in dynamically typed languages.


>
>Whether the binding is static or dynamic, it is still bound to the
>implementation in the OOPLs (e.g., dispatch tables are still accessed by
>relative offset). What you seem to be saying is that physical coupling
>magically goes away when a language is interpreted just because the type
>mapping to the implementation is done "on the fly". It doesn't; you
>just pay for it in a different way (e.g., performance vs.
>compile-the-world).

TANSTAAFL. On the other hand there are expensive lunches and cheap
lunches.

The physical coupling I am talking about is the coupling that prevents
independent deployability. Let's say I have two modules A and B.
When I fix a bug, or add a feature, I'd like to only ship those
modules that have changed. I don't want to ship any modules that
haven't directly changed.

In statically typed languages, the physical dependencies are often so
strong that many unchanged modules must be deployed with the changed
modules. If I change module A, but B inherits from module A, I must
ship module B even though I didn't change it. In a dynamically typed
language I don't have to ship B. I only have to ship the modules that
I made direct changes to. This is a huge difference, and may be worth
paying a small performance price for. (The performance price has
gotten very small indeed for languages like Smalltalk and Python).

In statically typed language it is possible to minimize the set of
modules that need to be shipped by following the dependency management
principle that I espouse.

>> So, OO languages do not do a "terrible job at physical coupling".
>> They give us the tools to deal with that coupling better than most
>> languages do.
>
>All of the OOPLs are still worse than most procedural languages because
>of higher levels of abstraction, subclassing, polymorphic access, etc.

No. All of the OOPLS, whether static or dynamic, enable independent
deployability more than procedural languages do.

Dmitry A. Kazakov

unread,
Mar 1, 2005, 4:35:23 AM3/1/05
to
On Mon, 28 Feb 2005 14:28:41 -0600, Robert C. Martin wrote:

> On Sun, 27 Feb 2005 21:38:02 +0100, "Dmitry A. Kazakov"
> <mai...@dmitry-kazakov.de> wrote:
>
>>On Sun, 27 Feb 2005 12:35:43 -0600, Robert C. Martin wrote:
>>
>>> On Sun, 27 Feb 2005 17:00:25 +0100, "Dmitry A. Kazakov"
>>> <mai...@dmitry-kazakov.de> wrote:
>>>
>>>>On Sun, 27 Feb 2005 09:04:32 -0600, Robert C. Martin wrote:
>>>>
>>>>> In dynamic languages the developer does not have to deal with physical
>>>>> couplings. They are all resolved at runtime.
>>>>
>>>>Disagree. There is nobody at run time who can do it.
>>>
>>> Disagree. The names of methods and classes are initially looked up at
>>> runtime.
>>
>>So? When the target is not found, there is no other way to deal with that
>>than to throw an exception.
>
> In the case where all the couplings are resolved, they are resolved at
> runtime. The compiler does not resolve them.

But it shall check if the couplings are indeed resolvable. Otherwise it
makes no sense. And an ability to check that is again a coupling. It might
be a weaker coupling, but also it might be a stronger coupling.

> This means that each
> source code module is independent of all others; and no change to one
> module can physically force a change to another.

If you mean source code changes, then that is achievable independently on
dynamic vs. static typing issue. The obvious point is that you are not
forced to map all couplings into type relations, neither you can do that.
So if you don't then the static nature of type relations will be
irrelevant. For example, if you change only the implementation of a module,
that does not have any effect on other modules. The question is what is
implementation. The beauty of dynamic polymorphism is exactly in that. It
splits then implementation of a polymorphic routine into separate modules,
which can be changed independently.

>>I agree with H. S. Lahman that coupling does not disappear,
>
> True, but it moves. And moving it to runtime makes for *much* more
> flexible source code. (Not to mention much faster build times).

It is not the moving that can bring an advantage here. In first place it is
splitting couplings into parts. Some of them indeed are moved to run time.
Others remain at compile time and *ensure* that the run time ones will
never fail. That rest cannot be reduced to null. If you try to do that it
will hit back in the form of exception handling code.

H. S. Lahman

unread,
Mar 2, 2005, 7:18:21 PM3/2/05
to
Responding to Martin...

>>>>So the problem is not whether the designer /can/ reduce physical
>>>>coupling to low levels, it is about the fact that physical coupling
>>>>exists so that the developer /must/ deal with it. There is also the
>>>>problem of the performance hit. Lakos measured up to 3 orders of
>>>>magnitude performance hits when reducing physical coupling to near zero.
>>>
>>>
>>>In dynamic languages the developer does not have to deal with physical
>>>couplings. They are all resolved at runtime. There is a performance
>>>hit, but nowadays it's very small.
>>
>>Are you saying that you do not need to practice your Principles for
>>dependency management when you program in Smalltalk? As I recall, a lot
>>of your original examples on your web site were from Smalltalk.
>
>
> None of the examples I have written have been in Smalltalk. I've
> never written more than 1000 lines of Smalltalk. I've written more
> Phython and Ruby than Smalltalk; but haven't written any articles with
> examples in those languages either.

OK, I stand corrected. Somebody in the early XP crowd was talking about
refactoring with Smalltalk, though. (Maybe Jeffries/C3?)

>
> To answer your question, many of the principles I talk about are for
> statically typed languages; and have either no application, or a very
> altered application, in dynamically typed languages.
>
> For example, the Interface Segregation Principle (ISP) is a strategy
> for limiting the incidental or accidental dependence of clients upon
> method that they don't call, but that are declared in service objects.
> This is a large issue in statically typed language, but a complete
> non-issue in dynamically typed languages.

OK. But what about principles like OCP and DIP where one creates
abstract interfaces expressly to avoid the namespace coupling of
concrete extensions? Surely you would do the same in a dynamically
bound OOPL, right?

>>Whether the binding is static or dynamic, it is still bound to the
>>implementation in the OOPLs (e.g., dispatch tables are still accessed by
>>relative offset). What you seem to be saying is that physical coupling
>>magically goes away when a language is interpreted just because the type
>>mapping to the implementation is done "on the fly". It doesn't; you
>>just pay for it in a different way (e.g., performance vs.
>>compile-the-world).
>
>
> TANSTAAFL. On the other hand there are expensive lunches and cheap
> lunches.
>
> The physical coupling I am talking about is the coupling that prevents
> independent deployability. Let's say I have two modules A and B.
> When I fix a bug, or add a feature, I'd like to only ship those
> modules that have changed. I don't want to ship any modules that
> haven't directly changed.
>
> In statically typed languages, the physical dependencies are often so
> strong that many unchanged modules must be deployed with the changed
> modules. If I change module A, but B inherits from module A, I must
> ship module B even though I didn't change it. In a dynamically typed
> language I don't have to ship B. I only have to ship the modules that
> I made direct changes to. This is a huge difference, and may be worth
> paying a small performance price for. (The performance price has
> gotten very small indeed for languages like Smalltalk and Python).

Again, this is just arguing that the problem goes away if the language
is interpreted (i.e., there is no physical coupling if there are no
"compilable units"). So one trades work to manage dependencies for a
performance overhead in all situations. IOW, in a dynamically bound
OOPL one has to pay the fee (performance) for not incurring the
statically bound fee (dependency management).

[BTW, I am also not convinced the performance price is all that small.
For example, to provide the subclassing deployability in your example,
when constructing an instance on-the-fly the interpreter will have to
find and "walk" every class definition in the line of ascent. Granted,
it only does that once while the instance may be accessed many times.
But it has to do it for every instance created during the execution.]

I would further argue that this is only one manifestation of physical
coupling. If anything, the mapping of namespaces is a bigger problem
for dynamically bound OOPLs than for statically bound OOPLs. By the
time the compiler hands off to the linker, everything has been resolved
to relative addresses but in a dynamically bound OOPL one still needs
identity for type checking.

>>>So, OO languages do not do a "terrible job at physical coupling".
>>>They give us the tools to deal with that coupling better than most
>>>languages do.
>>
>>All of the OOPLs are still worse than most procedural languages because
>>of higher levels of abstraction, subclassing, polymorphic access, etc.
>
>
> No. All of the OOPLS, whether static or dynamic, enable independent
> deployability more than procedural languages do.

Only for a very narrow definition of 'deployability' and then only if
the developer does the grunt work. For example, I can add procedures
and state variables to my heart's content anywhere in a C .h file. I
can then compile its body file and deploy the resulting object code.
Everything else will Just Work without any performance penalty or any
developer added effort. IOW, your ISP always works for non-OOPLs.

In general I can't do that with any class definition file for any
statically bound OOPL without compiling a lot of other modules -- even
when I haven't changed any ADTs or signatures. If I do a lot of work
(e.g., ISP), I can reduce the amount of recompilation, but I can't
eliminate it. And I can't deploy that source in a dynamically bound
OOPL without always paying the overall performance penalty.

Robert C. Martin

unread,
Mar 2, 2005, 8:06:45 PM3/2/05
to
On Thu, 03 Mar 2005 00:18:21 GMT, "H. S. Lahman"
<h.la...@verizon.net> wrote:

>OK. But what about principles like OCP and DIP where one creates
>abstract interfaces expressly to avoid the namespace coupling of
>concrete extensions? Surely you would do the same in a dynamically
>bound OOPL, right?

No. In a dynamically typed language there is no reason to create an
abstract class, or interface, to avoid namespace coupling. There is
no namespace coupling in these languages. The sender of a message has
no need to know anything about the type of the object it is sending
to. You can obtain an opaque object from any source and send it any
message you like. The compiler doesn't check.

So:

o = getSomeObject();
o.someMessage();

'o' is a variable. I get some object from someplace, and then I send
it a message. The compiler happily accepts this even though it has no
idea what type 'o' is, or if it can respond to 'someMessage'. Those
two lines will compile without the need for the compiler to access any
other declarations, header files, .class files, or any other extra
information. Those two lines are enough.

So a java style interfaces are almost worthless in these language.
C++ style abstract classes are sometimes useful for inheritance of
implementation, but almost never for inheritance of interface.

Robert C. Martin

unread,
Mar 2, 2005, 8:45:44 PM3/2/05
to
On Thu, 03 Mar 2005 00:18:21 GMT, "H. S. Lahman"
<h.la...@verizon.net> wrote:

>> In statically typed languages, the physical dependencies are often so
>> strong that many unchanged modules must be deployed with the changed
>> modules. If I change module A, but B inherits from module A, I must
>> ship module B even though I didn't change it. In a dynamically typed
>> language I don't have to ship B. I only have to ship the modules that
>> I made direct changes to. This is a huge difference, and may be worth
>> paying a small performance price for. (The performance price has
>> gotten very small indeed for languages like Smalltalk and Python).
>
>Again, this is just arguing that the problem goes away if the language
>is interpreted (i.e., there is no physical coupling if there are no
>"compilable units").

The use of the word "interpreted" is a bit off here. Most of these
languages are compiled down into byte codes. The byte codes may be
interpreted at first (as in Java) but good systems could swap in
native code (as in Java).

>[BTW, I am also not convinced the performance price is all that small.

Think of it as the cost of linking, done at runtime. Rather like the
cost of loading a dll. In a good system you pay for it once.

>I would further argue that this is only one manifestation of physical
>coupling. If anything, the mapping of namespaces is a bigger problem
>for dynamically bound OOPLs than for statically bound OOPLs. By the
>time the compiler hands off to the linker, everything has been resolved
>to relative addresses but in a dynamically bound OOPL one still needs
>identity for type checking.

Nowadays, even statically typed languages are being driven towards
DLLs and Shared libraries. So the linker never gets to finish it's
job, and the runtime environment is left to resolve the remaining
references.

Some dynamic languages solve the namespace problem by shipping the
entire executable image (smalltalk). For others you have to supply
search paths so that the runtime system can find all the little
components. In Microsoft systems (written in C++) this is called DLL
Hell.

So, though I agree that it is a problem, it is neither unique to, nor
worse than statically typed languages.

Robert C. Martin

unread,
Mar 2, 2005, 8:51:50 PM3/2/05
to
On Thu, 03 Mar 2005 00:18:21 GMT, "H. S. Lahman"
<h.la...@verizon.net> wrote:

>> No. All of the OOPLS, whether static or dynamic, enable independent
>> deployability more than procedural languages do.
>
>Only for a very narrow definition of 'deployability' and then only if
>the developer does the grunt work. For example, I can add procedures
>and state variables to my heart's content anywhere in a C .h file. I
>can then compile its body file and deploy the resulting object code.
>Everything else will Just Work without any performance penalty or any
>developer added effort. IOW, your ISP always works for non-OOPLs.

I don't recognize that as ISP. Also, I don't quite agree with the
premise. If I make a change to a .h file, I must recompile every
module that #includes that .h file. Then I must relink the system
before I can deploy it. If I am linking into DLLs, and if that .h file
is included in more than one DLL, then I must rebuild and redeploy
each DLL.

>In general I can't do that with any class definition file for any
>statically bound OOPL without compiling a lot of other modules -- even
>when I haven't changed any ADTs or signatures.

In C++, if I design the system well, I can make changes to concrete
classes without recompiling anything else. I can build that class
into a single DLL or Jar file, and not have to rebuild or redeploy any
others.

>If I do a lot of work
>(e.g., ISP), I can reduce the amount of recompilation, but I can't
>eliminate it. And I can't deploy that source in a dynamically bound
>OOPL without always paying the overall performance penalty.

Granted. However, the ability to separate and independently deploy
modules (dlls, shared libraries, or even jar files) is greatly
enhanced by the ability to create polymorphic interfaces. Procedural
languages must rely on vector tables to achieve the same independent
deployability.

H. S. Lahman

unread,
Mar 3, 2005, 5:44:09 PM3/3/05
to
Responding to Martin...

>>OK. But what about principles like OCP and DIP where one creates
>>abstract interfaces expressly to avoid the namespace coupling of
>>concrete extensions? Surely you would do the same in a dynamically
>>bound OOPL, right?
>
>
> No. In a dynamically typed language there is no reason to create an
> abstract class, or interface, to avoid namespace coupling. There is
> no namespace coupling in these languages. The sender of a message has
> no need to know anything about the type of the object it is sending
> to. You can obtain an opaque object from any source and send it any
> message you like. The compiler doesn't check.
>
> So:
>
> o = getSomeObject();
> o.someMessage();

This is a solution, not the problem. The caller here (i.e., the method
containing the code fragment) is using o, in the terminology of your
OCP. If the assignment of o is "hard-wired" to a specific object, the
caller cannot cannot be extended to use a different object without
modifying the assignment in the caller and OCP is violated. The fix is
to not hard-wire a specific object in the assignment, which you do here
by delegating the selection to getSomeObject. Then the OCP problem for
the caller goes away.


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

H. S. Lahman
h...@pathfindermda.com
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com

blog: http://pathfinderpeople.blogs.com/hslahman
(888)OOA-PATH

H. S. Lahman

unread,
Mar 3, 2005, 6:09:16 PM3/3/05
to
Responding to Martin...

>>>In statically typed languages, the physical dependencies are often so
>>>strong that many unchanged modules must be deployed with the changed
>>>modules. If I change module A, but B inherits from module A, I must
>>>ship module B even though I didn't change it. In a dynamically typed
>>>language I don't have to ship B. I only have to ship the modules that
>>>I made direct changes to. This is a huge difference, and may be worth
>>>paying a small performance price for. (The performance price has
>>>gotten very small indeed for languages like Smalltalk and Python).
>>
>>Again, this is just arguing that the problem goes away if the language
>>is interpreted (i.e., there is no physical coupling if there are no
>>"compilable units").
>
>
> The use of the word "interpreted" is a bit off here. Most of these
> languages are compiled down into byte codes. The byte codes may be
> interpreted at first (as in Java) but good systems could swap in
> native code (as in Java).

To the extent that dynamically bound languages compile to bytecodes, I
think you are arguing my case for me. Those structures make the run
time environment more efficient (e.g., finding the right type to check).
I would expect the performance to depend on the efficiency of
constructing and traversing those structures. That, in turn, I would
expect to be based on the way dependencies were managed in the source
(at least to some extent).

>>[BTW, I am also not convinced the performance price is all that small.
>
>
> Think of it as the cost of linking, done at runtime. Rather like the
> cost of loading a dll. In a good system you pay for it once.

I don't think it is quite that simple. Consider your subclassing
example of deployment. To ensure that degree of deployability, when
creating an instance the run time environment must "walk" every class
definition in the line of ascent to properly build the instance. And it
has to do that for every instance created.

>>I would further argue that this is only one manifestation of physical
>>coupling. If anything, the mapping of namespaces is a bigger problem
>>for dynamically bound OOPLs than for statically bound OOPLs. By the
>>time the compiler hands off to the linker, everything has been resolved
>>to relative addresses but in a dynamically bound OOPL one still needs
>>identity for type checking.
>
>
> Nowadays, even statically typed languages are being driven towards
> DLLs and Shared libraries. So the linker never gets to finish it's
> job, and the runtime environment is left to resolve the remaining
> references.

Filling in a relative entry point table when a DLL is opened and using
hard-wired indexing through it for access is one thing. Managing type
identity for checking on every access is quite another.


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

H. S. Lahman
h...@pathfindermda.com
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com

blog: http://pathfinderpeople.blogs.com/hslahman
(888)OOA-PATH

H. S. Lahman

unread,
Mar 3, 2005, 6:48:17 PM3/3/05
to
REsponding to Martin...

>>>No. All of the OOPLS, whether static or dynamic, enable independent
>>>deployability more than procedural languages do.
>>
>>Only for a very narrow definition of 'deployability' and then only if
>>the developer does the grunt work. For example, I can add procedures
>>and state variables to my heart's content anywhere in a C .h file. I
>>can then compile its body file and deploy the resulting object code.
>>Everything else will Just Work without any performance penalty or any
>>developer added effort. IOW, your ISP always works for non-OOPLs.
>
>
> I don't recognize that as ISP. Also, I don't quite agree with the
> premise. If I make a change to a .h file, I must recompile every
> module that #includes that .h file. Then I must relink the system
> before I can deploy it. If I am linking into DLLs, and if that .h file
> is included in more than one DLL, then I must rebuild and redeploy
> each DLL.

That's the normal, bullet-proof approach. It's bullet-proof because it
deals with every possible change. But it is only /necessary/ if you
make a change to a state variable or signature that _is already accessed
in the original code_. If all you do is add stuff that nobody
references in other modules, then you can compile it alone and link it
with the existing object modules and it will Just Work.

ISP comes in because the other code that does not need the added stuff
is never affected by it. (I could subsequently modify the added stuff,
recompile it, relink it, and everything would still Just Work.)

>>In general I can't do that with any class definition file for any
>>statically bound OOPL without compiling a lot of other modules -- even
>>when I haven't changed any ADTs or signatures.
>
>
> In C++, if I design the system well, I can make changes to concrete
> classes without recompiling anything else. I can build that class
> into a single DLL or Jar file, and not have to rebuild or redeploy any
> others.

Only if you provide another class (Facade, abstract class, etc.) so that
no other class directly accesses it (i.e., no external module bodies
include its header). In the C example the existing state variables and
procedures were accessed directly (i.e., the header was included).

>>If I do a lot of work
>>(e.g., ISP), I can reduce the amount of recompilation, but I can't
>>eliminate it. And I can't deploy that source in a dynamically bound
>>OOPL without always paying the overall performance penalty.
>
>
> Granted. However, the ability to separate and independently deploy
> modules (dlls, shared libraries, or even jar files) is greatly
> enhanced by the ability to create polymorphic interfaces. Procedural
> languages must rely on vector tables to achieve the same independent
> deployability.

Say, what?!? I've deployed C, Basic, BLISS, FORTRAN, and COBOL in
libraries and DLLs with relatively few problems. We even did C, Basic,
FORTRAN, and C++ in the same application once. I've had more problems
with C++ than all the rest combined. In fact, we ended up deploying our
C++ device driver within a C Facade because that was the only way we
could ensure the rest of the world would be able to talk to it.

And it wasn't even possible to link in LISP or Smalltalk with other
languages until relatively recently.


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

H. S. Lahman
h...@pathfindermda.com
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com

blog: http://pathfinderpeople.blogs.com/hslahman
(888)OOA-PATH

0 new messages