473,395 Members | 1,815 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Elegant design with interfaces (in C#)

Question about best use of interfaces:

Say there's a 'Master' class that needs to implement a few
interfaces:

class Master : I1, I2, I3
{
}

The actual code already exists in smaller classes that each
implement one or two of those interfaces:

class Group1 : I1
{
}

class Group2 : I2, I3
{
}

The goal is to have the larger Master object serve as a substitute
for (ie wrap) the two smaller Group objects. IOW, I need to be
able to call Master.Function1() just like I'd call Group1.Function1().
Or cast an I1 pointer to working code in Master.

I'd love to just instantiate Group1 and Group2 and 'point' the
Master object's interfaces at them en masse. I'm looking
for some way for a factory to say:

class Master : I1, I2, I3
{
I1 = new Group1();
I2 = new Group2();
...
}

Of course I know the above is an idealized abstraction, but I'd
like avoid having to map each individual function in every interface
by hand. What is the best way to do this?

Jun 24 '06 #1
18 1954
How about you don't have the 'master' class implement the three other
interfaces, but rather have it encapsulate them.

class Master
{
public I1 referenceI1;
public I2 referenceI2;

public Master()
{
referenceI1 = new I1();
referenceI2 = new I2();
}
}

public callingcode()
{
Master m = new Master();
m.referenceI1.I1method();
m.referenceI2.I2method();
}

nope... not OO. But then again, there's a reason that multiple inheritance
is not supported in C#.

It's a source of inefficiency, defects, and brittle code. Not a good
practice. My guess is that you came over to C# from C++ and you figure you
can use this mechanism to get it to work.

If you really break down your problem with techniques like CVA, you can
nearly always factor out the multiple inheritance and end up with a better
design. In those rare cases where you cannot... either do the kludge above
or the one you refer to (hard-coding calls for each method).

Think about what you are trying to do and I'm willing to bet that you
probably don't need the multiple inheritance.

Good luck,
--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
--
"_dee" <no****@nomail.com> wrote in message
news:86********************************@4ax.com...
Question about best use of interfaces:

Say there's a 'Master' class that needs to implement a few
interfaces:

class Master : I1, I2, I3
{
}

The actual code already exists in smaller classes that each
implement one or two of those interfaces:

class Group1 : I1
{
}

class Group2 : I2, I3
{
}

The goal is to have the larger Master object serve as a substitute
for (ie wrap) the two smaller Group objects. IOW, I need to be
able to call Master.Function1() just like I'd call Group1.Function1().
Or cast an I1 pointer to working code in Master.

I'd love to just instantiate Group1 and Group2 and 'point' the
Master object's interfaces at them en masse. I'm looking
for some way for a factory to say:

class Master : I1, I2, I3
{
I1 = new Group1();
I2 = new Group2();
...
}

Of course I know the above is an idealized abstraction, but I'd
like avoid having to map each individual function in every interface
by hand. What is the best way to do this?

Jun 24 '06 #2
Nick Malik [Microsoft] wrote:
How about you don't have the 'master' class implement the three other
interfaces, but rather have it encapsulate them.

class Master
{
public I1 referenceI1;
public I2 referenceI2;

public Master()
{
referenceI1 = new I1();
referenceI2 = new I2();
}
}

public callingcode()
{
Master m = new Master();
m.referenceI1.I1method();
m.referenceI2.I2method();
}

nope... not OO. But then again, there's a reason that multiple
inheritance is not supported in C#.

It's a source of inefficiency, defects, and brittle code. Not a good
practice. My guess is that you came over to C# from C++ and you
figure you can use this mechanism to get it to work.


I always find that a hard to believe argument. If I look at how Eiffel
does MI, I dont think there are major problems with every day code.
Sure, there are always problems with corner cases, but that's also the
case with SI.

If you look at interfaces, they're a way to define multiple TYPE
inheritance, where you fill in the implementation yourself. With
multiple IMPLEMENTATION inheritance (i.e. what's called MI in short)
you get that implementation for free. True, you can shoot yourself in
the foot easily, but that's also the case with SI + multiple type
inheritance: because you've to provide the implementation yourself, you
can end up with duplicate code.

In this particular case, I agree that aggregation is perhaps a good
approach, where the master simply inherits all the interfaces and
delegates the implementation to aggregated instances of Group1 and
Group2. Though IMHO not ideal.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
Jun 24 '06 #3
On Sat, 24 Jun 2006 02:11:07 -0700, "Nick Malik [Microsoft]"
<ni*******@hotmail.nospam.com> wrote:
How about you don't have the 'master' class implement the three other
interfaces, but rather have it encapsulate them.

class Master
{
public I1 referenceI1;
public I2 referenceI2;

public Master()
{
referenceI1 = new I1();
referenceI2 = new I2();
}
}

public callingcode()
{
Master m = new Master();
m.referenceI1.I1method();
m.referenceI2.I2method();
}
Thanks for your reply, Nick. The objective was to avoid the second
level of reference (referenceI1) above. This is so a factory can
assemble groups of sub-objects into one larger entity that is regarded
as a "Master" object and pass that to a function that uses it without
knowing anything more than what interfaces are available.
User-functions that used to call the smaller sub-objects can now use
the larger one.

To think of what is probably a crappy analogy, say you had the option
to use simulated 3D graphics, or to use hardware-accelerated 3D. There
are objects:

Sim3DCircle : IDrawCircle
Sim3DBox : IDrawBox
Accel3DCircle : IDrawCircle
Accel3DBox : IDrawBox

You want the factory to put those together into a larger object,
according to what hardware is available, then pass that larger object
as though it implements IDrawCircle and IDrawBox directly. So on the
user side, you could do this:

Master M = Factory(params); // factory assembles sub-objects
IDrawCircle IDC = (IDrawCircle)Master;
IDrawBox IDB = (IDrawBox)Master;

You would not need to know what the factory put inside the Master
object. (This is starting to sound like a Design Patterns excercise,
but I'm more interested in how the factory would wire up the Master's
internals)

Something like the interface structure above is done in DirectX, for
instance, where you can create a FilterGraph, then cast IMediaControl,
etc. from the FilterGraph object. IMediaControl can be controlling a
video file, an audio file, etc. The user doesn't need to know.

But part of the charm is that the interfaces can be cast directly.
nope... not OO. But then again, there's a reason that multiple inheritance
is not supported in C#.

It's a source of inefficiency, defects, and brittle code. Not a good
practice. My guess is that you came over to C# from C++ and you figure you
can use this mechanism to get it to work.
I may be missing something, but I thought the whole point of
interfaces was to get around problems with multiple inheritance (MI),
including the diamond inheritance model.

So while I did indeed come from C++ (didn't everyone?), I was never
enamored of MI. In fact, I've never looked at multiple interfaces as
multiple inheritance.
If you really break down your problem with techniques like CVA, you can
nearly always factor out the multiple inheritance and end up with a better
design. In those rare cases where you cannot... either do the kludge above
or the one you refer to (hard-coding calls for each method).

Think about what you are trying to do and I'm willing to bet that you
probably don't need the multiple inheritance.


I was trying to approach the initial design from an abstract
viewpoint, and thought that this was the best looking and simplest
from the user standpoint. Implementing the internals may be another
story.

So...any ideas on how the factory could wire up the interfaces in my
example Circle/Box code above? It looks like I'd have to create the
internal Circle and Box drawing objects first, then write functions
inside Master that matched their Interface functions, but called into
the internal objects. That's a lot of ugly code.

Jun 24 '06 #4
In article <86********************************@4ax.com>,
_dee <no****@nomail.com> wrote:
Question about best use of interfaces:

Say there's a 'Master' class that needs to implement a few
interfaces:

class Master : I1, I2, I3
{
}

The actual code already exists in smaller classes that each
implement one or two of those interfaces:

class Group1 : I1
{
}

class Group2 : I2, I3
{
}

The goal is to have the larger Master object serve as a substitute
for (ie wrap) the two smaller Group objects. IOW, I need to be
able to call Master.Function1() just like I'd call Group1.Function1().
Or cast an I1 pointer to working code in Master.

I'd love to just instantiate Group1 and Group2 and 'point' the
Master object's interfaces at them en masse. I'm looking
for some way for a factory to say:

class Master : I1, I2, I3
{
I1 = new Group1();
I2 = new Group2();
...
}

Of course I know the above is an idealized abstraction, but I'd
like avoid having to map each individual function in every interface
by hand. What is the best way to do this?


The answer to your explicit question would probably best be found in a
C# newsgroup. In this newsgroup, you will mainly get responses about the
theoretical integrity of such a construct.

A basic heuristic of OO programming, is that most of the methods of a
class should use most of the fields of the class most of the time. What
you are asking about is how to "elegantly" make a class that has
completely independent fields. There may be an elegant way to do it in
C#, but no OO guru would find the concept elegant.
Jun 24 '06 #5
_dee wrote:
Question about best use of interfaces:

Say there's a 'Master' class that needs to implement a few
interfaces:

class Master : I1, I2, I3
{
}

The actual code already exists in smaller classes that each
implement one or two of those interfaces:

class Group1 : I1
{
}

class Group2 : I2, I3
{
}

The goal is to have the larger Master object serve as a substitute
for (ie wrap) the two smaller Group objects. IOW, I need to be
able to call Master.Function1() just like I'd call Group1.Function1().
Or cast an I1 pointer to working code in Master.

I'd love to just instantiate Group1 and Group2 and 'point' the
Master object's interfaces at them en masse. I'm looking
for some way for a factory to say:

class Master : I1, I2, I3
{
I1 = new Group1();
I2 = new Group2();
...
}

Of course I know the above is an idealized abstraction, but I'd
like avoid having to map each individual function in every interface
by hand. What is the best way to do this?


Hi _dee

Maybe, ServiceContainer class could help you out. It basically allows
you to register services via AddService, and then retrieve them via
GetService. Check it out in msdn.

This is not as elegant as what you wrote in original post. But you can
achieve dynamic composure of different implementation (if I'm not
mistaking, this is being used by the Winforms designer).

HTH,
Sasa
Jun 24 '06 #6
Nick Malik [Microsoft] wrote:
How about you don't have the 'master' class implement the three other
interfaces, but rather have it encapsulate them.

class Master
{
public I1 referenceI1;
public I2 referenceI2;

public Master()
{
referenceI1 = new I1();
referenceI2 = new I2();
}
}

public callingcode()
{
Master m = new Master();
m.referenceI1.I1method();
m.referenceI2.I2method();
}
This seems fine, but the referenceI* can be set from anywhere (and not
only from the builder). I actually sometimes miss friend declaration in
C# :-(

I'm guessing (but currently am too lazy and tired to try it out), that
strongly typed Master which would receive ServiceContainer in its
constructor, and then simply delegate to appropriate services should do
the trick.
nope... not OO. But then again, there's a reason that multiple inheritance
is not supported in C#.
IMHO, _dee's problem is not about multiple inheritance, and actually
cannot be resolved if one had that possibility in C#. The problem
amounts to setting the implementations in runtime (which your code
resolves).

But in real multiple inheritance (i.e. inheritance of implementation and
not just interface) on does that in compile time.
It's a source of inefficiency, defects, and brittle code. Not a good
practice. My guess is that you came over to C# from C++ and you figure you
can use this mechanism to get it to work.


I agree with Frans Bouma's comments on this.

Sasa
Jun 24 '06 #7
On Sat, 24 Jun 2006 15:10:13 GMT, "Daniel T." <da******@earthlink.net>
wrote:
In article <86********************************@4ax.com>,
_dee <no****@nomail.com> wrote:
I'd love to just instantiate Group1 and Group2 and 'point' the
Master object's interfaces at them en masse. I'm looking
for some way for a factory to say:

class Master : I1, I2, I3
{
I1 = new Group1();
I2 = new Group2();
...
}

Of course I know the above is an idealized abstraction, but I'd
like avoid having to map each individual function in every interface
by hand. What is the best way to do this?


The answer to your explicit question would probably best be found in a
C# newsgroup. In this newsgroup, you will mainly get responses about the
theoretical integrity of such a construct.


That's fine with me. The question seemed part theoretical, part
practical, so I posted it to the main C# group + comp.object. If
there is a theoretical side that I'm overlooking, I'd like to know
about that early on. See below.
A basic heuristic of OO programming, is that most of the methods of a
class should use most of the fields of the class most of the time. What
you are asking about is how to "elegantly" make a class that has
completely independent fields. There may be an elegant way to do it in
C#, but no OO guru would find the concept elegant.


Interesting answer, of course, Daniel. Not sure exactly how that
would relate, as I wanted to isolate both side: The factory would not
know how the object was used--the user would not know how it is
created. The object itself would simply do what it could for the user
and 'stub out' the rest.

In the very simplified example (posted in my followup): A
shape-drawer object would be created and passed back to the user. The
creation side would not know if the user was only going to draw
circles, and never needed the square-drawing function.

The flip side: If the creator could not locate a square-drawing
function, it would stub that out so DrawSquare() did nothing. It
would give the user what it could.

IOW, I don't want to generate exceptions in this case, but just draw
what I can. Given the modularity of the underlying code, I thought it
would be nice to simply plug in the low-level blocks: the factory
would create the Master object with internal 'pointers' to the blocks
it thought were best-suited.

On a cursory glance, this would seem like a place to pursue
'interfaces,' and they would indeed solve the specification issues.
There would seem to be two ways of implementing that:

1: Hand-wire the Master object's functions to individual functions in
DrawCircle and DrawSquare. That would be lots of tedious work, but
would allow the user to regard the Master object in more general
fashion. I guess that's what you object to (ahem) aesthetically.

2: Use a second level of indirection, as suggested by others. This
would allow the mix/match of functional blocks, but the user would no
longer be able to call the interface functions directly--it would have
to refer to the secondary layer in the Master object.

This seems like it should have #3, but I'm not coming up with it.

Jun 24 '06 #8
On Sat, 24 Jun 2006 20:48:07 +0200, Sasa <sa*****@gmail.com> wrote:
Nick Malik [Microsoft] wrote:
How about you don't have the 'master' class implement the three other
interfaces, but rather have it encapsulate them.

class Master
{
public I1 referenceI1;
public I2 referenceI2;

public Master()
{
referenceI1 = new I1();
referenceI2 = new I2();
}
}

public callingcode()
{
Master m = new Master();
m.referenceI1.I1method();
m.referenceI2.I2method();
}
This seems fine, but the referenceI* can be set from anywhere (and not
only from the builder). I actually sometimes miss friend declaration in
C# :-(


The calling code would also have to know something about the internals
of the Master object. The 'references' above deal with specific
subobjects.
I'm guessing (but currently am too lazy and tired to try it out), that
strongly typed Master which would receive ServiceContainer in its
constructor, and then simply delegate to appropriate services should do
the trick.


I'll check into ServiceContainer. Thanks to those who suggested that.
nope... not OO. But then again, there's a reason that multiple inheritance
is not supported in C#.


IMHO, _dee's problem is not about multiple inheritance, and actually
cannot be resolved if one had that possibility in C#. The problem
amounts to setting the implementations in runtime (which your code
resolves).


I have never thought of multiple interfaces as MI. (Actually, I
thought the former was done all the time?). If a concrete object
inherits duplicate *specs* for a function, those specs will all be
satisfied by a single implementation of that function. Of course it's
up to the designer to figure out whether that function will work for
all interfaces that use it, but at least it doesn't have as many dark
corners as MI. Especially in a language like C#, where everything
inherits from 'object.'

But that seems tangential to this particular problem. I think.
Jun 24 '06 #9
Responding to _dee...
Question about best use of interfaces:

Say there's a 'Master' class that needs to implement a few
interfaces:

class Master : I1, I2, I3
{
}

The actual code already exists in smaller classes that each
implement one or two of those interfaces:

class Group1 : I1
{
}

class Group2 : I2, I3
{
}


My response is basically that of Daniel T. Why do you want to create a
Facade class (Master) when the interfaces are already defined for the
group classes? Usually one employs a Facade because there is a
syntactic mismatch between a unified interface the clients want to see
and the disparate interfaces provided by a cluster of individual
objects. Thus:

class Master: I1
{
}

class group1: I2
{
}

class group2: I3
{
}

class group3: I4
{
}

where the I2, I3, and I4 interfaces are largely defined so that the
groupN classes can talk to each other. Meanwhile the client doesn't
care about that and wants to talk to I1. In your case the Facade is
providing to the clients exactly the same interfaces that are directly
available. So why don't the clients talk to them directly? Remember
the OO paradigm is based on peer-to-peer collaboration so one tries to
avoid middlemen.
*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hs*@pathfindermda.com
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH

Jun 25 '06 #10
In article <re********************************@4ax.com>,
_dee <no****@nomail.com> wrote:
On Sat, 24 Jun 2006 15:10:13 GMT, "Daniel T." <da******@earthlink.net>
wrote:
In article <86********************************@4ax.com>,
_dee <no****@nomail.com> wrote:
I'd love to just instantiate Group1 and Group2 and 'point' the
Master object's interfaces at them en masse. I'm looking
for some way for a factory to say:

class Master : I1, I2, I3
{
I1 = new Group1();
I2 = new Group2();
...
}

Of course I know the above is an idealized abstraction, but I'd
like avoid having to map each individual function in every interface
by hand. What is the best way to do this?


The answer to your explicit question would probably best be found in a
C# newsgroup. In this newsgroup, you will mainly get responses about the
theoretical integrity of such a construct.


That's fine with me. The question seemed part theoretical, part
practical, so I posted it to the main C# group + comp.object. If
there is a theoretical side that I'm overlooking, I'd like to know
about that early on. See below.
A basic heuristic of OO programming, is that most of the methods of a
class should use most of the fields of the class most of the time. What
you are asking about is how to "elegantly" make a class that has
completely independent fields. There may be an elegant way to do it in
C#, but no OO guru would find the concept elegant.


Interesting answer, of course, Daniel. Not sure exactly how that
would relate, as I wanted to isolate both side: The factory would not
know how the object was used--the user would not know how it is
created. The object itself would simply do what it could for the user
and 'stub out' the rest.


How would the factory not know? The factory knows what interfaces the
Master object supports, those are the only ways a Master object can be
used. The factory knows.
In the very simplified example (posted in my followup): A
shape-drawer object would be created and passed back to the user. The
creation side would not know if the user was only going to draw
circles, and never needed the square-drawing function.
Why would one bother to hand a Master object to a client that only used
the I2 interface? Why not just give it an I2 object? In your followup
example a client that used an IDrawCircle could be given either a
Sim3DCircle or an Accel3DCircle as appropriate for the environment.

It is unjustified for the client to assume or even expect that the
object received implements interfaces other than the one it uses. It is
unjustified for the client to assume that it should use the same
*object* in two completely different contexts.

Frankly, I'm very leery of your example. "DrawCircle" doesn't sound like
a class to me, it sounds like a function. What methods would such a
class have? What data?
The flip side: If the creator could not locate a square-drawing
function, it would stub that out so DrawSquare() did nothing. It
would give the user what it could.

IOW, I don't want to generate exceptions in this case, but just draw
what I can. Given the modularity of the underlying code, I thought it
would be nice to simply plug in the low-level blocks: the factory
would create the Master object with internal 'pointers' to the blocks
it thought were best-suited.
None of this justifies or even relates to the existence of the Master
class. Everything described above is the job of the factory.
On a cursory glance, this would seem like a place to pursue
'interfaces,' and they would indeed solve the specification issues.
There would seem to be two ways of implementing that:

1: Hand-wire the Master object's functions to individual functions in
DrawCircle and DrawSquare. That would be lots of tedious work, but
would allow the user to regard the Master object in more general
fashion. I guess that's what you object to (ahem) aesthetically.


Well, maybe I haven't been clear. What I object to is a class that
contains non-communicating behavior. There is simply no reason for the
Master class to exist as you have explained it so far.
Jun 25 '06 #11
On Sun, 25 Jun 2006 02:52:28 GMT, "Daniel T." <da******@earthlink.net>
wrote:
In article <re********************************@4ax.com>,
_dee <no****@nomail.com> wrote:
On Sat, 24 Jun 2006 15:10:13 GMT, "Daniel T." <da******@earthlink.net>
wrote:
>A basic heuristic of OO programming, is that most of the methods of a
>class should use most of the fields of the class most of the time.
Interesting answer, of course, Daniel. Not sure exactly how that
would relate, as I wanted to isolate both side: The factory would not
know how the object was used--the user would not know how it is
created. The object itself would simply do what it could for the user
and 'stub out' the rest.


How would the factory not know? The factory knows what interfaces the
Master object supports, those are the only ways a Master object can be
used. The factory knows.


In my shape-drawer example, the factory would never know if the User
side ever called the circle-drawing function. It could just draw
squares.
In the very simplified example (posted in my followup): A
shape-drawer object would be created and passed back to the user. The
creation side would not know if the user was only going to draw
circles, and never needed the square-drawing function.


Why would one bother to hand a Master object to a client that only used
the I2 interface? Why not just give it an I2 object? In your followup
example a client that used an IDrawCircle could be given either a
Sim3DCircle or an Accel3DCircle as appropriate for the environment.


But the client may need to draw squares, etc. If the interfaces were
each specialized, then I'd end up handing off a ton of interfaces:
triangle, octagon, etc. I need to have a larger object that is made
in one place, used in another. I'm trying to isolate both sides of
that. In this case a low-level generalized shape-drawer will not
work.
It is unjustified for the client to assume or even expect that the
object received implements interfaces other than the one it uses. It is
unjustified for the client to assume that it should use the same
*object* in two completely different contexts.

Frankly, I'm very leery of your example. "DrawCircle" doesn't sound like
a class to me, it sounds like a function. What methods would such a
class have? What data?


I was hoping that it would be a bit more intuitive. I'm not actually
drawing anything; I was looking for a simple model.

OK, here's another try: Say you wanted to read tag information from a
media file. You have one central concept: a media file. But you
don't know what type of file it is...could be MP3, could be OGG, could
even be a video file.

It doesn't make sense to require the user to open a different viewer
for each file type. The user just wants to get an idea of what it is.
In fact, without a file extension, the internals could be completely
unknown to the user, and they would not know what type of viewer to
use.

So you browse to the file, double-click, and the factory figures out
the file type, then builds a viewer, and hands the viewer back. The
User can ask for 'artist name' which would be relevant to most MP3 and
OGG files, but maybe not a video file. Or it could ask for (pixel)
dimensions, which would be valid for the video file, but not for
audio. Or it could ask for audio stream type, which would be valid
for all.

I feel like I just way over-simplified that, but that's a bit closer
to the intent, if 1000 times simpler.

Somewhere along the line there would have to be a Master object, or
there would be no way to deal with the unknowns, and no way for a
client to be sufficiently generalized. If the client asks for
dimensions of an MP3 file, it can get back a 'not implemented' flag
(in this case, it's perfectly fine), but it needs to have that
functionality. Otherwise it could not get the dimensions of a video
file. And of course it does not know ahead of time what type of file
it is.

Anyway, the idea is that the objects need to implement interfaces that
are sometimes common, sometimes specialized, and sometimes null. If
there were such a thing as 'aiming' an interface pointer, I'd be home
free. I could select the correct sub-objects and create a master
object from those.
Jun 25 '06 #12
On Sat, 24 Jun 2006 16:56:45 -0400, _dee <no****@nomail.com> wrote:

In the very simplified example (posted in my followup): A
shape-drawer object would be created and passed back to the user. The
creation side would not know if the user was only going to draw
circles, and never needed the square-drawing function.

The flip side: If the creator could not locate a square-drawing
function, it would stub that out so DrawSquare() did nothing. It
would give the user what it could.

On a cursory glance, this would seem like a place to pursue
'interfaces,' and they would indeed solve the specification issues.
There would seem to be two ways of implementing that:

1: Hand-wire the Master object's functions to individual functions in
DrawCircle and DrawSquare. That would be lots of tedious work, but
would allow the user to regard the Master object in more general
fashion. I guess that's what you object to (ahem) aesthetically.

2: Use a second level of indirection, as suggested by others. This
would allow the mix/match of functional blocks, but the user would no
longer be able to call the interface functions directly--it would have
to refer to the secondary layer in the Master object.

This seems like it should have #3, but I'm not coming up with it.


Now that I think about it:

#3: Use an abstract base class that implements the required
interfaces. Most/all functions are stubbed out by default. Each
sub-object inherits from that base class and overrides the functions
that make sense for its purpose. Each sub-object now becomes the
analog of the 'Master' object in my previous example. The factory can
hand back a ref to the abstract base, so all functions would be
available to the user (even if stubbed out).

I guess this sounds more scattered that what it is. There actually is
commonality in the targets and in their handlers. I believe the
'Master' concept is correct here, and I don't know how else I'd
achieve the combination of isolation and generality.

If the factory makes more specialized objects, then the user will have
to be make all the decisions about whether a given functionality is
present or not. In this case, that's beyond what it should need to
do. In the example, using MP3, OGG and AVI files, the client would
just want to say: Show me the file's stats. It does not want to have
specialized knowledge of what dialect of AVI file, for example.

The abstract base class sounds logical but maybe ugly. Still probably
not as tedious and error-prone as having the factory map the null
functions.
Jun 25 '06 #13
On Sun, 25 Jun 2006 00:21:49 GMT, "H. S. Lahman"
<h.******@verizon.net> wrote:
My response is basically that of Daniel T. Why do you want to create a
Facade class (Master) when the interfaces are already defined for the
group classes?
Actually, Facade is an appropriate analogy, with the requirement that
the facade be accessible in the same way as the sub-objects (hence the
use of interfaces). Now that I think of it, that's probably why Nick
mentioned multiple inheritance--it does look a bit like that.

In most cases each sub-object will implement 90% to 100% of the
interfaces' requirements. There are odd things that don't fit (like
my pixel dimensions for an audio file analogy) but not enough to
warrant a complete change in superstructure.

Those odd functions can be stubbed out with no real change in
high-level function. They'll just do nothing. The 'null object' that
implements those stubs would usually be the only other sub-object
required. I didn't want to restrict it to that though.
Usually one employs a Facade because there is a
syntactic mismatch between a unified interface the clients want to see
and the disparate interfaces provided by a cluster of individual
objects.
There's some confusing overlap in the terms 'Adapter' and 'Facade' but
I didn't think Facade was confined to syntactical mismatches.
Thus:

class Master: I1
{
}

class group1: I2
{
}

class group2: I3
{
}

class group3: I4
{
}

where the I2, I3, and I4 interfaces are largely defined so that the
groupN classes can talk to each other.
Sorry, you lost me. The interfaces that I had in mind don't need to
talk to each other. They spec the way that the user can regard the
final object: The user should be able to say "Give me the audio
specs" or "give me video specs". The object has the option to say
"That's not currently relevant."
Meanwhile the client doesn't
care about that and wants to talk to I1. In your case the Facade is
providing to the clients exactly the same interfaces that are directly
available. So why don't the clients talk to them directly?


That's exactly what I wanted it to look like to the client. But I
don't want to pass multiple Interfaces back to the client. I wanted
to collect them into one object. Other than that, it kind of sounds
like you're describing the same thing.

IOW, I'd like to be able to cast the 'master' object to any of the
interface types. You couldn't do that if it was just a container for
the I-references.

In case you've dealt with Windows programming, there's something
similar done with DirectX. You can create a FilterGraph to talk to
any type of media file. Then cast IMediaControl to that filter graph
to get it to play. Or IPosition to find out its current playback
position, etc. I'd love to know how that was implemented.
Jun 25 '06 #14
_dee wrote:

[snipped most of the stuff]
That's exactly what I wanted it to look like to the client. But I
don't want to pass multiple Interfaces back to the client. I wanted
to collect them into one object. IOW, I'd like to be able to cast the 'master' object to any of the
interface types. You couldn't do that if it was just a container for
the I-references.


You could if you would write your cast operator. But I would still
prefer getters or methods.

Thinking again about the problem, I think proposed ServiceContainer is
an overkill if you assemble implementations at one point and then simply
access them, but not change the configuration once all implementations
are assembled.

Your master could look something like this:

class Master
{
public Master(I1 implI1, ...);

public I1 ImplI1 {get;}
...
}

Which is basically what Nick suggested, but implementations can be set
only during the construction.
The factory (or is it rather a builder?) then determines implementations
in runtime and simply returns the built Master instance which then
represents one specific combination of implementations of relevant
interfaces.

Personally I think this is fine, since Master class (which should be
renamed to something meaningful) serves only to hold members which will
be used together, so that you don't have to send this stuff separately
via parameters.

Sasa
Jun 25 '06 #15
Responding to _dee...
My response is basically that of Daniel T. Why do you want to create a
Facade class (Master) when the interfaces are already defined for the
group classes?

Actually, Facade is an appropriate analogy, with the requirement that
the facade be accessible in the same way as the sub-objects (hence the
use of interfaces). Now that I think of it, that's probably why Nick
mentioned multiple inheritance--it does look a bit like that.

In most cases each sub-object will implement 90% to 100% of the
interfaces' requirements. There are odd things that don't fit (like
my pixel dimensions for an audio file analogy) but not enough to
warrant a complete change in superstructure.


Yes, that does sound like Facade. If I understand this, one object, say
Group1, provides 90% of what the client wants but some other object, say
Group2, provides the other 10%. However, you want that allocation to be
transparent to the client. That is, you want the client to use I1 for
100% of the desired functionality.

But in that case one has different interfaces:

class master : I1
{
// provides all responsibilities to client in one interface
// dispatches to Group1 or Group2, as needed
}

class Group1 : I2
{
// provides 90% of the I1 responsibilities
}

class Group2 : I3
{
// provides 10% of the I1 responsibilities
}

If so, then I don't see any way around a somewhat tedious dispatch in
Master because that sort of re-dispatching is what Facade does.

However, if the split is really 90/10, then I would consider daisy
chaining Group1 and Group2. That is, let Group1 re-dispatch the 10% to
Group2 transparently to the client. Then Group1 provides the full
interface and the client only talks to Group1. (In effect this makes
Group1 the Facade but we are putting 90% of the functionality there as
well and letting it dispatch only 10% to Group2.)

The price of that, though, is much tighter coupling of Group1 and
Group2. If there is a change to Group2, then Group1 will very likely
also have to change. That may or may not be a problem depending on how
likely things are to change and whether the Group1/Group2 is a simple
message re-dispatch or is a more complicated collaboration.

[Note the the GoF pattern implementations all use this sort of
re-dispatch when they provide delegation rather than letting the client
talk directly to the delegated object. Aesthetically that is not good
OOA/D practice but the nature of the re-dispatch is so benign that it
rarely makes a difference.]

Those odd functions can be stubbed out with no real change in
high-level function. They'll just do nothing. The 'null object' that
implements those stubs would usually be the only other sub-object
required. I didn't want to restrict it to that though.
Now this is a very different problem. However, I have to ask: if they
do nothing, why have them at all? If this is really the case, then you
don't need Master or Group2 above at all. Group1 can provide the I1
interface to the client and just no-op the 10% of responsibilities that
aren't relevant.

That's too obvious, so I have to assume something else is going on.
Such as there is some context where the 10% is relevant and you will
need a dispatch. However, you can get around that problem in the model
above by adding a variation on the Observer pattern. The receiver is
either a null object or Group2. You register the appropriate one for
the context and Master dispatches as usual. Observer just makes sure
the right object get the message. (Obviously you can do the same thing
with the daisy-chain approach as well.)
Usually one employs a Facade because there is a
syntactic mismatch between a unified interface the clients want to see
and the disparate interfaces provided by a cluster of individual
objects.

There's some confusing overlap in the terms 'Adapter' and 'Facade' but
I didn't think Facade was confined to syntactical mismatches.


I'm just describing how Facade is /usually/ used. So long as you have
multiple objects (Group1, Group2, ...) that implement the functionality,
Facade is more appropriate. Adapter just resolves syntactic mismatches
with a single object's interface.

Thus:

class Master: I1
{
}

class group1: I2
{
}

class group2: I3
{
}

class group3: I4
{
}

where the I2, I3, and I4 interfaces are largely defined so that the
groupN classes can talk to each other.

Sorry, you lost me. The interfaces that I had in mind don't need to
talk to each other. They spec the way that the user can regard the
final object: The user should be able to say "Give me the audio
specs" or "give me video specs". The object has the option to say
"That's not currently relevant."


OK. I inferred a different problem from the description.

I assume the use of 'option' here means that sometimes you need the
functionality and sometimes you don't. If so, I think a single object
that always provides the 90% combined with Observer, as described above,
would be the way to go.
Meanwhile the client doesn't
care about that and wants to talk to I1. In your case the Facade is
providing to the clients exactly the same interfaces that are directly
available. So why don't the clients talk to them directly?

That's exactly what I wanted it to look like to the client. But I
don't want to pass multiple Interfaces back to the client. I wanted
to collect them into one object. Other than that, it kind of sounds
like you're describing the same thing.


I think it is less about multiple interfaces than multiple relationships
and collaborations. If the functionality is spread across multiple
objects, then the client needs to collaborate with them on a
peer-to-peer basis. The fact that different interfaces are required for
those collaborations is incidental.

There are times, though, when one wants to hide multiple objects from
the client via Facade, but that is usually because those objects need to
collaborate with each other to service the client's request and one
wants to make that collaboration transparent to the client.

One can argue, though, that using Observer to deal with the 10% context
switching is a similar situation that one wants to make transparent to
the client. That is, the context switch is not relevant to what the
client /thinks/ it wants to do.
*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hs*@pathfindermda.com
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH

Jun 25 '06 #16
In article <7i********************************@4ax.com>,
_dee <no****@nomail.com> wrote:
On Sun, 25 Jun 2006 02:52:28 GMT, "Daniel T." <da******@earthlink.net>
wrote:
In article <re********************************@4ax.com>,
_dee <no****@nomail.com> wrote:
On Sat, 24 Jun 2006 15:10:13 GMT, "Daniel T." <da******@earthlink.net>
wrote:A basic heuristic of OO programming, is that most of the methods of a
>class should use most of the fields of the class most of the time.

Interesting answer, of course, Daniel. Not sure exactly how that
would relate, as I wanted to isolate both side: The factory would not
know how the object was used--the user would not know how it is
created. The object itself would simply do what it could for the user
and 'stub out' the rest.


How would the factory not know? The factory knows what interfaces the
Master object supports, those are the only ways a Master object can be
used. The factory knows.


In my shape-drawer example, the factory would never know if the User
side ever called the circle-drawing function. It could just draw
squares.


So. What does that get you?
In the very simplified example (posted in my followup): A
shape-drawer object would be created and passed back to the user. The
creation side would not know if the user was only going to draw
circles, and never needed the square-drawing function.


Why would one bother to hand a Master object to a client that only used
the I2 interface? Why not just give it an I2 object? In your followup
example a client that used an IDrawCircle could be given either a
Sim3DCircle or an Accel3DCircle as appropriate for the environment.


But the client may need to draw squares, etc. If the interfaces were
each specialized, then I'd end up handing off a ton of interfaces:
triangle, octagon, etc. I need to have a larger object that is made
in one place, used in another. I'm trying to isolate both sides of
that. In this case a low-level generalized shape-drawer will not
work.


If the client requests something that conforms to the ICircleDraw
interface, it should neither expect nor require that the same object
also implement the ISquareDraw interface. The client should request
another object for that. Of course the Factory may hand the client a
reference to the same object if it wants, but that is not a
justification for making an object full of non-communicating behavior.
It is unjustified for the client to assume or even expect that the
object received implements interfaces other than the one it uses. It is
unjustified for the client to assume that it should use the same
*object* in two completely different contexts.

Frankly, I'm very leery of your example. "DrawCircle" doesn't sound like
a class to me, it sounds like a function. What methods would such a
class have? What data?


I was hoping that it would be a bit more intuitive. I'm not actually
drawing anything; I was looking for a simple model.

OK, here's another try: Say you wanted to read tag information from a
media file. You have one central concept: a media file. But you
don't know what type of file it is...could be MP3, could be OGG, could
even be a video file.

It doesn't make sense to require the user to open a different viewer
for each file type. The user just wants to get an idea of what it is.
In fact, without a file extension, the internals could be completely
unknown to the user, and they would not know what type of viewer to
use.

So you browse to the file, double-click, and the factory figures out
the file type, then builds a viewer, and hands the viewer back. The
User can ask for 'artist name' which would be relevant to most MP3 and
OGG files, but maybe not a video file. Or it could ask for (pixel)
dimensions, which would be valid for the video file, but not for
audio. Or it could ask for audio stream type, which would be valid
for all.

I feel like I just way over-simplified that, but that's a bit closer
to the intent, if 1000 times simpler.

Somewhere along the line there would have to be a Master object, or
there would be no way to deal with the unknowns, and no way for a
client to be sufficiently generalized. If the client asks for
dimensions of an MP3 file, it can get back a 'not implemented' flag
(in this case, it's perfectly fine), but it needs to have that
functionality. Otherwise it could not get the dimensions of a video
file. And of course it does not know ahead of time what type of file
it is.

Anyway, the idea is that the objects need to implement interfaces that
are sometimes common, sometimes specialized, and sometimes null. If
there were such a thing as 'aiming' an interface pointer, I'd be home
free. I could select the correct sub-objects and create a master
object from those.


In none of the above, would you need a "master" object that is both an
OGG file and an MP3 file and a video file. Sure one class may need to
implement several interfaces that's natural, but it should never
implement them all using contained objects that operate independently of
each-other. That's the point I'm trying to make. If such is the case,
the Master class simply isn't necessary.
Jun 25 '06 #17
SP

<snipped>
In case you've dealt with Windows programming, there's something
similar done with DirectX. You can create a FilterGraph to talk to
any type of media file. Then cast IMediaControl to that filter graph
to get it to play. Or IPosition to find out its current playback
position, etc. I'd love to know how that was implemented.


This is explicit interface inheritance. You need to cast to the interface to
access the methods. The FilterGraph implements both the IMediaControl and
the IPosition interfaces.

SP
Jun 26 '06 #18
<<most of previous message is clipped>>

"_dee" <no****@nomail.com> wrote in message
news:4t********************************@4ax.com...

I was trying to approach the initial design from an abstract
viewpoint, and thought that this was the best looking and simplest
from the user standpoint. Implementing the internals may be another
story.

I really don't know much about what it is you are actually trying to do.
You may (or may not) have an error in your 'abstract' approach. Usually,
when I end up with a conundrum like the one you are facing, I try to go back
to principles. I ask "What is it I am encapsulating?" I will break down my
structure into a kind of 'soup' and try to construct an entirely different
object heirarchy, just to see if I am really implementing the problem in a
good way.

Design patterns are useful, as you probably know, for encapsulating not only
'things' but also algorithms, and operators, and complete abstract concepts
useful for creating a flexibility mechanism in your code. I've been known
to see the first part, and occasionally forget the second: that I have to
justify each construct by looking at the flexibility I am trying to add. In
other words, sometimes I make the mistake of using a pattern just because
the object heirarchy would look good or it makes some kind of logical sense,
without considering the possibility that my code will NEVER ACTUALLY VARY in
the way that my OO design would allow it to. If this is the case, then I
have stepped over the line into 'overdesign' and have created code that the
programmer who follows me will someday discard. I do not know if this is
the case in your code.

As I said, when I run into something that doesn't smell right, as the code
above appears not to do for you, then I re-examine my heirarchy to see if I
have made the mistake I describe above.
So...any ideas on how the factory could wire up the interfaces in my
example Circle/Box code above?
I have no suggestions that have not been offered by others in this forum.
It looks like I'd have to create the
internal Circle and Box drawing objects first, then write functions
inside Master that matched their Interface functions, but called into
the internal objects. That's a lot of ugly code.


In the rare cases where it is justified to have multiple objects that are
encapsulated within a 'master' object, this kind of wiring is not pretty,
but it is necessary.

I hope this helps.

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
--
Jun 27 '06 #19

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

36
by: Andrea Griffini | last post by:
I did it. I proposed python as the main language for our next CAD/CAM software because I think that it has all the potential needed for it. I'm not sure yet if the decision will get through, but...
7
by: Bora Eryilmaz | last post by:
I am working on designing a set of abstract classes that would be subclassed by the users and they have to implement the abtract (virtual) methods. Does anybody know of a good reference on...
2
by: SammyBar | last post by:
Hi, I'm trying to bind a custom collection class to a data grid, following the guidelines from the article http://msdn.microsoft.com/msdnmag/issues/05/08/CollectionsandDataBinding/default.aspx....
4
by: emma middlebrook | last post by:
Hi Straight to the point - I don't understand why System.Array derives from IList (given the methods/properties actually on IList). When designing an interface you specify a contract. Deriving...
5
by: __PPS__ | last post by:
Hello all, I was working on someone else's code to implement some classes. The task seemed to be simple and I was confident that I won't spent alot of time on that task... But! I've already spent...
0
by: YellowFin Announcements | last post by:
Introduction Usability and relevance have been identified as the major factors preventing mass adoption of Business Intelligence applications. What we have today are traditional BI tools that...
9
by: Grizlyk | last post by:
Somebody have offered std colors to C++ in the msg here: http://groups.google.com/group/comp.lang.c++/browse_frm/thread/2e5bb3d36ece543b/1acf6cd7e3ebdbcd#1acf6cd7e3ebdbcd The main objection to...
20
by: mike3 | last post by:
Hi. (Xposted to both comp.lang.c++ and comp.programming since I've got questions related to both C++ language and general programming) I've got the following C++ code. The first routine runs in...
8
by: =?Utf-8?B?QmVu?= | last post by:
Hi, I have a couple of questions about the proper design of classes. I'll use a simple Customer class for my question. 1) Lets say that I have this Customer class like I said, and I want to...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.