Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a complicated condition

Condition constructions are easy to write when you have a simple condition and a possibly complicated body:

if simple_condition_expressed_in_one_liner
  complicated_body_that_may_be_long
  complicated_body_that_may_be_long
  complicated_body_that_may_be_long
end

but sometimes, you have a complicated condition and a simple body like this:

if condition1 and
condition2 and
condition3 and
some_more_complicated_condition_that_cannot_be_written_on_a_single_line and
still_some_more_complicated_condition_that_cannot_be_written_on_a_single_line
  simple_body
end

In such case, is there a good way to write it?

like image 608
sawa Avatar asked Feb 17 '23 21:02

sawa


2 Answers

I always try to refactor into smaller descriptive methods.

Using your example, instead of:

until (print "Username : "; gets.chomp == "user") and
      (print "Password : "; gets.chomp == "pa$$word")
  puts "Error, incorrect details"
end

I would use:

def correct_user
  print "Username : "
  gets.chomp == "user"
end

def correct_password
  print "Password : "
  gets.chomp == "pa$$word"
end

until correct_user and correct_password
  puts "Error, incorrect details"
end
like image 148
Miguel Rodrigues Avatar answered Feb 19 '23 10:02

Miguel Rodrigues


I personally put the entire conditional statement into a separate method. This may sound a lot like what has been suggested already but I put the entire thing into a method instead of breaking it up.

simple_body if complicated_condition

def complicated_condition
  condition1 and
  condition2 and
  condition3 and
  some_more_complicated_condition_that_cannot_be_written_on_a_single_line and
  still_some_more_complicated_condition_that_cannot_be_written_on_a_single_line
end

I may or may not break up the condition into more methods depending on what the conditions are and whether I will end up using those methods later (too many methods used for only one purpose starts to become code smell).

It makes the code readable (I can skim the code and see what it is doing) and maintainable (I can alter the condition if need be and I know exactly where it is).

If I put this into a class, I would put the method under private since there's no reason the 'outside' needs to use it.

EDIT: If the conditions require the values of the variables at the time it is used in a condition, perhaps consider passing in binding into the method.

opt = :mysql
simple_body if complicated_condition(binding)

opt = :oracle
simple_body if complicated_condition(binding)

def complicated_condition(b)
  condition1 and
  condition2 and
  condition3 and
  some_more_complicated_condition_that_cannot_be_written_on_a_single_line and
  still_some_more_complicated_condition_that_cannot_be_written_on_a_single_line and
  eval('opt', b) == :mysql
end
like image 30
Charles Caldwell Avatar answered Feb 19 '23 10:02

Charles Caldwell