C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Humble dialog access

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
lotusny78@yahoo.com
Guest





PostPosted: Wed Nov 16, 2005 9:27 am    Post subject: Humble dialog access Reply with quote



Hi everyone,

When creating a humble dialog (a smart logic class with minimal wrapper
class, see
[url]http://www.objectmentor.com/resources/articles/TheHumbleDialogBox.pdf)[/url],
should the wrapper class functions called by the smart class be
private, with the smart class as a friend, or public and don't worry
about the user calling them directly?

Put more generally, how do I set it up so that the function is
accessible to only the logic class and is this necessary/important?

To avoid distraction, the motivation for splitting the DB connection
into 2 classes (DatabaseConnection & ConnectionLogic) is to get as much
code under test as possible, while isolating code that is not feasible
to put under test (CRecordset::...). Assume that this structure is set
in stone for the purposes of this question.

e.g.

class DatabaseConnection
{
public:
//this function will only be used by ConnectionLogic
virtual bool isOpen() const = 0;
}

class MockConnection
{
public:
virtual bool isOpen() const { return amOpen; }
bool amOpen;
};

class RealConnection
{
public:
RealConnection() { myLogic.reset(new ConnectionLogic(*this)); }
virtual bool isOpen() const { return CRecordset::isOpen(); }
private:
auto_ptr<ConnectionLogic> myLogic;
};

class ConnectionLogic
{
ConnectionLogic(DatabaseConnection& db) : myDb(db) {}
....
void do() { ... if(myDb.isOpen()) ... }
private:
DatabaseConnection& myDb;
};

Also, can anyone explain why the new ConnectionLogic is in the body
instead of the initialization list?


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

Back to top
Alberto Ganesh Barbati
Guest





PostPosted: Thu Nov 17, 2005 8:04 am    Post subject: Re: Humble dialog access Reply with quote



[email]lotusny78 (AT) yahoo (DOT) com[/email] wrote:
Quote:
When creating a humble dialog (a smart logic class with minimal wrapper
class, see
[url]http://www.objectmentor.com/resources/articles/TheHumbleDialogBox.pdf)[/url],
should the wrapper class functions called by the smart class be
private, with the smart class as a friend, or public and don't worry
about the user calling them directly?

Whatever you feel that the user should not call directly then you should
declare it private, especially if you can declare it private without too
much hassle. That's a general rule of thumb, regardless of which pattern
you are trying to implement.

Quote:
class DatabaseConnection
{
public:
//this function will only be used by ConnectionLogic
virtual bool isOpen() const = 0;
}

class MockConnection
{
public:
virtual bool isOpen() const { return amOpen; }
bool amOpen;
};

class RealConnection
{
public:
RealConnection() { myLogic.reset(new ConnectionLogic(*this)); }
virtual bool isOpen() const { return CRecordset::isOpen(); }
private:
auto_ptr<ConnectionLogic> myLogic;
};

This calls for undefined behaviour, because at this point
ConnectionLogic is still an incomplete type and std::auto_ptr<> does not
work with incomplete types. Notice that a forward declaration like
"class ConnectionLogic;" is not enough: you have to provide the whole
definition of class ConnectionLogic before you can use it as a parameter
to std::auto_ptr<>.

Quote:
Also, can anyone explain why the new ConnectionLogic is in the body
instead of the initialization list?

No reason whatsoever. I would have put it in a ctor initializer, I find
it to be better programming style, but it's a matter of taste.

HTH,

Ganesh

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


Back to top
lotusny78@yahoo.com
Guest





PostPosted: Wed Nov 23, 2005 8:36 pm    Post subject: Re: Humble dialog access Reply with quote



Quote:
Also, can anyone explain why the new ConnectionLogic is in the body
instead of the initialization list?


Quote:
No reason whatsoever. I would have put it in a ctor initializer, I find
it to be better programming style, but it's a matter of taste.


If the this pointer for the RealConnection class is passed in the
initialization list, isn't there a danger that the ConnectionLogic
class uses it before the class is completely initialized?

e.g. ConnectionLogic(DatabaseConnection& db) : myDb(db) {
myDb.doSomething(); }

I got the privacy issue. I was thinking about selective friendship. I
wanted to give access to only certain functions to a helper class. I
decided to split the interface into two classes.


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


Back to top
Alberto Ganesh Barbati
Guest





PostPosted: Thu Nov 24, 2005 8:04 am    Post subject: Re: Humble dialog access Reply with quote

[email]lotusny78 (AT) yahoo (DOT) com[/email] wrote:
Quote:
Also, can anyone explain why the new ConnectionLogic is in the body
instead of the initialization list?

No reason whatsoever. I would have put it in a ctor initializer, I find
it to be better programming style, but it's a matter of taste.

If the this pointer for the RealConnection class is passed in the
initialization list, isn't there a danger that the ConnectionLogic
class uses it before the class is completely initialized?

Strictly speaking, even using *this in the constructor body has the same
problem. That's because *this is to be considered "completely
initialized" only after the constructor call has completed (compare with
clause 3.Cool. However, your remark has a certain truth in it (it seems
that I had been too hasty in writing my answer, I apologize). The main
difference is that once entered into the constructor body you are sure
that all *subobjects* have been fully constructed. This means that you
don't run the risk of accessing uninitialized stuff (which is very bad),
but you still are not safe against logic errors. For example:

class DatabaseConnection;

class ConnectionLogic
{
ConnectionLogic(DatabaseConnection& db);

private:
DatabaseConnection& myDb;
};

class RealConnection
{
public:
RealConnection()
{
myLogic.reset(new ConnectionLogic(*this));
open(); // will make isOpen() return true
}

virtual void do() const
{
assert(isOpen());
...
}

private:
auto_ptr<ConnectionLogic> myLogic;
...
};

ConnectionLogic::ConnectionLogic(DatabaseConnection& db)
: myDb(db)
{
myDb.do(); // ops! will call RealConnection::do()
// but connection is not yet open!
}

HTH,

Ganesh

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


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.