- I like that the contracts are right there in the code and not in a separate file.
- The actual Contract methods only run once upon loading each class, so they don't cause a performance hit. I'd like a way to make them all noops (so they don't add any instrumentation) when running in "production".
- My thought is that if you can define pre- and post-conditions as you're doing, then you can cut out a lot of the checks in your tests, so that as long as the tests exercise the code, you can rely on the post-conditions to do quite a bit of the validation. Plus you're validating outputs all over the place constantly, so you'd probably catch edge cases you never even expected.
- I'm disappointed that your system seems to offer little more than type checking (unless I'm mistaken). I'd like something that gives me true pre- and post-conditions: basically passing a block of Ruby code for each one, with common idioms abbreviated so I don't need to write a whole block if the conditions are simple.
Good luck on the project!
> I'd like a way to make them all noops
Sure! There's a default failure callback that gets called when a contract fails. You can just clear this callback in prod:
if ENV == PRODUCTION
class Contract
def self.failure_callback(data)
# blank
end
end
end
> I'm disappointed that your system seems to offer little more than type checkingNay! You can write your own contracts to do anything you want. So yes, lambdas are allowed in contracts:
Contract lambda { |x| x.is_valid_email? } => Bool
def save_email(email)
# save an email
end
> with common idioms abbreviatedI provide some common idioms already, but you can make your own abbreviations:
ValidEmail = lambda { |x| x.is_valid_email? }
Contract ValidEmail => Bool
def save_email(email)
Let me know if you have any other questions :)