[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.vb.general.discussion

Hey Class, this is me again, don't you see?

mm

2/9/2011 4:54:00 PM

Hello:

I'm changing a design of a program to a more OO one, and I'm facing
something that may be a limitation of VB about OO programing, but anyway
I'll discuss the issue here.

I have an object, a class, that will have clients that will use
instances of it. The clients could be forms for example.

More than one client will use the same instance of an object, because
many properties or services that the object provides will be the same
for several clients at the same time, so I won't duplicate everything
creating a new object for each client.
But... some properties won't be the same, they are customized for each
client, they could share the same settings with others clients or not.
So, I decided to implement this on this way:

The object is created with all the common things that will be for every
client.
When one client needs to use the object, it set its own custom
parameters for the other properties that are customized. The Class
object returns a ClientID.

The Class object keeps a track for all the clients with their "preferences".

So, when a client needs something that is common, it doesn't need to
supply the ClientID, but when it needs something that is customized, it
must supply the ClientID in order for the class to know what to return
to this client.

But... couldn't the class "see" what client is asking for something,
without having to ask for the ClientID every time?

Shouldn't the Class object be able to know at least the ObjectPtr of the
object from where it's being called (when a property or method is
accessed) or something like this?

34 Answers

ralph

2/9/2011 8:10:00 PM

0

On Wed, 09 Feb 2011 13:53:52 -0300, Eduardo <mm@mm.com> wrote:

>Hello:
>
>I'm changing a design of a program to a more OO one, and I'm facing
>something that may be a limitation of VB about OO programing, but anyway
>I'll discuss the issue here.
>
>I have an object, a class, that will have clients that will use
>instances of it. The clients could be forms for example.
>
>More than one client will use the same instance of an object, because
>many properties or services that the object provides will be the same
>for several clients at the same time, so I won't duplicate everything
>creating a new object for each client.
>But... some properties won't be the same, they are customized for each
>client, they could share the same settings with others clients or not.
>So, I decided to implement this on this way:
>
>The object is created with all the common things that will be for every
>client.
>When one client needs to use the object, it set its own custom
>parameters for the other properties that are customized. The Class
>object returns a ClientID.
>
>The Class object keeps a track for all the clients with their "preferences".
>
>So, when a client needs something that is common, it doesn't need to
>supply the ClientID, but when it needs something that is customized, it
>must supply the ClientID in order for the class to know what to return
>to this client.
>
>But... couldn't the class "see" what client is asking for something,
>without having to ask for the ClientID every time?
>
>Shouldn't the Class object be able to know at least the ObjectPtr of the
>object from where it's being called (when a property or method is
>accessed) or something like this?

There is a lot of questions ... for example, just how "custom" are
these additonal services (what you called Properties)?

If these services are consistent then it appears you can just define
Interfaces for them.

' Class CBase
Implements IClientAStuff
Implements IClientBStuff
Implements IClientCStuff

' Class Client A
Private WithEvents oBase As CBase
Private oStuff As IClientAStuff
Property Let Init ( ByRef obj As CBase )
Set oBase = obj
Set oStuff = obj
' later in your code
' to access Base properties
z = oBase.Property1
' to access ClientA Stuff
y = oStuff.PropertyCustom

However, there isn't anything particularly wrong with what you are
doing. ("Correctness" often boils down to "elegance", ie, how
convoluted is the mechanism.)

Something else to consider. When one starts creating this pattern, the
question becomes is your design perhaps backwards? Do you actually
have one object that has to morph itself to each client, or do you in
fact have several unique objects that merely share or use the services
of the base class. ie,

' Class CClientAStuff
Implements IBase
' Class CClientBStuff
Implements IBase
....
' Class Client A
Private WithEvents oStuff As CClientAStuff
Private oBase As CBase
....

-ralph

mm

2/9/2011 9:42:00 PM

0

El 09/02/11 05:09 p.m., ralph escribió:

Hello Ralph,

A couple of points:

1) In my case, the object doesn't have events, it just provides already
ready to use data.
So the clients don't have to do anything but just use the data provided
by the object, that prepared that data.

2) There is not interface difference for different clients. All clients
are of the same type, and uses the properties or services in the same
way with the same interface.

The only that vary are some preferences concerning to the data.

An example:

Suppose that "the object" supplies stuff for parties.
It has several party parlors that are clients.

It supplies dishes, they are all the same type for every client. When a
client ask for dishes he must specify if small, medium or large, they
are all in stock.

The same for glasses. The object has stock for several (previosly known)
types of glasses that the clients can ask for (and they will).

But there are some other stuff, that is not in stock, because there are
too many varieties to have stock of everything. So the clients at the
beginning, have to specify what brand of beer he will use, and what food
for desert.
So the object prepares that data for this client and may be also other
clients that selected the same beer.

The client can change this "customizable preferences" at any time, but
he has to notify the change to the object, so it prepares the new data.

So, when a client asks for some packs of beers, it only specifies the
size of the bottle (big or small), because the brand that he uses is
already known by the object.

ralph

2/9/2011 10:04:00 PM

0

On Wed, 09 Feb 2011 13:53:52 -0300, Eduardo <mm@mm.com> wrote:


>So, when a client needs something that is common, it doesn't need to
>supply the ClientID, but when it needs something that is customized, it
>must supply the ClientID in order for the class to know what to return
>to this client.
>
>But... couldn't the class "see" what client is asking for something,
>without having to ask for the ClientID every time?
>
>Shouldn't the Class object be able to know at least the ObjectPtr of the
>object from where it's being called (when a property or method is
>accessed) or something like this?

In general it is best the 'server' has limited knowledge about the
'client' that is using his services. This aids in preserving
reusability and the polymorphic nature of the service. You will find
little built-in or automatic capablity in most OOPLs for services to
gain that information. (There are extensions in many can be applied to
do this, but not in VB so we'll ignore it for now. <g>)

If a service does need to know more about its client, there are two
basic mechanisms to manage this. 1) Pass the client object to the
service, 2) Register the client with the server and receive a
token/identifier. It sounds like you have explored both of those.

Then it might be time to explore whether or not you have the ownership
reversed. Perhaps what you have is an object that needs various types
of clients to do its job?

-ralph

mm

2/9/2011 10:27:00 PM

0

El 09/02/11 07:04 p.m., ralph escribió:

Order changed

> Then it might be time to explore whether or not you have the ownership
> reversed. Perhaps what you have is an object that needs various types
> of clients to do its job?

No, they are all the same.

> If a service does need to know more about its client, there are two
> basic mechanisms to manage this. 1) Pass the client object to the
> service, 2) Register the client with the server and receive a
> token/identifier. It sounds like you have explored both of those.

I considered option 1) but I don't need a reference to the object, I
just need to identify the objects (clients), so I implemented 2)

My question was because I didn't like for the clients to have to supply
this token/identifier every time they access the server (for something
customizable). But I would like the server "to see" the client and
realize who it is whithout having to ask for this identifier every time
and all the times.

Larry Serflaten

2/9/2011 10:41:00 PM

0


"Eduardo" <mm@mm.com> wrote

> The only that vary are some preferences concerning to the data.

There is something ralph said that makes perfect sence to me.

"When one starts creating this pattern, the question becomes
is your design perhaps backwards?"

If it were me, my first attempt would have been to have the class
implement the unique properties, while sharing values that are
common among all classes. Those common values could be kept
in an object by themselves to make them easy to share by setting
one object reference in the initialization process of the class.

If your common values where kept in a class by themselves you
could declare a Public variable in a standard module where your
class initialization procedure could make sure the global instance is
available:

Option Explicit

Private mDrink As String

Private Sub Class_Initialize()
' Create global instance if needed
If gCommon Is Nothing Then
Set gCommon = New cCommon
End If
End Sub

' Shared
Public Property Get Dishes(ByVal Size As Long) As String
Dishes = gCommon.Dishes
End Property

' Unique
Public Property Get Drink(ByVal Amount As Single) As String
Drink = mDrink
End Property



Just something to think about...
LFS






mm

2/9/2011 11:03:00 PM

0

El 09/02/11 07:40 p.m., Larry Serflaten escribió:
> "Eduardo"<mm@mm.com> wrote
>
>> The only that vary are some preferences concerning to the data.
>
> There is something ralph said that makes perfect sence to me.
>
> "When one starts creating this pattern, the question becomes
> is your design perhaps backwards?"
>
> If it were me, my first attempt would have been to have the class
> implement the unique properties, while sharing values that are
> common among all classes. Those common values could be kept
> in an object by themselves to make them easy to share by setting
> one object reference in the initialization process of the class.
>
> If your common values where kept in a class by themselves you
> could declare a Public variable in a standard module where your
> class initialization procedure could make sure the global instance is
> available:
>
> Option Explicit
>
> Private mDrink As String
>
> Private Sub Class_Initialize()
> ' Create global instance if needed
> If gCommon Is Nothing Then
> Set gCommon = New cCommon
> End If
> End Sub
>
> ' Shared
> Public Property Get Dishes(ByVal Size As Long) As String
> Dishes = gCommon.Dishes
> End Property
>
> ' Unique
> Public Property Get Drink(ByVal Amount As Single) As String
> Drink = mDrink
> End Property
>
>
>
> Just something to think about...
> LFS

Larry, they are all common but just for that instance of the object.
They are not common for all the instances of the object.

My example could't illustrate that.


Schmidt

2/10/2011 7:53:00 AM

0


"Eduardo" <mm@mm.com> schrieb im Newsbeitrag
news:iiv6ek$h67$1@speranza.aioe.org...

> Larry, they are all common but just for that
> instance of the object.
> They are not common for all the instances of the object.

Now I'm confused... ;-)

You mean, that each client creates a separate
Instance of this "global Class" for its own use?

If that is the case, how many "differently behaving"
clients are there (which are "consumers" of your
global data-instance)?

In either case - some small Code-Snippets would
be great, which demonstrate the principle you
currently have running (just one small Server-Class
and two different Client-Consumers + 2 or 3 Properties
which can demonstrate the problem you're currently
fighting with).

Olaf


mm

2/10/2011 9:43:00 AM

0

El 10/02/11 04:53 a.m., Schmidt escribió:
> "Eduardo"<mm@mm.com> schrieb im Newsbeitrag
> news:iiv6ek$h67$1@speranza.aioe.org...
>
>> Larry, they are all common but just for that
>> instance of the object.
>> They are not common for all the instances of the object.

Hello Olaf

> Now I'm confused... ;-)
>
> You mean, that each client creates a separate
> Instance of this "global Class" for its own use?

No, in that case it wouldn't have some properties customizables, but
everything would be customized for the only client.

Neither the object would have to know what client is using something
(properties/methods) because it would be only one client for each instance.

> If that is the case, how many "differently behaving"
> clients are there (which are "consumers" of your
> global data-instance)?
>
> In either case - some small Code-Snippets would
> be great, which demonstrate the principle you
> currently have running (just one small Server-Class
> and two different Client-Consumers + 2 or 3 Properties
> which can demonstrate the problem you're currently
> fighting with).

It works this way:
There is another object that I call "server" in my program, so the other
object I've been talking, sometimes called also server (here in the
messages of the newsgroup), we will call it just "object".

When a client starts, it sends to the server an object request. The
server keeps a collection of object instances that are already loaded
and prepared (if a client asked for them before). If it's the first
request, it created a new instance of the "object".

Back to the client, it send the request for an object, and supply a
parameter that defines whith what, let's say... document will the object
instance be prepared.

So, all the objects instances differ that are prepared with different
documents.

Lets say ClientA sends a request for an Object providing data according
to Document1, the server looks if there is already an Object with
Document1 in its objects collection, if there is already one, it returns
a reference of that object instance to the client, and from now and
ahead the client will work directly with the Object.

The only other function of the server is to keep a maximun of 10 Object
instances in its collection, if this limit is exceeded, it looks for the
older object in the collection, and deletes it from the collection.

Back to ClientA, it asked for an Object/Document1, and it's already with
the object reference that the server provided.

If the Object instance was just created, it prepared all the basic data
with Document1 at the time it created.
But there are also other "customizable" data that would be too much to
prepare for every possibility that a client could ask for, so it works
this way: it expect for the client to say how it will need the data to
be customized. They are actually 4 long parameters that the client sends
to the object. The possibilities are not 4 * 2^32, but much less, but
still many.

But there is another thing to consider, still when theorically any
client can ask for any combination, in practice in the most of cases the
clients will ask for the same customization.

So, back to ClientA, it says it will work with &H1&-&H5&-&H3&-&H8&.
With this customization supplied, the Object must prepare the
customizable data according to this.

Then there is another client, ClientB, that also asks for an Document1
object to the server. The server already has in its collection a
reference to the instance that is already using ClientA, and returns to
ClientB a reference of the same instance of the Object that is already
using ClientA.

When ClientB receive the reference for Object/Document1, it specify the
customization to the Object, it is the same as Client1:
&H1&-&H5&-&H3&-&H8&, so the object has everythig prepared, ready to use
inmediately.

ClientC ask also for an Object/Document1 to the server, the server
returns the reference, ClientC specifies the custimization to the
Object, and it says &H2&-&H6&-&H3&-&H8&. There is a difference, so the
Object/Document1 instance now will have to prepare the customization
&H2&-&H6&-&H3&-&H8& that ClientC needs. The Object keeps this customized
data in a collection inside it.

At this time there is only one instance of the Object.

But ClintD asks for an Object/Document2 to the server, so the server
creates another instance of the Object, now with data of Document2, so
Object/Document2 prepares itself with the basic data...

And so on.

So... the Object needs to identify the clients in order to provide the
customized data.

Then when a client sends the customization information (4 longs), the
Object returns a ClientID to the client (a long), so in the future when
the client asks for some customized data, it must provide the ClientID
to the Object in order for the Object to know what to return.

The Object keeps a track of the clients and their customization (in a
client collection).

I didn't explain it better before because I thought it was quite complex
to explain all these details.

But the point is: why the client has to send the ClientID every time?

In the Client code:

YParameter = 111

Variable1 = Object.GiveMeDataCusmizableX(YParameter, _
ZParameter, ClientID)

YParameter = 112

Variable2 = Object.GiveMeDataCusmizableX(YParameter, _
ZParameter, ClientID)

Variable25 = Object.GiveMeDataCusmizableT(JParameter, _
ClientID)

It always has to supply the ClientID, that's what I don't like.

Does the object should not see what client is asking for something
without the client having to say "I'm client 4" every time it asks for
something? (Hence the title "Hey Class, this is me again, don't you see?")
That was the point. I'm pretty sure that that's not possible in VB6, but
I still wanted to discuss it.

Thanks.

Larry Serflaten

2/10/2011 3:10:00 PM

0


"Eduardo" <mm@mm.com> wrote

> Does the object should not see what client is asking for something
> without the client having to say "I'm client 4" every time it asks for
> something? (Hence the title "Hey Class, this is me again, don't you see?")
> That was the point. I'm pretty sure that that's not possible in VB6, but
> I still wanted to discuss it.

You miight as well consider the discusion closed on that path because
there is no way for the 'object' to know who is accessing a property
(of those properties that are defined as normal Properties)

But perhpas the actual context should be brought to light, because
what you ask for is not a typical situation. You have a server that
gives out objects, and you want those objects to appear one way
to one client, and another way to another client. That is not normal
usage.

If the number of different ways the object need to morph into was
a very limited set, you might get by identifying and creating an interface
for each set. But you indicate that there is going to be a large number
of different combinations, so an interface based remedy is not practical.

So lets start with the terminology, your server is actually going to be
a factory whose job it is to deal out objects of a number of different
types. It is a factory in essence, so lets call that the factory.

The clients are going to call on the factory to give out objects of
the type they need and then want to customize the objects to suit
the need.

So the question is, why don't the clients ask the factory for the
type of object they need, including the customization wanted?

That way the factory can keep track of the objects and their
configurations sets. If a client calls for a type and set that is already
running, it gets the running object, otherwise the factory creates
a new type and configures it to the required specification before
handing it over.

Again the actual context of what the types (documents) are,
and how they are customised and used may shed some light
on a completely different approach that is more commonly
used to solve the problem....

A factory that gives out morphing objects just isn't one of
the GoF patterns that I recognise. Maybe others with more
experience with patterns might have seen something similar?

LFS






Schmidt

2/10/2011 3:28:00 PM

0


"Eduardo" <mm@mm.com> schrieb

[Explanation in detail...]

Ok, better background now...
(though ... maybe for the next time ... small code-snippets
make it easier to get the grasp on something, more than
any "text-only"-explanation could accomplish, no matter
how large it may be).

Now, eating my own dog-food... ;-) ...I've uploaded a small
demo, how you could work with Private UDTs in something
like "DocType-DataHolder"-classes - and how one can work
with different Client-Behaviours against these raw DataContainers,
using an additional (as always Ralph ;-) "intermediate layer"
(a small DataHandler-Class for each DocType).

In short, the Client will not get an Object-Reference to the
Document-encapsulating RawData-Class - he will only
get an Object-Reference to the Handler-Class - a Class
which stores no data, but contains the Reference to the
RawData-Class and the few client-behaviour-settings
and all the Delegate-HandlerMethods

Note, that the RawData-Classes already support full
persistence (Loading/Saving against Files) - but the
Demo does not make use of it currently.

Hope that this is not an "already a bit overboarding
approach" - but once you've started with classes,
you can as well "go all the way" IMO.
Does not mean, that I consider the approach in any
way "perfect" - at the complexitiy-level you currently
work on, everything follows more or less some personal
taste. But maybe you get some ideas.
What (in a way) could be considered "innovative"
in the example below, is how I've implemented
someting like a "generic Property-Access, working
against the DataClass' Private m.UDT" (to avoid
double-implementation of Property-mapping against
the UDT-members, so that a real "full-blown" Property-
Implementation is done only in the *Handler*-Classes.


www.datenhaus.de/Downloads/DocHandling.zip


Olaf