View mode: basic / threaded / horizontal-split · Log in · Help
August 08, 2007
Checked exceptions [Re: Hijacking]
Nick Sabalausky wrote:
> "Rioshin an'Harthen" <rharth75@hotmail.com> wrote in message 
> news:f974u9$9k1$1@digitalmars.com...
>> "Walter Bright" <newshound1@digitalmars.com> kirjoitti viestissä 
>> news:f95leh$hn4$1@digitalmars.com...
>>> It might be one of those things like exception specifications where 
>>> everyone says it's a good idea but guiltily hate in secret <g>.
>> Exception specification *is* a good idea. Although I do hate it - try to 
>> remember what a specific method may throw when you write your code, 
>> especially if the error is ambiguous like "Unhandled exception" it's 
>> really irritating - but I hate unspecified exceptions even more, as the 
>> problem then is to even remember to put in the necessary try-catch-finally 
>> blocks.
> 
> Not to start a big big debate on it, but my own personal feeling on that 
> (after having used a fair amount of it) is that the specification of 
> exceptions belongs in generated documentation (whether javadoc-style or as 
> part of the IDE as with "some_function() -> Called By..."). I normally 
> prefer having to explicity specify things (yea, strong-typing fan here ;) ), 
> but personally, I find it overkill in this case. (Not to mention it gave me 
> flashbacks of writing C/C++ headers. j/k ;) ). 

I agree with this 100%.  With check exceptions it just becomes too 
annoying and verbose.  Without them, often it is too difficult to find 
out what exceptions are possible for a function to throw.

So the right place seems to be an analysis / doc-generation tool / IDE.

--bb
August 08, 2007
Re: Hijacking
Walter Bright wrote:
> kris wrote:
>> There's a related problem where a public method is added to a 
>> base-class A (as in your example) but where the signature is *exactly* 
>> that of one existing in derived class B. If A actually calls that new 
>> method internally, "bad things"tm will almost certainly happen, since 
>> B never intended to effectively override the newly-added method in A.
>>
>> This is a very hard problem to isolate yet can be easily remedied by 
>> the compiler. The request was first made two or three years back, and 
>> once or twice since then: you make the "override" keyword *required*.
>>
>> When "override" is required, the compiler can easily trap this related 
>> type of hijacking and avoid such nasty surprises.
> 
> That is a good point. The reason I haven't added it is because I'm not 
> sure how annoying it will be to have to always add the 'override' 
> keyword. It might be one of those things like exception specifications 
> where everyone says it's a good idea but guiltily hate in secret <g>.
> 
> Mitigating factors are private and final methods cannot be overridden.

Although, I generally like the idea, I fear that requiring 'override' 
will have side effects for mixins.  The writer of the mixin has no way 
of knowing if the methods will override something or not.

I'm thinking the only reasonable solution would be to allow mixins to go 
on as they currently are, without enforcing the use of 'override'. 
However, an accidental override that comes in via a mixin seems like a 
very likely source of subtle bugs.  And requiring a special exception to 
the rules is not really desirable in the first place.

--bb
August 08, 2007
Re: Hijacking
Sean Kelly wrote:
> BCS wrote:
>> Reply to Walter,
>>
>>> Derek Parnell wrote:
>>>
>>>> On Sun, 05 Aug 2007 11:47:18 -0700, Walter Bright wrote:
>>>>
>>>>> I want to continue a bit in the Overloading/Inheritance thread which
>>>>> is getting a little long, on a closely related issue which I find to
>>>>> be important, but so rarely referred to that I had to come up with a
>>>>> name for it - hijacking.
>>>>>
>>>> I'm just wondering what the NSA is making of this discussion :)
>>>>
>>> Hopefully, they'll analyze the site, get excited about D, and use D
>>> for their next generation software!
>>
>> Fat chance, most of D's advantages don't exist in under ~5000 LOC and 
>> anything over that and the NSA won't touch it. Besides there isn't 20+ 
>> years of best practices in how to right secure software in D (as this 
>> is in C)
> 
> I'd think DBC would be a perk, if nothing else.  Assuming the NSA 
> currently uses C, that is.
> 
> 
> Sean

I thought NSA used ADA it was designed for such purposes.

-Joel
August 08, 2007
Re: Hijacking
Reply to janderson,

> Sean Kelly wrote:
> 
>> BCS wrote:
>> 
>>> Reply to Walter,
>>> 
>>>> Derek Parnell wrote:
>>>> 
>>>>> On Sun, 05 Aug 2007 11:47:18 -0700, Walter Bright wrote:
>>>>> 
>>>>>> I want to continue a bit in the Overloading/Inheritance thread
>>>>>> which is getting a little long, on a closely related issue which
>>>>>> I find to be important, but so rarely referred to that I had to
>>>>>> come up with a name for it - hijacking.
>>>>>> 
>>>>> I'm just wondering what the NSA is making of this discussion :)
>>>>> 
>>>> Hopefully, they'll analyze the site, get excited about D, and use D
>>>> for their next generation software!
>>>> 
>>> Fat chance, most of D's advantages don't exist in under ~5000 LOC
>>> and anything over that and the NSA won't touch it. Besides there
>>> isn't 20+ years of best practices in how to right secure software in
>>> D (as this is in C)
>>> 
>> I'd think DBC would be a perk, if nothing else.  Assuming the NSA
>> currently uses C, that is.
>> 
>> Sean
>> 
> I thought NSA used ADA it was designed for such purposes.
> 
> -Joel
> 

The only experience I have (yes I do have a tiny bit) is in C and is only 
about 500 loc.
August 08, 2007
Re: Hijacking
Bill Baxter wrote:
> Although, I generally like the idea, I fear that requiring 'override' 
> will have side effects for mixins.  The writer of the mixin has no way 
> of knowing if the methods will override something or not.

I didn't think of that.

But I'll put the check in as a warning, and we'll see if there are real 
problems or not.
August 08, 2007
Re: Hijacking
Walter Bright wrote:
> Bill Baxter wrote:
>> Although, I generally like the idea, I fear that requiring 'override' 
>> will have side effects for mixins.  The writer of the mixin has no way 
>> of knowing if the methods will override something or not.
> 
> I didn't think of that.
> 
> But I'll put the check in as a warning, and we'll see if there are real 
> problems or not.

There are probably on two likely scenarios for that:
#1 - The mixin and the base class happen to have symbol overlap.
#2 - The mixin was previously used by the base class.

In the case of #1, the resulting errors could actually be a boon, alerting the user to a 
potential (serious) hazard.  On the other hand, if the overlap is not an issue, or even on 
purpose, the workaround is clumsy and kludgy:

class B {
  int foo() {...}
}

template M {
  int foo() {...}
  int bar() {...}
}

class D : B {
  mixin M _m;

  alias _m.bar bar;

  override int foo () { return _m.foo(); }
}

Chances are that a relative straightforward CheckOverrides() template or CTF could be used 
to auto-generate this.  There is still, however, the issue of a superfluous proxy method 
being written, whether by the programmer or by CheckOverrides().

In the case of #2, there are two sub-scenarios.

In the first, the situation is an accident.  Perhaps D was not previously derived from B, 
but is now as a result of refactoring, and the unnecessary mixin statement was simply 
missed.  The compiler has caught a programmer error.  Good Thing.

In the second, perhaps class B had overwritten some of the mixin's methods to behave 
differently, and class D intends to re-mix the default behavior (perhaps to expose its own 
changes).  In this case perhaps one could wrap the mixin statement and subsequent 
overwrites in an 'override {...}' block and be good to go.

template M {
  int foo() {...}
  int bar() {...}
}

class B {
  mixin M;

  int foo() {...custom version...}
}

class D : B {
  override {
    mixin M;

    int bar() {...custom version...}
  }
}

It makes for nice grouping as well, even if it is a workaround.

Of course I might have missed some other case where this could happen.

-- Chris Nicholson-Sauls
August 08, 2007
Re: Hijacking
Bill Baxter wrote:
> Walter Bright wrote:
>> kris wrote:
>>> There's a related problem where a public method is added to a 
>>> base-class A (as in your example) but where the signature is 
>>> *exactly* that of one existing in derived class B. If A actually 
>>> calls that new method internally, "bad things"tm will almost 
>>> certainly happen, since B never intended to effectively override the 
>>> newly-added method in A.
>>>
>>> This is a very hard problem to isolate yet can be easily remedied by 
>>> the compiler. The request was first made two or three years back, and 
>>> once or twice since then: you make the "override" keyword *required*.
>>>
>>> When "override" is required, the compiler can easily trap this 
>>> related type of hijacking and avoid such nasty surprises.
>>
>> That is a good point. The reason I haven't added it is because I'm not 
>> sure how annoying it will be to have to always add the 'override' 
>> keyword. It might be one of those things like exception specifications 
>> where everyone says it's a good idea but guiltily hate in secret <g>.
>>
>> Mitigating factors are private and final methods cannot be overridden.
> 
> Although, I generally like the idea, I fear that requiring 'override' 
> will have side effects for mixins.  The writer of the mixin has no way 
> of knowing if the methods will override something or not.
> 
> I'm thinking the only reasonable solution would be to allow mixins to go 
> on as they currently are, without enforcing the use of 'override'. 
> However, an accidental override that comes in via a mixin seems like a 
> very likely source of subtle bugs.  And requiring a special exception to 
> the rules is not really desirable in the first place.
> 
> --bb

Interesting point. I think, however, that an explicit solution which 
re-enables using mixins as overriding functions is the best solution (as 
you point out, the alternative is subtle bugs). Perhaps a new form of 
alias, to add the override?

template Foo()
{
    int foo() { return x*x; }
}

class Base
{
    int foo() { return 5; }
}

class Derived : Base
{
    int x = 5;

    mixin Foo my_foo;

    // specify that my_foo.foo overrides Base.foo
    alias my_foo.foo Base.foo;

    // or specify that my_foo.foo is an override
    alias my_foo.foo override foo;

    // (but obviously not both at once)
}

  -- Reiner

PS. Notice how I've (not-so-)subtly worked in my suggestion from 
http://www.digitalmars.com/d/archives/digitalmars/D/Implementing_required_methods_with_alias_56011.html 
;-)
August 08, 2007
Re: Checked exceptions [Re: Hijacking]
Bill Baxter wrote:
> Nick Sabalausky wrote:
>> "Rioshin an'Harthen" <rharth75@hotmail.com> wrote in message 
>> news:f974u9$9k1$1@digitalmars.com...
>>> "Walter Bright" <newshound1@digitalmars.com> kirjoitti viestissä 
>>> news:f95leh$hn4$1@digitalmars.com...
>>>> It might be one of those things like exception specifications where 
>>>> everyone says it's a good idea but guiltily hate in secret <g>.
>>> Exception specification *is* a good idea. Although I do hate it - try 
>>> to remember what a specific method may throw when you write your 
>>> code, especially if the error is ambiguous like "Unhandled exception" 
>>> it's really irritating - but I hate unspecified exceptions even more, 
>>> as the problem then is to even remember to put in the necessary 
>>> try-catch-finally blocks.
>>
>> Not to start a big big debate on it, but my own personal feeling on 
>> that (after having used a fair amount of it) is that the specification 
>> of exceptions belongs in generated documentation (whether 
>> javadoc-style or as part of the IDE as with "some_function() -> Called 
>> By..."). I normally prefer having to explicity specify things (yea, 
>> strong-typing fan here ;) ), but personally, I find it overkill in 
>> this case. (Not to mention it gave me flashbacks of writing C/C++ 
>> headers. j/k ;) ). 
> 
> I agree with this 100%.  With check exceptions it just becomes too 
> annoying and verbose.  Without them, often it is too difficult to find 
> out what exceptions are possible for a function to throw.
> 
> So the right place seems to be an analysis / doc-generation tool / IDE.
> 
> --bb

Interesting thing I'd like to mention, again about how IDEs affect the 
language design and influence it's advantages and disadvantages.
I too find checked exceptions annoying, but this is an example of a 
language disadvantage has been practically nullified by the IDE (JDT).

First I took a slightly modified ExceptionAdapter class such as the one 
from Bruce Eckel's article:
http://www.mindview.net/Etc/Discussions/CheckedExceptions
(basicly ExceptionAdapter is class that wraps a checked exception in an 
unchecked exception, allowing it to be thrown unchecked)
So when you have something like this:
  foo.doSomething(); // throws a normal exception
and Java will complain that an exception is thrown, you add this:
  try {
    foo.doSomething(); // throws a normal exception
  } catch(FooException fe) {
    ExceptionAdapter.unchecked(fe);
  }
and there is no longer a compiler error (unchecked is a static method 
that wraps the exception), without having needed to put throws clauses 
in all method along the call hierarchy.
This is an interesting workaround, but it is still annoying to have to 
write that try-catch code whenever an exception is thrown.
The second part is where JDT comes in. Whenever you have this:
  foo.doSomething(); // throws a normal exception
the IDE compiler will show and highlight the error, and then you can 
press Ctrl+1 on the error (Quick-Assist), showing a list of possible 
fixes, one of them being "Surround with Try-Catch". If you select it, 
JDT will automatically add the try-catch code, like this:
  try {
    foo.doSomething(); // throws a normal exception
  } catch(FooException fe) {
    // TODO: catch exception here
  }
Note that the catch clause is automatically set to the thrown exception. 
But furthermore you can change the template of code that is created with 
this try-catch quick-fix, so that instead of the "// TODO:" line, you 
put the "ExceptionAdapter.unchecked(...);" line. So now whenever this 
quick fix is invoked, it will automatically generate all necessary code, 
and you're now able to avoid the checked exception problem with just a 
few keystrokes (Ctrl+1, Down, Enter). :)
As an added bonus, if some time you feel the need to rigorously specify 
your code, you can then search for calls of the 
ExceptionAdapter.unchecked method, to find points where you can turn 
unchecked exceptions into checked ones.

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
August 08, 2007
Re: Checked exceptions [Re: Hijacking]
On Wed, 08 Aug 2007 15:38:14 +0400, Bruno Medeiros  
<brunodomedeiros+spam@com.gmail> wrote:

> Bill Baxter wrote:
>> Nick Sabalausky wrote:
>>> "Rioshin an'Harthen" <rharth75@hotmail.com> wrote in message  
>>> news:f974u9$9k1$1@digitalmars.com...
>>>> "Walter Bright" <newshound1@digitalmars.com> kirjoitti viestissä  
>>>> news:f95leh$hn4$1@digitalmars.com...
>>>>> It might be one of those things like exception specifications where  
>>>>> everyone says it's a good idea but guiltily hate in secret <g>.
>>>> Exception specification *is* a good idea. Although I do hate it - try  
>>>> to remember what a specific method may throw when you write your  
>>>> code, especially if the error is ambiguous like "Unhandled exception"  
>>>> it's really irritating - but I hate unspecified exceptions even more,  
>>>> as the problem then is to even remember to put in the necessary  
>>>> try-catch-finally blocks.
>>>
>>> Not to start a big big debate on it, but my own personal feeling on  
>>> that (after having used a fair amount of it) is that the specification  
>>> of exceptions belongs in generated documentation (whether  
>>> javadoc-style or as part of the IDE as with "some_function() -> Called  
>>> By..."). I normally prefer having to explicity specify things (yea,  
>>> strong-typing fan here ;) ), but personally, I find it overkill in  
>>> this case. (Not to mention it gave me flashbacks of writing C/C++  
>>> headers. j/k ;) ).
>>  I agree with this 100%.  With check exceptions it just becomes too  
>> annoying and verbose.  Without them, often it is too difficult to find  
>> out what exceptions are possible for a function to throw.
>>  So the right place seems to be an analysis / doc-generation tool / IDE.
>>  --bb
>
> Interesting thing I'd like to mention, again about how IDEs affect the  
> language design and influence it's advantages and disadvantages.
> I too find checked exceptions annoying, but this is an example of a  
> language disadvantage has been practically nullified by the IDE (JDT).
>
> First I took a slightly modified ExceptionAdapter class such as the one  
> from Bruce Eckel's article:
> http://www.mindview.net/Etc/Discussions/CheckedExceptions
> (basicly ExceptionAdapter is class that wraps a checked exception in an  
> unchecked exception, allowing it to be thrown unchecked)
> So when you have something like this:
>    foo.doSomething(); // throws a normal exception
> and Java will complain that an exception is thrown, you add this:
>    try {
>      foo.doSomething(); // throws a normal exception
>    } catch(FooException fe) {
>      ExceptionAdapter.unchecked(fe);
>    }
> and there is no longer a compiler error (unchecked is a static method  
> that wraps the exception), without having needed to put throws clauses  
> in all method along the call hierarchy.
> This is an interesting workaround, but it is still annoying to have to  
> write that try-catch code whenever an exception is thrown.
> The second part is where JDT comes in. Whenever you have this:
>    foo.doSomething(); // throws a normal exception
> the IDE compiler will show and highlight the error, and then you can  
> press Ctrl+1 on the error (Quick-Assist), showing a list of possible  
> fixes, one of them being "Surround with Try-Catch". If you select it,  
> JDT will automatically add the try-catch code, like this:
>    try {
>      foo.doSomething(); // throws a normal exception
>    } catch(FooException fe) {
>      // TODO: catch exception here
>    }
> Note that the catch clause is automatically set to the thrown exception.  
> But furthermore you can change the template of code that is created with  
> this try-catch quick-fix, so that instead of the "// TODO:" line, you  
> put the "ExceptionAdapter.unchecked(...);" line. So now whenever this  
> quick fix is invoked, it will automatically generate all necessary code,  
> and you're now able to avoid the checked exception problem with just a  
> few keystrokes (Ctrl+1, Down, Enter). :)
> As an added bonus, if some time you feel the need to rigorously specify  
> your code, you can then search for calls of the  
> ExceptionAdapter.unchecked method, to find points where you can turn  
> unchecked exceptions into checked ones.

I don't agree (almost complitely). Checked expession is not simply  
annoying. Sometimes they lead to bad-style and erroneous code. For example  
imagine you redefine some method:

class MySpecializedClass extends SomeGeneralClass
{
  public void someMethod() throws DomainSpecificException { ... }
}

but you need to use temporary file in someMethod() implementation (or need  
to run some external tool, or need to use some crypto library). And  
File.createTempFile throws IllegalArgumentException or IOException or  
SecurityException, but no one of them is in someMethod 'throws' clause.

In such case you have only two possibilities: wrap the exception which is  
thrown by File.createTempFile into some another exception (it is good if  
DomainSpecificException allows that, but in an usual case it don't) or  
catch and hide the original exception. As I seen in the past many  
developers prefered catch and hide exception. And this is not a good  
approach I think.

So in my opinion it is better to write code which doesn't depend on  
particular kind of exception. Assumption that any part of code could  
throws any kind of exception lead to more reliable software (Erlang is an  
evidence).

The exception safety in much more hard in C++ where there is manual memory  
management and there isn't scope()-constructs like in D. So I hope that  
writting exception safe code in D is much more easy, than in C++ or in  
Java with checked exceptions.

However sometimes is good to know that some method doesn't throw exception  
at all (it could be necessary for exception safety, like C++ convection  
that swap() methods and destructors are exception free). So I suppose to  
introduce 'nothrows' modifier as a sign that some routine is exception  
free:

bool is_item_in_array( int[] array, int item ) nothrows { ... }

Compiler could checks nothrows-routines. It is an error if  
nothrows-routine calls any routine without 'nothrows' modifier.

So it could be an crear advice to programmer: if it has some data which  
must be protected from exception and he calls any routine without  
'nothrows' modifier he must do some action to protect his data.

-- 
Regards,
Yauheni Akhotnikau
August 08, 2007
Re: Yet more ideas about 'nothrows' routines [was: Checked exceptions [Re: Hijacking]]
On Wed, 08 Aug 2007 17:05:07 +0400, eao197 <eao197@intervale.ru> wrote:

> So in my opinion it is better to write code which doesn't depend on  
> particular kind of exception. Assumption that any part of code could  
> throws any kind of exception lead to more reliable software (Erlang is  
> an evidence).
>
> The exception safety in much more hard in C++ where there is manual  
> memory management and there isn't scope()-constructs like in D. So I  
> hope that writting exception safe code in D is much more easy, than in  
> C++ or in Java with checked exceptions.
>
> However sometimes is good to know that some method doesn't throw  
> exception at all (it could be necessary for exception safety, like  
> C++ convection that swap() methods and destructors are exception free).  
> So I suppose to introduce 'nothrows' modifier as a sign that some  
> routine is exception free:
>
> bool is_item_in_array( int[] array, int item ) nothrows { ... }
>
> Compiler could checks nothrows-routines. It is an error if  
> nothrows-routine calls any routine without 'nothrows' modifier.
>
> So it could be an crear advice to programmer: if it has some data which  
> must be protected from exception and he calls any routine without  
> 'nothrows' modifier he must do some action to protect his data.

Yet more ideas about 'nothrows' modifier (sorry for wasting your time).

Which routines need 'nothrows' specifications?

Obvious (for me) answer is: various forms of cleanup-routines. For  
example: File.close, Mutex.release, DbConnection.disconnect and so on.  
E.g. routines which will be used in destructors, scope-constructs and  
finally-blocks. So, compiler could checks all calls in those constructs  
and reports warning (or even errors) if any method without 'nothrows' is  
being called.

Even more. In some situation cleanup actions could be performed in  
catch-blocks. To ensure that no exception will be thrown during cleanup  
programmer could write:

nothrows {
  ... // some actions...
}

and compiler will check all calls in such block.

For example:

// Create new DB connection for user.
// And checks user right. If user has no right (has expiried password) then
// exception is thrown.
UserSession
open_user_section( string user_name, string user_password )
  {
     auto db_connection = establish_db_connection();
     try
      {
         check_user_rights( db_connection, user_name, user_password );
         ... // Some other actions...
      }
     catch( Exception x )
      {
        nothrows
           {
             cleanup_db_connection( db_connection );
             ... // Some other cleanup actions...
           }
        log_session_creation_error( x );
        throw;
      }

    return new UserSession( db_connection, user_name );
  }

So compiler could check that no exception is allowed in cleanup actions.  
But new exception could be thrown in 'log_session_creation_error' method.

-- 
Regards,
Yauheni Akhotnikau
1 2 3 4 5 6
Top | Discussion index | About this forum | D home