- Concrete classes considered harmful - 20 Updates
- Concrete classes considered harmful - 3 Updates
- Struggling with bind syntax - 2 Updates
Mr Flibble <flibble@i42.co.uk>: Jul 12 01:51AM +0100 On 11/07/2015 22:17, Ian Collins wrote: > time to time. > Oh by the way, I also use int in my code, so I guess by your standards > I'm already not a very good engineer. If you lazily use 'int' all over your code without actually thinking if it is appropriate then that does indeed make you a not very good engineer. Perhaps you should be using Java rather than C++. > I've been unit testing everything I write for over a decade now and I've > yet to encounter problems with non-abstract base classes. Go and and > learn about mock objects. It is virtually impossible to unit test a class that has dependencies on lots of other concrete classes that themselves require unit testing. I know all about mock objects thanks and that is the point: it is easy to make a class being unit tested use a mock object if that mock object complies to an abstract interface and is created by a mock object factory. /Flibble |
Mr Flibble <flibble@i42.co.uk>: Jul 12 01:52AM +0100 On 12/07/2015 00:16, Chris Vine wrote: > Rob Pike (one of the originators of Go and of UTF-8 and a member of > the unix team): "Object-oriented design is the roman numerals of > computing." What utter idiocy. > Chris /Flibble |
Ian Collins <ian-news@hotmail.com>: Jul 12 01:20PM +1200 Mr Flibble wrote: >> Oh by the way, I also use int in my code, so I guess by your standards >> I'm already not a very good engineer. > If you lazily use 'int' all over your code.... Which I don't. >> learn about mock objects. > It is virtually impossible to unit test a class that has dependencies on > lots of other concrete classes that themselves require unit testing. The code bases I work on have a mix of abstract and concrete classes. All are TDD projects, so there is effectively 100% test coverage. How would you define "lots of other concrete classes"? most of ours depend on very few others. Having too many dependencies is more of a design issue than having dependencies on concrete classes. > know all about mock objects thanks and that is the point: it is easy to > make a class being unit tested use a mock object if that mock object > complies to an abstract interface and is created by a mock object factory. Unless the the class has non-trivial inline member functions, whether it is abstract or not has little bearing on mocking. In this instance, using the Pimpl idiom is just as effective as abstract base classes. Given the three options of abstract, concrete without non-trivial inline member functions or Pimpl classes all are equally simple to mock. I have nothing against using abstract base classes, but in the small embedded world where much of my code is used the cost is often (rightly or wrongly) considered to high a price to pay. -- Ian Collins |
Mr Flibble <flibble@i42.co.uk>: Jul 12 02:32AM +0100 On 12/07/2015 02:20, Ian Collins wrote: > would you define "lots of other concrete classes"? most of ours depend > on very few others. Having too many dependencies is more of a design > issue than having dependencies on concrete classes. You are obviously doing it wrong (TM). Unit testing and TDD are not synonyms and TDD itself is actually considered harmful: you can *not* design software to a high standard by designing things downwards from tests. A good design involves first defining an architecture along with abstractions (interfaces) and object interactions all of which should be driven by system requirements and not by passing brain-dead isolated tests. /Flibble |
Ian Collins <ian-news@hotmail.com>: Jul 12 03:48PM +1200 Mr Flibble wrote: >> on very few others. Having too many dependencies is more of a design >> issue than having dependencies on concrete classes. > You are obviously doing it wrong (TM). My clients and bank manager would argue otherwise. -- Ian Collins |
Ian Collins <ian-news@hotmail.com>: Jul 12 04:14PM +1200 Mr Flibble wrote: > You are obviously doing it wrong (TM). Unit testing and TDD are not > synonyms and TDD itself is actually considered harmful: So is crossing the road.. It appears that you consider everything you don't do (whether you understand it or not) to be harmful. > tests. A good design involves first defining an architecture along with > abstractions (interfaces) and object interactions all of which should be > driven by system requirements and not by passing brain-dead isolated tests. I agree. No one who uses TDD writes brain-dead isolated tests. -- Ian Collins |
Juha Nieminen <nospam@thanks.invalid>: Jul 12 11:32AM >>> its constructor. >> Why? > Good luck unit testing a class that has lots of dependencies on concretions. So we should just forget what makes C++ so efficient as it is, and just turn it into a less-efficient Java/C# variant? Unit testing is ok, but I'm not happy if unit testing means that my program needs to be 10 times slower than it could be, even when making the final release build. (And no, I'm not even exaggerating with that "10 times slower".) --- news://freenews.netfront.net/ - complaints: news@netfront.net --- |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jul 12 01:46PM +0100 On Sun, 12 Jul 2015 11:32:53 +0000 (UTC) > program needs to be 10 times slower than it could be, even when making > the final release build. > (And no, I'm not even exaggerating with that "10 times slower".) It's mocking rather than unit testing as such where the issue tends to arise. However, there is no need to adopt complicated abstract interfaces on the Flibble model just to provide dependency injection for mocking purposes. Where mocking is the best way of unit testing a particular implementation, concrete classes are just as capable of being designed for dependency injection. (Admittedly, the frameworks for this are not as well developed.) Possibly it is Flibble's title for this thread ("concrete classes considered harmful") which is part of the problem, because on the face of it, as a statement it is ridiculous. You then get to the issue of what he means by "dependencies on concrete classes". So far as his principle forbids composing types using concrete types, then he is also (in my view) way off the mark. Chris |
Mr Flibble <flibble@i42.co.uk>: Jul 12 01:46PM +0100 On 12/07/2015 04:48, Ian Collins wrote: >>> issue than having dependencies on concrete classes. >> You are obviously doing it wrong (TM). > My clients and bank manager would argue otherwise. Clients are oblivious to whether or not you have solved their problem the correct way; if it all barely hangs together and just meets their requirements they are usually happy even if the actual implementation is shite. Egregious have-a-go cowboy developers can often make money out of poor quality work; doesn't make it right. /Flibble |
Mr Flibble <flibble@i42.co.uk>: Jul 12 01:54PM +0100 On 12/07/2015 13:46, Chris Vine wrote: > It's mocking rather than unit testing as such where the issue tends to > arise. However, there is no need to adopt complicated abstract > interfaces on the Flibble model just to provide dependency injection for Abstract interfaces are not "complicated"; abstract interfaces are actually simpler than the concrete classes that implement them; abstract interfaces allow loose coupling; abstract interfaces are a win-win as far as designing, implementing and maintaining software is concerned. The only issue with abstract interfaces is performance when using them with C++ (hence the reason for this thread). /Flibble |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jul 12 02:21PM +0100 On Sun, 12 Jul 2015 13:54:44 +0100 > abstract interfaces allow loose coupling; abstract interfaces are a > win-win as far as designing, implementing and maintaining software is > concerned. Abstract interfaces have their uses, but often best hidden as an implementation detail behind a concrete class. std::function is a good example of this, which is a templated concrete type which happens to use an internal helper type with a virtual function and inheritance for type erasure purposes. (In consequence, the std::function concrete type enables you to implement the strategy pattern or the observer pattern without having you write your own abstract interfaces, so improving design and reducing coupling.) |
Mr Flibble <flibble@i42.co.uk>: Jul 12 02:40PM +0100 On 12/07/2015 14:21, Chris Vine wrote: > enables you to implement the strategy pattern or the observer pattern > without having you write your own abstract interfaces, so improving > design and reducing coupling.) What utter garbage mate. We are talking about dependencies between classes and dependencies on concrete classes result in tight coupling rather than the lose coupling that abstract interfaces provide. Yes you can use type erasure via std::function to achieve loose coupling however if multiple methods are involved than an interface can and usually is both more convenient and makes more sense from a design point of view: it makes your dependencies both named and explicit. You are suffering from the design over-genericization syndrome typical of C++ programmers. I suspect you are trolling though; do it again and you will be blocked. /Flibble |
David Harmon <source@netcom.com>: Jul 12 06:58AM -0700 On Sat, 11 Jul 2015 04:04:55 +0100 in comp.lang.c++, Mr Flibble <flibble@i42.co.uk> wrote, >replaced with dependencies on abstractions. A class should not new its >member objects for example but rather should use a factory passed into >its constructor. No. A better guideline is avoid using 'new' in application-level code. Use 'new' only where doing so solves some problem, preferably inside a library class whose whole purpose is managing allocated memory, preferably using RIAA. Overuse of 'new' is a symptom of Java brain damage. |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jul 12 02:59PM +0100 On Sun, 12 Jul 2015 14:40:35 +0100 > typical of C++ programmers. > I suspect you are trolling though; do it again and you will be > blocked. For someone who began a post with the title "concrete classes considered harmful", which is about as troll-full as you can get, and that I have fully explained my views, you have quite a nerve. The fact is that you have a one-track mind and you get locked into your own point of view to the exclusion of all others. The same was apparent in your "Avoid 'int', 'long' and 'short'..." and "Avoid 'int' and associates" postings, an issue that required you to start two separate threads on the same point. Anyway, be my guest. Chris |
Mr Flibble <flibble@i42.co.uk>: Jul 12 03:45PM +0100 On 12/07/2015 14:58, David Harmon wrote: > library class whose whole purpose is managing allocated memory, > preferably using RIAA. Overuse of 'new' is a symptom of Java brain > damage. What utter nonsense. Perhaps you are confusing new with delete? Using new is fine but using delete isn't as you should be wrapping objects you new in a smart pointer. A good example of when you should use new (or in this case make_unique) is when you want to populate: std::vector<std::unique_ptr<IShape>> where IShape is an interface abstracting shapes. /Flibble |
Mr Flibble <flibble@i42.co.uk>: Jul 12 04:30PM +0100 On 12/07/2015 16:28, Stefan Ram wrote: > interface (well, template parameter) (well, »concept«) > »Compare«, which is the type of the comparison argument, > which is »injected« by the caller. Typing '::std' instead of 'std' is a bit silly. /Flibble |
woodbrian77@gmail.com: Jul 12 11:23AM -0700 On Sunday, July 12, 2015 at 10:30:50 AM UTC-5, Mr Flibble wrote: > Typing '::std' instead of 'std' is a bit silly. I use ::std for clarity. Brian Ebenezer Enterprises http://webEbenezer.net |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 12 09:37PM +0200 > On Sunday, July 12, 2015 at 10:30:50 AM UTC-5, Mr Flibble wrote: >> Typing '::std' instead of 'std' is a bit silly. > I use ::std for clarity. I've used global namespace qualification in macros, for correctness, because you never know where a macro can be used. And I've used global namespace qualification for clarity for identifiers from the Windows API. However, I don't think "::std::x" is more clear than "std::x"; on the contrary, those little "::" are more like noise to my eyes. Cheers, - Alf -- Using Thunderbird as Usenet client, Eternal September as NNTP server. |
woodbrian77@gmail.com: Jul 12 02:34PM -0700 On Sunday, July 12, 2015 at 2:37:27 PM UTC-5, Alf P. Steinbach wrote: > because you never know where a macro can be used. And I've used global > namespace qualification for clarity for identifiers from the Windows > API. I don't know what the context will be for library code that I write either. > However, I don't think "::std::x" is more clear than "std::x"; on > the contrary, those little "::" are more like noise to my eyes. Sorry, but I don't have a better idea. |
Luca Risolia <luca.risolia@linux-projects.org>: Jul 13 12:38AM +0200 > I use ::std for clarity. It has been shown several times on this NG that :: before std is completely unuseful. |
ram@zedat.fu-berlin.de (Stefan Ram): Jul 12 03:28PM >Dependencies on concrete classes are considered harmful and should be >replaced with dependencies on abstractions. We already have this in C++ when appropriate. For example, ::std::sort( ::std::begin( a ), ::std::end( a ), ::std::greater<int>() ); . »sort« does not depend on a concrete class, but on the interface (well, template parameter) (well, »concept«) »Compare«, which is the type of the comparison argument, which is »injected« by the caller. |
ram@zedat.fu-berlin.de (Stefan Ram): Jul 12 07:04PM >I use ::std for clarity. I use /both/ »std« without a preceding »::« /and/ »::std«. »std« I use whenever I mean »any nearby namespace that happens to have the name "std" wherever my source code snippet is pasted into«. And »::std« I use for the reserved namespace of C++'s standard library. |
ram@zedat.fu-berlin.de (Stefan Ram): Jul 12 07:10PM >>I use ::std for clarity. >And »::std« I use for the reserved namespace of >C++'s standard library. »Whenever a name x defined in the standard library is mentioned, the name x is assumed to be fully qualified as ::std::x, unless explicitly described otherwise. For example, if the Effects section for library function F is described as calling library function G, the function ::std::G is meant.« 17.6.1.1p3 |
Juha Nieminen <nospam@thanks.invalid>: Jul 12 11:39AM > { > return vec.size() == N && is_sorted(vec.begin(), vec.end()); > } That still doesn't test it properly. See my other post about why. --- news://freenews.netfront.net/ - complaints: news@netfront.net --- |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 12 02:30PM +0200 On 12-Jul-15 1:39 PM, Juha Nieminen wrote: >> } > That still doesn't test it properly. See my other post about why. > --- news://freenews.netfront.net/ - complaints: news@netfront.net --- One way to practically ensure the same numbers, without using a known good sort implementation, could be to use a simple order-independent checksum such as XOR (should not change from raw data to sorted), plus a few confidence boosters of known data and results. Cheers & hth., - Alf -- Using Thunderbird as Usenet client, Eternal September as NNTP server. |
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:
Post a Comment