Boost logo

Boost :

From: scott (scottw_at_[hidden])
Date: 2004-02-29 22:53:16


Hi Mark,

You have introduced a third perspective - looks promising. Hope
I can keep track of all the differences and still contribute in some
useful manner.

> [mailto:boost-bounces_at_[hidden]]On Behalf Of Mark Blewett
>

<snip>

>
> class MyServant : public Servant
> {
> public:
> MyServant(Scheduler* scheduler) : Servant(scheduler) {}
> void do_fn(int x, int y) { std::cout << x << " " <<
> y << std::endl; }
> };
>

> class MyServant : public Servant
> {
> public:
> MyServant(Scheduler* scheduler) :
> Servant(scheduler), fn(this,
> &MyServant::do_fn) {}
> MethodProxy<MyServant, int, int> fn;
> private:
> void do_fn(int x, int y) { std::cout << x << " " <<
> y << std::endl; }
> };
>

<snip>

I understand the direction that both Matthew and yourself are heading. The
resulting interface for clients of your class, is concise. Fully bound
functions
are a nice packaging and there are plenty of precendents. There is one
design
constraint that this direction would impose on clients, that rules it out as
a solution for me. This doesnt necessarily interest you but just in case, I
will try to paint the picture as briefly as I can.

If active objects (i.e. classes deriving from Servant) communicate by
calling
methods defined in each other, then they have compile-time knowledge of each
other. Reasonable assumption I suppose. However, it follows that every
client of a
particular object, i.e. an active object that calls a member of another
active
object, is itself required to provide a specific interface. That being the
interface that the second object uses to respond.

Returning to the db server example; every client must derive from a common
class that defines all the members that the server might call. Perhaps like
this;

class DbServant : public Servant
{
public:
        DbServant(Scheduler* scheduler) :
        Servant(scheduler), fn(this,
                &DbServant::do_fn) {}
                MethodProxy<DbServant, int, int> fn;
private:
        void do_fn(int x, int y)
        { std::cout << x << " " << y << std::endl; }
};

class MyReadOnlyViewer : public DbServant
{
        // Run a status display repeated around
        // the factory
};

class MyViewerAndController : public DbServant
{
        // Run a window with controls
        // for modifying the data model
};

This (hopefully) seems like a reasonable circumstance. But as coded the
db_server would be calling methods defined in DbServant when what you
really want is different implementations for MyReadOnlyViewer and
MyViewerAndController. I assume that with some twiddling your technique
could accomodate these kind of requirements (given that you are still
reading and still interested).

Would the db_server also have a separate "db_interface" class?

Also, if this kind of interface class technique has any legs is it
also (potentially) dragging lots of implementation details along
with it? Can that be avoided? Should it be?

Cheers,
Scott


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk