Why are there no other statements in Ruby?

I was looking for a Ruby code quality tool the other day, and I came across a pelusa gem that looks interesting. One of the things he checks is the number of else statements used in this Ruby file.

My question is: why is this bad? I understand that if/else often add a lot of complexity (and I understand that the goal is to reduce the complexity of the code), but how is a method that checks two cases written without else ?

Recall that I have two questions:

1) Is there a reason, besides reducing the complexity of the code, what else could be avoided?

2) Here an example method from the application I'm working on uses the else . How would you write this without him? The only option I could think of is a triple statement, but there is enough logic here that I think that a three-dimensional statement will be more complex and difficult to read.

 def deliver_email_verification_instructions if Rails.env.test? || Rails.env.development? deliver_email_verification_instructions! else delay.deliver_email_verification_instructions! end end 

If you wrote this using the ternary operator, it would be:

 def deliver_email_verification_instructions (Rails.env.test? || Rails.env.development?) ? deliver_email_verification_instructions! : delay.deliver_email_verification_instructions! end 

It is right? If so, is it not difficult to read? Does this else help? Is there another, better, else way to write this that I don't think about?

I think I'm looking for stylistic considerations here.

+7
source share
2 answers

Let me start by saying that there is nothing wrong with your code, and as a rule, you should know that no matter what the code quality tool tells you, it may be completely stupid, because it lacks context for evaluating what you are actually doing.

But back to the code. If there was a class that had exactly one method, where the fragment

 if Rails.env.test? || Rails.env.development? # Do stuff else # Do other stuff end 

it would be quite normal (there are always different approaches to this thing, but you do not need to worry about it, even if programmers will hate you for not arguing with them about this: D).

Now comes the hard part. People are lazy, like hell, and therefore code snippets like the ones above are easy targets for coding / inserting (therefore, people will argue that they should be avoided in the first place, because if you extend the class later, you probably just copy and paste the material than actually reorganize it).

As an example, consider a code snippet. I basically suggest the same as @Mik_Die, however his example is equally inclined to copy / paste like yours. Therefore, this should be done (IMO):

 class Foo def initialize @target = (Rails.env.test? || Rails.env.development?) ? self : delay end def deliver_email_verification_instructions @target.deliver_email_verification_instructions! end end 

This may not apply to your application as it is, but I hope you get an idea, namely: Do not repeat yourself. Ever. Each time you repeat yourself, you not only make your code less maintainable, but as a result are also more prone to errors in the future, because one or even 99/100 cases of what you copied and pasted can be changed, but one of the remaining cases is what @disasterOfEpicProportions calls at the end :)


Another point that I forgot about was caused by @RayToal (thanks :), which is that if / else constructs are often used in combination with logical input parameters, which leads to constructs like this (the actual code from the project which I should support):

 class String def uc(only_first=false) if only_first capitalize else upcase end end end 

Let's not ignore the obvious problems with method naming and monkey problems, and focus on the if / else construct, which is used to give the uc method two different behaviors depending on the only_first parameter. Such code is a violation of the principle of single responsibility, because your method does more than one thing , so you should have written two methods in the first place.

+6
source
 def deliver_email_verification_instructions subj = (Rails.env.test? || Rails.env.development?) ? self : delay subj.deliver_email_verification_instructions! end 
+2
source

All Articles