class User
# This code is buggy and needs several test cases to assert the bugs are fixed.
def self.friend(user1, user2, type)
r = Relationship.new
r.user1 = user1
r.user2 = user2
r.type = type
code = 0
if !["friend", "spouse"].include? type
type = "undefined" # BUG! We meant to write `r.type = "unknown"`. We are completely reliant on tests to catch it.
code = 1
end
r.save!
r_other = Relationship.find_by_sql(...)
logger.info "Interesting new relationship!" if r = r_other # BUG! We meant to write `r == r_other`. A test probably won't catch this.
return code
end
# This code requires fewer tests, but is more verbose.
def self.friend_better(final user1, final user2, final type) # These parameter reference are immutable.
final r = Relationship.new # This local variable is immutable as well.
r.user1 = user1
r.user2 = user2
code = 0 # A normal Ruby variable.
if !["friend", "spouse"].include? type
type = "undefined" # RUNTIME ERROR! The runtime knows an error exists because we explicitly declared the parameter reference final
code = 1
end
r.save!
final r_other = Relationship.find_by_sql(...)
logger.info "Interesting new relationship!" if r = r_other # RUNTIME ERROR! We cannot make the assignment since the `r` reference is immutable.
return code
end
# This best of both worlds. Requires fewer tests while still easy to understand.
def self.friend_best(user1, user2, type) # All references are implicitly immutable unless declared otherwise.
r = Relationship.new # The reference to `r` is immutable.
r.user1 = user1
r.user2 = user2
r.type = type
var code = 0 # Must be explicitly declared mutable since we are planning to change it.
if !["friend", "spouse"].include? type
type = "undefined" # RUNTIME ERROR! We meant to write `r.type = "unknown"`, but the runtime caught it since the `type` reference is immutable. No need to add a test case!
code = 1 # Works fine since the variable was declared mutable.
end
r.save!
r_other = Relationship.find_by_sql(...)
logger.info "Interesting new relationship!" if r = r_other # RUNTIME ERROR! We meant to write `r == r_other`, but the runtime caught it since the `r` reference is immutable.
return code
end
end