-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider use of functions as well? #22
Comments
On a related note you depend on the godoc syntax specification but I cannot find one - https://stackoverflow.com/questions/53101458/where-is-the-specification-for-godoc-itslef |
Hi @KantarBruceAdams I identify three points in your message, please correct me if I'm wrong: Invariants. So far, we had very little feedback on people using gocontracts, so I didn't look into the issue. I created an issue on github just right now for further discussion: #25 Toggling contracts. This is actually already possible with gocontracts. You can create two files that define the same constant (say Then you need to include that file in all the files where you define contracts and include it in the conditions (as I would suggest you to introduce one build tag per package or per library (whatever seems like a better fit), so that the users of your code can decide the granularity of the contracts applied, e.g., when they are performing integration testing against your code. An additional benefit of this approach is that you explicitly document when your contracts apply so that the users of the library can double-check themselves if the contracts are verified or not (and if not, why not). Please let me know if that didn't / doesn't work for you and what the concrete blockers are. Reverse-contracting. This seemed to us like a too difficult task akin to a tar pit 😄 I think there would be too many edge cases which needed to be covered that it would sap a lot of energy to implement, while we couldn't identify a clear use case in our code base. Regarding godoc syntax: could you please clarify a bit? What do you mean by it? |
Hi @KantarBruceAdams Please let me know if the text is clear enough. |
Actually the main point of this:
You could generate:
But I subverted my own thread.
At the moment it is hard to mix gocontracts with godbc. |
Hi @KantarBruceAdams, I see it actually as beneficial to dispense of a function call: the contract checking code is explicit and directly readable, while the constants in the conditions allow you to easily track in which situations the contract is verified (or not). Moreover, the constant boolean in the condition allows for arbitrary granularity of contract toggling, while the function from an external library imposes the granularity on the caller. |
For me there are several benefits:
If you want arbitrary granularity of contract toggling I don't think the condition is perfect. Another thing is I don't like having to repeat the condition in the message. |
Hi @KantarBruceAdams , However, Go does not support such an approach: there are no macros and you don't even have optional arguments. That's why we implemented gocontracts in the first place: so that you define conditions only once, and you read them in the violation message automatically.
Could you please make an example? I fail to see how these two code snippets are different to read: // SomeFunc does something.
//
// SomeFunc requires:
// * x > 0
// * x < 100
// * some condition: y > 3
//
// SomeFunc ensures:
// * strings.HasPrefix(result, "hello")
//
// Some text here.
func SomeFunc(x int, y int) (result string, err error) {
// Pre-conditions
switch {
case !(x > 0):
panic("Violated: x > 0")
case !(x < 100):
panic("Violated: x < 100")
case !(y > 3):
panic("Violated: some condition: y > 3")
default:
// Pass
}
// Post-condition
defer func() {
if !(strings.HasPrefix(result, "hello")) {
panic("Violated: strings.HasPrefix(result, \"hello\")")
}
}(); // some comment here
return
} and: // SomeFunc does something.
//
// SomeFunc requires:
// * x > 0
// * x < 100
// * some condition: y > 3
//
// SomeFunc ensures:
// * strings.HasPrefix(result, "hello")
//
// Some text here.
func SomeFunc(x int, y int) (result string, err error) {
// Pre-conditions
godbc.Require(x > 0, "Violated: x > 0")
godbc.Require(x < 100, "Violated: x < 100")
godbc.Require(y > 3, "Violated: some condition: y > 3")
// Post-condition
defer func() {
godbc.Ensure(strings.HasPrefix(result, "hello"),
"Violated: strings.HasPrefix(result, \"hello\")")
}(); // some comment here
return
} The machine can't access contracts in real time in neither of the snippets. Function calls are marginally shorter, but then the reader might not realize that they panic. I see the only real benefit of the function approach when the user of the gocontracts can specify individually her |
I have left an honourable mention of gocontracts in regards to discussions about attributes/annotations in go. C++20 includes contracts as attributes |
Thanks! I'll keep an eye on it. It would be so much better if they integrated DbC in the language. |
Hi @KantarBruceAdams, import "github.com/lpabon/godbc"
// SomeFunc does something.
//
// SomeFunc preamble:
// godbc.Require(x > 0, "x positive")
// godbc.Require(x < 100, "x not too large")
func SomeFunc(x int) {
// Preamble
godbc.Require(x > 0, "x positive")
godbc.Require(x < 100, "x not too large")
// function body ...
} Could you please let me know if this resolves your issue? |
Hi,
I have been looking for DBC support for go as well. I like your approach of ensuring that the generated code agrees with the documentation. I wonder if we could have the best of both worlds if you generated code that used functions to implement the contract as per https://godoc.org/github.com/lpabon/godbc?
Personally I want to assert pre-conditions in production but not post-conditions (which are often hard to compute and covered by extensive unit tests.
I also want to document all my pre-conditions , post-condiions and invariants even those that are hard to compute.
Coming from C++ I used doxygen for DBC commenting, an assertion macro for pre-conditions and unit tests for post-conditions and invariants. Generating a contract checking wrapper to a function would be very useful in the testing context.
The ultimate DBC package to me, might allow:
e.g. "foobar() must have been invoked first to setup the snafu"
I would like to propose a minimum change towards this goal of:
so that your package is still usable/preferable even if the code generation part is not used.
I presume this package overwrites generated contracts rather than "checking that pre-conditions, post-conditions and invariants in the code and documentation match" which is a harder problem but please correct me if I am wrong.
What is the current behaviour if code for a check cannot be generated?
Is this left to be picked up as a build failure downstream?
Regards,
Bruce.
The text was updated successfully, but these errors were encountered: