Skip to content
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

Contract propagation #9

Closed
pdaw opened this issue Mar 20, 2016 · 8 comments
Closed

Contract propagation #9

pdaw opened this issue Mar 20, 2016 · 8 comments
Milestone

Comments

@pdaw
Copy link
Member

pdaw commented Mar 20, 2016

I wonder if we could inherit contacts from parent classes.

For example, we define an interface with common contract and all children (without own contract) would be obligated to fulfills parent's requirements.

I'm not sure if it's possible with goaop/framework.

@lisachenko
Copy link
Member

Sorry, I'm going to sleep now, can discuss tomorrow.

In short: this is doable in runtime, we just take our method, then recursively ask for prototype method or for parent class, then take our annotations and just run them all.

@pdaw
Copy link
Member Author

pdaw commented Mar 20, 2016

Cya. To read tommorow - I am wondering if goaop/framework could help us or we have to do it manually with pure reflection mechanism.

@lisachenko
Copy link
Member

@pdaw I think goaop can't help here, it just puts an interceptor in the source code, but logic of interceptors described in the concrete aspects, for example, in ContractCheckerAspect, etc.

PhpDeal otherwise, can handle this specific job pretty nice by looking at parent methods and querying annotations from them, so all contracts from the parent classes will be applied too. As DbC is development-only tool (it's recommended as a best practice, no contract checks in production mode), this reflection API shouldn't be a performance killer (can be pre-cached in array like this Class::method => array of contracts)

@pdaw
Copy link
Member Author

pdaw commented Mar 21, 2016

I get it, may you tag it as enhancement?

@pdaw
Copy link
Member Author

pdaw commented Mar 23, 2016

@lisachenko

I think it can works in two modes:

  1. Contract overrides parents' ones. Otherwise parents' contracts are applied.
  2. Contract does not override parents' contracts, so all contracts are executed.

It would be handled with some extra annotation, ex. @contract\Override. Default version may be the second one.

@lisachenko
Copy link
Member

H! There are rules for applying DbC contracts for inheritance (these rules are based on Liskov principle):

  1. Subclasses in an inheritance hierarchy are allowed to weaken preconditions (but not strengthen them)
  2. Subclasses in an inheritance hierarchy are allowed to strengthen postconditions and invariants (but not weaken them).

So, for all Ensure and Invariant annotations we MUST collect all parents annotations and check them. If we have some more postconditions in the current class, they should be verified as well. But we SHOULD check if the parent method defines exactly the same contract to execute it only once.

For Verify annotations we should take them only from the current class and run them, no checks for parent contracts. In this way we can give an ability to weaken them. But we SHOULD check special cases for all possible inheritDoc comments in our doc block.

@pdaw
Copy link
Member Author

pdaw commented Mar 24, 2016

@lisachenko

Thanks for your full and detailed answer :) I'll try to implement it in free time.

@lisachenko
Copy link
Member

Closed in #10, released in 0.4.0

@lisachenko lisachenko added this to the 0.4.0 milestone Apr 2, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants