Specification-Driven Development of an Executable Metamodel in Eiffel - PowerPoint PPT Presentation

About This Presentation
Title:

Specification-Driven Development of an Executable Metamodel in Eiffel

Description:

TDD uses tests as specifications that drive the development process. ... The fun case (multi-dispatch) was initially missed (a unit test failed) ... – PowerPoint PPT presentation

Number of Views:36
Avg rating:3.0/5.0
Slides: 15
Provided by: scie379
Category:

less

Transcript and Presenter's Notes

Title: Specification-Driven Development of an Executable Metamodel in Eiffel


1
Specification-Driven Development of an Executable
Metamodel in Eiffel
  • Richard Paige, Phil Brooke, and Jonathan Ostroff
  • paige_at_cs.york.ac.uk, phil.brooke_at_plymouth.ac.uk,
    jonathan_at_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.

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 Meyers
    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 xgt0
  • do -- your algorithm goes here, e.g.,
    Newton's method
  • ensure
  • (ResultResult - x).abs lt epsilon
  • epsilon old epsilon
  • end
  • epsilon DOUBLE -- accuracy
  • invariant
  • 0 lt epsilon and epsilon lt 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

10
Encoding Constraints in Eiffel
  • We used Eiffels 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((i1INHERITANCE)
    BOOLEAN do
  • Result closure.for_all((i2 INHERITANCE)
    BOOLEAN do
  • -- return true iff i1 and i2 do not form a
    cycle
  • Result not (i1.sourcei2.target and
  • i1.targeti2.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 classs 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 wed 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. Its 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 dont reduce the amount of tests that
    need to be written.
  • Its easy to underspecify contracts, or simply
    get them wrong.
  • Need tests to catch these errors.
Write a Comment
User Comments (0)
About PowerShow.com