egonSchiele / contracts.ruby

Contracts for Ruby.
http://egonschiele.github.com/contracts.ruby
BSD 2-Clause "Simplified" License
1.44k stars 82 forks source link

RFC: Flags to turn off pattern matching and evaluation #273

Closed indigoviolet closed 3 years ago

indigoviolet commented 6 years ago

We'd like to be able to turn off the pattern matching/method overloading behavior altogether -- it can lead to unpleasant surprises, and we don't want someone inadvertently writing code that relies on it in our environment.

Similarly, I think it'd be valuable to have a feature that allows selective disabling of validation of contracts after having loaded them. (The idea being, it might permit running contracts in non-perf-sensitive codepaths in production or a fraction of prod requests)

I've sketched a version of how I thought this might work to get some feedback from you about

a) is this likely to get merged if completed? b) is this a reasonable approach? c) any big pitfalls that I'm not thinking of

I haven't tested this very much at all, will proceed to do so if you think this is a good direction to pursue.

egonSchiele commented 6 years ago

I like this idea! Answers:

a) is this likely to get merged if completed? Yes. b) is this a reasonable approach? Yes. c) any big pitfalls that I'm not thinking of *Here are some things that have caused issues in the past, I would construct a test case with a combination of these: pattern matching (especially with calls that cause contract failures) + contracts in modules instead of classes, with those modules being then included in a class + contracts inside a class << self block.

I like the support class, and I like the option to turn off decorators, invariants, and pattern matching selectively. I don't understand:

Similarly, I think it'd be valuable to have a feature that allows selective disabling of validation of contracts after having loaded them. (The idea being, it might permit running contracts in non-perf-sensitive codepaths in production or a fraction of prod requests)

Isn't this essentially the existing NO_CONTRACTS functionality?

indigoviolet commented 6 years ago

Isn't this essentially the existing NO_CONTRACTS functionality?

Maybe I'm misunderstanding, but my reading of the code and experimentation suggests not-

https://github.com/egonSchiele/contracts.ruby/blob/78be9e20218d60f4619d5ea1a16fc7892064f500/lib/contracts/method_handler.rb#L102

We will completely ignore decorators at startup if NO_CONTRACTS is set; I'm interested in something more dynamic, where I can write a block similar to

https://github.com/egonSchiele/contracts.ruby/blob/78205dee5df85bb1f75a448552be583cd8373c90/spec/support.rb#L1-L6

but for use in non-test code- ie. decorators are defined but not evaluated.

This probably shouldn't be done via environment variable, and instead some global variable -- I'll explore that.

egonSchiele commented 6 years ago

Oh that's a neat idea. Agreed, NO_CONTRACTS doesn't let you suspend contracts for a short time

nathan-appere commented 5 years ago

@indigoviolet did you end up using this in prod?