Open md-work opened 7 years ago
Hi @md-work, this is a neat idea. Based on the comments in https://github.com/egonSchiele/contracts.ruby/issues/193, would you like to add a contract that says "if an exception is raised, catch it and raise a contract exception"? Or would you want to annotate methods saying "this can throw an exception"?
Hi @egonSchiele I'm talking about "this can throw an exception".
Examples:
Contract String => String raises Errno::ENOENT
def read_file(filename)
# This raises Errno::ENOENT if the filename doesn't exist.
# In this case everything's fine the Contract should let the
# exception pass (or re-raise it without modification).
# But in case the user doesn't has permissions to read the file,
# this raises Errno::EACCES.
# In this case the Contract should catch the exception and raise an
# own exception instead (e.g. a RaiseContractError).
return File.read(filename).to_s
end
Contract Integer, Integer => Integer raises Contracts::None
def add(num_a, num_b)
# This should never raise an exception.
return num_a + num_b
end
# This method usually never raises an exception. Just in one very rare
# situation, about which the programmer forgot when he wrote the
# contract.
# So if the method gets 23 it raises :illuminati and the Contract
# should catch that and raise an own exception instead.
Contract Integer => Integer raises Contracts::None
def some_fun(number)
if number = 23
raise :illuminati
else
return number
end
end
# Same with a fixed contract.
Contract Integer => Integer raises :illuminati
def some_fun(number)
if number = 23
raise :illuminati
else
return number
end
end
# Same for throw-catch like for raise-rescue.
Contract Integer => Integer throws :illuminati
def some_fun(number)
if number = 23
throw :illuminati
else
return number
end
end
# And for both, raise-rescue and throw-catch.
Contract Integer => Integer throws :illuminati raises :answer
def some_fun(number)
if number = 23
raise :illuminati
elsif number = 42
throw :answer
else
return number
end
end
Some notes
Contract ... throws ...
should be considered to throw nothing. (except whitelisted objects/classes)
Thanks for this really great gem!
It helps a lot checking the types of objects being send up and down the stack trough method calls and returns. Sadly there's still no way to check the type of objects being send trough the stack by the Ruby
raise
andthrow
commands.I'm thinking about something similar to
throws Exception
in Java. (sure this isn't Java and the checking can only be done dynamically, not statically)What do you think about adding such an feature to Contracts?
See also: #193