EiffelBase2
Overview
EiffelBase2, currently under development, is a general-purpose data structures library for Eiffel. It is intended as the future replacement for the EiffelBase library ("Classic EiffelBase" in this document), which has for many years played a central role in Eiffel development.
Design goals
The design goals for EiffelBase2 are:
- Verifiability. The library is designed to allow proofs of correctness.
- Full contracts. Partly as a result of the verifiability goal, but also for clarity and documentation, the contracts associated with classes and features should describe the relevant semantics in its entirety.
- Simple and consistent hierarchy, in particular avoidance of descendant hiding and of "taxomania" (classes not representing a meaningful abstraction, unnecessary inheritance links).
- As in Classic EiffelBase, application of a systematic classification (a theory) of fundamental data structures.
- Full traversal mechanisms, based on external cursors (with internal cursors also provided when useful).
- Client-interface compatibility with corresponding classes in Classic EiffelBase, whenever it does not conflict with the preceding goals.
Design overview
A design decision that significantly influenced the architecture of the library is using external iterators to traverse containers as apposed to internal ones available in classic EiffelBase. In the design inspired by external iterators we found it natural to separate containers (with their measurements and modification means) from interfaces to access elements of containers, here called observers.
On the observer side we distinguish maps (with the defining property "accessing elements by unique keys") and iterators (providing linear traversal). An observer can be either used by a container (as a supplier) or inherited by it. The first case produces an external access mechanism and is useful when multiple instances of an observer for the same container can exist at the same time; the second case results in an internal acess mechanism and allows only one instance of an observer per container at a time. In the rest of the library maps are mostly inherited and iterators are mostly used, but this is not enforced by the design. For infinite sequences like RANDOM it makes sense to inherit from an iterator, because they cannot have more than one active iterator.
On the other side, a container is a finite storage of values. Containers are deliberately confined to finite structures and understood real, physical storage. Infinite structures, instead, are usually represented as functions or mechanisms that are external to a program. Most of the time we can only access their elements (not add or remove) and for this purpose we have observers: maps and iterators (the latter in the infinite case are called streams).
Containers may be classified based on different means of modification, but previous experience shows that a complete and clean classification here is impossible (there are two many kinds of modification, basically one per "concrete" data structure). So concrete data structures mostly just inherit directly from CONTAINER. There is one exception: SEQUENCE, which represents a sequence of values accessible by indices from a continuous interval. It serves as a common ancestor for ARRAY and LIST and factors out their common search and replacement mechanisms.
Below you can find the class diagram of EiffelBase2, split into two hierarchies (according to connectedness). The first one is a hierarchy of containers and maps. Note: dash-bordered ovals stand for classes that might be included in the library, but are not the first priority of the developers.
The second one is a hierarchy of streams and iterators.
Model-based contracts
Status and roadmap
Development of EiffelBase has started as a project at ETH Zurich; see the project page. Documentation and other material will soon be transferred to the present page.