ruby-core

Mailing list archive

[ruby-core:66694] [ruby-trunk - Feature #10481] Add "if" and "unless" clauses to rescue statements

From: plasticchicken@...
Date: 2014-12-04 16:38:24 UTC
List: ruby-core #66694
Issue #10481 has been updated by Brian Hempel.

File smime.p7s added

 You=E2=80=99re right there may be some risk for anti-patterns, but from my=
 experience this example in the original proposal is practical:
=20
 begin
   ...
 rescue =3D> e if e.message =3D=3D "some error"
   ...handle error...
 end
=20
 Sometime code libraries forget to make a separate object for every error a=
nd you are forced to match on the error message. Right now, you have to wri=
te code like:
=20
 begin
 =E2=80=A6
 rescue =3D> e
   raise unless e.message =3D~ /card declined/i
   =E2=80=A6handle error=E2=80=A6
 end
=20
 Granted, the best solution is to fix the code library.
=20
 Brian Hempel
=20
=20
 On Dec 4, 2014, at 11:25 AM, bruka <bruka@idatainc.com> wrote:
=20
 > I'm trying to think of use cases for this, but every scenario I think of=
, leads towards anti-patterns and bad programming practices. Here is my 2 (=
3) cents:
 >=20
 > Anti-pattern #1: Using rescue clauses as conditionals to direct program =
flow.
 >=20
 > I use the 'raise if my_obj.not_as_expected?' style as well, but I always=
 make sure that those statements are trivially simple, that they appear in =
obvious places, and that there is at most 1 rescue clause. I think even thi=
s style is an anti-pattern, but I tell myself that if the code is simple en=
ough that it's ok.
 >=20
 > Anti-pattern #2: Too many rescue clauses.
 >=20
 > Things like:
 > rescue SomeError =3D> e if e.error_code =3D=3D 1
 >   ...handle error code 1...
 > rescue SomeError =3D> e if e.error_code =3D=3D 2
 >   ...handle error code 2...
 > end
 >=20
 > is a code smell to me. Indicative that the method is doing too many thin=
gs and that perhaps has too much fan-out. Might be a  violation of the Law =
of Demeter, where the method knows the types of objects it is working with,=
 the types of errors they throw, and the internal structure of those error =
objects.
 >=20
 > Anti-pattern #3: Programming flow is more difficult to follow.
 >=20
 > It reminds of conditionals at the end of loops e.g.
 >=20
 > my_arr.each do |ele|
 > ...10 lines of code...
 > end if some_condition
 >=20
 > You read the entire loop and at the end you realize that it only runs in=
 certain cases. Similar with the conditional rescues. You're jumping back a=
nd forth in your method to try to figure out what happens when. Not fun.
 >=20
 > Moreover, as another person noted, skipping the rescue clause can depriv=
e you of valuable debugging information. Why not just send the error to ano=
ther object to be processed:
 >=20
 > rescue StandardError =3D> ex
 >       MyErrorProcessor.handle( ex, self )
 > end
 >=20
 > These are just opinions on software architecture and I have nothing to s=
ay about the technical implementation of this. I may just be overthinking i=
t, but again I think you need to show some good real-world use cases.
 >=20
 > On Thu, Dec 4, 2014 at 3:24 AM, <alex@opengroove.org> wrote:
 > Issue #10481 has been updated by Alex Boyd.
 >=20
 >=20
 > Any update on this? Is this just waiting for 2.2 to make it out the door?
 >=20
 > ----------------------------------------
 > Feature #10481: Add "if" and "unless" clauses to rescue statements
 > https://bugs.ruby-lang.org/issues/10481#change-50283
 >=20
 > * Author: Alex Boyd
 > * Status: Assigned
 > * Priority: Normal
 > * Assignee: Yukihiro Matsumoto
 > * Category:
 > * Target version:
 > ----------------------------------------
 > I'd like to propose a syntax change: allow boolean "if" and "unless" cla=
uses to follow a rescue statement.
 >=20
 > Consider the following:
 >=20
 > ~~~ruby
 > begin
 >   ...
 > rescue SomeError =3D> e
 >   if e.error_code =3D=3D 1
 >     ...handle error...
 >   else
 >     raise
 >   end
 > end
 > ~~~
 >=20
 > This is a fairly common way of dealing with exceptions where some condit=
ion above and beyond the exception's type determines whether the exception =
should be rescued. It's verbose, though, and it's not obvious at first glan=
ce exactly what conditions are being rescued, especially if "...handle erro=
r..." is more than a few lines long. I propose that the following be allowe=
d:
 >=20
 > ~~~ruby
 > begin
 >   ...
 > rescue SomeError =3D> e if e.error_code =3D=3D 1
 >   ...handle error...
 > end
 > ~~~
 >=20
 > "unless" would, of course, be allowed as well:
 >=20
 > ~~~ruby
 > begin
 >   ...
 > rescue SomeError =3D> e unless e.error_code =3D=3D 2
 >   ...handle error...
 > end
 > ~~~
 >=20
 > A rescue statement whose boolean condition failed would be treated the s=
ame as if the exception being raised didn't match the exception being rescu=
ed, and move on to the next rescue statement:
 >=20
 > ~~~ruby
 > begin
 >   ...
 > rescue SomeError =3D> e if e.error_code =3D=3D 1
 >   ...handle error code 1...
 > rescue SomeError =3D> e if e.error_code =3D=3D 2
 >   ...handle error code 2...
 > end
 > ~~~
 >=20
 > And finally, catch-all rescue statements would be allowed as well:
 >=20
 > ~~~ruby
 > begin
 >   ...
 > rescue =3D> e if e.message =3D=3D "some error"
 >   ...handle error...
 > end
 > ~~~
 >=20
 >=20
 > ---Files--------------------------------
 > rescue-conditions.diff (6.76 KB)
 > rescue-conditions.diff (6.57 KB)
 >=20
 >=20
 > --
 > https://bugs.ruby-lang.org/
 >

----------------------------------------
Feature #10481: Add "if" and "unless" clauses to rescue statements
https://bugs.ruby-lang.org/issues/10481#change-50294

* Author: Alex Boyd
* Status: Assigned
* Priority: Normal
* Assignee: Yukihiro Matsumoto
* Category:=20
* Target version:=20
----------------------------------------
I'd like to propose a syntax change: allow boolean "if" and "unless" clause=
s to follow a rescue statement.

Consider the following:

~~~ruby
begin
  ...
rescue SomeError =3D> e
  if e.error_code =3D=3D 1
    ...handle error...
  else
    raise
  end
end
~~~

This is a fairly common way of dealing with exceptions where some condition=
 above and beyond the exception's type determines whether the exception sho=
uld be rescued. It's verbose, though, and it's not obvious at first glance =
exactly what conditions are being rescued, especially if "...handle error..=
." is more than a few lines long. I propose that the following be allowed:

~~~ruby
begin
  ...
rescue SomeError =3D> e if e.error_code =3D=3D 1
  ...handle error...
end
~~~

"unless" would, of course, be allowed as well:

~~~ruby
begin
  ...
rescue SomeError =3D> e unless e.error_code =3D=3D 2
  ...handle error...
end
~~~

A rescue statement whose boolean condition failed would be treated the same=
 as if the exception being raised didn't match the exception being rescued,=
 and move on to the next rescue statement:

~~~ruby
begin
  ...
rescue SomeError =3D> e if e.error_code =3D=3D 1
  ...handle error code 1...
rescue SomeError =3D> e if e.error_code =3D=3D 2
  ...handle error code 2...
end
~~~

And finally, catch-all rescue statements would be allowed as well:

~~~ruby
begin
  ...
rescue =3D> e if e.message =3D=3D "some error"
  ...handle error...
end
~~~


---Files--------------------------------
rescue-conditions.diff (6.76 KB)
rescue-conditions.diff (6.57 KB)
smime.p7s (4.78 KB)


--=20
https://bugs.ruby-lang.org/

In This Thread

Prev Next