Design pattern question

C

Chris F Clark

1) I would really like to ask this on comp.lang.c#, but no such group
exists. However, perhaps someone in one of the above two groups
will know the answer and help me out.

In my product, I use a variation of a design pattern called
"generation gap". In particular, there is library code that knows
about certain classes that are user customized and generated with
those customizations on behalf of the user. This is done via "opaque"
types. I'll show a C++ implementation w/o namespaces in a sec.
However, I want to do a similar idea in C# (and in Java). The problem
is that I can't figure out how to do this pattern in a namespace
compatible way.

Library Code:

typedef class UserClass *UserClassPtr;

class SomeLibraryClass {
UserClassPtr someMemberFunction(); // UserClass is "opaque" here
}

////////////////////////////////////////////////////////////////////
Generated Code:

typedef class UserClass *UserClassPtr;

class UserClass {
int userSpecificMemeber; // User customizations
}

class GeneratedClass : public SomeLibraryClass {
UserClassPtr someMemberFunction()
{
return new UserClass(); // UserClass is NOT "opaque" here
}
}


////////////////////////////////////////////////////////////////////

The above scheme works relatively well in C++.

I can put the implementation details in the library code and compile
it once. The library can also give the abstract interface that users
can know about the generated classes. This allows users to write
programs to that abstract interface without knowing the details of the
actual generated classes. The UserClass which they can customize
however, is an important part of that. If the system were a
event-driven GUI, this data might be thought of as the "call back"
data. In old C language programs, this would be a "void *" that the
user would cast to find the right data. However, it is better that we
make it a real type and get some level of type safety.

That type safety is limited though, because imagine that we generate
two or more "families" of generated classes. The library uses only
pointers to the types, so it is relatively immune to the types.
However, the generated code has access to the "real" UserClass type
and it can access the members of that type. Code which is "client" to
the library, is safe if it only uses pointers, or if it has the
appropriate generated code family visible to it, so that it sees one
customized version. However, if the client code sees both families,
then ther are two definitions of the client class, and it is not safe
for the client code to access the members.

This brings us to the namespace issue. One solution to two classes of
the same name is to have them in separate namespaces. However, how
does one in the library refer something so that each generated
namespace gets its own copy. The following doesn't work:

namespace Library
{

typedef class UserClass *UserClassPtr;

class SomeLibraryClass {
UserClassPtr someMemberFunction(); // UserClass is "opaque" here
}

// Error no UserClass in Library namespace
}

namespace GeneratedCode
{
using Library;

typedef class UserClass *UserClassPtr;

class UserClass { // Not in Library namespace
int userSpecificMemeber; // User customizations
}

class GeneratedClass : public SomeLibraryClass {
UserClassPtr someMemberFunction()
{
return new UserClass(); // UserClass is NOT "opaque" here
}
}

}


The problem is particularly noticable in languages like C# where there
are no explicit "pointer" types. I don't know how to say this is a
"type to be defined later" (and I don't want to just say "object"
because in real life the client software and the generated software
are related and it is much more convenient if the type can just "pass
thru" the system, so that the client software can easily access the
data created for it by the (user customized version of the) generated
code).


Suggestions?
-Chris
 
V

Victor Bazarov

Chris said:
1) I would really like to ask this on comp.lang.c#, but no such group
exists. However, perhaps someone in one of the above two groups
will know the answer and help me out.

There is microsoft.public.dotnet.languages.csharp...
[...]
Suggestions?

"Pointer to implementation" (pimpl) idiom
"Handle" idiom (used a lot in MS Windows API)

I think essentially you're looking for a base class/interface and its
implementation. Instead of wrapping your classes from your different
"families" in namespaces, wrap them in classes.

Perhaps I didn't understand the problem, though.

V
 
C

Chris F Clark

Thanks for the microsoft... pointer, I'll look into it.
I think essentially you're looking for a base class/interface and its
implementation. Instead of wrapping your classes from your different
"families" in namespaces, wrap them in classes.

I think you do understand the problem. The prototype was done that
way, with an explicit "interface" class that replaced the "pointer" type.

In the library:

interface class UserClassPtr;

In the generated code:

class UserClass implements UserClassPtr
{ // customizations
};

However, the user community didn't like having to "cast" from the
interface back to their concrete class to access their customizations.
The problem being that there are quite a few library functions that
are used in the generated code that return these objects. So, the
user writing the customizations find themselves writing these casts
all-the-time (perhaps several per line for perhaps a few hundred
lines). Example:

//Target and Source are library functions that return UserClassPtr

UserClass(Target()).userField =
UserClass(Source(1)).userField + UserClass(Source(2)).userField;

compared to:

//Target and Source are library functions that return UserClass

Target().userField = Source(1).userField + Source(2).userField;

-Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top