"E S" <eero.saynatkari / kolumbus.fi> schrieb im Newsbeitrag
news:20050211034606.MREY15813.fep31-app.kolumbus.fi / mta.imail.kolumbus.fi...
> > L?hett?j?: Mark Probert <probertm / acm.org>
> > Aihe: Re: Really confused about exceptions now
> >
> > Hi ..
> >
> >  On Thursday 10 February 2005 13:25, Gennady Bystritksy wrote:
> > >
> > > When you do not have explicit "return" statement in your rescue, the
> > > execution falls down to the end of the method and returns whatever
the
> > > last executed statement had returned (FYI: puts() returns nil).
> > >
> > Thank you.  So, a more correct version of the method is:
> >
> >   def alive?
> >       begin
> >           t = TCPSocket.new(@host, @port)  ### line 143
> >           return true
> >
> >       rescue Errno::ETIMEDOUT
> >           @exception = " Timed out (#{@host}:#{@port})"
> >       rescue SocketError => e
> >           @exception = " Socket error - #{e}"
> >       rescue Exception => e
> >           @exception = e
> >       end
> >       return false
> >   end
>
> Just for clarity, you could restructure that one more time :)
>
> def alive?
>   begin
>     t = TCPSocket.new(@host, @port)  ### line 143
>
>   rescue Errno::ETIMEDOUT
>     @exception = " Timed out (#{@host}:#{@port})"
>     false
>   rescue SocketError => e
>     @exception = " Socket error - #{e}"
>     false
>   rescue Exception => e
>     @exception = e
>     false
>
>   # Alive!
>   else
>     true
>
>   # Clean up
>   ensure
>     # Close the socket if it's open
>   end
> end

Hm, the usual idiom is this:

acquire_resource
begin
  use resource
ensure
  free resource
end

Which means ensure is never called if the acquire fails.  So I would do it
like this:

def alive?
  # you might want to clear @exception here

  begin
    TCPSocket.new(@host, @port).close
    # we would have a separate begin-ensure-end block
    # here if we were using the socket
    true
  rescue Exception => e
    @exception = e
    false
  end
end

.... and defer the print formatting of the exception to a later point in
time.  These are the advantages:

 - smaller and more readable code

 - the original exception is retained for later use

 - faster, as there is no processing done on the exception,
   which might never occur if @exception is never printed
   or otherwise evaluated

You might want to consider an alternative approach:

def error?
  begin
    TCPSocket.new(@host, @port).close
    nil
  rescue Exception => e
    e
  end
end

This returns the exception directly and you can do whatever you want with
it or just use it in a boolean context.

Kind regards

    robert