$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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