Eiffel (programming language)

From Wikipedia, the free encyclopedia

Eiffel
Paradigm: object-oriented
Appeared in: 1986
Designed by: Bertrand Meyer
Developer: Bertrand Meyer & Eiffel Software
Typing discipline: static typing, strong typing
Major implementations: EiffelStudio, SmartEiffel, Visual Eiffel
Influenced by: Ada, Simula, Z
Influenced: Sather, Ruby, Java, C#, D

Eiffel is an ISO-standardized object-oriented programming language designed for extensibility, reusability, reliability and programmer productivity. Eiffel is used in academia as a language for teaching computer-programming principles, and in industry as a development platform. Industries that have adopted Eiffel include finance, aerospace, health care, and video games. Since 1985, many suppliers have developed Eiffel programming environments.

The design of the Eiffel language is closely connected with the Eiffel programming method. Both are based on a set of principles, including Design by contract, Command-query separation, Uniform access principle, Single choice principle, Open-closed principle, and Option-Operand separation.

Many concepts initially introduced by Eiffel have later found their way into other languages such as Java and C#, and Eiffel continues to try language-design ideas, particularly through the ECMA/ISO standardization process.

Contents

[edit] Overview

The key characteristics of the Eiffel language include:

  • Mechanisms supporting Design by contract (routine pre- and postconditions, class invariants), tightly integrated with the inheritance mechanism and other language constructs.
  • Object-oriented program structure, in which classes serve as the basic unit of decomposition.
  • Static typing.
  • Support for automatic memory management, typically implemented by garbage collection.
  • Central role of inheritance, including multiple inheritance and mechanisms to make inheritance safe (renaming, redefinition, "select", non-conforming inheritance).
  • A uniform type system handling both value and reference semantics, where all types including basic types such as INTEGER are based on classes.
  • Genericity, constrained and unconstrained.
  • "Agents" (objects wrapping computations, closely connected with closures and lambda calculus).
  • "Once" routines (evaluated only the first time around), for object sharing and decentralized initialization.
  • Keyword-based syntax ALGOL/Pascal tradition but separator-free (semicolon is optional); operator syntax available for routines.

[edit] Design goals

Eiffel emphasizes declarative statements over procedural code and attempts to eliminate the need for bookkeeping instructions.

Eiffel shuns coding tricks or coding techniques intended as optimization hints to the compiler. The aim is not only to make the code more readable, but also to allow programmers to concentrate on the important aspects of a program without getting bogged down in implementation details. Eiffel's simplicity is intended to promote simple, extensible, reusable and reliable answers to computing problems. Compilers provide extensive optimization techniques such as automatic inlining which remove part of the burden of optimization from the programmer, with the aim of producing extremely efficient code comparable to e.g. C++.

[edit] Background

Eiffel was originally developed by Eiffel Software, a company founded by Bertrand Meyer (originally called Interactive Software Engineering Inc. or ISE). Object-Oriented Software Construction contains a detailed treatment of the concepts and theory of object technology, which led to the design of Eiffel.[1]

The goal of the language, libraries, and programming methods is to create reliable, reusable software modules. Eiffel supports multiple inheritance, genericity, polymorphism, encapsulation, type-safe conversions, and parameter covariance. Its most important contribution to software engineering is Design by contract (DbC), in which assertions, preconditions, postconditions, and class invariants are used to assist in assuring program correctness without sacrificing efficiency.

Eiffel's design is based on object-oriented programming theory, with only minor influence of other paradigms or concern for support of legacy code. The language has formal support for abstract data types. Under Eiffel's design, a software text should be able to reproduce its design documentation from the text itself, using a formalized implementation of the "Abstract Data Type".

[edit] Implementations and environments

EiffelStudio is an integrated development environment available under both an open source and a commercial licenses. It offers an object-oriented environment for software engineering, using user-interface techniques such as pick-and-drop. EiffelEnvision is a plugin for Microsoft Visual Studio which allows users to edit, compile, and debug Eiffel apps from within the Microsoft Visual Studio IDE. EiffelStudio and EiffelEnvision are free for non-commercial use. Two open source implementations are available: SmartEiffel—the GNU implementation, based on an older version of the language—and Visual Eiffel.

Originally, the language Sather was based on Eiffel, but it has diverged, and now includes several functional programming features. The Apple Media Tool includes an Eiffel-based Apple Media Language.

The interractive teaching language Blue (programming language) is also heavily based on Eiffel, but development has since ceased in favour of BlueJ.

[edit] Specifications and standards

The Eiffel language definition is an international standard of ISO, the International Organization for Standardization. The standard was developed by ECMA International and its first version approved by ECMA on 21 June 2005 as ECMA standard 367, Eiffel: Analysis, Design and Implementation Language. The second edition was adopted by ECMA in June 2006 and in the same month by ISO (official publication by ISO occurred in November 2006). Its text can be found, and used free of charge, on the ECMA site[2]. The ISO version [3] has different formatting but identical text.

Eiffel Software and the Eiffel library developer Gobo have committed to implementing the standard; Eiffel Software's EiffelStudio 5.7 implements some of the major new mechanisms, in particular inline agents, assigner commands, bracket notation. The SmartEiffel team has turned away from this standard to create its own version of the language, which they believe to be closer to the original style of Eiffel. Object Tools has not to date expressed a position.

The standard cites the following as earlier Eiffel Language specifications:

  • Bertrand Meyer: Eiffel: The Language, Prentice Hall, second printing, 1992 (first printing: 1991)
  • Bertrand Meyer: Standard Eiffel (revision of preceding entry), ongoing, 1997-present, at Bertrand Meyer's ETL3 page, and
  • Bertrand Meyer: Object-Oriented Software Construction, Prentice Hall: first edition, 1988; second edition, 1997.

[edit] Syntax and semantics

[edit] Overall structure

An Eiffel "system" or "program" is a collection of classes. Above the level of classes, Eiffel defines cluster, which are essentially a group of classes, and possibly of subclusters (nested clusters). Clusters are not a syntactic language construct, but rather a standard organizational convention. Typically an Eiffel application will be organized with each class in a separate file, and each cluster in a directory containing class files. In this organization, subclusters are subdirectories. For example, under standard organizational and casing conventions, x.e might be the name of a file that defines a class called X.

A class contains features, which are similar to "members", "attributes" or "methods" in other object-oriented programming languages. A class also defines its invariants, and contains other properties, such as a "notes" section for documentation. Eiffel's standard data types, such as ARRAY are all themselves classes, and collections are modified and accessed via features rather than special syntax. Moreover, unlike some "impure" object-oriented languages like Java, Eiffel eschews "basic datatypes" outside of its class system.

Every system must have a class designated as "root", with one of its creation procedures designated as "root procedure". Executing a system consists of creating an instance of the root class and executing its root procedure. Generally, doing so creates new objects, calls new features, and so on.

Eiffel has six basic executable instructions: assignment; object creation; routine call; conditional; iteration; and choice. Eiffel's control structures are strict in enforcing structured programming: every block has exactly one entry and exactly one exit.

[edit] Scoping

Unlike many object-oriented languages, but like Smalltalk, Eiffel does not permit any assignment into fields of objects, except within the features of an object. Eiffel emphasizes information hiding and data abstraction, by requiring formal interfaces to data mutation. To put it in the language of other object-oriented programming languages, all Eiffel fields are "private", and "setters" are needed to modify values. An upshot of this is that "setters" can, and normally do, implement the invariants Eiffel provides syntax for.

[edit] "Hello, world!"

Conventionally, the look-and-feel of a programming language is given with a "Hello, world!" toy program. In Eiffel such a program might look like:

   class 
       HELLO_WORLD
   create
       make
   feature
      make
         do
            io.put_string ("Hello, world!")
            io.put_new_line
         end
   end

[edit] "Design by Contract"

The concept of Design by Contract is central to Eiffel. The mechanisms are tightly integrated with the language. Contracts guide redefinition of features in inheritance.

  • Routine precondition: The precondition may only be weakened by inheritance; any call that meets the requirements of the ancestor meets those of the descendant.
  • Routine postcondition: The postcondition can only be strengthened by inheritance; any result guaranteed by the ancestor is still provided by the descendant.
  • Class invariant

In addition, the language supports a "check instruction" (a kind of "assert") and loop invariants.

[edit] Features, commands, queries

The primary characteristic of a class is that it contains a set of features. As a class represents a set of run-time objects (its instances), a feature is an operation on these objects. Operations are of two kinds:

  • Queries, which give information about an instance.
  • Commands, which modify an instance.

This distinction is important to the Eiffel method. In particular:

  • Uniform Access Principle: from the outside, whether a query is an attribute (field in each object) or a function (algorithm) should not make any difference. For example a_vehicle.speed could be an attribute, accessed from the object's representation; or it could be computed by a function that divides distance by time. The notation is the same in both cases, so that it's easy to change representation without affecting the rest of the software.
  • Command-Query Separation Principle: Queries must not modify the instance. This is not a language rule but a methodological principle. So in good Eiffel style one does not find "get" functions that change something and return a result; instead there are commands (procedures) to change objects, and queries to obtain information about the object, resulting from preceding changes.

[edit] Overloading

A class in Eiffel is a mapping from feature names to features. Names can be reused in different classes, but always map to a specific feature within one class. Overloading in Eiffel is simply the mapping of the same name in different classes to different corresponding features. For example to have several behaviors for "+", depending on the class of the objects responding to the operator, a program can define several aliases, e.g.

  a + b  for a, b: INTEGER
  a + b  for a, b: REAL
  a + b  for a, b: VECTOR [INTEGER]

Eiffel, by design, does not allow argument overloading where a given class has multiple same-named feature, such as f (x: X) and f (y: Y), such as you might find in C++ or Haskell. Since operators are aliases for named features, this same design choice/limitation applies to operator overloading as to parametric polymorphism generally.

[edit] Genericity

Classes can be generic, to express that they are parameterized by types. Generic parameters appear in square brackets:

  class LIST [G] ...

G is known as a "formal generic parameter". (Eiffel reserves "argument" for routines, and uses "parameter" only for generic classes.) With such a declaration G represents within the class an arbitrary type; so a function can return a value of type G, and a routine can take an argument of that type:

  item: G do ... end
  put (x: G) do ... end

The LIST [INTEGER] and LIST [WORD] are "generic derivations" of this class. Permitted combinations(with n: INTEGER, w: WORD, il: LIST [INTEGER], wl: LIST [WORD]) are

  n := il.item
  wl.put (w)

INTEGER resp. WORD are the "actual generic parameters" in these generic derivations.

It is also possible to have 'constrained' formal parameters, for which the actual parameter must inherit from a given class, the "constraint". For example in

  class HASH_TABLE [G, KEY -> HASHABLE]

a derivation HASH_TABLE [INTEGER, STRING] is valid only if STRING inherits from HASHABLE (as it indeed does in typical Eiffel libraries). Within the class, having KEY constrained by HASHABLE means that for x: KEY it is possible to apply to x all the features of HASHABLE, as in x.hash_code.

[edit] Inheritance basics

To inherit from one or more others, a class will include a inherit clause at the beginning:

  class C inherit
     A
     B
  ... Rest of class declaration ...

The class may redefine (override) some or all of the inherited features. This must be explicitly announced at the beginning of the class through a redefine subclause of the inheritance clause, as in

  class C inherit
     A
        redefine f, g, h end
     B
        redefine u, v end

[edit] Deferred classes and features

Classes may be defined with deferred class rather than with class to indicate that the class may not be directly instantiated. Non-instantiatable classes are called abstract classes in some other object-oriented programming languages. In Eiffel parlance, only an "effective" class can be instantiated (it may be a descendent of a deferred class). A feature can also be deferred by using the deferred keyword in place of a do clause. If a class has any deferred features it must be declared as deferred; however, a class with no deferred features may nonetheless itself be deferred.

Deferred classes play some of the same role as interfaces in languages such as Java, though many object-oriented programming theorists believe interfaces are themselves largely an answer to Java's lack of multiple-inheritance (which Eiffel has).[specify]

[edit] Renaming

A class that inherits from one or more others gets all its features, by default under their original names. It may, however, change their names through rename clauses. This is required in the case of multiple inheritance if there are name clashes between inherited features; without renaming, the resulting class would violate the no-overloading principle noted above and hence would be invalid.

[edit] Tuples

Tuples types may be viewed as a simple form of class, providing only attributes and the corresponding "setter" procedure. A typical tuple type reads

  TUPLE [name: STRING; weight: REAL; date: DATE]

and could be use to describe a simple notion of birth record if a class is not needed. An instance of such a tuple is simply a sequence of values with the given types, given in brackets, such as

  ["Brigitte", 3.5, Last_night]

Components of such a tuple can be accessed as if the tuple tags were attributes of a class, for example if t has been assigned the above tuple then t.weight has value 3.5.

Thanks to the notion of assigner command (see below), dot notation can also be used to assign components of such a tuple, as in

  t.weight := t.weight + 0.5

The tuple tags are optional, so that it is also possible to write a tuple type as TUPLE [STRING, REAL, DATE]. (In some compilers this is the only form of tuple, as tags were introduced with the ECMA standard.)

The precise specification of e.g. TUPLE [A, B, C] is that it describes sequences of at least three elements, the first three being of types A, B, C respectively. As a result TUPLE [A, B, C] conforms to (may be assigned to) TUPLE [A, B], to TUPLE [A] and to TUPLE (without parameters), the topmost tuple type to which all tuple types conform.

[edit] Agents

Eiffel's "agent" mechanism wraps operations into objects. This mechanism can be used for iteration, event-driven programming, and other contexts in which it is useful to pass operations around the program structure. Other programming languages, especially ones that emphasize functional programming, allow a similar pattern using continuations, closures, or generators; Eiffel's agents emphasize the language's object-oriented paradigm, and use a syntax and semantics similar to code blocks in Smalltalk and Ruby.

For example, to execute the my_action block for each element of my_list, one would write:

  my_list.do_all (agent my_action)

To execute my_action only on elements satisfying my_condition, a limitation/filter can be added:

  my_list.do_if (agent my_action, agent my_condition)

In these examples, my_action and my_condition are routines. Prefixing them with agent yields an object that represents the corresponding routine with all its properties, in particular the ability to be called with the appropriate arguments. So if a represents that object (for example because a is the argument to do_all), the instruction

  a.call ([x])

will call the original routine with the argument x, as if we had directly called the original routine: my_action (x). Arguments to call are passed as a tuple, here [x].

It is possible to keep some arguments to an agent open and make others closed. The open arguments are passed as arguments to call: they are provided at the time of agent use. The closed arguments are provided at the time of agent definition. For example, if action2 has two arguments, the iteration

  my_list.do_all (agent action2 (?, y))

iterates action2 (x, y) for successive values of x, where the second arguments remained set to y. The question mark ? indicates an open argument; y is a closed argument of the agent. Note that the basic syntax agent f is a short hand for agent f (?, ?, ...) with all arguments open. It is also possible to make the target of an agent open through the notation {T}? where T is the type of the target.

The distinction between open and closed operands (operands = arguments + target) corresponds to the distinction between bound and free variables in lambda calculus. An agent expression such as action2 (?, y) with some operands closed and some open corresponds to a version of the original operation curried on the closed operands.

The agent mechanism has been recently generalized to allow defining an agent without reference to an existing routine (such as my_action, my_condition, action2), through inline agents as in

  my_list.do_all
     (agent (s: STRING)
        require
           not_void: s /= Void
        do
           s.append_character(',')
        ensure
           s.count = old s.count + 1
        end
     )

The inline agent passed here can have all the trappings of a normal routine, including precondition, postcondition, rescue clause (not used here), and a full signature. This avoids defining routines when all that's needed is a computation to be wrapped in an agent. This is useful in particular for contracts, as in an invariant clause that expresses that all elements of a list are positive:

  my_list.for_all (agent (x: INTEGER): BOOLEAN do Result := (x > 0) end)

The current agent mechanism leaves a possibility of run-time type error (if a routine with n arguments is passed to an agent expecting m arguments with m < n). This can be avoided by a run-time check through the precondition valid_arguments of call. Several proposals for a purely static correction of this problem are available, including a language change proposal by Ribet et al. [4].

[edit] Once routines

A routine's result can be cached using the once keyword in place of do. Non-first calls to a routine require no additional computation or resource allocation, but simply return a previously computed result. A common pattern for "once functions" is to provide shared objects; the first call will create the object, subsequent ones will return the reference to that object. The typical scheme is:

  shared_object: SOME_TYPE
     once
        create Result.make (args)
               -- This creates the object and returns a reference to it through Result
     end

The returned object—Result in the example—can itself be mutable, but its reference remains the same.

Often "once routines" perform a required initialization: multiple calls to a libraries can include a call to the initialization procedure, but only the first such call will perform the required actions. Using this pattern initialization can be decentralized, avoiding the need for a special initialization module. "Once routines" are similar in purpose and effect to the singleton pattern in many programming languages, and to the Borg pattern used in Python.

The ECMA specification allows variants of "once" (qualified by a keyword in parentheses, e.g. once (THREAD): once per process, once per thread, once per object. This is not, however, fully implemented yet by current compilers (typically, only PROCESS and THREAD).

[edit] Conversions

Eiffel provides a mechanism to allow conversions between various types. The mechanisms coexists with inheritance and complements it. To avoid any confusion between the two mechanisms, the design enforces the following principle:

(Conversion principle) A type may not both conform and convert to another.

For example NEWSPAPER may conform to PUBLICATION, but INTEGER converts to REAL (and does not inherit from it).

The conversion mechanism simply generalizes the ad hoc conversion rules (such as indeed between INTEGER and REAL) that exist in most programming languages, making them applicable to any type as long as the above principle is observed. For example a DATE class may be declared to convert to STRING; this makes it possible to create a string from a date simply through

  my_string := my_date

as a shortcut for using an explicit object creation with a conversion procedure:

  create my_string.make_from_date (my_date)

To make the first form possible as a synonym for the second, it suffices to list the creation procedure (constructor) make_from_date in a convert clause at the beginning of the class.

As another example, if there is such a conversion procedure listed from TUPLE [day: INTEGER; month: STRING; year: INTEGER], then one can directly assign a tuple to a date, causing the appropriate conversion, as in

     Bastille_day := [14, "July", 1789]

[edit] Exception handling

Exception handling in Eiffel is done at the routine level. If any operation fails in a routine the entire routine is considered as not having satisfied its "contract" and an error is produced. If the routine is not set up to handle the error the failure is propagated up to the routine that called it and the process repeats.

In Eiffel one defines an exception handler using the rescue keyword which defines a block of code to be executed upon failure. Using the retry keyword in the rescue section (the only section it is allowed to be used in) causes the routine to be executed again after making the changes specified. This allows the programmer to correct mistakes in the input data or to keep track of the number of attempts at executing the routine.

-- Connect to a server or give up after 10 attempts
  
  connect_to_server (server: SOCKET)
    require
      server /= Void and then server.address /= Void
    local
      attempts: INTEGER
    do
      server.connect
    rescue
      if attempts < 10 then
          attempts := attempts + 1
          retry
      end
    end
  

[edit] Concurrency

A number of networking and threading libraries are available, such as EiffelNet and EiffelThreads. A concurrency model for Eiffel, based on the concepts of Design by Contract, is SCOOP (software), or Simple Concurrent Object-Oriented Programming, not yet part of the official language definition but available as an add-on from ETH Zurich.

[edit] Operator and bracket syntax, assigner commands

Eiffel's view of computation is completely object-oriented in the sense that every operation is relative to an object, the "target". So for example an addition

 [1] a + b

is conceptually understood as if it were a function call

  [2] a.plus (b)

with target a, feature plus and argument b.

Of course [2] is the conventional syntax and usually preferred. Operator syntax makes it possible to use either form by declaring the feature (for example in INTEGER, but this applies to other basic classes and can be used in any other for which such an operator appropriate):

  plus alias "+" (other: INTEGER): INTEGER
        ... Normal function declaration...
        end

The range of operators that can be used as "alias" is quite broad; they include predefined operators such as "+" but also "free operators" made of non-alphanumeric symbols. This makes it possible to design special infix and prefix notations, for example in mathematics and physics applications.

Every class may in addition have one function aliased to "[]", the "bracket" operator, allowing the notation a [i, ...] as a synonym for a.f (i, ...) where f is the chosen function. This is particularly useful for container structures such as arrays, hash tables, lists etc. For example access to an element of a hash table with string keys can be written

  number := phone_book ["JILL SMITH"]

"Assigner commands" are a companion mechanism designed in the same spirit of allowing well-established, convenient notation reinterpreted in the framework of object-oriented programming. Assigner commands allow assignment-like syntax to call "setter" procedures. An assignment proper can never be of the form a.x := v as this violates information hiding; you have to go for a setter command (procedure). For example the hash table class can have the function and the procedure

  item alias "[]" (key: STRING): ELEMENT    [3]
        -- The element of key key
        -- ("Getter" query)
     do
        ...
     end
  
put(e: ELEMENT; key: STRING): ELEMENT -- Insert the element e, associating it with the key key. -- ("Setter" command) do ... end

Then to insert an element you have to use an explicit call to the setter command:

  [4] phone_book.put (New_person, "JILL SMITH")

It is possible to write this equivalently as

  [5] phone_book  ["JILL SMITH"] := New_person

(in the same way that phone_book ["JILL SMITH"] is a synonym for number := phone_book.item ("JILL SMITH")), provided the declaration of item now starts (replacement for [3]) with

  item alias "[]" (key: STRING): ELEMENT assign put

This declares put as the assigner command associated with item and, combined with the bracket alias, makes [5] legal and equivalent to [4]. (It could also be written, without taking advantage of the bracket, as phone_book.item ("JILL SMITH") := New_person.

[edit] Lexical and syntax properties

Eiffel is not case-sensitive. The tokens make, maKe and MAKE all denote the same identifier. See, however, the "style rules" below.

Comments are introduced by -- (two consecutive dashes) and extend to the end of the line.

The semicolon, as instruction separator, is optional. Most of the time the semicolon is just omitted, except to separate multiple instructions on a line. This results in less clutter on the program page.

There is no nesting of feature and class declarations. As a result the structure of an Eiffel class is simple: some class-level clauses (inheritance, invariant) and a succession of feature declarations, all at the same level.

It is customary to group features into separate "feature clauses" for more readability, with a standard set of basic feature tags appearing in a standard order, for example:

  class HASH_TABLE [ELEMENT, KEY -> HASHABLE] inherit
        TABLE [ELEMENT]
feature -- Initialization ... Declarations of initialization commands (creation procedures/constructors) ...
feature -- Access ... Declarations of non-boolean queries on the object state, e.g. item ...
feature -- Status report ... Declarations of boolean queries on the object state, e.g. is_empty ...
feature -- Element change ... Declarations of commands that change the structure, e.g. put ...
etc. end

In contrast to most curly bracket programming languages, Eiffel makes a clear distinction between expressions and instructions. This is in line with the Command-Query Separation principle of the Eiffel method.

[edit] Style conventions

Much of the documentation of Eiffel uses distinctive style conventions, designed to enforce a consistent look-and-feel. Some of these conventions apply to the code format itself, and others to the standard typographic rendering of Eiffel code in formats and publications where these conventions are possible.

While the language is case-insensitive, the style standards prescribe the use of all-capitals for class names (LIST), all-lower-case for feature names (make), and initial capitals for constants (Avogadro). The recommended style also suggests underscore to separate components of a multi-word identifier, as in average_temperature.

The specification of Eiffel includes guidelines for displaying software texts in typeset formats: keywords in bold, user-defined identifiers and constants are shown in italics, comments, operators, and punctuation marks in roman, with program text in blue as in the present article to distinguish it from explanatory text. For example, the "Hello, world!" program given above would be rendered as below in Eiffel documentation:

class 
    HELLO_WORLD
create
    make
feature
   make
      do
         io.put_string ("Hello, world!")
         io.put_new_line
      end
end

[edit] Interfaces to other tools and languages

Eiffel is a purely object-oriented language but provides an open architecture for interfacing with "external" software in any other programming language.

It is possible for example to program machine- and operating-system level operations in C. Eiffel provides a straightforward interface to C routines, including support for "inline C" (writing the body of an Eiffel routine in C, typically for short machine-level operations).

Although there is no direct connection between Eiffel and C, all of the current Eiffel compilers except one (Visual Eiffel) output C source code as an intermediate language, to submit to a C compiler, for optimizing and portability. On .NET, the EiffelStudio compiler directly generates CIL (Common Intermediate Language) code for the .NET virtual machine. The SmartEiffel compiler can also output Java bytecode.

[edit] References

  1. ^ Object-Oriented Software Construction, Second Edition, by Bertrand Meyer, Prentice Hall, 1997, ISBN 0-13-629155-4
  2. ^ ECMA International: Standard ECMA-367 —Eiffel: Analysis, Design and Programming Language 2nd edition (June 2006); available online at www.ecma-international.org/publications/standards/Ecma-367.htm
  3. ^ International Standards Organization: Standard ISO/IEC DIS 25436, available online at [1]
  4. ^ Philippe Ribet, Cyril Adrian, Olivier Zendra, Dominique Colnet: Conformance of agents in the Eiffel language, in Journal of Object Technology, vol. 3, no. 4, April 2004, Special issue: TOOLS USA 2003, pp. 125-143. Available on line from the JOT article page

[edit] External links