Monday, February 1, 2016

Digest for comp.lang.c++@googlegroups.com - 25 updates in 7 topics

Juha Nieminen <nospam@thanks.invalid>: Feb 01 09:30AM

> Premise: Multiple inheritance is universally accepted as bad
 
When asked *why* multiple inheritance is bad, one, and only one example is
always and ever given: Diamond inheritance.
 
So why not say that diamond inheritance is bad, rather than multiple
inheritance? Why is MI blamed for a different pattern?
 
There is absolutely nothing wrong with multiple inheritance. Not from
a practice point of view nor from a design point of view.
 
From a design point of view inheritance creates an "is-a" relationship.
Multiple inheritance simply adds additional "is-a" relationships
(which I like to call "and-a").
 
For example:
 
class Button: public Widget, public ReferenceCountable
 
means "Button is-a Widget and-a ReferenceCountable (object)"
 
The above example also demonstrates why multiple inheritance is useful.
Ostensibly both Widget and ReferenceCountable have members and methods
of their own, and their usage in this situation is sensible.
 
"Interfaces" are nothing more than a crippled form of multiple inheritance.
Saying otherwise is silly. The design relationship is exactly the same
(your class will have an "is-a" relationship with an interface in the
exact same way as with an actual class. There is no practical difference.)
 
The crippling of interfaces simply causes needless code repetition in
many cases (because the same methods need to be implemented again and
again; moreover, many of the languages offering interfaces do not offer
any way of avoiding this code repetition.) Code repetition is one of the
worst designs in programming.
 
Why not allow method implementations and members in interfaces? There is
no technical nor designwise reason not to allow that. Simply disallow
diamond inheritance if that's so scary.
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
scott@slp53.sl.home (Scott Lurndal): Feb 01 02:02PM

>>show how virtual inheritance works.
 
> We do care about proper lifetime control in this newsgroup and
> usually use smart pointers instead of raw pointers, even if it
 
Speak for yourself, kemosabe.
"Öö Tiib" <ootiib@hot.ee>: Feb 01 06:26AM -0800

On Monday, 1 February 2016 16:02:26 UTC+2, Scott Lurndal wrote:
 
> > We do care about proper lifetime control in this newsgroup and
> > usually use smart pointers instead of raw pointers, even if it
 
> Speak for yourself, kemosabe.
 
Was "kemosabe" mean here as "trusty scout" or "faithful friend"?
Victor Bazarov <v.bazarov@comcast.invalid>: Feb 01 09:22AM -0500

On 2/1/2016 6:22 AM, Stefan Ram wrote:
 
> When a function »m« calls another function »f«, we call »m« a
> »client« of »f«, but how to we call »f« then? One does not
> call a function a »server«, does one?
 
In the latter case I'm more familiar with referring to 'm' as a "caller"
(usually inside the 'f' function), and if one has to give 'f' a special
name, it's a "called function". However, given that the compiler is
free to inline the code (or refrain from generating the code that would
call it _at all_ in some cases), no special term is in common use, I
believe. I have heard a "callee", but not often enough to make it
customary.
 
V
--
I do not respond to top-posted replies, please don't ask
Robert Wessel <robertwessel2@yahoo.com>: Feb 01 01:01AM -0600

On Mon, 01 Feb 2016 01:17:06 +0200, Paavo Helde
 
>Private methods are untestable only if they are never called by the
>public methods. TDD tests the features and does not care how the class
>provides these features.
 
 
While TDD is not our prime methodology, we commonly* have** "friend
class TestAbc;" in our definitions of class Abc (a bit of additional
fiddle - namely a forward declaration of class TestAbc - needed if
there's a namespace involved). At least for those cases when we want
tests for private functions. Ugly? A bit, sure. And yes, it
requires the maintenance of enough discipline so that people don't
write TestAbc classes just to poke around where they oughtn't.
 
 
 
*FSVO "commonly"
 
**For historical reasons the prefix string is actually "tharness"
rather than "Test".
leigh.v.johnston@googlemail.com: Feb 01 04:23AM -0800

Designing software through trial and error by fixing failing "tests" rather than by applying some intelligence and thinking about abstractions, interfaces, class hierarchies and object hierarchies is, quite frankly, both absurd and possibly even harmful and I am amazed that you cannot see this.
 
TDD is the totally wrong approach to software development. Design first, implement second and unit test third.
"Öö Tiib" <ootiib@hot.ee>: Feb 01 06:06AM -0800

> by applying some intelligence and thinking about abstractions, interfaces, class
> hierarchies and object hierarchies is, quite frankly, both absurd and possibly
> even harmful and I am amazed that you cannot see this.
 
You talk about software architecture. We write tests to test functionality not
architecture. It is impossible to write compiling (but possibly yet failing) tests
when the architecture elements (IOW interfaces, abstractions and hierarchies)
aren't already in place. When it is inconvenient to write tests then it indeed
indicates (early) that architecture might be is complicated and non-robust
enough and may be worth correcting.
 
 
> TDD is the totally wrong approach to software development. Design first,
> implement second and unit test third.
 
That is orthogonal. For example there is software that will contain about 12
modules, 8 classes in average per module, (so 96 classes) and making one
of those classes takes about 3.5 days. Lets say a programmer took a class and
implemented it and unit tests for it with 2 days. Who cares in what order
he did that? Are we some sort of micro-managers or engineers?
Cholo Lennon <chololennon@hotmail.com>: Feb 01 11:22AM -0300

> amazed that you cannot see this.
 
> TDD is the totally wrong approach to software development. Design
> first, implement second and unit test third.
 
I agree with you. The first time I used TDD (don't confuse with writing
a unit test, a common mistake) was in a TDD course that my company sent
me. It was really weird. The teacher presented the problem to solve:
convert decimal numbers to roman numbers. Well, my group designed and
implemented the solution in a few minutes, wrong the teacher said! after
that, he explained how we should think and solve the problem using TDD:
Start with a simple test that fail. After that add the solution for 1
and test. Add the solution for 2 and test, etc. Try to find a pattern.
The iteration process was long because the pattern was changing. It was
your first time, the teacher said; future problems will be solved more
quickly.
 
I don't know, after several years of trying to apply the technic in
C++/Java/Python I'am still unconvinded. The teacher explained that TDD
avoids "analysis paralysis" (get stuck in a problem due to overthinking
it). You have to think the problem on the fly, try, fail, fix... but
IMO most of the time thinking in advance, solves the problem more
quickly and with a better design.
 
Regards
 
 
--
Cholo Lennon
Bs.As.
ARG
Ian Collins <ian-news@hotmail.com>: Feb 01 05:04PM +1300

Jerry Stuckle wrote:
>>> it's impossible for the scenario to occur in production, anyway.
 
>> So you consume all of the memory on your test box, what then?
 
> Then you test.
 
On a shared development system? Yeah right.
 
>>> 100 times.
 
>> ..and if each call would fetch and parse a file from the internet?
 
> Then it fetches and parses a file from the internet.
 
Evey one of the dozens or hundreds of times a day you run your unit tests?
 
 
> If a unit test trashes the host or creates a DOS attack on a remote
> server, then the test is incorrect or the class fails. If it can happen
> during testing, it can happen during production.
 
I don't think you understand the concept of layered testing. The topic
of this discussion has been unit testing, not acceptance or system
testing. The code being tested may not even be targeted at the system
you are developing on (especially if you are unit testing embedded
code). The development may not even have access to the devices that are
feeding data into the code under test. You have to mock.
 
--
Ian Collins
Ian Collins <ian-news@hotmail.com>: Feb 01 05:06PM +1300

Alf P. Steinbach wrote:
 
> Well this was called "stress testing", some 15 years ago.
 
> Checking… Yep, still.
> https://en.wikipedia.org/wiki/Stress_testing_%28software%29
 
Exactly: stress testing != unit testing!
 
> impractical. So one measures. And only if the measurements say OK, does
> one then assemble the thing and test the complete reality.
 
> Yes?
 
Yes. If the engine is an embedded application, the unit tests are the
measurements.
 
--
Ian Collins
Ian Collins <ian-news@hotmail.com>: Feb 01 05:11PM +1300

Jerry Stuckle wrote:
 
>> So you didn't implement your mock correctly, go back and fix it.
 
> And how do you know if it is implemented correctly if it isn't the full
> class?
 
Er, you have a specification?
 
Don't forget a mock is often a simple (even machine generated) piece of
code with behavior driven by the tests.
 
> Tell me - how is your mock class going to do the same work as the real
> class if it isn't the real class? It's a lot more than just returning a
> value from a method call.
 
It isn't. It is going to do what the tests require it to do. If the
real code parses a file and returns an object, the mock may simply
return a predefined (by the tests) object or sequence of objects. Or if
the tests require the mock to throw an exception for a particular test,
that is all it will do.
 
--
Ian Collins
Ian Collins <ian-news@hotmail.com>: Feb 01 05:14PM +1300

Jerry Stuckle wrote:
>> by the developers. All of the system and acceptance tests have been
>> written by our testers.
 
> Too bad. I'm sure you had a fair amount of bugs in the code.
 
Barely any: manufacturers of embedded systems don't like product recalls
which is why we had so many tests. If the process hadn't been
effective, it would have been repeated for many years.
 
--
Ian Collins
Jerry Stuckle <jstucklex@attglobal.net>: Jan 31 11:16PM -0500

On 1/31/2016 11:14 PM, Ian Collins wrote:
 
> Barely any: manufacturers of embedded systems don't like product recalls
> which is why we had so many tests. If the process hadn't been
> effective, it would have been repeated for many years.
 
Manufacturers of operating systems and heavily used applications such as
IBM (where I first learned how to develop and test) don't like product
recalls, either - and are quite stringent in their testing.
 
Neither are any of the other companies I have consulted for - both as a
developer and a project manager.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Jerry Stuckle <jstucklex@attglobal.net>: Jan 31 11:18PM -0500

On 1/31/2016 11:06 PM, Ian Collins wrote:
 
>> Checking… Yep, still.
>> https://en.wikipedia.org/wiki/Stress_testing_%28software%29
 
> Exactly: stress testing != unit testing!
 
If you need to test a class for out of memory processing, you need to
stress test it.
 
 
>> Yes?
 
> Yes. If the engine is an embedded application, the unit tests are the
> measurements.
 
Who said anything about embedded applications? This is the first time
it has been mentioned in the whole thread. Are you trying to change the
rules again? I see you've tried multiple times so far.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Jerry Stuckle <jstucklex@attglobal.net>: Jan 31 11:21PM -0500

On 1/31/2016 11:04 PM, Ian Collins wrote:
 
>>> So you consume all of the memory on your test box, what then?
 
>> Then you test.
 
> On a shared development system? Yeah right.
 
You test on a test system. Like all testing should be done.
 
 
>>> ..and if each call would fetch and parse a file from the internet?
 
>> Then it fetches and parses a file from the internet.
 
> Evey one of the dozens or hundreds of times a day you run your unit tests?
 
If necessary, yes.
 
> you are developing on (especially if you are unit testing embedded
> code). The development may not even have access to the devices that are
> feeding data into the code under test. You have to mock.
 
Oh, I understand it, all right. I first encountered it as a developer
for IBM in around 1982.
 
But once again you're trying to change the topic by bringing up embedded
systems. Nothing about embedded systems has been mentioned until you
brought it up. But I've seen you're good at trying to change the topic.
 
However, the same is true with embedded systems - at least all of the
ones I've worked on as a consultant in the last 25 or so years.
 
And mocking a device is NOT the same as mocking a class other code is
dependent on. Do you understand the difference?
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Jerry Stuckle <jstucklex@attglobal.net>: Jan 31 11:25PM -0500

On 1/31/2016 11:11 PM, Ian Collins wrote:
 
> Er, you have a specification?
 
> Don't forget a mock is often a simple (even machine generated) piece of
> code with behavior driven by the tests.
 
If the class completely follows the specifications, then it is not a
mock class. If it does not completely follow the specifications, you
cannot thoroughly test dependent classes.
 
> return a predefined (by the tests) object or sequence of objects. Or if
> the tests require the mock to throw an exception for a particular test,
> that is all it will do.
 
But if the class has to process a file, then you cannot test it properly
unless you process that file. Returning predefined objects or sequence
of objects does not properly process the input file - and return the
appropriate information. So all you're doing is testing a subset of the
possible results. Such a process is always prone to errors.
 
Proper testing would include a real class with real input, both good and
bad, and the appropriate processing for all of it.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Ian Collins <ian-news@hotmail.com>: Feb 01 05:38PM +1300

Jerry Stuckle wrote:
>> feeding data into the code under test. You have to mock.
 
> Oh, I understand it, all right. I first encountered it as a developer
> for IBM in around 1982.
 
I don't think you do, otherwise you would realise the difference between
unit and system testing. You most certainly do not want your unit tests
to stress test your development system, or do anything that consumes
significant time or resources. Unit tests should run as quickly as
possible, if the take too long to run, you will back off running them.
I develop with "make" = "make test", so my unit tests are run for ever
code change.
 
> But once again you're trying to change the topic by bringing up embedded
> systems. Nothing about embedded systems has been mentioned until you
> brought it up. But I've seen you're good at trying to change the topic.
 
That's a poor strawman, there was no change in topic.
 
I could just as easily substituted any piece of software. Note I said
"especially if you are unit testing embedded code" not "only if you are
unit testing embedded code". Embedded code is simple an extreme example
of something you wouldn't unit test on target.
 
> ones I've worked on as a consultant in the last 25 or so years.
 
> And mocking a device is NOT the same as mocking a class other code is
> dependent on. Do you understand the difference?
 
From the perspective of software other than its driver, a device is a
class other code. Device driver tests use mock hardware, the code that
uses driver class mocks the driver class and so on up the stack.
 
--
Ian Collins
Ian Collins <ian-news@hotmail.com>: Feb 01 05:48PM +1300

Jerry Stuckle wrote:
 
> If the class completely follows the specifications, then it is not a
> mock class. If it does not completely follow the specifications, you
> cannot thoroughly test dependent classes.
 
You can (and thousands of us do) because it *pretends* to implement the
specification. I suggest you do some research on mock objects and how
they are used.
 
>> that is all it will do.
 
> But if the class has to process a file, then you cannot test it properly
> unless you process that file.
 
Quite - because you aren't testing it! You are testing the code that
process the resulting object.
 
> of objects does not properly process the input file - and return the
> appropriate information. So all you're doing is testing a subset of the
> possible results. Such a process is always prone to errors.
 
You've lost the plot, *we are not testing the file processing*. We are
testing the processing of the result of the file processing.
 
> Proper testing would include a real class with real input, both good and
> bad, and the appropriate processing for all of it.
 
Indeed it does, but not unit testing something that has no interest in
how those files are processed.
 
I've said it before but it bears repeating: layered testing.
 
--
Ian Collins
Paavo Helde <myfirstname@osa.pri.ee>: Feb 01 09:52AM +0200

On 1.02.2016 1:50, Jerry Stuckle wrote:
> If you don't test the independent class first, you have no idea where
> the problem lies. And as you get more and more classes involved the
> problem becomes more difficult.
 
The debugger will show me where the problem lies. But you are right, if
there are separate tests it would be easier to pinpoint the problem. For
example, if after some unrelated change 10 tests start to fail, among
them the tests for A and B, then it makes sense to start with B and its
test as B is the simplest class and likely the core of the issue.
 
 
> The design will define the class dependencies. And every time you have
> to rewrite A to adapt it to be, you are wasting programmer time, test
> group time, and potentially inserting more bugs.
 
The code is changing every day because of the changing requirements,
changing priorities, changing environment, etc. You cannot design
everything up-front.
 
The extensive automated test suites are there exactly for allowing to
change, adapt and refactor the code base without the fear of introducing
new bugs. Ideally, the codebase would become wax instead of layers of
petrified sediments. It is very easy to reshape wax.
 
 
> A proper design means the independent classes can be written first, and
> the dependent ones later. This eliminates the need for programmers to
> rewrite dependent code.
 
Agreed - if you can get the design 100% right before starting the coding
it would be perfect. However, in my experience this rarely happens, and
even then there would be later changes because of unforeseeable factors.
David Brown <david.brown@hesbynett.no>: Feb 01 11:31AM +0100

On 01/02/16 00:55, Jerry Stuckle wrote:
>> include testers.
 
> Not a chance. Never in any of the major projects I've been involved in
> have any tests been performed by the developers.
 
Our systems and integration test people would be pretty annoyed if our
developers handed them code that had not been tested. Do you think
developers just write some code, see that it compiles without warnings,
and say "give that a shot and see if it works" ? Before passing code on
to the next layer of testers, the developers will do everything
practically possible (using TDD, unit tests, automated test benches,
simulations, whatever) to ensure there are no known bugs and their tests
are as complete as possible.
"Öö Tiib" <ootiib@hot.ee>: Feb 01 03:37AM -0800

On Sunday, 31 January 2016 23:44:29 UTC+2, Ian Collins wrote:
> Doesn't anyone have colleagues any more? Sorry, I just hate the term
> "coworkers"!
 
No! Colleagues still win 200:19
http://www.googlefight.com/coworker-vs-colleague.php
 
The term I typically use sounds root-by-stem translated as "workfellow",
"workmate" or "workpartner". Only "workmate" is what I have actually heard
said in English. Sorry, if I translate it sometimes as "coworker".
ram@zedat.fu-berlin.de (Stefan Ram): Feb 01 11:22AM

When a computer downloads a web page, the computer is called
»client« and the source of the download is called »server«.
 
When a function »m« calls another function »f«, we call »m« a
»client« of »f«, but how to we call »f« then? One does not
call a function a »server«, does one?
Juha Nieminen <nospam@thanks.invalid>: Feb 01 09:20AM

> 'int' considered dangerous: use a <cstdint> sized integer typedef instead.
 
It depends on what you are doing. If you are writing a library that should
be as portable as possible, and expected to be used in wildly different
platforms, from ols small embedded systems to modern 64-bit processors, then
perhaps.
 
If, however, you are writing closed-source software for a specific platform
(let's say, for example, iOS), then it might even be better to use int for
integers whose maximum size is irrelevant. On that particular platform you
can be sure that int will have a minimum size and will never get smaller
even in future versions of that platform, so you'll be A-ok.
 
Why use int instead of an equivalent std type? Because 'int' is ostensibly
always the most efficient integral type of the system, even in future
versions of the platform. You'll never know if the std type you chose
will be the most efficient in a future version.
 
> On a related matter eschewing unsigned integer types is foolish as one
> should use an unsigned type when dealing with unsigned values.
 
unsigned causes problems when it's mixed with signed types. And this
happens quite easily.
 
Example: Image size cannot be negative. Negative values are nonsensical.
Therefore it makes sense to use unsigned to store image dimensions?
In theory yes. In practice you'd better use a signed type because
image coordinates *can* become negative in many situations (eg. line
drawing, or sprite coordinates), and you'll run into problems when
mixing signed coordinates with unsigned image sizes.
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
Derwin Crummel <dwc@nowhere.invalid>: Jan 31 03:56PM -0800

Found this function in application code for a NNTP client. Errors are
marked below. Clearly, the iterator is mis-applied here but how to
fix?
 
int TArticleBank::CreateArticleIndex (TArticleIndexList * pIndexLst)
{
ASSERT( pIndexLst );
 
CSingleLock sLock(&m_crit, TRUE);
 
// RLW - only call PuntLinkInformation if there are articles to
move to m_setNodes
if (GetCount() > 0)
{
// move m_Stage to m_setNodes
PuntLinkInformation ();
}
 
// Note: flat list is created during Link(). So go directly(!) to
// the m_setNodes
 
STLMapArtNode::iterator it = m_setNodes.begin();
 
while (it != m_setNodes.end() )
{
TArtNode * pNode = *it++; //error C2440
 
ASSERT(pNode);
 
pNode->CreateArticleIndex ( pIndexLst );
 
}
return 0;
}
 
//-------------------------------------------------------------------------
int TArticleBank::Empty ()
{
CSingleLock sLock(&m_crit, TRUE);
 
ASSERT(m_Stage.size() == 0);
m_Stage.clear();
 
STLMapArtNode::iterator it = m_setNodes.begin();
 
while (it != m_setNodes.end())
{
TArtNode * pNode = *it; //error C2440
 
// delete call (1/3)
delete pNode;
it++;
}
m_setNodes.erase (m_setNodes.begin(), m_setNodes.end());
 
m_ids.Empty();
 
delete m_pMyViewFilter;
m_pMyViewFilter = 0;
 
return 0;
}
 
error C2440: 'initializing' : cannot convert from 'const
ob_artnode_ptr' to 'TArtNode *'
Victor Bazarov <v.bazarov@comcast.invalid>: Jan 31 07:31PM -0500

On 1/31/2016 6:56 PM, Derwin Crummel wrote:
> TArtNode * pNode = *it++; //error C2440
 
> ASSERT(pNode);
 
> pNode->CreateArticleIndex ( pIndexLst );
 
A set (if 'm_setNodes' is declared as 'std::set') contains *constant*
objects. Once they are inserted, they are not subject to any mutation.
 
You can pull it out, mutate it as you please, then reinsert it.
 
 
> while (it != m_setNodes.end())
> {
> TArtNode * pNode = *it; //error C2440
 
Same idea. You can't get a mutable object that retains its position in
the set. If you need to remove it, then remove it (using .erase(it)),
get the iterator that it returns, and then do what you want with the
pointer.
 
Perhaps you should consider storing smart pointers in that set. When
removed from the set, they will destroy the object they point to.
 
> }
 
> error C2440: 'initializing' : cannot convert from 'const
> ob_artnode_ptr' to 'TArtNode *'
 
V
--
I do not respond to top-posted replies, please don't ask
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: