Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   Are so many subclasses such a good idea? (http://www.velocityreviews.com/forums/t619930-are-so-many-subclasses-such-a-good-idea.html)

khapi@yahoo.com 06-12-2008 08:51 PM

Are so many subclasses such a good idea?
 
Hi folks,

I noticed that the standard library has a bunch of
subclasses like std::bad_alloc, std::runtime_error
that derive from std::exception.

I gather that in order to use one of these error
subclasses, one creates an instance of that subclass,
using whichever one is appropriate.

But is this really a good design practice?
It seems odd that the creators of std chose subclasses
for different situations. Why didn't they create
methods for each situation instead?

Thanks.

Marcel Müller 06-12-2008 08:56 PM

Re: Are so many subclasses such a good idea?
 
Hi

khapi@yahoo.com schrieb:
> I noticed that the standard library has a bunch of
> subclasses like std::bad_alloc, std::runtime_error
> that derive from std::exception.

[...]
> But is this really a good design practice?
> It seems odd that the creators of std chose subclasses
> for different situations. Why didn't they create
> methods for each situation instead?


??? - how do you usually throw a /method/ ?

And if you want to catch these errors selectively, there is no other
clean way.
Furthermore that many types don't harm. So where is the problem?


Marcel

khapi@yahoo.com 06-12-2008 09:23 PM

Re: Are so many subclasses such a good idea?
 
On Jun 12, 4:56*pm, Marcel Müller <news.5.ma...@spamgourmet.com>
wrote:

> ??? - how do you usually throw a /method/ ?


I meant not so much to throw a method, but to throw a value
that in the catch section is handled but just one class
that handles exceptions, or better yet just one function.

> And if you want to catch these errors selectively, there is no other
> clean way.


Much cleaner:

enum {ERRORCODE_UNHAPPY, ...};
try {
if (whatever())
throw ERRORCODE_UNHAPPY;
}
catch (int e) {
error_processing(e);
}

> Furthermore that many types don't harm. So where is the problem?


Having too many subclasses obscures the meaning of
what's really going on. I've seen C++ code that have
3 or 4 subclasses deep. It's hard to guess what
the deeper classes really do.

Kai-Uwe Bux 06-12-2008 09:49 PM

Re: Are so many subclasses such a good idea?
 
khapi@yahoo.com wrote:

> On Jun 12, 4:56*pm, Marcel Müller <news.5.ma...@spamgourmet.com>
> wrote:
>
>> ??? - how do you usually throw a /method/ ?

>
> I meant not so much to throw a method, but to throw a value
> that in the catch section is handled but just one class
> that handles exceptions, or better yet just one function.
>
>> And if you want to catch these errors selectively, there is no other
>> clean way.

>
> Much cleaner:
>
> enum {ERRORCODE_UNHAPPY, ...};
> try {
> if (whatever())
> throw ERRORCODE_UNHAPPY;
> }
> catch (int e) {
> error_processing(e);
> }


And where is the _selective_ catching of errors?


Think about

void f ( void ) {
try {
// some code that might throw
}
catch ( some_exception const & e ) {
}
}

void g ( void ) {
try {
f();
}
catch ( some_other_exception const & e ) {
...
}
}

The point is: different exceptions can rise up in the call stack to
different levels. The type determines which catch handler is used.


>> Furthermore that many types don't harm. So where is the problem?

>
> Having too many subclasses obscures the meaning of
> what's really going on. I've seen C++ code that have
> 3 or 4 subclasses deep. It's hard to guess what
> the deeper classes really do.


That seems to be more a problem of documentation and the naming scheme
employed rather than the depth of the derivation. Besides, with standard
exception classes, they all do the same (provide a message by means of the
what() method). The type system is just used to classify errors and allow
to catch exceptions at the right level in the call stack.


Best

Kai-Uwe Bux

khapi@yahoo.com 06-12-2008 10:26 PM

Re: Are so many subclasses such a good idea?
 
On Jun 12, 5:49 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:

> And where is the _selective_ catching of errors?


Here:
try {
if (a)
throw(UNHAPPY);
if (b)
throw(UNHAPPIER);
if (c)
throw(UNHAPPIEST);
} catch (int which) {
switch (which) {
case UNHAPPY: ... break;
case UNHAPPIER: ... break;
case UNHAPPIEST: ... break;
}
}

> The point is: different exceptions can rise up in the call stack to
> different levels. The type determines which catch handler is used.


True, that reinforces C++'s compile-time typing,
which some consider to be an advantage of C++.




Noah Roberts 06-12-2008 11:21 PM

Re: Are so many subclasses such a good idea?
 
khapi@yahoo.com wrote:
> On Jun 12, 5:49 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
>
>> And where is the _selective_ catching of errors?

>
> Here:
> try {
> if (a)
> throw(UNHAPPY);
> if (b)
> throw(UNHAPPIER);
> if (c)
> throw(UNHAPPIEST);
> } catch (int which) {
> switch (which) {
> case UNHAPPY: ... break;
> case UNHAPPIER: ... break;
> case UNHAPPIEST: ... break;
> }
> }


Because that's a LOT cleaner.

red floyd 06-13-2008 01:46 AM

Re: Are so many subclasses such a good idea?
 
khapi@yahoo.com wrote:
> Hi folks,
>
> I noticed that the standard library has a bunch of
> subclasses like std::bad_alloc, std::runtime_error
> that derive from std::exception.
>
> I gather that in order to use one of these error
> subclasses, one creates an instance of that subclass,
> using whichever one is appropriate.
>
> But is this really a good design practice?
> It seems odd that the creators of std chose subclasses
> for different situations. Why didn't they create
> methods for each situation instead?
>


Because that's not extensible. What if I want a new exception type

class my_exception : std::public exception
{
// internals redacted
};

How would you provide that in your scheme of things?

Pascal J. Bourguignon 06-13-2008 09:35 AM

Re: Are so many subclasses such a good idea?
 
"Daniel T." <daniel_t@earthlink.net> writes:

> khapi@yahoo.com wrote:
>> On Jun 12, 5:49 pm, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
>>
>> > And where is the _selective_ catching of errors?

>>
>> Here:
>> try {
>> if (a)
>> throw(UNHAPPY);
>> if (b)
>> throw(UNHAPPIER);
>> if (c)
>> throw(UNHAPPIEST);
>> } catch (int which) {
>> switch (which) {
>> case UNHAPPY: ... break;
>> case UNHAPPIER: ... break;
>> case UNHAPPIEST: ... break;
>> }
>> }

>
> From the above, it looks like you haven't quite gotten the hang of what
> polymorphism is for. Polymorphism allows one to remove all those
> duplicated switch statements.


It was a counter-example!

The reason why it's good to have a lot of subclasses is indeed to use
polymorphism.

try{
doSomething();
}catch(UnhappinesDegree e){
e->recover();
}


--
__Pascal Bourguignon__

anon 06-13-2008 12:05 PM

Re: Are so many subclasses such a good idea?
 
Chris Thomasson wrote:

[...]

>
> The C++ exception handling mechanism is very expressive. I personally
> like it a lot. Here is another example. Take a mutex class which can
> throw exceptions. Here is one way to write it:
> __________________________________________________ _________________
> class mutex_with_exceptions {
> pthread_mutex_t m_mtx;
>
> [...];
>
> public:
> struct error {
> struct base {};
>
> struct lock {
> struct base : public error::base {};
> struct invalid : public lock::base {};
> struct priority_violation : pubilc lock::invalid {};
> struct deadlock : public lock::base {};
> struct max_recursion : public lock::base {};
>
> static void raise_status(int const status) {
> switch (status) {
> case EINVAL:
> throw priority_violation();
> case EAGAIN:
> throw max_recursion();
> case EDEADLK:
> throw deadlock();
> default:
> assert(false);
> std::unexpected();
> }
> }
> };
>
> struct unlock {
> struct base : public error::base {};
> struct not_owner : public unlock::base {};
>
> static void raise_status(int const status) {
> switch (status) {
> case EPERM:
> throw not_owner();
> default:
> assert(false);
> std::unexpected();
> }
> }
> };
> };
>
> public:
> void lock() {
> int const status = pthread_mutex_lock(&m_mtx);
> if (status) {
> error::lock::raise_status(status);
> }
> }
>
> void unlock() {
> int const status = pthread_mutex_unlock(&m_mtx);
> if (status) {
> error::unlock::raise_status(status);
> }
> }
> };


I must say: VERY NICE :)

> __________________________________________________ _________________
>
>
>
> The exception hierarchy for the `mutex_with_exceptions' class is verbose.
>
>
> Any thoughts?


I like this explanation. Just small remark - your base class doesn't
inherit from std::exception

Bart van Ingen Schenau 06-13-2008 01:15 PM

Re: Are so many subclasses such a good idea?
 
On Jun 12, 10:51 pm, kh...@yahoo.com wrote:
> Hi folks,
>
> I noticed that the standard library has a bunch of
> subclasses like std::bad_alloc, std::runtime_error
> that derive from std::exception.
>
> I gather that in order to use one of these error
> subclasses, one creates an instance of that subclass,
> using whichever one is appropriate.
>
> But is this really a good design practice?
> It seems odd that the creators of std chose subclasses
> for different situations. Why didn't they create
> methods for each situation instead?
>
> Thanks.


You should differentiate between exception-classes and 'normal'
classes when looking at the inheritance trees.
For 'normal' classes, it is usually a bit suspect to have a very deep
inheritance tree (although there will probably be exceptions).
For exception-classes, the hierarchy also gives an indication how the
different exception-classes are related to each other and a deep
inheritance tree often works good.

For example, you have the following errors that can be reported: index-
out-of-range, out-of-memory, io-error.
The io-error classification can be further divided in network-error
and file-error.
The network-error classification can be divided into host-not-found,
link-lost and connection-refused.
The file-error classification can be divided into file-not-existing
and file-not-accessible.
If you model this as a class hierarchy, it is immediately clear that
file-not-existing and file-not-accessible belong to the bigger
category of file-errors. And if you chose to handle all io-errors
identically at some level, you don't even have to know that there are
more specific types below that level, nor do you have to change
anything when someone adds a write-error to the category of file-
errors.

Try doing that with numeric error codes.

Bart v Ingen Schenau


All times are GMT. The time now is 04:27 AM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57