Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Testing Program Question

Reply
Thread Tools

Testing Program Question

 
 
Öö Tiib
Guest
Posts: n/a
 
      02-14-2010
On Feb 14, 4:08*pm, "Leigh Johnston" <(E-Mail Removed)> wrote:
>
> It is a nonsense to say that virtual functions shouldn't be public: a public
> virtual destructor is fine if you want to delete through a base class
> pointer. *Bjarne Stroustrup's first virtual function example in TC++PL is a
> public Employee:rint() method, I see no problem with this. *You are
> probably thinking of virtual functions which are called as part of some
> algorithm implemented in a base class, such virtual functions need not be
> public as it makes no sense for them to be but it does not follow that this
> is the case for all virtual functions.
>


Yes, virtual functions may be public. It is better when they are not
since otherwise such function has two jobs to do. It has to specify
external interface of class and it has to specify inner hook for
derived classes to modify behavior of base. Missions of hook and
interface are critical and so burdening it all onto one function goes
against good practice of separating concerns.

Therefore policies against virtual functions in public interface are
more and more common. There are even special prefixes for virtual
functions like 'do' demanded by some style policies i have seen. This
does not concern destructors since destructors have all same interface
and have separate paragraph in all style policies anyway.
 
Reply With Quote
 
 
 
 
Öö Tiib
Guest
Posts: n/a
 
      02-14-2010
On Feb 14, 8:10*pm, "Leigh Johnston" <(E-Mail Removed)> wrote:
> It is not the end of the world to move from public virtual to
> private/protected virtual if the situation changes to require it:
>
> Iteration #1 (Initial design)
>
> class foo
> {
> public:
> * * virtual void xyzzy();
>
> };
>
> class bar : foo
> {
> public:
> * * virtual void xyzzy();
>
> };
>
> Iteration #2 (need to do new stuff before virtual function is called)
>
> class foo
> {
> public:
> * * void xyzzy() { /* new stuff */ do_xyzzy(); }
> protected:
> * * virtual void do_xyzzy() = 0; // forces clients to rewrite their code
> (provide a new override)
>
> };
>
> class bar : foo
> {
> protected:
> * * virtual void do_xyzzy();
>
>
>
> };


Yes, it is exactly so simple and it gives lot of benefits. Base class
is in complete control of its interface and contract, can check pre
and postconditions, inject instrumentation and so on in a single
place. Implementation is also free to take its natural form and no
compromises are needed with interface. If it needs to change then
change/add/split the non-public virtuals, public interface stays
stable and not virtual.

All that yo-yo with virtuals is one of the biggest sources of issues
in C++ so this 'no virtual interfaces' idiom should make lot of sense
if to think a bit. Also like James Kanze suggested it reduces need for
defenses all over the place by moving some of them to front.
 
Reply With Quote
 
 
 
 
Öö Tiib
Guest
Posts: n/a
 
      02-14-2010
On Feb 14, 10:54*pm, "Leigh Johnston" <(E-Mail Removed)> wrote:
> > All that yo-yo with virtuals is one of the biggest sources of issues
> > in C++ so this 'no virtual interfaces' idiom should make lot of sense
> > if to think a bit. Also like James Kanze suggested it reduces need for
> > defenses all over the place by moving some of them to front.

>
> You misunderstand me, I am advocating that virtual interfaces are fine in
> themselves and it is not too difficult to mutate said interfaces as
> required. *Obviously I am in favour of keeping public interfaces as simple
> and minimalist as possible and quite often I have virtual methods which are
> protected/private when they from part of a class's implementation rather
> than public interface.
>
> The following are fine for example:
>
> class interface
> {
> public:
> * * virtual void foo() = 0;
> * * virtual void bar() = 0;
>
> };
>
> class widget
> {
> public:
> * * virtual void draw() const;
>
> };
>
> It is wrong to say that virtual functions must not be public.
>
> /Leigh


Yes, virtual interface is not wrong. All i say is that having the
interface and implementation separated helps a lot and brings no
downsides whatsoever. This is one good policy how to draw line and
separate interface from implementation. Lot of people, experts of the
trade, establish within their teams and follow that policy. It is good
from the start and it is hard to find solid reasons why not to on most
cases.

You can establish interface and start to code. Others can start to
write code that uses that interface. If it happens that you need to
split processing into several phases for more flexibility of it, then
you do it, it is implementation detail:

class Widget
{
public:
int draw( Gadget& ) const;
bool isDone() const;
// ...
private:
virtual int doDrawPhase1( Gadget& ) const = 0;
virtual int doDrawPhase2( Gadget& ) const = 0;
virtual bool doIsDone() const = 0;
// ...
};

Kind of win-win-win situation. It is still the same amount of
instructions produced if you inline draw() and isDone() but you have
checkpoint within your base interface.
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      02-15-2010
On Feb 15, 1:45*am, "Leigh Johnston" <(E-Mail Removed)> wrote:
>
> I consider myself to be an expert of sorts (well competent at least) and I
> am sure you do think the same of yourself. *I've been programming C++ since
> 1993 and have worked on large and small projects and never really had a
> problem with virtual functions being public. *I will not stop this practice
> now because a *subset* of the C++ community advocates against it. *If the
> *entire* C++ community advocates against it then maybe I would think
> different.


My position about the issue is certainly not as strong as to forbid
public virtuals what so ever. I have experienced clear benefits of
it ... but where everybody expects public virtual returning covariant
like for example clone() i implement it and do not implement some sort
of cloning factory that Andrei Alexandrescu suggests somewhere to
avoid breaking the idiom. On clear corner cases it is better to not be
too pedantic.
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      02-15-2010
On Feb 15, 4:09*pm, "Leigh Johnston" <(E-Mail Removed)> wrote:
> "Öö Tiib" <(E-Mail Removed)> wrote in message
>
> news:(E-Mail Removed)...
>
>
>
>
>
> > On Feb 15, 1:45 am, "Leigh Johnston" <(E-Mail Removed)> wrote:

>
> >> I consider myself to be an expert of sorts (well competent at least) and
> >> I
> >> am sure you do think the same of yourself. *I've been programming C++
> >> since
> >> 1993 and have worked on large and small projects and never really had a
> >> problem with virtual functions being public. *I will not stop this
> >> practice
> >> now because a *subset* of the C++ community advocates against it. *If the
> >> *entire* C++ community advocates against it then maybe I would think
> >> different.

>
> > My position about the issue is certainly not as strong as to forbid
> > public virtuals what so ever. I have experienced clear benefits of
> > it ... but where everybody expects public virtual returning covariant
> > like for example clone() i implement it and do not implement some sort
> > of cloning factory that Andrei Alexandrescu suggests somewhere to
> > avoid breaking the idiom. On clear corner cases it is better to not be
> > too pedantic.

>
> Alexandrescu uses public virtual functions in MC++D also, look at his take
> on Visitor Pattern for example.
>
> /Leigh


Of course. This is easy to see why. Visitor pattern is a way how
double dispatch is implemented using specific purpose interface. The
purpose of accept() and visit() is defined and is not likely to change
so some concerns are solved and no point to separate them.

The only reason to use private virtual idiom there may be for
simplifying instrumenting that interface for example to do deep
exception safety unit tests on all the different visitors visiting.
Might be good idea with mission-critical products.
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      02-16-2010
On Feb 14, 2:08 pm, "Leigh Johnston" <(E-Mail Removed)> wrote:
> "James Kanze" <(E-Mail Removed)> wrote in message


> news:(E-Mail Removed)...
> > On Feb 13, 12:41 pm, "Leigh Johnston" <(E-Mail Removed)> wrote:
> >> > Asserts are a sort of life jacket, to prevent things from
> >> > ****ing up too much when you screwed up. Removing them
> >> > from production code is akin to wearing a life jacket
> >> > when practicing in the harbor, but taking it off when you
> >> > go to sea. Sometimes, it's necessary to remove asserts
> >> > for performance reasons, and for some particular
> >> > applications (games?), it's probably preferrable to
> >> > remove them completely (in which case, you do have to
> >> > study what happens when they are removed---there's no
> >> > point in removing an assert if you're just going to get a
> >> > crash three statements later).


> >> I disagree, why do you think assert was designed to do
> >> nothing for NDEBUG?


> > So that you can turn it off when you have to. The designed use
> > would be to use some application specific macro, defined (or
> > not) in the command line, and then to wrap the (few) critical
> > functions in something like:


> > #ifdef PRODUCTION
> > #undef NDEBUG // Just in case.
> > #define NDEBUG
> > #include <assert.h>
> > #endif
> > void critical_function()
> > {
> > // ...
> > }
> > #undef NDEBUG
> > #include <assert.h>


> > Why do you think you're allowed to include <assert.h> multiple
> > times, with it's meaning depending each time on the current
> > definition of NDEBUG?


> >> Asserts were designed to be used as a debugging tool so should
> >> do nothing in released production code *unless* a higher
> >> degree of defensiveness is required.


> > That's your opinion. It doesn't correspond to the design of the
> > feature, nor good programming practices.


> Sorry but I disagree with your opinion.


For the most part, I'm not stating opinion. Look closely at the
design of assert, and the guarantees it gives you.

> Different software has different requirements regarding how
> defensive you should be. A typical application should not be
> using assert to terminate in a released product.


A typical application in what domain. It's clear that any
critical software must terminate as soon as it is in doubt. And
I've pointed out why this is true for an editor (and the same
logic also holds for things like spreadsheets). I also
recognize that there are domains where it isn't true. I'm not
sure, however, what you consider "typical".

> A released product should be using exceptions for errors which
> are valid during runtime. Assert is used for catching
> programming errors, not valid runtime errors or bad user
> input.


There's no disagreement on that.

> >> I disagree that only games are an exception,


> > They're certainly not the only exception. But such exceptions
> > are just that, exceptions. Most software should ship with
> > asserts turned on, *if* they can afford the performance impact.
> > (An awful lot of software is IO bound, so the performance impact
> > can be ignored.)


> >> I would also argue that such defensiveness is not required for
> >> a typical office application for example (e.g. a word
> >> processor).


> > It depends on whether you consider trashing the users work
> > acceptable or not. And what the other costs are---since it
> > costs nothing to leave it, assuming no performance problems, and
> > requires extra work to remove it, it's more or less stupid to
> > choose the less robust solution.


> Programmers should get into the habit of adequately testing
> their software prior to release (assert helps with this) and
> users should get into the habit of regularly backing up their
> important data.


It would help if you'd read what was written, before disagreeing
with it. No one is arguing against testing. And it's not the
user who's backing up his data, it's the editor---all of the
editors I know to day regularly checkpoint their data in case
they crash. The whole point is that if there is a programming
error, and the editor continues, it's liable to overwrite the
checkpoint with corrupt data (or the user, not realizing that
the data is corrupt, is liable to overwrite his own data).

> >> The amount of software which requires less defensiveness
> >> probably outnumbers the amount of software that requires
> >> increased defensiveness. If you are worried about cosmic
> >> rays hitting your ram chips then perhaps you should use
> >> assert more!


> > You should always use assert liberally. We're talking about
> > whether you should turn it off in production code. In other
> > words, whether you should take an additional, explicit action
> > (defining NDEBUG) to render the software less robust.


> Using assert liberally is fine (I have no problem with this)
> but this (in most cases) is an aid during development only,
> rather creating hundreds of crash points in a released product
> (in most cases).


If you've tested correctly, leaving the asserts active creates
zero crash points in the released product. And if you've missed
a case, crashing is the best thing you can do, rather than
continuing, and possibly destroying more data.

[...]
> >> This is the usual argument put forward in favour of more
> >> defensive programming but in my opinion having an assert after
> >> every other line of code is overkill for a typical office
> >> application as I have already said.


> > I've never seen assert's used that heavily. And how often or
> > where you write an assert is a different question---in general,
> > a minimum would be to assert preconditions for a function, at
> > least when that function is called from other modules, and
> > post-conditions for a virtual function, when the derived classes
> > may be called from other modules. (This means, of course, that
> > your virtual functions shouldn't be public. But that's a pretty
> > well established rule anyway.)


> I am sorry but you are wrong, you should either be extremely
> defensive or not defensive at all, somewhere in-between is
> pointless.


When someone starts issuing statements as ridiculous as that, I
give up. It's not humanly possible to be 100% defensive.

> Extremely defensive means at least one assert at some point
> after call a function which has side effects (which could be a
> precondition check before a subsequent function call). This
> is overkill for typical desktop applications for example.


> It is a nonsense to say that virtual functions shouldn't be
> public: a public virtual destructor is fine if you want to
> delete through a base class pointer.


The destructor is an obvious exception. But most experts today
generally agree that virtual functions should usually be either
protected or private.

Again, there are exceptions, and I have classes with only public
virtual functions. (Callbacks are a frequent example.) But
they're just that: exceptions.

> Bjarne Stroustrup's first virtual function example in TC++PL
> is a public Employee:rint() method, I see no problem with
> this.


For teaching, neither do I. (For that matter, a print function
might be an exception. It's hard to imagine any reasonable pre-
or post-conditions.)

> You are probably thinking of virtual functions which are
> called as part of some algorithm implemented in a base class,
> such virtual functions need not be public as it makes no sense
> for them to be but it does not follow that this is the case
> for all virtual functions.


No, I'm not thinking of the template method pattern. I'm
thinking of programming by contract.

> >> >> Genuine runtime errors (e.g. out of memory, disk space
> >> >> or user input error) are best handled by exceptions or
> >> >> return codes.


> >> > Agreed. Any program which has an assertion failure on
> >> > user input error is broken, and the same probably holds
> >> > for out of memory, although it's discutable for some
> >> > applications. (What happens if the "out of memory"
> >> > occurs because the runtime is trying to grow the stack?
> >> > Or if the only possible cause of "out of memory" is a
> >> > memory leak? Or simply that your OS doesn't handle "out
> >> > of memory" safely?)


> >> Running out of stack space is more likely to be due to a
> >> programming error rather than a valid runtime error
> >> condition.


> > Probably in most applications, although it also depends
> > somewhat on the OS. (Linux and Solaris don't have
> > "pre-allocated" stacks of a specific size, so using too much
> > heap can cause a stack overflow in some specific cases.)
> > I've worked on applications with embedded recursive descent
> > parsers, parsing various forms of user input. How deep the
> > stack needs to be depends on the complexity of the
> > expression given to it by the user. But in most cases, even
> > then, you can set some arbitrary complexity limit, test it,
> > and ensure that the stack is large enough to handle it.


> Writing code without some bound on stack growth is incorrect
> in my opinion.


Yes, but only because we can't catch the overflow in the same
way we can catch bad_alloc. Otherwise, the principle is the
same.

> A compiler should not stack fault when parsing source code of
> any complexity for example, it should either be non-recursive
> (be heap bound) or have some hard limit. A stack fault is not
> acceptable, running out of heap is acceptable and can be
> signalled via an exception.


Most people would disagree with you in general, concerning a
compiler. Why should it have an artificial hard limit?

In fact, the fact that running out of stack cannot be gracefully
caught means that we do have to do something. But don't confuse
the cause and the effect.

--
James Kanze
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      02-16-2010
On Feb 15, 1:13 pm, "Leigh Johnston" <(E-Mail Removed)> wrote:

[...]
> Read GoF: even though it includes the Template Method most of
> the examples for the other design patterns use public virtual
> functions.


Would they do the same today? In 1995, most people hadn't even
heard of private virtual functions.

--
James Kanze
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      02-16-2010
* James Kanze:
>
> In fact, the fact that running out of stack cannot be gracefully
> caught means that we do have to do something. But don't confuse
> the cause and the effect.


Another angle is to focus on prevention rather than detection.

A semi-portable way to check for available stack space is to use the de facto
standard 'alloca', which it seems has the same behavior on a wide range of
platforms, returning NULL if there isn't enough space.

Curiously, I've never used that solution; what it solves seems to not be that
big a problem in practice, i.e. it's probably a solution looking for a problem?

And I can imagine that on some systems the alloca that I mentioned here might
cause virtual allocated address space to be mapped to actual memory.

Which might slow down things.


Cheers,

- Alf
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      02-16-2010
* Alf P. Steinbach:
> * James Kanze:
>>
>> In fact, the fact that running out of stack cannot be gracefully
>> caught means that we do have to do something. But don't confuse
>> the cause and the effect.

>
> Another angle is to focus on prevention rather than detection.
>
> A semi-portable way to check for available stack space is to use the de
> facto standard 'alloca', which it seems has the same behavior on a wide
> range of platforms, returning NULL if there isn't enough space.
>
> Curiously, I've never used that solution; what it solves seems to not be
> that big a problem in practice, i.e. it's probably a solution looking
> for a problem?
>
> And I can imagine that on some systems the alloca that I mentioned here
> might cause virtual allocated address space to be mapped to actual memory.
>
> Which might slow down things.


Oh, discovery:

the reason that I've never used the alloca technique that I mention above seems
to be that alloca *is not* consistently defined on different platforms.

<url: http://www.mkssoftware.com/docs/man3/alloca.3.asp>
guarantees 0 on error,

<url: http://msdn.microsoft.com/en-us/library/wb1s57t5%28VS.71%29.aspx>
guarantees a "stack overflow exception" on error, and

<url: http://www.kernel.org/doc/man-pages/online/pages/man3/alloca.3.html>
says the error behavior is undefined.

Perhaps the group can benefit from this info.


Cheers,

- Alf
 
Reply With Quote
 
Ersek, Laszlo
Guest
Posts: n/a
 
      02-16-2010
In article <hlcs0f$lrg$(E-Mail Removed)-september.org>, "Alf P. Steinbach" <(E-Mail Removed)> writes:
> * Alf P. Steinbach:
>> * James Kanze:
>>>
>>> In fact, the fact that running out of stack cannot be gracefully
>>> caught means that we do have to do something. But don't confuse
>>> the cause and the effect.

>>
>> Another angle is to focus on prevention rather than detection.
>>
>> A semi-portable way to check for available stack space is to use the de
>> facto standard 'alloca', which it seems has the same behavior on a wide
>> range of platforms, returning NULL if there isn't enough space.
>>
>> Curiously, I've never used that solution; what it solves seems to not be
>> that big a problem in practice, i.e. it's probably a solution looking
>> for a problem?
>>
>> And I can imagine that on some systems the alloca that I mentioned here
>> might cause virtual allocated address space to be mapped to actual memory.
>>
>> Which might slow down things.

>
> Oh, discovery:
>
> the reason that I've never used the alloca technique that I mention above seems
> to be that alloca *is not* consistently defined on different platforms.


Perhaps under some circumstances you could use something like this to
pre-test availability of stack space:

http://groups.google.com/group/comp....b2fc2487928f47

Cheers,
lacos
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
testing testing 123 neville Computer Support 7 06-28-2005 05:06 PM
testing testing neville Computer Support 16 06-05-2005 09:02 PM
testing testing neville Computer Support 2 05-27-2005 09:57 AM
testing testing 123 daniel edwards Computer Support 4 05-20-2004 10:36 PM
testing--news2004--testing Boomer Computer Support 3 09-24-2003 06:54 PM



Advertisments