From: Michael Mol on
On Dec 17, 8:32 am, Jonathan Lee <cho...(a)shaw.ca> wrote:
> On Dec 16, 8:50 am, Michael Mol <mike...(a)gmail.com> wrote:
> > The two approaches under consideration are:
>
> > OBJHANDLE objHandle = factoryObj.CreateObject();
> > objHandle->OperateOnObject(42);
> > // or
> > (*objHandle)OperateOnObject(42);
> > objHandle->DestroyObject();
>
> > and an approach which is used as follows:
>
> > OBJHANDLE objHandle = factoryObj.CreateObject();
> > objHandle.OperateOnObject(42);
> > objHandle.DestroyObject();
>
> > The question is, which approach is more appropriate and intuitive for C
> > ++, and why? I ask because this is a matter of matter of debate
> > between another coworker and I, and the third coworker consulted had
> > no opinion.
>
> I have two thoughts:
> 1) The second example is an odd sort of indirection. Are all your
> methods called "DoSomethingToObject"? It seems like your handler
> class does nothing except "hold" the object. Which leads me to
> think
> 2) If you're going to use indirection, use dereference. But change
> the method names. Instead of
> objHandle.OperateOnObject(42);
> this seems much more natural:
> objHandle->Operate(42);
> The notation suggests you are acting on the held object. No
> need for "OnObject" or similar.
>
> So if you insist on keeping the method names, the "." notation makes
> more sense. If you're willing to change, "->" would be even better.

I should have used different method names for the example; The ones
given were intended to be generic, but I should have used somthing
similar to DoSomething(). The actual method names in place are closer
to, e.g. GetThroughput(), AttachListener(), DetachListener(), etc.

OBJHANDLE itself is currently actually implemented as a pointer to the
class in question, but typedef'd in a way that direct dereferencing is
impossible (to force checking for validity, rather than risk
dereferencing a NULL, destroyed or otherwise invalid pointer). The
container class in question, as written, contains that value.

If I'm reading your post correctly, then since the wrapper class
doesn't contain the object itself, but rather access to the object,
then you would suggest that the -> syntax is preferred.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: jp on
On Dec 16, 8:50 am, Michael Mol <mike...(a)gmail.com> wrote:
> Let's say you have a factory which returns handles to objects that it
> allocates. You pass these handles to the factory whenever you want to
> use the object or destroy it. The factory's "OperateOnObject" class
> verifies that the handle is within its object collection, and then
> marshals the OperateOnObject call to the class's internal
> OperateOnObject method. All external operations on the object
> instance are required to pass through the Factory in order to
> guarantee that the object instance is still valid at the time of call.
>
> This leads to code roughly like this. (Not using exceptions here, but
> rather return error codes.)
>
> // For the sake of scope, consider this as a global singleton factory.
> // For the sake of concerns over initialization and destruction,
> assume that's dealt with in code not shown.
> class SomeFactory
> {
> public:
> OBJHANDLE CreateObject();
> ERRCODE DestroyObject(OBJHANDLE);
> ERRCODE OperateOnObject(OBJHANDLE objHandle, int someArgument);
> protected:
> OBJCOLLECTION objCollection;
>
> } factoryObj;
>
> // In some function, somewhere
> OBJHANDLE objHandle = factoryObj.CreateObject();
> factoryObj.OperateOnObject(objHandle, 42);
> factoryObj.DestroyObject(objHandle);
>
> Providing objHandle as the first argument of every call to a distinct
> marshalling class instance proves tedious, so a means of overloading
> OBJHANDLE is desired such that explicit references to factoryObj are
> unnecessary. The resulting OBJHANDLE (a wrapper for the type formally
> known as OBJHANDLE) would not likely behave specially at construction
> or destruction, nor likely have a custom copy constructor.
>
> The two approaches under consideration are:
>
> OBJHANDLE objHandle = factoryObj.CreateObject();
> objHandle->OperateOnObject(42);
> // or
> (*objHandle)OperateOnObject(42);
> objHandle->DestroyObject();
>
> and an approach which is used as follows:
>
> OBJHANDLE objHandle = factoryObj.CreateObject();
> objHandle.OperateOnObject(42);
> objHandle.DestroyObject();
>
> Both approaches would have the exact same effects on the state of
> factoryObj and the members of OBJCOLLECTION, which would also be the
> same as the old code where the old OBJHANDLE type was passed as the
> first argument.
>
> The question is, which approach is more appropriate and intuitive for C
> ++, and why? I ask because this is a matter of matter of debate
> between another coworker and I, and the third coworker consulted had
> no opinion.

On 12/16/2009 8:50 AM, Michael Mol wrote:
> OBJHANDLE objHandle = factoryObj.CreateObject();
> factoryObj.OperateOnObject(objHandle, 42);
> factoryObj.DestroyObject(objHandle);

Technically, wouldn't this be

OBJHANDLEWRAPPER objHandleWrapper = factoryObj.CreateObject();
factoryObj.OperateOnObject(objHandleWrapper, 42);
factoryObj.DestroyObject(objHandleWrapper);

Given that, you should be able to operate directly on the wrapper
with:

objHandleWrapper.OperateOnObject(42);

Or, you could extract the handle from the wrapper and then use the
original syntax:

OBJHANDLE objHandle = objHandleWrapper.GetHandle();
factoryObj.OperateOnObject(objHandle, 42);

And obviously you could pass a pointer to the wrapper to another
function, and operate on that with:

SomeClass.SomeFunction(&objHandleWrapper);

void SomeClass::SomeFunction(OBJHANDLEWRAPPER* pObjHndWrpr)
{
pObjHndWrpr->OperateOnObject(42);
}

Just my thoughts...


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Michael Mol on
On Dec 17, 9:02 am, Anders Dalvander <goo...(a)dalvander.com> wrote:
> On Dec 16, 2:50 pm, Michael Mol <mike...(a)gmail.com> wrote:
>
> > The question is, which approach is more appropriate and intuitive for C
> > ++, and why?
>
> Each class and function should have responsibility for a single task
> or related tasks.

Basic OO design. That is exactly what the Factory is doing, in this
case, as it is maintaining a roster of all currently valid instances
identified by OBJHANDLE. The instances themselves have their own
class.

>
> The factory class should have the responsibility to create objects.
> The OBJHANDLE class should have the responsibility to perform its
> specific tasks.

The question I've asked was how to represent the syntax of using the
OBJHANDLE.

> The destructor of a class should have the responsibility to clean up
> resources and such.

The destructor of the class where an instance of which is identified
by OBJHANDLE has the responsibility of cleaning up the class
instance. That hasn't changed.

Actually, I fear I completely FUBAR'd this statement in a total mental
lapse:

"However, the factory
object can't be removed entirely, as it also manages the relationship
of object instances to each other and the system resources they happen
to extract. (A bit of internal behavior I hoped wasn't necessary to
describe in order to ask about intuitive of dereferencing syntax.) "

Those relationships are handled within the class of which that
OBJHANDLE identifies an instance*, not within the factory class.

* Sorry for the obtuse language; OBJHANDLE is intentionally not
directly associated with the type of the class it identifies, because
it's imperative that those class instances not be used without
checking for their validity. If I go ahead and call it a pointer, then
confusion would arise based on the assumption that it's already
directly usable as such. Hence the term "handle". I'm open to
becoming familiarized with clearer language and/or terminology.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Michael Mol on
On Dec 17, 1:19 pm, James Kanze <james.ka...(a)gmail.com> wrote:
> On Dec 16, 9:50 pm, Maxim Yegorushkin <maxim.yegorush...(a)gmail.com>
> wrote:
> > On 16/12/09 13:50, Michael Mol wrote:
[snip]

>
> Except that boost::smart_ptr won't necessarily work here---it will
> render destruction non-deterministic, and will cause objects to "leak"
> as soon as there are any cycles.
>
> Of course, his solution won't work either, since without garbage
> collection, there's absolutely no way to ensure that the invalid
> pointer
> remains invalid.

While the identifier space is currently sparse enough that that hasn't
been detected as a problem (normally, fewer than twenty allocations
occur within the lifetime of the application), that's an interesting
point. I originally sought to deal with it in the beginning by using
sequential integer values, but settled back on the raw pointer value
to deal with resulting code complexity. I suppose UUIDs would work,
but would be overkill. A 64-bit sequential integer could work as well;
The run time of the application, and the frequency of allocations,
would mean there would never be an overflow.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Flaamwing on
> // In some function, somewhere
> OBJHANDLE objHandle = factoryObj.CreateObject();
> factoryObj.OperateOnObject(objHandle, 42);
> factoryObj.DestroyObject(objHandle);
>
Technically, wouldn't this be

OBJHANDLEWRAPPER objHandleWrapper = factoryObj.CreateObject();
factoryObj.OperateOnObject(objHandleWrapper, 42);
factoryObj.DestroyObject(objHandleWrapper);

Given that, you should be able to operate directly on the wrapper
with:

objHandleWrapper.OperateOnObject(42);

Or, you could extract the handle from the wrapper and then use the
original syntax:

OBJHANDLE objHandle = objHandleWrapper.GetHandle();
factoryObj.OperateOnObject(objHandle, 42);

And obviously you could pass a pointer to the wrapper to another
function, and operate on that with:

SomeClass.SomeFunction(&objHandleWrapper);

void SomeClass::SomeFunction(OBJHANDLEWRAPPER* pObjHndWrpr)
{
pObjHndWrpr->OperateOnObject(42);
}

Just my thoughts...
John

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]