1 / 14

Specification-Driven Development of an Executable Metamodel in Eiffel

Richard Paige, Phil Brooke, and Jonathan Ostroff paige@cs.york.ac.uk , phil.brooke@plymouth.ac.uk , jonathan@cs.yorku.ca Department of Computer Science, University of York, UK. School of Computing, University of Plymouth, UK. Department of Computer Science, York University, Canada.

maylin
Télécharger la présentation

Specification-Driven Development of an Executable Metamodel in Eiffel

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Richard Paige, Phil Brooke, and Jonathan Ostroff paige@cs.york.ac.uk, phil.brooke@plymouth.ac.uk, jonathan@cs.yorku.ca Department of Computer Science, University of York, UK. School of Computing, University of Plymouth, UK. Department of Computer Science, York University, Canada. Specification-Driven Development of an Executable Metamodel in Eiffel

  2. Motivation • Test-driven development (TDD) due to Beck is increasingly popular for building systems with reliability and maintainability requirements. • Three steps: • Write a test (which will fail). • Write enough code to make the test pass. • Refactor the code to eliminate redundancies and design flaws. • TDD uses tests as specifications that drive the development process. • Two main limitations: code-based only; and tests have expressiveness limitations. • Despite these limitations, we claim that TDD could be useful for building metamodels, which are systems with substantial reliability and maintainability requirements. • But how do we deal with the above limitations?

  3. Specification-Driven Design • A model-driven extension of TDD. • With this approach, models (with contracts) and tests can be used to drive the design process. • The rest of the presentation: • A very short overview of SDD. • An overview of its application in building an executable metamodel in Eiffel. • The key idea: in SDD for metamodeling, a test is an encoding of a model (in Eiffel). • Running the test automatically checks the model against the (partial, incomplete) metamodel. • So the development process also gives us a framework for fully automatic conformance checking of models against metamodels.

  4. SDD • SDD is an integration of TDD and Meyer’s Design-by-Contract (DbC). • Start anywhere - writing tests, contracts, etc. • Emphasis is always on producing compilable and executable code. • Some tests (collaborative specifications) are scenarios.

  5. Design-by-Contract • Annotate classes with properties, and methods of classes with pre/postconditions. • These properties are the best form of documentation: they execute with the code, and are guaranteed to be consistent with the code. • Example of a class in Eiffel class MATH feature square_root(x: DOUBLE): DOUBLE is require x>=0 do -- your algorithm goes here, e.g., Newton's method ensure (Result*Result - x).abs <= epsilon; epsilon = old epsilon end epsilon: DOUBLE -- accuracy invariant 0 < epsilon and epsilon <= 0.001 end -- MATH

  6. Some Observations about SDD • Though one can start development with writing contracts, there are reasons to prefer writing tests first. • Closure: a unit test gives you a clear stopping point: write enough code to get it to work. Contracts may allow unnecessary design. • Collaborative specification-friendly: tests can formalise instances of collaborations more easily. Consider LIFO property of stacks -- difficult to specify using contracts, easy using tests. • In summary: • Contracts are good for fleshing out the design while making assumptions explicit. • Contracts spell out assumptions more completely, and often more concisely, than unit tests. • Tests are good for writing collaborative specifications, and as such are more likely to be used early in development.

  7. SDD of a Metamodel in Eiffel • The metamodel is equivalent to a subset of UML, consisting of class and collaboration diagrams. • The class diagrams include an OCL-like contract language for pre/post/invariants. • From this, we automatically generated Eiffel class stubs. • Methods were extended with simple preconditions to ensure non-NULL arguments.

  8. Writing Acceptance Tests • The SDD process continued by writing acceptance tests. • One test per metamodel well-formedness constraint. • Tests took the form of simple Eiffel programs that encoded models that either satisfied or invalidated constraints. • e.g., a test generating a model with an inheritance cycle, a test generating a model with clashes in a namespace. • Constraints were prioritised based on complexity and our opinion of how essential it was to capture immediately. • e.g., constraint ensuring valid method calls in assertions was postponed for three iterations (existing tools could handle it initially). • e.g., cycle-free property for aggregation was first iteration since it involved constraints on graphical syntax.

  9. Example: Model Encoding Test class ACCEPTANCE_TEST inherit UNIT_TEST creation make feature {ANY} no_aggregation_cycles: BOOLEAN is local a, b, c: E_CLASS; c_to_a, a_to_b, b_to_c: AGGREGATION; m: MODEL do create a.make("A"); create b.make("B"); create c.make("C"); create c_to_a; create a_to_b; create b_to_c; create m.make; ... c_to_a.set_source(c); c_to_a.set_target(a); b_to_c.set_source(b); b_to_c.set_target(c); a_to_b.set_source(a); a_to_b.set_target(b); ... m.prepare Result := true end make is do make_test; add_violation_test( agent no_aggregation_cycles ); to_html("accept.html") end end

  10. Encoding Constraints in Eiffel • We used Eiffel’s declarative specification technique - agents - to capture constraints. • This promotes understandability, readability, and direct mapping from OCL/OCL-like constraints to code. • Example: no_inheritance_cycles: BOOLEAN is do Result := closure.for_all((i1:INHERITANCE): BOOLEAN do Result := closure.for_all((i2: INHERITANCE): BOOLEAN do -- return true iff i1 and i2 do not form a cycle Result := not (i1.source=i2.target and i1.target=i2.source) end) end) end • Clauses like the above are added to class invariants, to be checked when unit tests are run. • Each constraint is implemented within the SDD process.

  11. Gaps between Tests and Code • Occasionally the gap between the unit test (capturing a model) and the agent-based code needed was substantial. • e.g., checking that method calls were legitimate according to a class’s information hiding policy. • The simple case (single-dispatch) was straightforward to test and implement. • The fun case (multi-dispatch) was initially missed (a unit test failed). • Added additional agent code, which duplicated much of the original agent code for single dispatch. • Refactored this.

  12. Some Observations • Useful approach. • We emphasised the TDD parts of SDD. • Contracts were predominantly for guarding routine calls (i.e., preconditions) and for capturing invariants. • Sometimes contracts got very complex, e.g., for checking covariant overriding. • In this case we wrote a unit test with a simple example of covariance overriding, and refactored the agent code. • This was much simpler because we could use sequencing to capture the well-formedness condition. • Generally, minimal class-level refactoring was done; we’d need this if we added new views. • Deliverable: a testing suite as application evidence for correctness of the metamodel.

  13. Conclusions and Future Work • Fast, reliable way to build executable metamodels. • Useful to be able to switch between testing and modeling. • Side-effect: we can fully automatically check models for conformance to the metamodel. • Further work: • Improving support for encoding contracts within the metamodel. It’s not easy to use right now. • Adding a state chart view. • Additional metamodels, particularly MOF.

  14. Conclusions • Contracts and tests both make useful forms of specification. • They are complementary and can be used synergistically. • Contracts are good at making design decisions explicit (but be sure to keep these in your code). • Tests can express collaborations more easily, and appear to be more useful early in the design process. • Contracts don’t reduce the amount of tests that need to be written. • It’s easy to underspecify contracts, or simply get them wrong. • Need tests to catch these errors.

More Related