created 20.11

git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@2267 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
eifops
2020-12-04 15:34:39 +00:00
parent 0f1156d9cc
commit 5049d0d511
2944 changed files with 62467 additions and 0 deletions

View File

@@ -0,0 +1,155 @@
[[Property:modification_date|Fri, 04 Jan 2019 15:06:26 GMT]]
[[Property:publication_date|Thu, 03 Jan 2019 18:00:43 GMT]]
[[Property:uuid|146E241E-C367-4F16-9CCE-6F11E5F7860A]]
[[Property:weight|1]]
[[Property:title|Eiffel Code Comments]]
==Comment Mark Up ==
The Eiffel compiler and EiffelStudio's code browsing tools support a special, light-weight mark up in comments and strings for referencing classes and features. EiffelStudio's code browsing tools use this mark up to better facilitate code navigation and browsing. In addition, marked up comments and strings will be examined and altered when performing a class or feature ''rename'' refactoring.
===Syntax===
The syntax for marking up classes and features is very compact, to ensure retained legibility. You'll see no need for XML or other types of verbose mark up found in other languages, which can impede the comment's very nature as a quick reference.
To mark up a class reference, surround the class name in an open (` { `) and matching closing (` } `) brace:
<e>
-- See {DEBUG_OUTPUT} for more information.
</e>
To mark up a feature reference, implemented in the same class or parent, surround the name with two single back quotes (`` `...` ``):
<e>
-- See `debug_output` for more information.
</e>
The earlier convention, which you will still find in much existing code, used a single back quote for opening and a matching normal quote for closing, as in
<e>
-- See `debug_output' for more information.
</e>
The new convention, with back quotes both for opening and for closing, is the recommended one.
In the case where a reference to a feature is not accessible to the containing class directly, use a combination of the class reference mark up and a feature name, ''sans'' quotation marks:
<e>
-- See {DEBUG_OUTPUT}.debug_output for more information.
</e>
The rules that apply for comments, as described above, can also be utilized in any manifest or verbatim string:
<e>
note
description: "Augments searching facilities of {STRING_8}"
</e>
==Precursor Comments==
{{Version|6.2}}
Precursor comments declarations are a new mechanism added to EiffelStudio 6.2 to replicate a parent feature declaration's comments in the redefined/effective feature. The purpose of the mechanism is to reduce comment duplication, ease comment maintenance and facilitate augmentation.
For the purpose of demonstration, take the following deferred interface:
<e>
deferred class
BASE
feature -- Query
test (a_arg: INTEGER): BOOLEAN
-- Comments for a feature.
--
-- `a_arg`: An integer value.
-- `Result`: Could be True or False.
deferred
end
end
</e>
And effective implementation of it:
<e>
class
TEST
inherit
BASE
feature -- Query
test (a_arg: INTEGER): BOOLEAN
-- <Precursor>
do
end
end
</e>
<e>TEST</e> instead of replicating the comment makes use of the precursor comment declaration (<e>-- <Precursor></e>), which supporting code browsing tool will expand to show the precursor feature's contracts. The declaration is optional but is only supported for existing code out there that do not have comments due to lax implementation. Even though optional, it is strongly recommended that you use <e>-- <Precursor></e> comment declaration, as it indicates to any reader the feature is a redefinition or effective implementation of a parent feature declaration.
=== Comment Augmentation ===
The precursor comments declaration also supports augmentation. All a comment author has to do is to write additional comments before and/or after the precursor comment declaration. As a requirement, the precursor comment declaration must appear on a separate line for no other purpose except for clarity. Failure to do so will results in the rendering of the comments as they are declared in the feature, i.e. with <e>-- <Precursor></e> as is.
<e>
test (a_arg: INTEGER): BOOLEAN
-- Comments before the original comments from {BASE}.
--
-- <Precursor>
--
-- Some additional comments.
do
end
</e>
Using the code browsing facilities of [[EiffelStudio]] the reader will be presented with an expanded comment, for the effective version of feature <e>test</e>, that now read
<e>
-- Comments before the original comments from {BASE}.
--
-- Comments for a feature.
--
-- `a_arg`: An integer value.
-- `Result`: Could be True or False.
--
-- Some additional comments.
</e>
For clarity it is a good idea to separate the agumented comments from the precursor comment declaration. Using the same example above but removing the one line spacing above and below the precursor comment declaration would results in the following, less readable comment:
<e>
-- Comments before the original comments from {BASE}.
-- Comments for a feature.
--
-- `a_arg`: An integer value.
-- `Result`: Could be True or False.
-- Some additional comments.
</e>
However, that said, it is pure discretion to use additional spacing or not. Some situation do not call for, other do and some might (when the original comment changes.)
=== Multiple Redefinitions and Selection ===
With Eiffel supporting multiple inheritance, a scenario will arise where two inherited redefine features are joined in a descendant.
By default the precursor comment declaration is replaced by the first located inherited feature comment, which may cause documentation irregularities. Because precursor comments are not signification to compilation they are not checked during compilation, such as is the way with the use of <e>Precursor</e>, resulting a compile time error when not selecting the parent class to call into. This can cause documentation irregularities because there is no guarantee that they feature comments viewed one project will be the same in another.
To facilitate correct documentation the precursor comment declaration can use an optional select clause, just like using <e>Precursor</e> in the Eiffel code.
<e>
f (a_arg: INTEGER): BOOLEAN
-- <Precursor {BASE}>
do
end
</e>
This will have exactly the same effect as using <e>-- <Precursor></e> when <e>f</e> is made effective/redefined from a single parent. However, when making effective/redefining from multiple parents then comments will come from the parent class declaration in <e>BASE</e>.
Again, because precursor comments do not affect compilation they are not checked at compile time. Specifying an incorrect class will yield a warning message in [[EiffelStudio]]'s code browsing tools, to the effect:
<e>
-- Unable to retrieve the comments from redefinition of {CLASS_NAME}.
</e>
=== Library Documentation Generation ===
Precursor comments are supported in all code browsing/documentation facilities, whether is be the integrated [[Contract Viewer]], the [[Feature Relation Tool]] or the Eiffel documentation generation facilities. Using <e>-- <Precursor></e> will ensure the comments are brought up from a parent declaration.

View File

@@ -0,0 +1,93 @@
[[Property:modification_date|Mon, 03 Dec 2018 10:00:43 GMT]]
[[Property:publication_date|Tue, 30 Oct 2018 14:56:21 GMT]]
[[Property:uuid|0CD0A1B2-42F8-48E0-B419-61B4DC076C1B]]
[[Property:weight|2]]
[[Property:title|Eiffel Coding Standard]]
==Language consideration==
* Do not put a blank line between
:* '''create''' and creation instructions
:* '''inherit''' and parent clauses
* Do not use assertion clauses without tag names.
A sample of proper formatting of code:
<e>note
description: "Descr...."
date: "$date: $"
class A
inherit
B
rename
f as g
end
create
make
feature {NONE} -- Initialization
make (a: INTEGER)
-- Initialize Current with `a`.
do
end
invariant
a_positive: a > 0
end</e>
==Style==
* If instructions:
<e>if expr1 then
...
elseif expr2 then
...
else
...
end</e>
If expressions are very long, break them on conjunctions as in:
<e>if
expr1 and then
expr2
then
...
end</e>
* Loop instructions:
<e>from
...
until
...
loop
...
end</e>
* Inspect instructions:
<e>inspect expr
when val1 then ....
else
...
end</e>
or
<e>inspect
expr
when val1 then
...
else
...
end</e>
* For punctuation, we always have
** a space before, and no after `(`
** no space before, and space after `)` `,` `:` or `;`
<e>require
a_tag: query (a, b, c) or other_query (c, d)
local
i: INTEGER; j: INTEGER
</e>

View File

@@ -0,0 +1,236 @@
[[Property:uuid|FF8DA311-55E5-4314-8B0C-AADB4645E686]]
[[Property:weight|3]]
[[Property:title|Local Declaration Guidelines]]
Local declaration style guidelines for contributing to the Eiffel Software code repository.
== Feature Arguments ==
Feature arguments should begin with the prefix ''<e>a_</e>'' and nothing more. The prefix ''<e>a_</e>'' represent a contraction of the word ''argument'' and does not represent the singular inflection - a ''noun'' - Therefore it is '''not''' valid to utilize ''an'' when the suffixed argument word begins with a vowel. The following is a correct usage:
<e>
perform (a_string: STRING; a_integer: STRING): CHARACTER
-- An example using routine argument variable names.
do
end
</e>
Here, the second argument ''<e>a_integer</e>'', is not considered ''A Integer'' but ''The Argument Integer'', hence the use if <e>a_</e> instead of ''<e>_an_</e>''.
=== Indexing Routine Argument Variable Names ===
In rare cases there is a need to use the same name on a routine's arguments, which of course no useful language would allow. Instead a slight form of indexing needs to be applied. In this case the use of ''<e>other</e>'' embedded in the variable name would suffice for most cases.
<e>
compare_strings (a_string: READABLE_STRING_GENERAL; a_other_string: like a_string): INTEGER_8
-- An example using 'other' to index the second routine argument name
do
...
end
</e>
=== In-line Agent Routine Arguments ===
When working with an in-line agent, to prevent conflicts with the enclosing routine's arguments, the prefix ''<e>ia_</e>'' should be used. The same rules regarding English language rules apply here as they do to routine arguments. The ''<e>ia_</e>'' prefix represents an ''In-line Argument''.
<e>
perform (a_string: STRING; a_integer: STRING)
-- An example using in-line agent argument variable names.
do
process (agent (ia_string: STRING; ia_integer: INTEGER)
do
...
end (a_string, a_integer))
end
</e>
==== Nested In-line Agent Routine Arguments ====
Although rare, a nested in-line agents need exists. When dealing with nested in-line agent routine argument names the prefix should contain the nested index, with the container in-line agent using either a ''1'' or no index in the prefix names. First/Top-level in-line agents (those that are not nested) can use the aforementioned ''<e>ia_</e>'' prefix or use ''<e>i1a_</e>'', the former being preferred. A second-level (first nested level) in-line agent should use the prefix ''<e>i2a_</e>'', third-level ''<e>i3a_</e>'' and so forth.
<e>
perform (a_string: STRING; a_integer: STRING)
-- An example using in-line agent argument variable names.
do
process (agent (ia_string: STRING; ia_integer: INTEGER)
do
-- An example of an nested, in-line agent
process (agent (i2a_string: STRING; i2a_integer: INTEGER)
do
....
end (ia_string.as_lower, ia_integer)
end (a_string, a_integer))
end
</e>
== Local Declarations ==
Routine local declaration should also be prefixed to prevent potential conflicts between routine arguments or class attributes. The prefix ''<e>l_</e>'' is typically used for variable moniker names longer than two character. There are other exceptions, these are discussed below.
=== Well Known Variable Names ===
Indexing/counter variables, as used in iteration loops, should not use a local prefix and should be terse. The variable ''<e>i</e>'' should be use to indicate it is an index variable. Additional index variables should follow alphabetically from ''<e>i</e>'' onwards.
Generally, paired with an indexing/counter variable, a stopping condition count or number-of-items variable is also used. There are two conventions used for this, generally used interchangeably; A count will use the same rules for local declarations and be called ''<e>l_count</e>'', a number-of-items variable will use a well-known contracted variable name '<e>nb</e>''.
<e>
perform (a_array: ARRAY [INTEGER])
-- An example using index and number-of-items local variable names.
local
i, nb: INTEGER
do
from
i := a_array.lower
nb := a_array.upper
until
i > nb
loop
...
i := i + 1
end
end
</e>
The case will commonly arise when multiple counters/number-of-items variables need to be used. In such cases the counter/number-of-items variable should be suffixed with the associated indexing/counter variable name. This is akin to [http://en.wikipedia.org/wiki/BASIC BASIC]'s <code>NEXT x</code> instruction:
<e>
perform (a_array: ARRAY [ARRAY [INTEGER]])
-- An example using multiple index and number-of-items local variable names.
local
l_sub_array: ARRAY [INTEGER]
i, nb_i: INTEGER
j, nb_j: INTEGER
do
from
i := a_array.lower
nb_i := a_array.upper
until
i > nb_i
loop
l_item := a_array[i]
if l_item /= Void then
from
j := l_item.lower
nb_j := l_item.upper
until
j > nb_j
loop
...
j := j + 1
end
end
i := i + 1
end
end
</e>
==== Other Well-Known Names ====
There are a number of other well know and simpler to use local variable names:
* ''<e>c</e>'' for any type of character.
* ''<e>e</e>'' for any type of exception (descendant of EXCEPTION).
* ''<e>s</e>'' for any type of string (descendant of READABLE_STRING_GENERAL).
* ''<e>uc</e>'' for a Unicode character.
* ''<e>us</e>'' for a Unicode string (descendant of READABLE_STRING_32).
* ''<e>nb</e>'' for a number or count of elements.
==== Rescue Clauses ====
When adding a rescue clause with a retry a state variable, typically used to determine if a <e>retry</e> has been performed, there is no need to use a local declaration prefix. In fact, it's recommended there is no prefix. Instead just use a variable named ''<e>retried</e>'':
<e>
perform
-- An example using a rescue/retry local variable name.
local
retried: BOOLEAN
do
if not retried then
...
end
rescue
retried := True
retry
end
</e>
=== Object Tests ===
Object test locals obey the same rules and other standard local declarations, that it, prefixing a variable moniker with ''<e>l_</e>''. However, due to the current scoping rules of object-tests, where no object test local may be reused, extraneous guidelines need to be defined.
<e>
close
-- An example using object-test scoped local variable names.
do
if attached {DISPOSABLE_I} Current as l_disposable then
l_disposable.dispose
end
end
</e>
==== In Contracts ====
Object tests may need to be defined in contracts, especially when projects/libraries are configured to use Void-Safe compilation checks. To prevent variable name conflicts from arising a secondary prefix should be used to define an object-test local. Again using ''<e>l_</e>'' but this time prefixed with the first character of the enclosing assertion clause. Such rules would dictated the following prefixes to be used in object-tests, for assertion clauses:
* ''<e>rl_</e>'' for <e>require</e>
* ''<e>el_</e>'' for <e>ensure</e>
* ''<e>cl_</e>'' for <e>check</e>
* ''<e>ll_</e>'' for <e>loop</e>
* ''<e>il_</e>'' for loop <e>invariant</e>
* ''<e>vl_</e>'' for loop <e>variant</e>
<e>
close
-- An example using object-test scoped local variable names in contracts.
require
is_interface_usable: attached {USABLE_I} Current as rl_usable implies rl_usable.is_interface_usable
do
...
ensure
not_is_interface_usable: attached {USABLE_I} Current as el_usable implies not el_usable.is_interface_usable
end
</e>
No prefix, other than ''<e>l_</e>'' is needed for class invariants because no conflicts in variable name reuse exist in an invariant scope.
=== In-line Agents ===
There is no real preferred convention for local declaration inside in-line agents and the ''<e>l_</e>'' prefix should be used if possible. However, for clarity this cannot always be such the case. When such as scenario arises the use of ''<e>il_</e>'' (in-line local) is preferred. It is recommended that all locals utilize the same prefix and '''not''' mix ''<e>l_</e>'' and <e>il_</e>''!
<e>
l_action := agent (ia_string: READABLE_STRING_GENERAL)
local
il_i, il_count: INTEGER
do
....
end
</e>
Notice that even well-known local declaration names are prefixed, this is to avoid conflicts with the containing routine or in-line agent as well as providing consistency in the naming of local variables.
With nested in-line agents use the same name index injection guideline, placing the nested index after the initial ''<e>i</e>'' prefix. For a second level in-line agent, this would be ''<e>i2l_</e>''.
== Indexing Variable Names ==
There will be times when variable names clash with one another and there is no choice but to apply the last-stop effort to naturally indexed variable names to suit. This last-stop effort is really a last-stop. Other attempts should be made to create unique variable names before applying natural indexing.
Natural indexing concerns itself with suffixing variables with a sequential natural index. The only exception is the first local declaration which may or may not have the primary index suffix ''<e>_1</e>''. To better illustrate, the following code examples are both valid uses of natural indexing:
<e>
perform
-- An example of using natural sequential indexes to avoid variable name clashes.
local
l_item_1: ITEM
l_item_2: ITEM
l_item_3: ITEM
do
...
end
</e>
or
<e>
perform
-- An example with the first index elided, which is also valid.
local
l_item: ITEM
l_item_2: ITEM
l_item_3: ITEM
do
...
end
</e>
If local declaration have to be indexed when first writing the code then it is far better to be explicit and use a natural sequential index for all similar local declaration (the former example). The latter example is valid and would exist when modifying existing code. There is no hard or fast rule here, each is valid as long as the indexes are sequential.
The examples apply to all variable declaration, not just local declarations.

View File

@@ -0,0 +1,766 @@
[[Property:uuid|46FFB0ED-CE10-4CA5-8F10-5E1D0AB6EE46]]
[[Property:weight|4]]
[[Property:title|Style Guidelines]]
Style Guidelines that EiffelStudio developers should use and are not intended or suggestions for developing code with the Eiffel language. The guidelines are to promote consistency in API design, making EiffelStudio's code base more readable to all.
==Status of this page==
[I am starting this page by copy-pasting from existing references. It will be edited and cleaned up later on.[[User:Bertrand Meyer|Bertrand Meyer]] 12:35, 22 May 2008 (PDT)
=From ''Object-Oriented Software Construction''=
Implementing the object-oriented method requires paying attention to many details of style, which a less ambitious approach might consider trifles.
==COSMETICS MATTERS!==
Although the rules appearing hereafter are not as fundamental as the principles of object-oriented software construction covered in earlier chapters, it would be foolish to dismiss them as just “cosmetics”. Good software is good in the large and in the small, in its high-level architecture and in its low-level details. True, quality in the details does not guarantee quality of the whole; but sloppiness in the details usually indicates that something more serious is wrong too. (If you cannot get the cosmetics right, why should your customers believe that you can master the truly difficult aspects?) A serious engineering process requires doing everything right: the grandiose and the mundane.
So you should not neglect the relevance of such seemingly humble details as text layout and choice of names. True, it may seem surprising to move on, without lowering our level of attention, from the mathematical notion of sufficient completeness in formal specifications (in the chapter on abstract data types) to whether a semicolon should be preceded by a space (in the present chapter). The explanation is simply that both issues deserve our care, in the same way that when you write quality O-O software both the design and the realization will require your attention.
We can take a cue from the notion of style in its literary sense. Although the first determinant of good writing is the authors basic ability to tell a story and devise a coherent structure, no text is successful until everything works: every paragraph, every sentence and every word.
===Applying the rules in practice===
Some of the rules of this chapter can be checked or, better yet, enforced from the start by software tools. Tools will not do everything, however, and there is no substitute for care in writing every piece of the software.
There is often a temptation to postpone the application of the rules, writing things casually at first and thinking “I will clean up everything later on; I do not even know how much of this will eventually be discarded”. This is not the recommended way. Once you get used to the rules, they do not add any significant delay to the initial writing of the software; even without special tools, it is always more costly to fix the text later than to write it properly from the start. And given the pressure on software developers, there is ever a risk that you will forget or not find the time to clean things up. Then someone who is asked later to take up your work will waste more time than it would have cost you to write the proper header comments, devise the right feature names, apply the proper layout. That someone may be you.
===Terseness and explicitness===
Software styles have oscillated between the terse and the verbose. In programming languages, the two extremes are perhaps APL and Cobol. The contrast between the Fortran-C-C++ line and the Algol-Pascal-Ada tradition — not just the languages themselves, but the styles they have bred — is almost as stark.
What matters for us is clarity and, more generally, quality. Extreme forms of terseness and verbosity can both work against these goals. Cryptic C programs are unfortunately not limited to the famous “obfuscated C” and “Obfuscated C++” contests; but the almost equally famous DIVIDE DAYS BY 7 GIVING WEEKS of Cobol is a waste of everyones attention.
The style that follows from this chapters rules is a particular mix of Algol-like explicitness (although not, it is hoped, verbosity) and telegram-style terseness. It never begrudges keystrokes, even lines, when they truly help make the software readable; for example, you will find rules that enjoin using clear identifiers based on full words, not abbreviations, as it is foolish to save a few letters by calling a feature disp (ambiguous) rather than display (clear and precise), or a class ACCNT (unpronounceable) rather than ACCOUNT. There is no tax on keystrokes. But at the same time when it comes to eliminating waste and unneeded redundancies the rules below are as pitiless as the recommendations of a General Accounting Office Special Commission on Improving Government. They limit header comments to indispensable words, getting rid of all the non-essential “the” and other such amenities; they proscribe over-qualification of feature names (as in account_balance in a class ACCOUNT, where balance is perfectly sufficient); against dominant mores, they permit the grouping of related components of a complex construct on a single line, as in from i := 1 invariant i <= n until i = n loop; and so on.
This combination of terseness and explicitness is what you should seek in your own texts. Do not waste space, as exaggerated size will in the end mean exaggerated complexity; but do not hesitate to use space when it is necessary to enhance clarity.
Also remember, if like many people you are concerned about how much smaller the text of an object-oriented implementation will be than the text of a comparable C, Pascal, Ada or Fortran program, that the only interesting answer will appear at the level of a significant system or subsystem. If you express a basic algorithm — at the level of Quicksort, say, or Euclids algorithm — in C and in the notation of this book, expect the O-O version to be at least as large. In many cases, if you apply the principles thoroughly, it will be larger, since it will include assertions and more type information. Yet in ISEs experience of looking at medium-scale systems we have sometimes found (without being able to give a general law, as the circumstances vary considerably) the object-oriented solution to be several times smaller. Why? This is not due to terseness at the “micro” level but to systemwide application of the architectural techniques of the O-O method:
Genericity is one of the key factors. We have found C programs that repeated essentially the same C code many times to handle different types. With a generic class — or for that matter a generic Ada package — you immediately get rid of that redundancy. It is disturbing in this respect to see that Java, a recent O-O language based on C, does not support genericity.
Inheritance is also fundamental in gathering commonalities and removing duplications.
Dynamic binding replaces many complex decision structures by much shorter calls.
Assertions and the associated idea of Design by Contract avoid redundant error checking, a principal source of bloat.
The exception mechanism gets rid of some error code.
If you are concerned with source size, make sure to concentrate on these architectural aspects. You should also be terse in expressing algorithms, but never skimp on keystrokes at the expense of clarity.
===The role of convention===
Most rules define a single permissible form, with no variants. The few exceptions include font use, which is governed by external considerations (what looks good in a book may not be visible on overhead transparencies), and semicolons, for which there exist two opposite schools with equally forceful arguments (although we will have a few universal rules anyway). In all other cases, in line with the introductory methodology chapters exhortations against wishy-washiness, the rules leave about as much room to doubt as a past due reminder from the Internal Revenue Service.
The rules are rooted in a careful analysis of what works and what works less well, resulting from many years of observation; some of the rationale will appear in the discussion. Even so, some rules may appear arbitrary at first, and indeed in a few cases the decision is a matter of taste, so that reasonable persons working from the same assumptions may disagree. If you object to one of the recommended conventions, you should define your own, provided you explain it in detail and document it explicitly; but do think carefully before making such a decision, so obvious are the advantages of abiding by a universal set of rules that have been systematically applied to thousands of classes over more than ten years, and that many people know and understand.
As noted in an earlier chapter (in the more general context of design principles), many of the style rules were originally developed for libraries, and then found their way into ordinary software development. In object technology, of course, all software is developed under the assumption that even if it is not reusable yet it might eventually be made reusable, so it is natural to apply the same style rules right from the start.
===Self-practice===
Like the design rules of the preceding chapters, the style rules which follow have been carefully applied to the many examples of this book. The reasons are obvious: one should practice what one preaches; and, more fundamentally, the rules do support clarity of thought and expression, which can only be good for a detailed presentation of the object-oriented method.
The only exceptions are a few occasional departures from the rules on software text layout. These rules do not hesitate to spread texts over many lines, for example by requiring that every assertion clause have its own label. Lines are not a scarce resource on computer screens; it has been observed that with the computer age we are reversing the direction of the next-to-last revolution in written communication, the switch from papyrus rolls to page-structured books. But this text is definitely a book, structured into pages, and a constant application of the layout-related rules would have made it even bigger than it is.
The cases of self-dispensation affect only two or three layout-related rules, and will be noted in their presentation below. Any exception only occurs after the first few examples of a construct in the book have applied the rules scrupulously.
Such exceptions are only justified for a paper presentation. Actual software texts should apply the rules literally.
===Discipline and creativity===
It would be a mistake to protest against the rules of this chapter (and others) on the grounds that they limit developer creativity. A consistent style favors rather than hampers creativity by channeling it to where it matters. A large part of the effort of producing software is spent reading existing software and making others read what is being written. Individual vagaries benefit no one; common conventions help everyone.
Some of the software engineering literature of the nineteen-seventies propounded the idea of “egoless programming”: developing software so that it does not reflect anything of its authors personality, thereby making developers interchangeable. Applied to system design, this goal is clearly undesirable, even if some managers may sometimes long for it (as in this extract of a programming management book quoted by Barry Boehm: “ºthe programmer[s] creative instincts should be totally dulled to insure uniform and understandable programming”, to which Boehm comments: “Given what we know about programmers and their growth motivation, such advice is a clear recipe for disaster”).
What quality software requires is egoful design with egoless expression.
More than style standards, what would seem to require justification is the current situation of software development, with its almost total lack of style standards. In no other discipline that demands to be called “engineering” is there such room for such broad personal variations of whim and fancy. To become more professional, software development needs to regulate itself.
==CHOOSING THE RIGHT NAMES==
The first aspect that we need to regulate is the choice of names. Feature names, in particular, will be strictly controlled for everyones benefit.
===General rules===
What matters most is the names of classes and features which will be used extensively by the authors of classes that rely on yours.
For feature and class names, use full words, not abbreviations, unless the abbreviations are widely accepted in the application domain. In a class PART describing parts in an inventory control system, call number, not num, the feature (query) giving the part number. Typing is cheap; software maintenance is expensive. An abbreviation such as usa in a Geographical Information System or copter in a flight control system, having gained an independent status as a word of its own, is of course acceptable. In addition, a few standard abbreviations have gained recognition over the years, such as PART for PARTIAL in class names such as PART_COMPARABLE describing objects equipped with a partial order relation.
In choosing names, aim for clarity. Do not hesitate to use several words connected by underscores, as in ANNUAL_RATE, a class name, or yearly_premium, a feature name.
Although modern languages do not place any limit on the length of identifiers, and treat all letters as significant, name length should remain reasonable. Here the rule is not the same for classes and for features. Class names are input only occasionally (in class headers, type declarations, inheritance clauses and a few other cases) and should describe an abstraction as completely as possible, so PRODUCT_QUANTITY_INDEX_EVALUATOR may be fine. For features, there is seldom a need for more than two or possibly three underscore-connected words. In particular, do not overqualify feature names. If a feature name appears too long, it is usually because it is overqualified:
===Composite Feature Name rule===
Do not include in a feature name the name of the underlying data abstraction (which should serve as the class name).
The feature giving the part number in class PART should be called just number, not part_number. Such over-qualification is a typical beginners mistake; the resulting names obscure rather than illuminate the text. Remember that every use of the feature will unambiguously indicate the class, as in part1 l number where part1 must have been declared with a certain type, PART or a descendant.
For composite names, it is better to avoid the style, popularized by Smalltalk and also used in such libraries as the X Window System, of joining several words together and starting the internal ones with an upper-case letter, as in yearlyPremium. Instead, separate components with underscores, as in yearly_ premium. The use of internal upper-case letters is ugly; it conflicts with the conventions of ordinary language; and it leads to cryptic names, hence to possible errors (compare aLongAndRatherUnreadableIdentifier with an_even_longer_but_ perfectly_clear_choice_of_name).
Sometimes, every instance of a certain class contains a field representing an instance of another class. This suggests using the class name also as attribute name. You may for example have defined a class RATE and, in class ACCOUNT, need one attribute of type RATE, for which it seems natural to use the name rate — in lower case, according to the rules on letter case stated below. Although you should try to find a more specific name, you may, if this fails, just declare the feature as rate: RATE. The rules on identifier choice explicitly permit assigning the same name to a feature and a class. Avoid the style of prefixing the name with the, as in the_rate, which only adds noise.
===Local entities and routine arguments===
The emphasis on clear, spelled-out names applies to features and classes. Local entities and arguments of a routine only have a local scope, so they do not need to be as evocative. Names that carry too much meaning might almost decrease the softwares readability by giving undue weight to ancillary elements. So it is appropriate to declare local entities (here in routines of TWO_WAY_LIST in the Base libraries) as
<e>
move (i: INTEGER)
-- Move cursor i positions, or after if i is too large.
local
c: CURSOR; counter: INTEGER; p: like FIRST_ELEMENT
remove
-- Remove current item; move cursor to right neighbor (of after if none).
local
succ, pred, removed: like first_element
</e>
If succ and pred had been features they would have been called successor and predecessor. It is also common to use the names new for a local entity representing a new object to be created by a routine, and other for an argument representing an object of the same type as the current one, as in the declaration for clone in GENERAL:
<e>
frozen clone (other: GENERAL): like other
</e>
===Letter case===
Letter case is not significant in our notation, as it is too dangerous to let two almost identical identifiers denote different things. But strongly recommended guidelines help make class texts consistent and readable:
Class names appear in all upper case: POINT, LINKED_LIST, PRICING_MODEL. Formal generic parameters too, usually with just one letter: G.
Names of non-constant attributes, routines other than once functions, local entities and routine arguments appear in all lower case: balance, deposit, succ, i.
Constant attributes have their first letter in upper case and the rest in lower case: Pi: INTEGER is 3.1415926524; Welcome_message: STRING is "Welcome!". This applies to unique values, which are constant integers.
The same convention applies to once functions, the equivalent of constants for non-basic types: Error_window, Io. Our first example, the complex number i, remained in lower case for compatibility with mathematical conventions.
This takes care of developer-chosen names. For reserved words, we distinguish two categories. Keywords such as do and class play a strictly syntactic role; they are written in lower case, and will appear in boldface (see below) in printed texts. A few reserved words are not keywords because they carry an associated semantics; written with an initial upper case since they are similar to constants, they include Current, Result, Precursor, True and False.
===Grammatical categories===
Precise rules also govern the grammatical category of the words from which identifiers are derived. In some languages, these rules can be applied without any hesitation; in English, as noted in an earlier chapter, they will leave more flexibility.
The rule for class names has already been given: you should always use a noun, as in ACCOUNT, possibly qualified as in LONG_TERM_SAVINGS_ACCOUNT, except for the case of deferred classes describing a structural property, which may use an adjective as in NUMERIC or REDEEMABLE.
Routine names should faithfully reflect the Command-Query separation principle:
Procedures (commands) should be verbs in the infinitive or imperative, possibly with complements: make, move, deposit, set_color.
Attributes and functions (queries) should never be imperative or infinitive verbs; never call a query get_value, but just value. Non-boolean query names should be nouns, such as number, possibly qualified as in last_month_balance. Boolean queries should use adjectives, as in full. In English, because of possible confusions between adjectives and verbs (empty, for example, could mean “is this empty?” or “empty this!”), a frequent convention for boolean queries is the is_ form, as in is_empty.
===Standard names===
You will have noted, throughout this book, the recurrence of a few basic names, such as put and item. They are an important part of the method.
Many classes will need features representing operations of a few basic kinds: insert an element into a structure, replace the value of an element, access a designated elementº Rather than devising specific names for the variants of these operations in every class, it is preferable to apply a standard terminology throughout.
Here are the principal standard names. We can start with creation procedures, for which the recommended is make for the most common creation procedure of a class. Non-vanilla creation procedures may be called make_some_qualification, for example make_polar and make_cartesian for a POINT or COMPLEX class.
====For commands the most common names are:====
*extend: Add an element.
*replace: Replace an element.
*force: Like put but may work in more cases; for example put for arrays has a precondition to require the index to be within bounds, but force has no precondition and will resize the array if necessary.
*remove: Remove an (unspecified) element.
*prune: Remove a specific element.
*wipe_out: Remove all elements.
====For non-boolean queries (attributes or functions):====
*item: The basic query for accessing an element: in ARRAY, the element at a given index; in STACK classes, the stack top; in QUEUE classes, the oldest element; and so on.
*infix "@": A synonym for item in a few cases, notably ARRAY.
: -- Note: no longer necessary; use bracket alias instead. Still present in existing libraries.
*count: Number of usable elements in a structure.
*capacity: Physical size allocated to a bounded structure, measured in number of potential elements. The invariant should include 0 <= count and count <= capacity.
====For boolean queries:====
*is_empty: Is the structure devoid of elements?
*is_full: Is there no more room in the representation to add elements? (Normally the same as count = capacity.)
*has: Is a certain element present? (The basic membership test.)
*is_extendible: Can an element be added? (May serve as a precondition to extend.)
*is_prunable: Can an element be removed? (May serve as a precondition to remove and prune.)
*is_readable: Is there an accessible element? (May serve as precondition to item and remove.)
*is_writable: Is it possible to change an element? (May variously serve as precondition to extend, replace, put etc.)
::Note: the variants without `is_' are also widely used, e.g. `prunable', but the `is_' form is now recommended.
A few name choices which may seem strange at first are justified by considerations of clarity and consistency. For example prune goes with prunable and extend with extendible; delete and add might seem more natural, but then s l deletable and s l addable would carry the wrong connotation, since the question is not whether s can be deleted or added but whether we can add elements to it or delete elements from it. The verbs prune and extend, with the associated queries, convey the intended meaning.
===The benefits of consistent naming===
The set of names sketched above is one of the elements that most visibly contribute to the distinctive style of software construction developed from the principles of this book.
Is the concern for consistency going too far? One could fear that confusion could result from routines that bear the same name but internally do something different. For example item for a stack will return the top element, and for an array will return an element corresponding to the index specified by the client.
With a systematic approach to O-O software construction, using static typing and Design by Contract, this fear is not justified. To learn about a feature, a client author can rely on four kinds of property, all present in the short form of the enclosing class:
*Its name.
*Its signature (number and type of arguments if a routine, type of result if a query).
*Its precondition and postcondition if any.
*Its header comment.
A routine also has a body, but that is not part of what client authors are supposed to use.
Three of these elements will differ for the variants of a basic operation. For example in the short form of class STACK you may find the feature
<e>
put (x: G)
-- Push x on top.
require
writable: not full
ensure
not_empty: not empty
pushed: item = x
</e>
whereas its namesake will appear in ARRAY as
<e>
put (x: G; i: INTEGER)
-- Replace by x the entry of index i
require
not_too_small: i >= lower
not_too_large: i <= upper
ensure
replaced: item (i) = x
</e>
The signatures are different (one variant takes an index, the other does not); the preconditions are different; the postconditions are different; and the header comments are different. Using the same name put, far from creating confusion, draws the readers attention to the common role of these routines: both provide the basic element change mechanism.
This consistency has turned out to be one of the most attractive aspects of the method and in particular of the libraries. New users take to it quickly; then, when exploring a new class which follows the standard style, they feel immediately at home and can zero in on the features that they need.
==USING CONSTANTS==
Many algorithms will rely on constants. As was noted in an early chapter of this book, constants are widely known for the detestable practice of changing their values; we should prepare ourselves against the consequences of such fickleness.
===Manifest and symbolic constants===
The basic rule is that uses of constants should not explicitly rely on the value:
====Symbolic Constant principle====
Do not use a manifest constant, other than the zero elements of basic operations, in any construct other than a symbolic constant declaration.
In this principle, a manifest constant is a constant given explicitly by its value, as in 50 (integer constant) or "Cannot find file" (string constant). The principle bars using instructions of the form
<e>
population_array l make (1, 50)
</e>
or
<e>
print ("Cannot find file") -- See mitigating comment below about this case
</e>
Instead, you should declare the corresponding constant attributes, and then, in the bodies of the routines that need the values, denote them through the attribute names:
<e>
US_state_count: INTEGER = 50
File_not_found: STRING = "Cannot find file"
</e>
<e>
population_array l make (1, state_count)
</e>
<e>
print (file_not_found)
</e>
The advantage is obvious: if a new state is added, or the message needs to be changed, you have only have to update one easy-to-locate declaration.
The use of 1 together with state_count in the first instruction is not a violation of the principle, since its prohibition applies to manifest constants “other than zero elements of basic operations”. These zero elements, which you may use in manifest form, include the integers 0 and 1 (zero elements of addition and multiplication), the real number 0.0, the null character written '%0', the empty string " ". Using a symbolic constant One every time you need to refer to the lower bound of an array (1 using the default convention) would lead to an unsustainable style — pedantic, and in fact less readable because of its verbosity. Sometimes, Freud is supposed to have said, a cigar is just a cigar; sometimes One is just 1.
Some other times 1 is just a system parameter that happens to have the value one today but could become 4,652 later — its role as additions zero element being irrelevant. Then it should be declared as a symbolic constant, as in Processor_count: INTEGER is 1 in a system that supports multiple processors and is initially applied to one processor.
The Symbolic Constant principle may be judged too harsh in the case of simple manifest strings used just once, such as "Cannot find file" above. Some readers may want to add this case to the exception already stated in the principle (replacing the qualification by “other than manifest string constants used only once in the same class, and zero elements of basic operations”). This book has indeed employed a few manifest constants in simple examples. Such a relaxation of the rule is acceptable, but in the long run it is probably preferable to stick to the rule as originally given even if the result for string constants looks a little pedantic at times. One of the principal uses of string constants, after all, is for messages to be output to users; when a successful system initially written for the home market undergoes internationalization, it will be that much less translation work if all the user-visible message strings (at least any of them that actually appear in the software text) have been put in symbolic constant declarations.
====Where to put constant declarations====
If you need more than a handful of local constant attributes in a class, you have probably uncovered a data abstraction — a certain concept characterized by a number of numeric or character parameters.
It is desirable, then, to group the constant declarations into a class, which can serve as ancestor to any class needing the constants (although some O-O designers prefer to use the client relation in this case). An example in the Base libraries is the class ASCII, which declares constant attributes for the different characters in the ASCII character set and associated properties.
==HEADER COMMENTS AND NOTE CLAUSES==
Although the formal elements of a class text should give as much as possible of the information about a class, they must be accompanied by informal explanations. Header comments of routines and feature clause answer this need together with the note clause of each class.
'''Terminology''': in earlier Eiffel versions the keyword <b>indexing</b> was used instead of <b>note</b>,
and "note clauses" were called "indexing clauses"
===Routine header comments: an exercise in corporate downsizing===
Like those New York street signs that read “Dont even think of parking here!”, the sign at the entrance of your software department should warn “Dont even think of writing a routine without a header comment”. The header comment, coming just after the is for a routine, expresses its purpose concisely; it will be kept by the short and flat-short forms:
<e>
distance_to_origin: REAL
-- Distance to point (0, 0)
local
origin: POINT
do
create origin
Result := distance (origin)
end
</e>
Note the indentation: one step further than the start of the routine body, so that the comment stands out.
Header comments should be informative, clear, and terse. They have a whole style of their own, which we can learn by looking at an initially imperfect example and improve it step by step. In a class CIRCLE we might start with
<e>
tangent_from (p: POINT): LINE
-- Return the tangent line to the current circle going through the point p,
-- if the point is outside of the current circle.
require
outside_circle: not has (p)
</e>
There are many things wrong here. First, the comment for a query, as here, should not start with “Return theº” or “Compute theº”, or in general use a verbal form; this would go against the Command-Query Separation principle. Simply name what the query returns, typically using a qualified noun for a non-boolean query (we will see below what to use for a boolean query and a command). Here we get:
<e>
-- The tangent line to the current circle going through the point p,
-- if the point p is outside of the current circle
</e>
Since the comment is not a sentence but simply a qualified noun, the final period disappears. Next we can get rid of the auxiliary words, especially the, where they are not required for understandability. Telegram-like style is desirable for comments. (Remember that readers in search of literary frills can always choose Proust novels instead.)
<e>
--Tangent line to current circle from point p,
-- if point p is outside current circle
</e>
The next mistake is to have included, in the second line, the condition for the routines applicability; the precondition, not has (p), which will be retained in the short form where it appears just after the header comment, expresses this condition clearly and unambiguously. There is no need to paraphrase it: this could lead to confusion, if the informal phrasing seems to contradict the formal precondition, or even to errors (a common oversight is a precondition of the form x >= 0 with a comment stating “applicable only to positive x”, rather than “non-negative”); and there is always a risk that during the softwares evolution the precondition will be updated but not the comment. Our example becomes:
<e>
-- Tangent line to current circle from point p.
</e>
Yet another mistake is to have used the words line to refer to the result and point to refer to the argument: this information is immediately obvious from the declared types, LINE and POINT. With a typed notation we can rely on the formal type declarations — which again will appear in the short form — to express such properties; repeating them in the informal text brings nothing. So:
<e>
-- Tangent to current circle from p.
</e>
The mistakes of repeating type information and of duplicating the preconditions requirements point to the same general rule: in writing header comments, assume the reader is competent in the fundamentals of the technology; do not include information that is obvious from the immediately adjacent short form text. This does not mean, of course, that you should never specify a type; the earlier example, -- Distance to point (0,0), could be ambiguous without the word point.
When you need to refer to the current object represented by a class, use phrasing such as current circle, current number and so on as above, rather than referring explicitly to the entity Current. In many cases, however, you can avoid mentioning the current object altogether, since it is clear to everyone who can read a class text that features apply to the current object. Here, for example, we just need
<e>
-- Tangent from p.
</e>
At this stage — three words, starting from twenty-two, an 87% reduction that would make the toughest Wall Street exponent of corporate downsizing jealous — it seems hard to get terser and we can leave our comment alone.
A few more general guidelines. We have noted the uselessness of “Return the ” in queries; other noise words and phrases to be avoided in routines of all kinds include “This routine computes”, “This routine returns”; just say what the routine does, not that it does it. Instead of
<e>
-- This routine records the last outgoing call.
</e>
write
<e>
-- Record outgoing call.
</e>
As illustrated by this example, header comments for commands (procedures) should be in the imperative or infinitive (the same in English), in the style of marching orders. They should end with a period. For boolean-valued queries, the comment should always be in the form of a question, terminated by a question mark:
<e>
has (v: G): BOOLEAN is
-- Does v appear in list?
</e>
A convention governs the use of software entities — attributes, arguments — appearing in comments. In typeset texts such as the above they will appear in italics (more on font conventions below); in the source text they should always appear between an opening quote (“backquote”) and a closing quote; the original text for the example is then:
<e>
-- Does v appear in list?
</e>
Tools such as the short class abstracter will recognize this convention when generating typeset output. Note that the two quotes should be different: v, not v.
Be consistent. If a function of a class has the comment Length of string, a routine of the same class should not say Update width of string if it affects the same property.
All these guidelines apply to routines. Because an exported attribute should be externally indistinguishable from argumentless functions — remember the Uniform Access principle — it should also have a comment, which will appear on the line following the attributes declaration, with the same indentation as for functions:
<e>
count: INTEGER
-- Number of students in course
</e>
For secret attributes a comment is desirable too but the rule is less strict.
===Feature clause header comments===
As you will remember, a class may have any number of feature clauses:
<e>
note
</e>
<e>
class LINKED_LIST [G]
inherit
</e>
<e>
creation
</e>
<e>
feature -- Initialization
make
</e>
<e>
feature -- Access
item: G
</e>
<e>
feature -- Status report
before: BOOLEAN
</e>
<e>
feature -- Status setting
</e>
<e>
feature -- Element change
put_left (v: G)
</e>
<e>
feature -- Removal
remove
</e>
<e>
feature {NONE} -- Implementation
first_element: LINKABLE [G].
</e>
<e>
end -- class LINKED_LIST
</e>
One of the purposes of having several feature clauses is to allow different features to have different export privileges; in this example everything is generally available except the secret features in the last clause. But another consequence of this convention is that you could, and should, group features by categories. A comment on the same line as the keyword feature should characterize the category. Such comments are, like header comments of routines, recognized an preserved by documentation tools such as short.
Eighteen categories and the corresponding comments have been standardized for the Base libraries, so that every feature (out of about 2000 in all) belongs to one of them. The example above illustrates some of the most important categories. Status report corresponds to options (set by features in the Status setting category, not included in the example). Secret and selectively exported features appear in the Implementation category. These standard categories always appear in the same order, which the tools know (through a user-editable list) and will preserve or reinstate in their output. Within each category, the tools list the features alphabetically for ease of retrieval.
The categories cover a wide range of application domains, although for special areas you may need to add your own categories.
===Note clauses===
Similar to header comments but slightly more formal are note clauses, appearing at the beginning of a class:
<e>
note
description: "Sequential lists, in chained representation"
names: "Sequence", "List"
contents: GENERIC
representation: chained
date: "$Date: 96/10/20 12:21:03 $"
revision: "$Revision: 2.4$"
class LINKED_LIST [G]
inherit
</e>
Note clauses proceed from the same Self-Documentation principle that has led to built-in assertions and header comments: include as much as possible of the documentation in the software itself. For properties that do not directly appear in the formal text, you may include note entries, all of the form
<e>
note_term: note_value, note_value,
</e>
where the note_term is an identifier and each note_value is some basic element such as a string, an integer and so on. Entries can indicate alternative names under which potential client authors might search for the class (names), contents type (contents), implementation choices (representation), revision control information, author information, and anything else that may facilitate understanding the class and retrieving it through keyword-based search tools — tools that support reuse and enable software developers to find their way through a potentially rich set of reusable components.
Both the note terms and the note values are free-form, but the possible choices should be standardized for each project. A set of standard choices has been used throughout the Base libraries; the above example illustrates six of the most common entry kinds. Every class must have a description entry, introducing as index_value a string describing the role of the class, always expressed in terms of the instances (as Sequential listsº, not “this class describes sequential lists”, or “sequential list”, or “the notion of sequential list” etc.). Most significant class texts in this book — but not short examples illustrating a specific point — include the description entry.
===Non-header comments===
The preceding rules on comments applied to standardized comments, appearing at specific places — feature declarations and beginning of feature clauses — and playing a special role for class documentation.
As in all forms of software development, there is also a need for comments within routine bodies, to provide further explanations
Another use of comments, although frequent in the practice of software development, does not figure much in software engineering and programming methodology textbooks. I am referring here to the technique of transforming some part of the code into comments, either because it does not work, or because it is not ready yet. This practice is clearly a substitute for better tools and techniques of configuration management. It has enriched the language with a new verb form, comment out, whose potential, surprisingly enough, has not yet been picked up by hip journalists, even though the non-technical applications seem attractive and indeed endless: “The last elections have enabled Congress to comment out the President”, “Letterman was commented out of the Academy Awards”, and so on.
Every comment should be of a level of abstraction higher than the code it documents. A famous counter-example is -- Increase i by 1 commenting the instruction i := i + 1. Although not always that extreme, the practice of writing comments that paraphrase the code instead of summarizing its effect is still common.
Low-level languages cry for ample commenting. It is a good rule of thumb, for example, that for each line of C there should be a comment line; not a negative reflection on C, but a consequence that in modern software development the role of C is to encapsulate machine-oriented and operating-system-level operations, which are tricky by nature and require a heavy explanatory apparatus. In the O-O part, non-header comments will appear much more sparsely; they remain useful when you need to explain some delicate operation or foresee possible confusion. In its constant effort to favor prevention over cure, the method decreases the need for comments through a modular style that yields small, understandable routines, and through its assertion mechanisms: preconditions and postconditions of routines, to express their semantics formally; class invariants; check instructions to express properties expected to hold at certain stages; the systematic naming conventions introduced earlier in this chapter. More generally, the secret of clear, understandable software is not adding comments after the fact but devising coherent and stable system structures right from the start.
==TEXT LAYOUT AND PRESENTATION==
The next set of rules affects how we should physically write our software texts on paper — real, or simulated on a screen. More than any others, they prompt cries of “Cosmetics!”; but such cosmetics should be as important to software developers as Christian Diors are to his customers. They play no little role in determining how quickly and accurately your software will be understood by its readers — maintainers, reusers, customers.
===Layout ===
The recommended layout of texts results from the general form of the syntax of our notation, which is roughly what is known as an “operator grammar”, meaning that a class text is a sequence of symbols alternating between “operators” and “operands”. An operator is a fixed language symbol, such as a keyword (do etc.) or a separator (semicolon, comma º); an operand is a programmer-chosen symbol (identifier or constant).
Based on this property, the textual layout of the notation follows the comb-like structure introduced by Ada; the idea is that a syntactically meaningful part of a class, such as an instruction or an expression, should either:
Fit on a line together with a preceding and succeeding operators.
Be indented just by itself on one or more lines — organized so as to observe the same rules recursively.
Each branch of the comb is a sequence of alternating operators and operands; it should normally begin and end with an operator. In the space between two branches you find either a single operand or, recursively, a similar comb-like structure.
As an example, depending on the size of its constituents a, b and c, you may spread out a conditional instruction as
<e>
if c then a else b end
</e>
or
<e>
if
c
then
a
else
b
end
</e>
or
<e>
if c then
a
else b end
</e>
You would not, however, use a line containing just if c or c end, since they include an operand together with something else, and are missing an ending operator in the first case and a starting operator in the second.
Similarly, you may start a class, after the note clause, with
<e>
class C inherit -- [1]
</e>
or
<e>
class C feature -- [2]
</e>
or
<e>
class -- [3]
C
feature
</e>
but not
<e>
class C -- [4]
feature
</e>
because the first line would violate the rule. Forms [1] and [2] are used in this book for small illustrative classes; since most practical classes have one or more labeled feature clauses, they should in the absence of an inherit clause use form [3] (rather than [2]):
<e>
class
C
feature -- Initialization
</e>
<e>
feature -- Access
</e>
etc.
===Height and width===
Like most modern languages, our notation does not attach any particular significance to line separations except to terminate comments, so that you can include two or more instructions (or two or more declarations) on a single line, separated by semicolons:
<e>
count := count + 1; forth
</e>
This style is for some reason not very popular (and many tools for estimating software size still measure lines rather than syntactical units); most developers seem to prefer having one instruction per line. It is indeed not desirable to pack texts very tightly; but in some cases a group of two or three short, closely related instructions can be more readable if they all appear on one line.
In this area it is best to defer to your judgment and good taste. If you do apply intra-line grouping, make sure that it remains moderate, and consistent with the logical relations between instructions. The Semicolon Style principle seen later in this chapter requires any same-line instructions to be separated by a semicolon.
For obvious reasons of space, this book makes a fair use of intra-line grouping, consistent with these guidelines. It also avoids splitting multi-line instructions into more lines than necessary; on this point one can recommend the books style for general use: there is really no reason to split from i:= 1 invariant i <= n until i = n loop or if a = b then. Whatever your personal taste, do observe the Comb structure.
===Indenting details===
The comb structure uses indentation, achieved through tab characters (not spaces, which are messy, error-prone, and not reader-parameterizable).
Here are the indentation levels for the basic kinds of construct, illustrated by the example on the facing page:
*Level 0: the keywords introducing the primitive clauses of a class. This includes note (beginning of a note clause), class (beginning of the class body), feature (beginning of a feature clause, except if on the same line as class), invariant (beginning of an invariant clause, not yet seen) and the final end of a class.
*Level 1: beginning of a feature declaration; note entries; invariant clauses.
*Level 2: the keywords starting the successive clauses of a routine. This includes require, local, do, once, ensure, rescue, end.
*Level 3: the header comment for a routine or (for consistency) attribute; declarations of local entities in a routine; first-level instructions of a routine.
Within a routine body there may be further indentation due to the nesting of control structures. For example the earlier if a then º instruction contains two branches, each of them indented. These branches could themselves contain loops or conditional instructions, leading to further nesting (although the style of object-oriented software construction developed in this book leads to simple routines, seldom reaching high levels of nesting).
A check instruction is indented, together with the justifying comment that normally follows it, one level to the right of the instruction that it guards.
<e>
note
description: "Example for formating"
class EXAMPLE inherit
MY_PARENT
redefine f1, f2 end
MY_OTHER_PARENT
rename
g1 as old_g1, g2 as old_g2
redefine
g1
select
g2
end
creation
make
feature -- Initialization
make
-- Do something.
require
some_condition: correct (x)
local
my_entity: MY_TYPE
do
if a then
b; c
else
other_routine
check max2 > max1 + x ^ 2 end
-- Because of the postcondition of other_routine.
new_value := old_value / (max2 max1)
end
end
feature -- Access
my_attribute: SOME_TYPE
-- Explanation of its role (aligned with comment for make)
... Other feature declarations and feature clauses ...
invariant
upper_bound: x <= y
end -- class EXAMPLE
</e>
Note the trailer comment after the end of the class, a systematic convention.
===Spaces===
White space contributes as much to the effect produced by a software text as silence to the effect of a musical piece.
The general rule, for simplicity and ease of remembering, is to follow as closely as possible the practice of standard written language. By default we will assume this language to be English, although it may be appropriate to adapt the conventions to the slightly different rules of other languages.
Here are some of the consequences. You will use a space:
Before an opening parenthesis, but not after:
<e>f (x) (not f (x), the C style, or f ( x)).</e>
After a closing parenthesis unless the next character is a punctuation sign such as a period or semicolon; but not before. Hence:
<e>proc1 (x); x := f1 (x) + f2 (y)</e>
After a comma but not before: \
<e>g (x, y, z)</e>.
After the two dash signs that start a comment:<e> -- A comment.</e>
Similarly, the default rule for semicolons is to use a space after but not before:
<e>
p1; p2 (x); p3 (y, z)
</e>
Here, however, some people prefer, even for English-based software texts, the French style of including a space both before and after, which makes the semicolon stand out and emphasizes the symmetry between the components before and after it:
<e>
p1 ; p2 (x) ; p3 (y, z)
</e>
Choose either style, but then use it consistently. (This book uses the English style.) English and French styles have the same difference for colons as for semicolons; since, however, the software notation only uses colons for declarations, in which the two parts — the entity being declared and its type — do not play a symmetric role, it seems preferable to stick to the English style, as in your_entity: YOUR_TYPE.
Spaces should appear before and after arithmetic operators, as in a + b. (For space reasons, this book has omitted the spaces in a few cases, all of the form n+1.)
For periods the notation departs from the conventions of ordinary written language since it uses periods for a special construct, as originally introduced by Simula. As you know, a l r means: apply feature r to the object attached to a. In this case there is a space neither before nor after the period. To avoid any confusion, this book makes the period bigger, as illustrated: l rather than just .
There is another use of the period: as decimal point in real numbers, such as 3.14. Here, to avoid any confusion, the period is not made any bigger.
Some European languages use a comma rather than a period as the separator between integral and fractional parts of numbers. Here the conflict is irreconcilable, as in English the comma serves to separate parts of big numbers, as in “300,000 dollars”, where other languages would use a space. The committee discussions for Algol 60 almost collapsed when some continental members refused to bow to the majoritys choice of the period; the stalemate was resolved when someone suggested distinguishing between a reference language, fixed, and representation languages, parameterizable. (In retrospect, not such a great idea, at least not if you ever have to compile the same program in two different countries!) Today, few people would make this a point of contention, as the spread of digital watches and calculators built for world markets have accustomed almost everyone to alternate between competing conventions.
===Precedence and parentheses===
The precedence conventions of the notation conform to tradition and to the “Principle of Least Surprise” to avoid errors and ambiguities.
Do not hesitate, however, to add parentheses for clarity; for example you may write (a = (b + c)) implies (u /= v) even though the meaning of that expression would be the same if all parentheses were removed. The examples in this book have systematically over-parenthesized expressions, in particular assertions, risking heaviness to avert uncertainty.
===The War of the Semicolons===
Two clans inhabit the computing world, and the hatred between them is as ferocious as it is ancient. The Separatists, following Algol 60 and Pascal, fight for the recognition of the semicolon as a separator between instructions; the Terminatists, rallied behind the contrasting flags of PL/I, C and Ada, want to put a semicolon behind every instruction.
Each sides arguments are endlessly relayed by its propaganda machine. The Terminatists worship uniformity: if every instruction is terminated by the same marker, no one ever has to ask the question “do I need a semicolon here?” (the answer in Terminatist languages is always yes, and anyone who forgets a semicolon is immediately beheaded for high treason). They do not want to have to add or remove a semicolon because an instruction has been moved from one syntactical location to another, for example if it has been brought into a conditional instruction or taken out of it.
The Separatists praise the elegance of their convention and its compatibility with mathematical practices. They see do instruction1; instruction2; instruction3 end as the natural counterpart of f (argument1, argument2, argument3). Who in his right mind, they ask, would prefer f (argument1, argument2, argument3,) with a superfluous final comma? They contend, furthermore, that the Terminatists are just a front for the Compilists, a cruel people whose only goal is to make life easy for compiler writers, even if that means making it hard for application developers.
The Separatists constantly have to fight against innuendo, for example the contention that Separatist languages will prevent you from including extra semicolons. Again and again they must repeat the truth: that every Separatist language worthy of the name, beginning with the venerated Patriarch of the tribe, Algol 60, has supported the notion of empty instruction, permitting all of
<e>
a; b; c
a; b; c;
; a ;; b ;;; c;
</e>
to be equally valid, and to mean exactly the same thing, as they only differ by the extra empty instructions of the last two variants, which any decent compiler will discard anyway. They like to point out how much more tolerant this convention makes them: whereas their fanatical neighbors will use any missing semicolon as an excuse for renewed attacks, the Separatists will gladly accept as many extra semicolons as a Terminatist transfuge may still, out of habit, drop into an outwardly Separatist text.
Modern propaganda needs science and statistics, so the Terminatists have their own experimental study, cited everywhere (in particular as the justification for the Terminatist convention of the Ada language): a 1975 measurement of the errors made by two groups of 25 programmers each, using languages that, among other distinguishing traits, treated semicolons differently. The results show the Separatist style causing almost ten times as many errors! Starting to feel the heat of incessant enemy broadcasts, the Separatist leadership turned for help to the author of the present book, who remembered a long-forgotten principle: quoting is good, but reading is better. So he fearlessly went back to the original article and discovered that the Separatist language used in the comparison — a mini-language meant only for “teaching students the concepts of asynchronous processes” — treats an extra semicolon after the final instruction of a compound, as in begin a; b; end, as an error! No real Separatist language, as noted above, has ever had such a rule, which would be absurd in any circumstance (as an extra semicolon is obviously harmless), and is even more so in the context of the articles experiment since some of the subjects apparently had Terminatist experience from PL/I and so would have been naturally prone to add a few semicolons here and there. It then seems likely, although the article gives no data on this point, that many of the semicolon errors were a result of such normally harmless additions — enough to disqualify the experiment, once and for all, as a meaningful basis for defending Terminatism over Separatism.
On some of the other issues it studies, the article is not marred by such flaws in its test languages, so that it still makes good reading for people interested in language design.
All this shows, however, that it is dangerous to take sides in such a sensitive debate, especially for someone who takes pride in having friends in both camps. The solution adopted by the notation of this book is radical:
====Semicolon Syntax rule====
Semicolons, as markers to delimit instructions, declarations or assertion clauses, are optional in almost all the positions where they may appear in the notation of this book.
“Almost” because of a few rare cases, not encountered in this book, in which omitting the semicolon would cause a syntactical ambiguity.
The Semicolon Syntax rule means you can choose your style:
*Terminatist: every instruction, declaration or assertion clause ends with a semicolon.
*Separatist: semicolons appear between successive elements but not, for example, after the last declaration of a feature or local clause.
*Moderately Separatist: like the Separatist style, but not worrying about extra semicolons that may appear as a result of habit or of elements being moved from one context to another.
*Discardist: no semicolons at all (except as per the Semicolon Style principle below).
This is one of the areas where it is preferable to let each user of the notation follow his own inclination, as the choice cannot cause serious damage. But do stick, at least across a class and preferably across an entire library or application, to the style that you have chosen (although this will not mean much for the Moderately Separatist style, which is by definition lax), and observe the following principle:
====Semicolon Style principle====
If you elect to include semicolons as terminators (Terminatist style), do so for all applicable elements.
If you elect to forego semicolons, use them only when syntactically unavoidable, or to separate elements that appear on the same line.
The second clause governs elements that appear two or more to a line, as in
<e>
found := found + 1; forth
</e>
which should always include the semicolon; omitting it would make the line quite confusing.
Just for once, this discussion has no advice here, letting you decide which of the four styles you prefer. Since the earliest version of the notation required semicolons — in other words, it had not yet been tuned to support the Semicolon Syntax rule — the first edition of this book used a Separatist style. For the present one I dabbled into a few experiments; after polling a sizable group of co-workers and experienced users of the notation, I found (apart from a handful of Terminatists) an almost equal number of Discardists and Separatists. Some of the Discardists were very forceful, in particular a university professor who said that the main reason his students loved the notation is that they do not need semicolons — a comment which any future language designer, with or without grandiose plans, should find instructive or at least sobering.
You should defer to your own taste as long as it is consistent and respects the Semicolon Style principle. (As to this book: for a while I stuck to the original Separatist style, more out of habit than of real commitment; then, hearing the approach of the third millenium and its call to start a new life free of antique superstitions, I removed all the semicolons over a single night of utter debauchery.)
===Assertions===
You should label assertion clauses to make the text more readable:
<e>
require
not_too_small: index >= lower
</e>
This convention also helps produce useful information during testing and debugging since, as you will remember, the assertion label will be included in the run-time message produced if you have enabled monitoring of assertions and one of them gets violated.
This convention will spread an assertion across as many lines as it has clauses. As a consequence, it is one of the rules to which the present book has made a few exceptions, again in the interest of saving space. When collapsing several clauses on one line, you should actually remove the labels for readability:
<e>
require
index >= lower; index <= upper
</e>
In normal circumstances, that is to say for software texts rather than a printed textbook, better stick to the official rule and have one labeled clause per line.
==FONTS==
In typeset software texts, the following conventions, used throughout this book and related publications, are recommended.
===Basic font rules===
Print software elements (class names, feature names, entitiesº) in italics to distinguish them from non-software text elements. This facilitates their inclusion in sentences of the non-software text, such as “We can see that the feature number is a query, not an attribute”. (The word number denotes the name of the feature; you do not want to mislead your reader into believing that you are talking about the number of features!)
Keywords, such as class, feature, invariant and the like, appear in boldface.
This was also the convention of the first edition of this book. At some stage it seemed preferable to use boldface italics which blends more nicely with italics. What was esthetically pleasing, however, turned out to hamper quality; some readers complained that the keywords did not stand out clearly enough, hence the return to the original convention. This is a regrettable case of fickleness. [M 1994a] and a handful of books by other authors show the intermediate convention.
Keywords play a purely syntactic role: they have no semantics of their own but delimit those elements, such as feature and class names, that do carry a semantic value. As noted earlier in this chapter, there are also a few non-keyword reserved words, such as Current and Result, which have a denotation of their own — expressions or entities. They are written in non-bold italics, with an initial upper-case letter.
Following the tradition of mathematics, symbols — colons and semicolons : ;, brackets [ ], parentheses ( ), braces { }, question and exclamation marks ? ! and so on — should always appear in roman (straight), even when they separate text in italics. Like keywords, they are purely syntactic elements.
Comments appear in roman. This avoids any ambiguity when a feature name — which, according to the principles seen earlier, will normally be a word from ordinary language — or an argument name appears in a comment; the feature name will be in italics and hence will stand out. For example:
<e>
accelerate (s: SPEED; t: REAL)
-- Bring speed to s in at most t seconds.
</e>
<e>
set_number (n: INTEGER)
-- Make n the new value of number.
</e>
In the software text itself, where no font variations are possible, such occurrences of formal elements in comments should follow a specific convention already mentioned earlier: they will appear preceded by a back quote and followed by a normal quote , as in
<e>
-- Make n the new value of number.
</e>
(Remember that you must use two different quote characters for opening and closing.) Tools that process class texts and can produce typeset output, such as short and flat, know this convention and so can make sure the quoted elements are printed in italics.
===Other font conventions===
The preceding font conventions work well for a book, an article or a Web page. Some contexts, however, may call for different approaches. In particular, elements in plain italics, and sometimes even bold italics, are not always readable when projected on a projection screen, especially if what you are projecting is the output of a laptop computer with a relatively small display.
In such cases I have come to using the following conventions:
Use non-italics boldface for everything, as this projects best.
Choose a wide enough font, such as Bookman (for which boldface may be called “demibold”).
Instead of italics versus roman versus bold, use color to distinguish the various elements: keywords in black; comments in red; the rest (entities, feature names, expressionsº) in blue. More colors can be used to highlight special elements.
These conventions seem to work well, although there is always room for improvement, and new media will undoubtedly prompt new conventions.
===Color===
The particularly attentive reader may by now have come to notice another convention used by this book: for added clarity, all formal elements — software texts or text extracts, but also mathematical elements — appear in color. This technique, which of course cannot be presented as a general requirement, enhances the effect of the rules seen so far on font usage.
==BIBLIOGRAPHICAL NOTES==
*[Waldén 1995] is the source of the idea of showing by example that even a longer separated_by_underscores identifier is easier to read than an internalUpperCase identifier.
*[Gannon 1975] is an experimental study of the effect of various language design choices on error rates.
*The rules on standard feature names were first presented in [M 1990b] and are developed in detail in [M 1994a].
*I received important comments from Richard Wiener on students appreciation of the optionality of semicolons, and from Kim Waldén on the respective merits of bold italics and plain bold.
==EXERCISES==
===Header comment style===
Rewrite the following header comments in the proper style:
<e>
reorder (s: SUPPLIER; t: TIME)
-- Reorders the current part from supplier s, to be delivered
-- on time t; this routine will only work if t is a time in the future.
require
not_in_past: t >= Now
</e>
<e>
next_reorder_date: TIME
-- Yields the next time at which the current part is scheduled
-- to be reordered.
</e>
===Semicolon ambiguity===
Can you think of a case in which omitting a semicolon between two instructions or assertions could cause syntactic ambiguity, or at least confuse a simple-minded parser? (Hint: a feature call can have as its target a parenthesized expression, as in (vector1 + vector2) l count.)

View File

@@ -0,0 +1,4 @@
[[Property:uuid|9396770A-E53B-4629-84A9-CB2A6680AAAD]]
[[Property:weight|5]]
[[Property:title|Coding Standards]]
Below are the coding and style guidelines followed at Eiffel Software to write the Eiffel and C code of EiffelStudio.

View File

@@ -0,0 +1,68 @@
[[Property:modification_date|Thu, 22 Nov 2018 19:50:45 GMT]]
[[Property:publication_date|Thu, 22 Nov 2018 19:50:45 GMT]]
[[Property:title|Example: Command line arguments]]
[[Property:weight|0]]
[[Property:uuid|ba852d83-3c02-4d38-088a-60b76fe5c63f]]
==Description==
Retrieve the list of command-line arguments given to the program.
Example command line:
<code lang="text">
myprogram -c "alpha beta" -h "gamma"
</code>
==Notes==
This class inherits functionality for dealing with command line arguments from class <code lang="eiffel">ARGUMENTS</code>. It uses the feature <code lang="eiffel">separate_character_option_value</code> to return the values by option name for each of the two arguments. <code lang="eiffel">ARGUMENTS</code> provides a rich set of features for command line argument processing.
The simple version in [[#Solution|Solution]] below is as submitted to Rosetta Code to illustrate class <code lang="eiffel">ARGUMENTS</code>, but it should be noted that <code lang="eiffel">separate_character_option_value</code> is of a detached type and will return a void reference if no value is found for a specified character option. Therefore, a safer version of the use of <code lang="eiffel">separate_character_option_value</code> would include object test on the result:
<code>
if attached separate_character_option_value ('c') as l_val then
print ("Command line argument value for option 'c' is: ")
print (l_val + "%N")
end
if attached separate_character_option_value ('h') as l_val then
print ("Command line argument value for option 'h' is: ")
print (l_val + "%N")
end
</code>
==Source==
Problem description from [http://rosettacode.org/wiki/Command-line_arguments Rosetta Code]
==Solution==
<code>
class
APPLICATION
inherit
ARGUMENTS
create
make
feature {NONE} -- Initialization
make
-- Print values for arguments with options 'c' and 'h'.
do
print ("Command line argument value for option 'c' is: ")
print (separate_character_option_value ('c') + "%N")
print ("Command line argument value for option 'h' is: ")
print (separate_character_option_value ('h') + "%N")
io.read_line -- Keep console window open
end
end
</code>
==Output (for command line arguments: -c "alpha beta" -h "gamma")==
<code lang="text">
Command line argument value for option 'c' is: alpha beta
Command line argument value for option 'h' is: gamma
</code>
{{SeeAlso|[[Execution_profiles|How to run with arguments]]}}

View File

@@ -0,0 +1,41 @@
[[Property:title|Example: Environment variables]]
[[Property:weight|0]]
[[Property:uuid|60c39a34-0794-4c1f-a150-7431afa3e693]]
==Description==
Using features from the class <code>EXECUTION_ENVIRONMENT</code> to create and retrieve an environment variable.
==Notes==
The <code>make</code> procedure of the class <code>APPLICATION</code> below uses the features <code>put</code> and <code>get</code>, inherited from the class <code>EXECUTION_ENVIRONMENT</code>, to create the environment variable <code>MY_VARIABLE</code> with value "Hello World!", and then to retrieve the value by key and print it.
==Solution==
<code>
class
APPLICATION
inherit
EXECUTION_ENVIRONMENT
create
make
feature {NONE} -- Initialization
make
-- Create and retrieve an environment variable.
do
put ("Hello World!", "MY_VARIABLE")
print (get ("MY_VARIABLE"))
end
end
</code>
==Output==
<code lang="text">
Hello World!
</code>

View File

@@ -0,0 +1,52 @@
[[Property:title|Example: File IO]]
[[Property:weight|0]]
[[Property:uuid|b26aa8e3-5963-94ae-b523-642c8b79637b]]
==Description==
Create a file "output.txt" containing the contents of "input.txt".
==Source==
Problem description from [http://rosettacode.org/wiki/File_IO Rosetta Code: File IO]
==Solution==
<code>
class
APPLICATION
create
make
feature {NONE} -- Initialization
make
-- Run application.
do
create input_file.make_open_read ("input.txt")
create output_file.make_open_write ("output.txt")
from
input_file.read_character
until
input_file.exhausted
loop
output_file.put (input_file.last_character)
input_file.read_character
end
input_file.close
output_file.close
end
feature -- Access
input_file: PLAIN_TEXT_FILE
output_file: PLAIN_TEXT_FILE
end
</code>

View File

@@ -0,0 +1,218 @@
[[Property:title|Example: Polymorphism]]
[[Property:weight|0]]
[[Property:uuid|e4a9db32-c087-21b7-f0d6-4685f0ce249d]]
==Description==
Create a class POINT and its heir CIRCLE to demonstrate polymorphic attachment and dynamic binding.
==Source==
Problem description from [http://rosettacode.org/wiki/Polymorphism Rosetta Code: Polymorphism]
Solution varies from Rosetta Code description (e. g., feature <code>out</code> is redefined in this solution, versus feature <code>print</code>.)
==Solution==
<code>
class
POINT
inherit
ANY
redefine
out
end
create
make, make_origin
feature -- Initialization
make (a_x, a_y: INTEGER)
-- Create with values `a_x' and `a_y'
do
set_x (a_x)
set_y (a_y)
ensure
x_set: x = a_x
y_set: y = a_y
end
make_origin
-- Create at origin
do
ensure
x_set: x = 0
y_set: y = 0
end
feature -- Access
x: INTEGER assign set_x
-- Horizontal axis coordinate
y: INTEGER assign set_y
-- Vertical axis coordinate
feature -- Element change
set_x (a_x: INTEGER)
-- Set `x' coordinate to `a_x'
do
x := a_x
ensure
x_set: x = a_x
end
set_y (a_y: INTEGER)
-- Set `y' coordinate to `a_y'
do
y := a_y
ensure
y_set: y = a_y
end
feature -- Output
out: STRING
-- Display as string
do
Result := "Point: x = " + x.out + " y = " + y.out
end
end
</code>
<code>
class
CIRCLE
inherit
POINT
rename
make as point_make
redefine
make_origin,
out
end
create
make, make_origin, make_from_point
feature -- Initialization
make (a_x, a_y, a_r: INTEGER)
-- Create with values `a_x' and `a_y' and `a_r'
require
non_negative_radius_argument: a_r >= 0
do
point_make (a_x, a_y)
set_r (a_r)
ensure
x_set: x = a_x
y_set: y = a_y
r_set: r = a_r
end
make_origin
-- Create at origin with zero radius
do
Precursor
ensure then
r_set: r = 0
end
make_from_point (a_p: POINT; a_r: INTEGER)
-- Initialize from `a_r' with radius `a_r'.
require
non_negative_radius_argument: a_r >= 0
do
set_x (a_p.x)
set_y (a_p.y)
set_r (a_r)
ensure
x_set: x = a_p.x
y_set: y = a_p.y
r_set: r = a_r
end
feature -- Access
r: INTEGER assign set_r
-- Radius
feature -- Element change
set_r (a_r: INTEGER)
-- Set radius (`r') to `a_r'
require
non_negative_radius_argument: a_r >= 0
do
r := a_r
ensure
r_set: r = a_r
end
feature -- Output
out: STRING
-- Display as string
do
Result := "Circle: x = " + x.out + " y = " + y.out + " r = " + r.out
end
invariant
non_negative_radius: r >= 0
end
</code>
<code>
class
APPLICATION
create
make
feature {NONE} -- Initialization
make
-- Run application.
local
my_point: POINT
my_circle: CIRCLE
do
create my_point.make_origin
print (my_point.out + "%N")
create {CIRCLE} my_point.make_origin
print (my_point.out + "%N")
create my_point.make (10, 15)
print (my_point.out + "%N")
create {CIRCLE} my_point.make (20, 25, 5)
print (my_point.out + "%N")
create my_circle.make (30, 35, 10)
print (my_circle.out + "%N")
create my_circle.make_from_point (my_point, 35)
print (my_circle.out + "%N")
end
end
</code>
==Output==
<code lang="text">
Point: x = 0 y = 0
Circle: x = 0 y = 0 r = 0
Point: x = 10 y = 15
Circle: x = 20 y = 25 r = 5
Circle: x = 30 y = 35 r = 10
Circle: x = 20 y = 25 r = 35
</code>

View File

@@ -0,0 +1,41 @@
[[Property:title|Example: Reverse a string]]
[[Property:weight|0]]
[[Property:uuid|d888d308-6bb7-edd5-ee25-92d04b5658d3]]
==Description==
Reverse the order of the characters in a give string of characters.
==Source==
Problem description from [http://rosettacode.org/wiki/Reverse_a_string Rosetta Code]
==Solution==
<code>
class
APPLICATION
create
make
feature
make
-- Demonstrate string reversal.
do
my_string := "Hello World!"
my_string.mirror
print (my_string)
end
my_string: STRING
-- Used for reversal
end
</code>
==Output==
<code lang="text">
!dlroW olleH
</code>

View File

@@ -0,0 +1,84 @@
[[Property:title|Example: Self-initializing attributes and assigner commands]]
[[Property:weight|0]]
[[Property:uuid|dbc107a4-42cd-606a-71b2-e0b70ac5482e]]
==Description==
Example of using a [[Void-safety: Background, definition, and tools#Self-initializing attributes|self-initializing attribute]] and an [[ET: The Dynamic Structure: Execution Model#Assigner commands|assigner command]].
==Notes==
The concepts of [[Void-safety: Background, definition, and tools#Self-initializing attributes|self-initializing attributes]] and [[ET: The Dynamic Structure: Execution Model#Assigner commands|assigner commands]] are independent of one another. However, this example shows how each works in a small amount of code.
The example consists of two classes: a root class, and class <code>PERSON</code>. The <code>PERSON</code> class has a self-initializing attribute of type <code>STRING</code> named <code>mood</code>. If <code>mood</code> is accessed before it is explicitly initialized, then the self-initializing code after the keyword <code>attribute</code> will be executed, setting the default mood to "Happy".
The attribute <code>mood</code> also has an assigner command, the procedure <code>set_mood</code>, designated as such by the <code>assign</code> keyword. This allows clients of class <code>PERSON</code> to appear to assign directly to <code>mood</code>. However, the assigner command <code>set_mood</code> will always get executed, and its precondition will be in force during such an apparent assignment.
The root class <code>APPLICATION</code> creates an instance of <code>PERSON</code> and prints the value of <code>mood</code>, getting the self-iniitalized value. Then it assigns to <code>mood</code>. When it prints again, it gets the updated value.
==Source==
Adapted from an example given on the Eiffel Software Users Group.
==Solution==
A root class:
<code>
class
APPLICATION
create
make
feature {NONE} -- Initialization
make
-- Print and set mood of `my_person'.
do
create my_person
print ("Mood: " + my_person.mood + "%N")
my_person.mood := "Ecstatic"
print ("Mood: " + my_person.mood + "%N")
end
feature -- Access
my_person: PERSON
end
</code>
Class PERSON:
<code>
class
PERSON
feature -- Access
mood: STRING assign set_mood
attribute
Result := "Happy"
end
feature -- Element change
set_mood (a_string: STRING)
require
single_token: a_string.occurrences (' ') = 0
do
mood := a_string
ensure
mood_set: mood = a_string
end
end
</code>
==Output==
<code>
Mood: Happy
Mood: Ecstatic
</code>

View File

@@ -0,0 +1,64 @@
[[Property:title|Example: Sieve of Eratosthenes]]
[[Property:weight|0]]
[[Property:uuid|e825c874-4266-b5ee-501c-221e6940dacd]]
==Description==
Deliver prime numbers up to a specified integer limit. Compute prime numbers using sieve of Eratosthenes.
==Notes==
This example uses the ''iteration'' (<code>across</code>) form of the Eiffel loop construct to traverse a list, an array, and an integer interval.
==Source==
Problem description from [http://rosettacode.org/wiki/Sieve_of_Eratosthenes Rosetta Code]
==Solution==
<code>
class
APPLICATION
create
make
feature
make
-- Run application.
do
across primes_through (100) as ic loop print (ic.item.out + " ") end
end
primes_through (a_limit: INTEGER): LINKED_LIST [INTEGER]
-- Prime numbers through `a_limit'
require
valid_upper_limit: a_limit >= 2
local
l_tab: ARRAY [BOOLEAN]
do
create Result.make
create l_tab.make_filled (True, 2, a_limit)
across
l_tab as ic
loop
if ic.item then
Result.extend (ic.target_index)
across ((ic.target_index * ic.target_index) |..| l_tab.upper).new_cursor.with_step (ic.target_index) as id
loop
l_tab [id.item] := False
end
end
end
end
end
</code>
==Output==
<code lang="text">
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
</code>

View File

@@ -0,0 +1,54 @@
[[Property:title|Example: Sleep]]
[[Property:weight|0]]
[[Property:uuid|a846db1c-2096-43a9-bb8b-a233c9e21421]]
==Description==
Write a program that does the following in this order:
# Input an amount of time to sleep in whatever units are most natural for your language (milliseconds, seconds, ticks, etc.). This unit should be noted in comments or in a description.
# Print "Sleeping..."
# Sleep the main thread for the given amount of time.
# Print "Awake!"
# End.
==Notes==
The feature <code lang="eiffel">sleep</code> is defined in the library class <code>EXECUTION_ENVIRONMENT</code>. So the demonstration class <code>APPLICATION</code> inherits from <code>EXECUTION_ENVIRONMENT</code> in order to make <code lang="eiffel">sleep</code> available.
<code lang="eiffel">sleep</code> takes an argument which declares the number of nanoseconds to suspend the thread's execution.
==Source==
Problem description from [http://rosettacode.org/wiki/Sleep Rosetta Code]
==Solution==
<code>
class
APPLICATION
inherit
EXECUTION_ENVIRONMENT
create
make
feature -- Initialization
make
-- Sleep for a given number of nanoseconds.
do
print ("Enter a number of nanoseconds: ")
io.read_integer_64
print ("Sleeping...%N")
sleep (io.last_integer_64)
print ("Awake!%N")
end
end
</code>
==Output (sleeping 10 seconds)==
<code lang="text">
Enter a number of nanoseconds: 10000000000
Sleeping...
Awake!
</code>

View File

@@ -0,0 +1,10 @@
[[Property:title|Examples]]
[[Property:description|how common programming problems can be solved using Eiffel]]
[[Property:weight|6]]
[[Property:uuid|1a59e03b-8bf0-8426-43b4-577761e40790]]
Here you will find examples of how common programming problems can be solved using Eiffel.
A set of examples is also included with the EiffelStudio distribution kit.

View File

@@ -0,0 +1,26 @@
[[Property:modification_date|Mon, 10 Sep 2018 09:10:34 GMT]]
[[Property:publication_date|Mon, 10 Sep 2018 09:10:34 GMT]]
[[Property:title|Introduction to the Examples Book]]
[[Property:weight|-1]]
[[Property:uuid|044fa742-f3ca-9f5b-01cc-7194ee172b08]]
EiffelStudio comes with a rich set of examples that you can use to learn how to use the many Eiffel facilities and libraries. You should look first to the examples distributed with EiffelStudio as your primary source of samples of Eiffel in use.
The examples in this book are somewhat different in nature and serve a different purpose.
Although some of the examples included here are provided by Eiffel Software, the intent is that the majority of the entries will be contributed by people like you who use Eiffel daily to solve real problems.
The inspiration for this book is the many ''program chrestomathies'' on the World-Wide Web. In natural language, a chrestomathy is a set of literary passages explicitly selected for the purpose of helping learn a language. A program chrestomathy is a set of problems for which solutions are represented in various programming languages with the aim of allowing programmers to compare language capabilities and programming techniques.
Program chrestomathies vary widely. At one end of the spectrum [http://99-bottles-of-beer.net/ 99 Bottles of Beer] has collected solutions in over one thousand programming languages, all targeted to a single problem: generate and print the complete lyrics of the song ''99 Bottles of Beer on the Wall''. There are several "Hello world!" chrestomathies. Other sites host multiple programming problems, all with solutions in many languages. One large multi-problem site is [http://rosettacode.org/wiki/Main_Page Rosetta Code]. In fact, Rosetta Code maintains a [http://rosettacode.org/wiki/Help:Similar_Sites list of links to many of the Web's other programming chrestomathy projects].
Eiffel has a presence on many of these sites. Still, the more examples, the better.
The purpose of the examples in this book, then, is two-fold. First, we get a set of Eiffel examples in the Eiffel online documentation with solutions to a different set of problems than the examples distributed with EiffelStudio. Second, examples from this set can be migrated to Rosetta Code or one of the other chrestomathies to improve Eiffel's presence on those sites. (The caveat to contributors is clear: '''Contribute only work that you have the authority to release, and only if you are willing to have your work shared on one or more of the program chrestomathies.''' By submitting content to this Examples book, you agree to release that content under terms no more restrictive than the GNU Free Documentation License.)
Sites like Rosetta Code and [http://en.literateprograms.org/LiteratePrograms:Welcome Literate Programs] offer a wide variety of programming problems or tasks for comparison of languages and techniques. Rosetta Code provides an index to the [http://rosettacode.org/wiki/Reports:Tasks_not_implemented_in_Eiffel tasks not yet implemented in Eiffel].
This book should include, but not necessarily be limited to, certain of the problems used as challenges by program chrestomathies.

View File

@@ -0,0 +1,6 @@
[[Property:title|Language reference]]
[[Property:link_title|Language]]
[[Property:weight|3]]
[[Property:uuid|17412f30-0451-4b2b-bdec-578ca2e619a6]]

View File

@@ -0,0 +1,32 @@
[[Property:modification_date|Wed, 11 Sep 2019 23:28:26 GMT]]
[[Property:publication_date|Wed, 11 Sep 2019 23:28:26 GMT]]
[[Property:uuid|C652AC71-8BAD-4387-A46C-21C9F5C3A68F]]
[[Property:weight|0]]
[[Property:title|Conditional expression]]
[[Property:link_title|Conditional]]
[[Eiffel_programming_language_syntax#Conditionals|Conditional expressions]] compute a value using different expressions depending on one or more conditions. If all expressions have the same type, the conditional expression as a whole has this type as well:
<e>
if time < noon then
"Good morning"
elseif time < evening then
"Good afternoon"
else
"Good evening"
end
</e>
has type `STRING`.
If the types of the expressions are different, the [[Types#Common_ancestor_types|common ancestor type]] is used as a type of the whole expression.
<e>
if time < noon then
"Good morning"
else
Void
end
</e>
has type `detachable STRING`.

View File

@@ -0,0 +1,85 @@
[[Property:uuid|3C1A6DEF-A6F1-4E64-A0BE-C07BDB382C93]]
[[Property:weight|0]]
[[Property:title|Manifest array]]
A manifest array is an expression denoting an array by simply listing its elements, as in `<<1, 4, 9, 16, 25>>`. The lower index is always `1` and the upper index is the number of items, `5` in this example.
The type of a manifest array is always `ARRAY [T]` where `T` is a type to which all the elements conform, `INTEGER` in the previous example. In case of a possible ambiguity you can make the type explicit, as in `{ARRAY [COMPARABLE]} <<7, "Eiffel">>`, where both `INTEGER`, the type of `7`, and `STRING`, the type of `"Eiffel"`, conform to `COMPARABLE`.
== What are manifest arrays good for? ==
Use a manifest array to initialize an element by simply listing its initial elements. For example, with the declaration
```eiffel
squares: ARRAY [INTEGER]
```
you can initialize `squares` through
```eiffel
squares := <<1, 4, 9, 16, 25>>
```
This is simpler than the alternative, which would be to create the array explicitly and give a value to every element in turn:
```eiffel
-- Arguments to `make_filled` are: default value, lower bound, upper bound.
create squares.make_filled (0, 1, 5)
squares [1] := 1
squares [2] := 4
squares [3] := 9
squares [4] := 16
squares [5] := 25
```
The first form, with the manifest array, is shorter, but the effect is the same.
Manifest arrays are normal arrays, not restricted in any way. You can for example add elements to them, as in
```eiffel
-- Arguments to `force` are: value, position.
squares.force (36, 6)
```
which will resize the array to bounds 1 and 6.
== Type of a manifest array: the implicit case ==
If you do not explicitly specify an array type, the type of the manifest array is as follows:
* For an empty manifest array `<<>>`: `ARRAY [NONE]`. (In the following cases we assume the array is not empty.)
* If all elements are of the same exact type `T`: `ARRAY [T]`.
* If the types of all elements all conform to a type `T`: `ARRAY [T]`. Note that in this case `T` is unique since two different types cannot conform to each other. (The preceding case, all types identical, is a special case of this one, since a type conforms to itself.)
* Otherwise: `ARRAY [ANY]`.
As an example of the third case (conformance of all elements to one of them), assume `POLYGON` and `CIRCLE` both conform to `FIGURE`. Then the manifest array `<<a_polygon, a_figure, a_circle>>`, with `a_polygon` of type `POLYGON` and so on, is `ARRAY [FIGURE]`.
== Type of a manifest array: the explicit case ==
With the preceding rule, the type of `<<7, "Eiffel">>` is the most general possible one, `ARRAY [ANY]`, since `INTEGER` and `STRING` do not conform to each other (either way). If you are not happy with this default type, you can make the array type explicit by writing it in braces:
```eiffel
{ARRAY [COMPARABLE]} <<7, "Eiffel">>
```
The rule in such a case is that in `{ARRAY [T]} <<element1, element2, ...>>` the types of all elements must conform to `T`.
As another example, with
```eiffel
figures: ARRAY [FIGURE]
```
you cannot assign `<<a_polygon, a_circle>>` to `figures` since the type of the manifest array is `ARRAY [ANY]`. To make this assignment possible, use an explicit type:
```eiffel
figures := {ARRAY [FIGURE]} <<a_polygon, a_circle>>
```
You can also use this form to give an explicit type to an empty array, which would otherwise be of type `ARRAY [NONE]`. For example, with `figures` declared as above:
```eiffel
figures := {ARRAY [FIGURE]} <<>>
```

View File

@@ -0,0 +1,5 @@
[[Property:uuid|F904B70B-4C34-459B-A146-E10C7EC30136]]
[[Property:weight|0]]
[[Property:title|Expressions]]
[[Eiffel%20programming%20language%20syntax#Expressions|Expressions]] are used to compute a value at run-time and have an associated type at compile-time.

View File

@@ -0,0 +1,44 @@
[[Property:uuid|88764AFC-7DC5-4547-8B8C-4C0A489B0620]]
[[Property:weight|0]]
[[Property:title|Types]]
== Common ancestor type ==
A '''common ancestor type''' is a type computed for a list of types using the following algorithm:
# Add `NONE` to the list of types (to make sure the list is never empty).
# If there is a separate type in the list, add a mark `separate` in front of all non-separate types in the list.
# If there is a detachable type in the list, add a mark `detachable` in front of all attached types in the list.
# If there is a type in the list to which all other types conform, it is the common ancestor type.
# Otherwise, add `ANY` to the list and repeat steps starting from step #2.
Here are some examples:
{|
! Type list
! Common ancestor type
|-
| (empty)
| <e>NONE</e>
|-
| <e>BOOLEAN</e>
| <e>BOOLEAN</e>
|-
| <e>BOOLEAN, BOOLEAN</e>
| <e>BOOLEAN</e>
|-
| <e>INTEGER_32, REAL_64, COMPARABLE</e>
| <e>COMPARABLE</e>
|-
| <e>INTEGER_32, REAL_64</e>
| <e>ANY</e>
|-
| <e>INTEGER_32, detachable COMPARABLE</e>
| <e>detachable COMPARABLE</e>
|-
| <e>INTEGER_32, separate COMPARABLE</e>
| <e>separate COMPARABLE</e>
|-
| <e>detachable STRING, separate COMPARABLE</e>
| <e>detachable separate COMPARABLE</e>
|}

View File

@@ -0,0 +1,525 @@
[[Property:modification_date|Thu, 13 Aug 2020 00:59:54 GMT]]
[[Property:publication_date|Wed, 11 Sep 2019 14:10:27 GMT]]
[[Property:title|Eiffel programming language reserved words]]
[[Property:link_title|Reserved words]]
[[Property:weight|1]]
[[Property:uuid|047ce062-45de-f25c-f356-ee8ec0fc2d1d]]
In the Eiffel programming language, there are certain words that are considered "reserved". These words have specific meanings recognized by the compiler. As such, it is invalid to attempt to use a reserved word as an ordinary language identifier.
The reserved words listed in the ISO/ECMA standard are shown below with a brief explanation of their meanings. Links are given where appropriate to the syntax definitions and to descriptions in the online documentation. Occasionally, references to the June 2006 standard document are used and are recognizable as clause numbers in parentheses, i.e., three integers separated by dots, for example: (8.14.1)
{{info|The list below includes all the Eiffel reserved words. Some of these words are considered ''language keywords'' while others are not. The distinction is that language keywords are reserved words that are used only as syntactical markers, and have no inherent semantic value. Examples are the keywords <code>do</code> and <code>end</code>. Non-keyword reserved words are those that do carry semantic value, such as <code>True</code> and <code>Current</code>.}}
{{note|The set of reserved words supported by the Eiffel Software implementation may vary somewhat from those specified in the current standard. See the [[Differences between standard ECMA-367 and Eiffel Software implementation|"differences" chapter of the online documentation]] for information on these variances.}}
==Reserved words==
===across===
Introduces an [[ET: Instructions#Loop|iteration]].
===agent===
Used to specify an [[ET: Agents|agent]].
:[[Eiffel programming language syntax#Agents|Syntax.]]
===alias===
Used to identify an alternative or alias feature name.
:[[Eiffel programming language syntax#Feature names|Syntax.]]
[[ET: The Dynamic Structure: Execution Model#Infix and prefix notations|Usage for infix/prefix notations.]]
[[ET: The Static Picture: System Organization#External software|Usage in interfaces to external software.]]
:[[Eiffel programming language syntax#External routines|Syntax.]]
===all===
Used in [[ET: Inheritance#Changing the export status|export adaptation]] to indicate that a chosen export status applies to all features inherited from a given parent.
:[[Eiffel programming language syntax#Export adaptation|Syntax.]]
===and===
The logical conjunction [[Eiffel programming language syntax#Operators|operator]]. Strict when used alone, nonstrict when used with [[#then|then]].
===as===
Used when [[ET: Inheritance#Multiple inheritance and renaming|renaming]] features in descendant classes.
:[[Eiffel programming language syntax#Rename clauses|Syntax.]]
===assign===
Used to designate [[ET: The Dynamic Structure: Execution Model#Abstraction|assigner commands]].
:[[Eiffel programming language syntax#Assigner marks|Syntax.]]
===attribute===
Introduces an attribute body, as in [[Void-safety: Background, definition, and tools#Self-initializing attributes|self-initializing attributes]].
:[[Eiffel programming language syntax#Attribute bodies|Syntax.]]
===check===
Identifies a [[ET: Other Mechanisms#Check|check instruction]].
:[[Eiffel programming language syntax#Check instructions|Syntax.]]
===class===
Used in a class header in the declaration of a [[ET: The Dynamic Structure: Execution Model#A simple class|class]].
:[[Eiffel programming language syntax#Class headers|Class header syntax.]]
===convert===
Used in converter clauses.
:[[Eiffel programming language syntax#Converter clauses|Syntax.]]
Used in feature names for operator aliases, supporting mixed type expressions causing a conversion of the target (8.5.14).
:[[Eiffel programming language syntax#Feature names|Syntax.]]
===create===
In the creators part of a class, introduces those procedures which can be used to [[ET: The Dynamic Structure: Execution Model#Creating and initializing objects|initialize instances]].
:[[Eiffel programming language syntax#Creators parts|Syntax.]]
Introduces a [[ET: The Dynamic Structure: Execution Model#Creating and initializing objects|creation instruction]].
:[[Eiffel programming language syntax#Creation instructions|Syntax.]]
Introduces a creation expression (8.20.18)
:[[Eiffel programming language syntax#Creation expressions|Syntax.]]
In [[ET: Inheritance#Constrained genericity|constrained genericity]], introduces a list of names of features which can be used as creation procedures with a generic class for a particular formal generic parameter. (8.12.10)
:[[Eiffel programming language syntax#Generic constraints|Syntax.]]
===Current===
A predefined entity indicating the current object.
:[[Eiffel programming language syntax#Entities and variables|Entity syntax.]]
:[[Eiffel programming language syntax#Types|Anchored types syntax.]]
===debug===
Introduces a [[ET: Other Mechanisms#Debug|debug instruction]].
:[[Eiffel programming language syntax#Debug Instructions|Syntax.]]
===deferred===
Used in class header to indicate a [[ET: Inheritance#Deferred features and classes|deferred class]].
:[[Eiffel programming language syntax#Class headers|Syntax.]]
Used in routine body to indicate a [[ET: Inheritance#Deferred features and classes|deferred feature]].
:[[Eiffel programming language syntax#Routine bodies|Syntax.]]
===do===
Introduces a sequence of instructions as a routine body, as shown in the [[ET: Hello World|Hello World]] example.
:[[Eiffel programming language syntax#Routine bodies|Syntax.]]
===else===
Used in [[ET-_Instructions#Conditional|conditional]] and [[ET-_Instructions#Multi-branch|multi-branch]] instructions to introduce a sequence of instructions to be executed in the case that no specified conditions are met.
:[[Eiffel programming language syntax#Conditionals|Conditional syntax.]]
:[[Eiffel programming language syntax#Multi-branch instructions|Multi-branch syntax.]]
Used in a [[Conditional_expression|conditional expression]] to compute a value in the case that no specified conditions are met.
:[[Eiffel programming language syntax#Conditionals|Conditional expression syntax.]]
Used as part of the double reserved word <code>or else</code>, the semi-strict disjunction operator.
:[[Eiffel programming language syntax#Operators|Syntax.]]
Used after the reserved word [[#require|<code>require</code>]] as a precondition extension, allowing the weakening of an inherited precondition (8.10.3).
:[[Eiffel programming language syntax#Assertions|Syntax.]]
===elseif===
Used in [[ET-_Instructions#Conditional|conditional]] instructions to effect a "multi-branch" choice instruction.
:[[Eiffel programming language syntax#Conditionals|Syntax.]]
Used in a [[Conditional_expression|conditional expression]] to effect a "multi-branch" choice to compute of a value.
:[[Eiffel programming language syntax#Conditionals|Conditional expression syntax.]]
===end===
Serves to terminate several Eiffel programming language constructs.
:Syntax for:
::[[Eiffel programming language syntax#Class declarations|Class declarations]]
::[[Eiffel programming language syntax#Feature bodies|Feature bodies]]
::[[Eiffel programming language syntax#Inheritance parts|Inheritance parts]]
::[[Eiffel programming language syntax#Check instructions|Check instructions]]
::[[Eiffel programming language syntax#Generic constraints|Generic constraints: renaming and constraint creators]]
::[[Eiffel programming language syntax#Conditionals|Conditional instructions]]
::[[Eiffel programming language syntax#Multi-branch instructions|Multi-branch instructions]]
::[[Eiffel programming language syntax#Conditionals|Conditional expressions]]
::[[Eiffel programming language syntax#Loops|Loops]]
::[[Eiffel programming language syntax#Debug instructions|Debug instructions]]
===ensure===
Introduces a [[ET: Design by Contract (tm), Assertions and Exceptions#Expressing assertions|postcondition]].
When followed by the reserved word [[#then|<code>then</code>]] denotes a postcondition extension, allowing the strengthening of an inherited postcondition (8.10.3).
:[[Eiffel programming language syntax#Assertions|Syntax.]]
===expanded===
Used in a class header to indicate that a class is [[ET: The Dynamic Structure: Execution Model#Type categories|expanded]].
:[[Eiffel programming language syntax#Class headers|Syntax.]]
===export===
Used to [[ET: Inheritance#Changing the export status|change the export status]] (availability to clients) of inherited features.
:[[Eiffel programming language syntax#Export adaptation|Syntax.]]
===external===
Denotes an [[ET: The Static Picture: System Organization#External software|external routine]]. External routines are commonly defined to interface with [[C externals|C external routines]] and [[C++ Externals|C++ external routines]].
:[[Eiffel programming language syntax#External routines|Syntax]]
===False===
Boolean manifest constant.
:[[Eiffel programming language syntax#Manifest constants|Syntax.]]
===feature===
Introduces a [[ET: Hello World|feature clause]].
:[[Eiffel programming language syntax#Feature parts|Syntax.]]
===from===
Used in [[ET: Other Mechanisms#Loop|loop]] initialization.
:[[Eiffel programming language syntax#Loops|Syntax.]]
===frozen===
Used in a class header to mark a class explicitly as frozen. A frozen class prohibits it from serving as a "conforming parent" to other classes. (8.4.5).
:[[Eiffel programming language syntax#Class headers|Syntax.]]
Used in a feature declaration to mark a feature as frozen. A frozen feature cannot be redefined by heir classes.
:[[Eiffel programming language syntax#New feature lists|Syntax.]]
Used with a formal generic parameter to indicate that conformance of generic derivations of the class require identical actual generic parameters. (8.12.3)
:[[Eiffel programming language syntax#Formal generic parameters|Syntax.]]
===if===
Used to introduce a [[ET-_Instructions#Conditional|conditional]].
:[[Eiffel programming language syntax#Conditionals|Conditional syntax.]]
Used to introduce a [[Conditional_expression|Conditional expression]].
:[[Eiffel programming language syntax#Conditionals|Conditional expression syntax.]]
===implies===
The semi-strict logical implication [[Eiffel programming language syntax#Operators|operator]].
===inherit===
Used in an [[ET: Inheritance|inherit]] clause.
:[[Eiffel programming language syntax#Inheritance parts|Syntax.]]
===inspect===
Introduces a [[ET-_Instructions#Multi-branch|multi-branch]] instruction.
:[[Eiffel programming language syntax#Multi-branch instructions|Syntax.]]
===invariant===
Used to introduce an invariant assertion as a [[ET: Design by Contract (tm), Assertions and Exceptions#Class invariants|class invariant]] or [[ET: Instructions#Loop|loop invariant]].
:[[Eiffel programming language syntax#Assertions|Assertions syntax.]]
:[[Eiffel programming language syntax#Class declarations|Syntax of class declaration including class invariant.]]
:[[Eiffel programming language syntax#Loops|Syntax of loop including loop invariant.]]
===like===
Used in the declaration of an [[ET: Inheritance#Covariance and anchored declarations|anchored]] entity.
:[[Eiffel programming language syntax#Types|Syntax.]]
===local===
Introduces the [[ET: The Dynamic Structure: Execution Model#Entities|local variable]] declarations in a feature body.
:[[Eiffel programming language syntax#Feature bodies|Feature bodies syntax.]]
:[[Eiffel programming language syntax#Local variables|Local variable declarations syntax.]]
===loop===
Introduces a [[ET: Other Mechanisms#Loop|loop]] body.
:[[Eiffel programming language syntax#Loops|Syntax.]]
===not===
The logical negation [[Eiffel programming language syntax#Operators|operator]].
===note===
Used to begin a Notes part, in a [[Eiffel programming language syntax#Class declarations|class declaration]], a [[Eiffel programming language syntax#Feature declarations|feature declaration]], or a [[Eiffel programming language syntax#Check instructions|check instruction]].
:[[Eiffel programming language syntax#Notes|Syntax.]]
===obsolete===
Used to mark [[ET: Other Mechanisms#Obsolete features and classes|obsolete features and classes]].
:[[Eiffel programming language syntax#Feature declarations|Feature declarations syntax.]]
:[[Eiffel programming language syntax#Class declarations|Class declarations declarations syntax.]]
:[[Eiffel programming language syntax#Obsolete marks|Obsolete mark syntax.]]
===old===
Introduces an ''old expression''. Old expressions are valid only in the [[ET: Design by Contract (tm), Assertions and Exceptions#Postconditions|postconditions]] of routines.
:[[Eiffel programming language syntax#Old postcondition expressions|Syntax.]]
===once===
Used to introduce [[ET: Other Mechanisms#Once routines and shared objects|once routines]] and once string expressions.
:[[Eiffel programming language syntax#Routine bodies|Once routine syntax.]]
:[[Eiffel programming language syntax#Expressions|Once string syntax.]]
===only===
Used in an ''only postcondition clause''. (8.9.11)
:[[Eiffel programming language syntax#"Old" postcondition expressions|Syntax.]]
===or===
The logical disjunction [[Eiffel programming language syntax#Operators|operator]]. Strict when used alone, nonstrict when used with [[#else|else]].
===Precursor===
Allows a redefined routine to access the routine it redefines, i.e, its [[ET: Inheritance#Redefinition|precursor]].
:[[Eiffel programming language syntax#Precursor|Syntax.]]
===redefine===
Used in an [[Eiffel programming language syntax#Inheritance parts|inheritance part]] of a [[Eiffel programming language syntax#Class declarations|class declaration]] to list those inherited features which, in the heir class, will receive new implementations, specifications, or both, i.e, those features being [[ET: Inheritance#Redefinition|redefined]].
:[[Eiffel programming language syntax#Redefinition|Redefine syntax.]]
===rename===
Used in an [[Eiffel programming language syntax#Inheritance parts|inheritance part]] of a [[Eiffel programming language syntax#Class declarations|class declaration]] to [[ET: Inheritance#Multiple inheritance and renaming|provide alternative names]] for inherited features in an heir class.
Used to rename features in a [[Eiffel programming language syntax#Generic constraints|generic constraint]]. (8.12.8).
:[[Eiffel programming language syntax#Rename clauses|Syntax.]]
===require===
Introduces a [[ET: Design by Contract (tm), Assertions and Exceptions#Expressing assertions|precondition]].
When followed by the reserved word [[#else|<code>else</code>]] denotes a precondition extension, allowing the weakening of an inherited precondition (8.10.3).
:[[Eiffel programming language syntax#Assertions|Syntax.]]
===rescue===
Introduces a [[ET: Design by Contract (tm), Assertions and Exceptions#Exception handling|rescue clause]] in a [[Eiffel programming language syntax#Feature bodies|feature body]].
:[[Eiffel programming language syntax#Rescue clauses|Syntax.]]
===Result===
A predefined [[ET: The Dynamic Structure: Execution Model#Entities|entity]] used to represent the final result of a function.
:[[Eiffel programming language syntax#Entities and variables|Syntax.]]
===retry===
An [[Eiffel programming language syntax#Instructions|instruction]] valid only in [[Eiffel programming language syntax#Rescue clauses|rescue clauses]] and used to [[ET: Design by Contract (tm), Assertions and Exceptions#Exception handling|re-execute the routine]] in which it appears.
:[[Eiffel programming language syntax#Rescue clauses|Syntax.]]
===select===
Used in an [[Eiffel programming language syntax#Inheritance parts|inheritance part]] of a [[Eiffel programming language syntax#Class declarations|class declaration]] to resolve possible ambiguities related to polymorphism and dynamic binding in the presence of [[ET: Inheritance#Repeated inheritance and selection|repeated inheritance]].
:[[Eiffel programming language syntax#Select clauses|Syntax.]]
===separate===
Used to support [[Concurrent programming with SCOOP]].
===then===
Used in [[ET-_Instructions#Conditional|conditional]] and [[ET-_Instructions#Multi-branch|multi-branch]] instructions to introduce a sequence of instructions to be executed in the case that a condition is met.
:[[Eiffel programming language syntax#Conditionals|Conditional syntax.]]
:[[Eiffel programming language syntax#Multi-branch instructions|Multi-branch syntax.]]
Used in a [[Conditional_expression|conditional expression]] to compute of a value in the case that a condition is met.
:[[Eiffel programming language syntax#Conditionals|Conditional expression syntax.]]
Used as part of the double reserved word <code>and then</code>, the semi-strict conjunction operator.
:[[Eiffel programming language syntax#Operators|Syntax.]]
Used after the reserved word [[#ensure|<code>ensure</code>]] as a postcondition extension, allowing the strengthening of an inherited postcondition (8.10.3).
:[[Eiffel programming language syntax#Assertions|Syntax.]]
===True===
Boolean manifest constant.
:[[Eiffel programming language syntax#Manifest constants|Syntax.]]
===TUPLE===
Denotes a [[ET: Other Mechanisms#Tuple types|TUPLE type]].
:[[Eiffel programming language syntax#Tuple types|Syntax.]]
===undefine===
Used in an [[Eiffel programming language syntax#Inheritance parts|inheritance part]] of a [[Eiffel programming language syntax#Class declarations|class declaration]] to [[ET: Inheritance#Joining and uneffecting|uneffect]] an inherited feature.
:[[Eiffel programming language syntax#Undefine clauses|Syntax.]]
===until===
Used in [[ET: Other Mechanisms#Loop|loop]] initialization.
:[[Eiffel programming language syntax#Loops|Syntax.]]
===variant===
Introduces a [[ET: Instructions#Loop|loop variant]].
:[[Eiffel programming language syntax#Variants|Syntax.]]
===Void===
A predefined entity name representing a [[ET: The Dynamic Structure: Execution Model#Basic operations|void (a.k.a., null) reference]].
===when===
Used in a [[ET-_Instructions#Multi-branch|multi-branch instruction]] to introduce cases.
:[[Eiffel programming language syntax#Multi-branch instructions|Syntax.]]
===xor===
The exclusive disjunction [[Eiffel programming language syntax#Operators|operator]].

View File

@@ -0,0 +1,785 @@
[[Property:modification_date|Mon, 29 Jul 2019 16:52:51 GMT]]
[[Property:publication_date|Mon, 29 Apr 2019 14:08:51 GMT]]
[[Property:title|Eiffel programming language syntax]]
[[Property:link_title|Syntax]]
[[Property:weight|0]]
[[Property:uuid|4CB56AD5-1586-41F6-9E81-085F47E992DC]]
The syntax specification shown here is a less complete and less formal version of that which is in the Eiffel ISO/ECMA standard document. The format is BNF-E. The Language Specification section of the standard document includes an overview of BNF-E.
There are a few parts of the syntax that are either non-production or non-representable in BNF-E. Some of these have been omitted from the following specification. These omitted parts of the syntax definition add to the precision of the specification, but knowledge of them is not always vital for developers.
In the BNF-E representation, generally non-terminals which are defined in the same group of productions in which they are used are not linked. However when a non-terminal is defined outside a group in which it is used, it is linked to the group in which it is defined.
__TOC__
The following section contains those non-production elements of the specification that are used later in the BNF-E specification.
==Eiffel non-production elements==
===Identifiers===
An '''identifier''' is a sequence of one or more alphanumeric [[#Characters|characters]] of which the first is a letter.
The definition is augmented by the rule that Identifiers are not valid if they are the same as one of the language's reserved words.
===Characters===
Characters are either:
* All 32-bit, corresponding to Unicode and to the Eiffel type CHARACTER_32.
* All 8-bit, corresponding to 8-bit extended ASCII and to the Eiffel type CHARACTER_8
===Reals===
A real -- specimen of Real -- is made of the following elements, in the order given:
* An optional decimal [[#Integers|Integer]], giving the integral part.
* A required "." (dot).
* An optional decimal [[#Integers|Integer]], giving the fractional part.
* An optional exponent, which is the letter ''e'' or ''E'' followed by an optional [[#Manifest constants|Sign]] and a decimal [[#Integers|Integer]].
No intervening character (blank or otherwise) is permitted between these elements. The integral and fractional parts may not both be absent.
===Strings===
A string -- specimen of construct String -- is a sequence of zero or more manifest characters.
===Simple strings===
A simple string -- specimen of Simple_string -- is a [[#Strings|String]] consisting of at most one line (that is to say, containing no embedded new-line manifest character), possibly containing [[#Special characters|codes for special characters]].
===Special characters===
{| border="2"
|+ Special Characters and Their Codes
|-
! Character
! Code
! Mnemonic name
|-
| @ || %A || At-sign
|-
| BS || %B || Backspace
|-
| ^ || %C || Circumflex
|-
| $ || %D || Dollar
|-
| FF || %F || Form feed
|-
| \ || %H || Backslash
|-
| ~ || %L || Tilde
|-
| NL (LF) || %N || Newline
|-
| `` ` `` || %Q || Backquote
|-
| CR || %R || Carriage return
|-
| # || %S || Sharp
|-
| HT || %T || Horizontal tab
|-
| NUL || %U || Null
|-
| &#124; || %V || Vertical bar
|-
| % || %% || Percent
|-
| ' || %' || Single quote
|-
| " || %" || Double quote
|-
| [ || %( || Opening bracket
|-
| ] || %) || Closing bracket
|-
| { || %< || Opening brace
|-
| } || %> || Closing brace
|}
* `%/123/` represents the character with decimal code `123` .
* And only for manifest character (for now)
** `'%/0x2200/'` represents the character with hexadecimal code U+2200 = '∀' (note `'%/0x2200/' = '%/8704/'` )
** `'%/0c21000/'` in octal
** `'%/0b10001000000000/'` in binary
===Line wrapping parts===
A sequence of characters consisting of the following, in order:
* % (percent character)
* Zero or more blanks or tabs
* New line (Line feed)
* Zero or more blanks or tabs
* % (percent character)
Line wrapping parts are used as separators between one [[#Simple strings|Simple_string]] and the next in a [[#Manifest strings|Basic_manifest_string]] so that the string can be split across lines.
===New line===
A specimen of New_line is a New Line.
==Eiffel BNF-E Syntax==
===Class names ===
Class_name ::= [[#Identfiers|Identifier]]
===Class declarations ===
Class_declaration ::= <nowiki>[</nowiki>[[#Notes|Notes]]<nowiki>]</nowiki>
[[#Class headers|Class_header]] <nowiki>[</nowiki>[[#Formal generic parameters|Formal_generics]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Obsolete marks|Obsolete]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Inheritance parts|Inheritance]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Creators parts|Creators]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Converter clauses|Converters]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Feature parts|Features]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Notes|Notes]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Assertions|Invariant]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Notes|Notes]]<nowiki>]</nowiki>
<code>end</code>
===Notes ===
Notes ::= <code>note</code> Note_list
Note_list ::= {Note_entry ";" ...}*
Note_entry ::= Note_name Note_values
Note_name ::= [[#Identifiers|Identifier]] ":"
Note_values ::= {Note_item ","...}+
Note_item ::= [[#Identifiers|Identifier]] | [[#Manifest constants|Manifest_constant]]
===Class headers ===
Class_header ::= <nowiki>[Header_mark]</nowiki> <code>class</code> [[#Class names|Class_name]]
Header_mark ::= <code>deferred</code> | <code>expanded</code> | <code>frozen</code>
===Obsolete marks ===
Obsolete ::= <code>obsolete</code> Message
Message ::= [[#Manifest strings|Manifest_string]]
===Feature parts ===
Features ::= Feature_clause+
Feature_clause ::= <code>feature</code> <nowiki>[</nowiki>[[#Clients|Clients]]<nowiki>]</nowiki> <nowiki>[</nowiki>[[#Feature parts|Header_comment]]<nowiki>]</nowiki> Feature_declaration_list
Feature_declaration_list ::= {[[#Feature declarations|Feature_declaration]] ";" ...}*
Header_comment ::= [[#Comments|Comment]]
===Feature declarations ===
Feature_declaration ::= [[#New feature lists|New_feature_list]] Declaration_body
Declaration_body ::= <nowiki>[</nowiki>[[#Formal argument and entity declarations|Formal_arguments]]<nowiki>] [Query_mark] [Feature_value] </nowiki>
Query_mark ::= Type_mark <nowiki>[</nowiki>[[#Assigner marks|Assigner_mark]]<nowiki>]</nowiki>
Type_mark ::= ":" [[#Types|Type]]
Feature_value ::= <nowiki>[Explicit_value] </nowiki>
<nowiki>[</nowiki>[[#Obsolete parts|Obsolete]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Feature parts|Header_comment]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Feature bodies|Attribute_or_routine]]<nowiki>]</nowiki>
Explicit_value ::= "=" [[#Manifest constants|Manifest_constant]]
===New feature lists ===
New_feature_list ::= {New_feature "," ...}+
New_feature ::= <nowiki>[</nowiki><code>frozen</code><nowiki>]</nowiki> [[#Feature names|Extended_feature_name]]
===Feature bodies ===
Attribute_or_routine ::= <nowiki>[</nowiki>[[#Assertions|Precondition]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Local variable declarations|Local_declarations]]<nowiki>]</nowiki>
Feature_body
<nowiki>[</nowiki>[[#Assertions|Postcondition]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Rescue clauses|Rescue]]<nowiki>]</nowiki>
<code>end</code>
Feature_body ::= [[#Routine bodies|Deferred]] | [[#Routine bodies|Effective_routine]] | [[#Attribute bodies|Attribute]]
===Feature names ===
Extended_feature_name ::= Feature_name <nowiki>[Alias]</nowiki>
Feature_name ::= [[#Identfiers|Identifier]]
Alias ::= <code>alias</code> '"' Alias_name '"' <nowiki>[</nowiki><code>convert</code><nowiki>]</nowiki>
Alias_name ::= [[#Operators|Operator]] | Bracket
Bracket ::= "<nowiki>[ ]</nowiki>"
===Operators ===
Operator ::= Unary | Binary
Unary ::= <code>not</code> | "+" | "-" | Free_unary
Binary ::= <nowiki>"+" | "-" | "*" | "/" | "//" | "\\" | "^" | ".." | "<" | ">" | "<=" | ">=" |</nowiki> <code>and</code> | <code>or</code> | <code>xor</code> | <code>and</code> <code>then</code> | <code>or</code> <code>else</code> | <code>implies</code> | Free_binary
{{note| Free_unary and Free_binary are free operators that are distinct from (respectively) the ''standard'' unary and binary operators (one- or two-character symbols) explicitly listed in the Unary and Binary productions. See ''Definition: Free operator'' in the standard for more precision.}}
===Assigner marks ===
Assigner_mark ::= <code>assign</code> [[#Feature names|Feature_name]]
===Inheritance parts ===
Inheritance ::= Inherit_clause+
Inherit_clause ::= <code>inherit</code> <nowiki>[Non_conformance]</nowiki> Parent_list
Non_conformance ::= "{" NONE "}"
Parent_list ::= {Parent ";" ...}+
Parent ::= [[#Types|Class_type]] <nowiki>[Feature_adaptation]</nowiki>
Feature_adaptation ::= <nowiki>[</nowiki>[[#Undefine clauses|Undefine]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Redefinition|Redefine]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Rename clauses|Rename]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Export adaptation|New_exports]]<nowiki>]</nowiki>
<nowiki>[</nowiki>[[#Select clauses|Select]]<nowiki>]</nowiki>
<code>end</code>
===Rename clauses ===
Rename ::= <code>rename</code> Rename_list
Rename_list ::= {Rename_pair "," ...}+
Rename_pair ::= [[#Feature names|Feature_name]] <code>as</code> [[#Feature names|Extended_feature_name]]
===Clients ===
Clients ::= "{" Class_list "}"
Class_list ::= {[[#Class names|Class_name]] "," ...}+
===Export adaptation ===
New_exports ::= <code>export</code> New_export_list
New_export_list ::= {New_export_item ";" ...}+
New_export_item ::= [[#Clients|Clients]] <nowiki>[</nowiki>[[#Feature parts|Header_comment]]<nowiki>]</nowiki> Feature_set
Feature_set ::= Feature_list | <code>all</code>
Feature_list ::= {[[#Feature names|Feature_name]] "," ...}+
===Formal argument and entity declarations ===
Formal_arguments ::= "(" [[#Formal argument and entity declarations|Entity_declaration_list]] ")"
Entity_declaration_list ::= {Entity_declaration_group ";" ...}+
Entity_declaration_group ::= Identifier_list [[#Feature declarations|Type_mark]]
Identifier_list ::= {[[#Identfiers|Identifier]] "," ...}+
===Routine bodies ===
Deferred ::= <code>deferred</code>
Effective_routine ::= Internal | [[#External routines|External]]
Internal ::= Routine_mark [[#Instructions|Compound]]
Routine_mark ::= <code>do</code> | Once
Once ::= <code>once</code> <nowiki>[</nowiki> "("Key_list ")" <nowiki>]</nowiki>
Key_list ::= {[[#Manifest strings|Manifest_string]] "," ...}+
===Local variable declarations ===
Local_declarations ::= <code>local</code> <nowiki>[</nowiki>[[#Formal argument and entity declarations|Entity_declaration_list]]<nowiki>]</nowiki>
===Instructions ===
Compound ::= {Instruction ";" ...}*
Instruction ::= [[#Creation instructions|Creation_instruction]] | [[#Feature calls|Call]] | [[#Assignments|Assignment]] | [[#Assigner calls|Assigner_call]] | [[#Conditionals|Conditional]] | [[#Multi-branch instructions|Multi_branch]]
| [[#Loops|Loop]] | [[#Debug instructions|Debug]] | [[#Precursor|Precursor]] | [[#Check instructions|Check]] | [[#Rescue clauses|Retry]]
===Assertions ===
Precondition ::= <code>require</code> <nowiki>[</nowiki><code>else</code><nowiki>]</nowiki> Assertion
Postcondition ::= <code>ensure</code> <nowiki>[</nowiki><code>then</code><nowiki>]</nowiki> Assertion <nowiki>[</nowiki>[[#"Only" postcondition clauses|Only]]<nowiki>]</nowiki>
Invariant ::= <code>invariant</code> Assertion
Assertion ::= {Assertion_clause ";" ...}*
Assertion_clause ::= <nowiki>[</nowiki>Tag_mark<nowiki>]</nowiki> Unlabeled_assertion_clause
Unlabeled_assertion_clause ::= [[#Expressions|Boolean_expression]] | [[#Comments|Comment]] | `class`
Tag_mark ::= Tag ":"
Tag ::= [[#Identfiers|Identifier]]
{{Note|Unlabeled_assertion_clause of the form `class` can be used only in a postcondition. It marks a feature that does not depend on object state and can be called without a target object using non-object call of the form `{CLASS_NAME}.feature_name (arguments)`.}}
==="Old" postcondition expressions ===
Old ::= <code>old</code> [[#Expressions|Expression]]
==="Only" postcondition clauses ===
Only ::= <code>only</code> <nowiki>[</nowiki>[[#Export adaptation|Feature_list]]<nowiki>]</nowiki>
===Check instructions ===
Check ::= <code>check</code> [[#Assertions|Assertion]] <nowiki>[</nowiki>[[#Notes|Notes]]<nowiki>]</nowiki> <code>end</code>
===Variants ===
Variant ::= <code>variant</code> <nowiki>[</nowiki>[[#Assertions|Tag_mark]]<nowiki>]</nowiki> [[#Expressions|Expression]]
===Precursor ===
Precursor ::= <code>Precursor</code> [Parent_qualification] <nowiki>[</nowiki>[[#Actual arguments|Actuals]]<nowiki>]</nowiki>
Parent_qualification ::= "{" [[#Class names|Class_name]] "}"
===Redefinition ===
Redefine ::= <code>redefine</code> [[#Export adaptation|Feature_list]]
===Undefine clauses ===
Undefine ::= <code>undefine</code> [[#Export adaptation|Feature_list]]
===Types ===
Type ::= Class_or_tuple_type | [[#Formal generic parameters|Formal_generic_name]] | Anchored
Class_or_tuple_type ::= Class_type | [[#Tuple types|Tuple_type]]
Class_type ::= [Attachment_mark] [[#Class names|Class_name]] <nowiki>[</nowiki>[[#Actual generic parameters|Actual_generics]]<nowiki>]</nowiki>
Attachment_mark ::= "?" | "!"
Anchored ::= [Attachment_mark] <code>like</code> Anchor
Anchor ::= [[#Feature names|Feature_name]] | <code>Current</code>
===Actual generic parameters ===
Actual_generics ::= <nowiki>"[" Type_list "]"</nowiki>
Type_list ::= {[[#Types|Type]] "," ...}+
===Formal generic parameters ===
Formal_generics ::= <nowiki>"[" Formal_generic_list "]"</nowiki>
Formal_generic_list ::= {Formal_generic ","...}+
Formal_generic ::= <nowiki>[</nowiki><code>frozen</code><nowiki>]</nowiki> Formal_generic_name <nowiki>[</nowiki>[[#Generic constraints|Constraint]]<nowiki>]</nowiki>
Formal_generic_name ::= <nowiki>[?]</nowiki> [[#Identfiers|Identifier]]
===Generic constraints ===
Constraint ::= "->" Constraining_types <nowiki>[Constraint_creators]</nowiki>
Constraining_types ::= Single_constraint | Multiple_constraint
Single_constraint ::= [[#Types|Type]] [Renaming]
Renaming ::= [[#Rename clauses|Rename]] <code>end</code>
Multiple_constraint ::= "{" Constraint_list "}"
Constraint_list ::= {Single_constraint "," ...}+
Constraint_creators ::= <code>create</code> [[#Export adaptation|Feature_list]] <code>end</code>
===Manifest arrays ===
Manifest_array ::= <nowiki>[</nowiki>Manifest_array_type<nowiki>]</nowiki> <code><<</code> Expression_list <code>>></code>
Manifest_array_type ::= <code>{</code> [[#Types|Type]] <code>}</code>
Expression_list ::= {[[#Expressions|Expression]] <code>,</code> ...}*
===Tuple types ===
Tuple_type ::= <code>TUPLE</code> <nowiki>[Tuple_parameter_list]</nowiki>
Tuple_parameter_list ::= <nowiki>"[" Tuple_parameters "]"</nowiki>
Tuple_parameters ::= [[#Actual generic parameters|Type_list]] | [[#Formal argument and entity declarations|Entity_declaration_list]]
===Manifest tuples ===
Manifest_tuple ::= <nowiki>"["</nowiki> [[#Manifest arrays|Expression_list]] <nowiki>"]"</nowiki>
===Converter clauses ===
Converters ::= <code>convert</code> Converter_list
Converter_list ::= {Converter ","...}+
Converter ::= Conversion_procedure | Conversion_query
Conversion_procedure ::= [[#Feature names|Feature_name]] "(" "{" [[#Actual generic parameters|Type_list]] "}" ")"
Conversion_query ::= [[#Feature names|Feature_name]] ":" "{" [[#Actual generic parameters|Type_list]] "}"
===Select clauses ===
Select ::= <code>select</code> [[#Export adaptation|Feature_list]]
===Conditionals ===
Conditional ::= <code>if</code> Then_part_list <nowiki>[Else_part]</nowiki> <code>end</code>
Then_part_list ::= {Then_part <code>elseif</code> ...}+
Then_part ::= [[#Expressions|Boolean_expression]] <code>then</code> [[#Instructions|Compound]]
Else_part ::= <code>else</code> [[#Instructions|Compound]]
Conditional_expression ::= <code>if</code> Then_part_expression_list <code>else</code> [[#Expressions|Expression]] <code>end</code>
Then_part_expression_list ::= {Then_part_expression <code>elseif</code> ...}+
Then_part_expression ::= [[#Expressions|Boolean_expression]] <code>then</code> [[#Expressions|Expression]]
===Multi-branch instructions ===
Multi_branch ::= <code>inspect</code> [[#Expressions|Expression]] <nowiki>[When_part_list] [Else_part]</nowiki> <code>end</code>
When_part_list ::= When_part+
When_part ::= <code>when</code> Choices <code>then</code> [[#Instructions|Compound]]
Choices ::= {Choice "," ...}+
Choice ::= [[#Constants|Constant]] | [[#Manifest constants|Manifest_type]] | Constant_interval | Type_interval
Constant_interval ::= [[#Constants|Constant]] ".." [[#Constants|Constant]]
Type_interval ::= [[#Manifest constants|Manifest_type]] ".." [[#Manifest constants|Manifest_type]]
===Loops ===
Loop ::=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>[</nowiki>Iteration<nowiki>]</nowiki><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>[</nowiki>Initialization<nowiki>]</nowiki><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>[</nowiki>[[#Assertions|Invariant]]<nowiki>]</nowiki><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>[</nowiki>Exit_condition<nowiki>]</nowiki><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Loop_body<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<nowiki>[</nowiki>[[#Variants|Variant]]<nowiki>]</nowiki><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>end</code>
Iteration ::= <code>across</code> [[#Expressions|Expression]] <code>as</code> [[#Identfiers|Identifier]]
Initialization ::= <code>from</code> [[#Instructions|Compound]]
Exit_condition ::= <code>until</code> [[#Expressions|Boolean_expression]]
Loop_body ::=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>loop</code> [[#Instructions|Compound]] |<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>all</code> [[#Expressions|Boolean_expression]] |<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>some</code> [[#Expressions|Boolean_expression]]
===Debug instructions ===
Debug ::= <code>debug</code> <nowiki>[</nowiki> "("[[#Routine_bodies|Key_list]] ")" ] [[#Instructions|Compound]] <code>end</code>
===Attribute bodies ===
Attribute ::= <code>attribute</code> [[#Instructions|Compound]]
===Entities and variables ===
Entity ::= Variable | Read_only
Variable ::= Variable_attribute | Local
Variable_attribute ::= [[#Feature names|Feature_name]]
Local ::= [[#Identfiers|Identifier]] | <code>Result</code>
Read_only ::= Formal | Constant_attribute | <code>Current</code>
Formal ::= [[#Identfiers|Identifier]]
Constant_attribute ::= [[#Feature names|Feature_name]]
===Creators parts ===
Creators ::= Creation_clause+
Creation_clause ::= <code>create</code> <nowiki>[</nowiki>[[#Clients|Clients]]<nowiki>]</nowiki> <nowiki>[</nowiki>[[#Feature parts|Header_comment]]<nowiki>]</nowiki> Creation_procedure_list
Creation_procedure_list ::= {Creation_procedure ","...}+
Creation_procedure ::= [[#Feature names|Feature_name]]
===Creation instructions ===
Creation_instruction ::= <code>create</code> <nowiki>[Explicit_creation_type]</nowiki> Creation_call
Explicit_creation_type ::= "{" [[#Types|Type]] "}"
Creation_call ::= [[#Entities and variables|Variable]] [Explicit_creation_call]
Explicit_creation_call ::= "." [[#Feature calls|Unqualified_call]]
===Creation expressions ===
Creation_expression ::= <code>create</code> [[#Creation instructions|Explicit_creation_type]] <nowiki>[</nowiki>[[#Creation instructions|Explicit_creation_call]]<nowiki>]</nowiki>
===Equality expressions ===
Equality ::= [[#Expressions|Expression]] Comparison [[#Expressions|Expression]]
Comparison ::= "=" | "/=" | "~" | "/~"
===Assignments ===
Assignment ::= [[#Entities and variables|Variable]] ":=" [[#Expressions|Expression]]
===Assigner calls ===
Assigner_call ::= [[#Expressions|Expression]] ":=" [[#Expressions|Expression]]
===Feature calls ===
Call ::= Object_call | Non_object_call
Object_call ::= <nowiki>[Target "."] Unqualified_call </nowiki>
Unqualified_call ::= [[#Feature names|Feature_name]] <nowiki>[</nowiki>[[#Actual arguments|Actuals]]<nowiki>]</nowiki>
Target ::= [[#Entities and variables|Local]] | [[#Entities and variables|Read_only]] | Call | Parenthesized_target
Parenthesized_target ::= <code>(</code> [[#Expressions|Expression]] <code>)</code>
Non_object_call ::= "{" [[#Types|Type]] "}" "." Unqualified_call
===Actual arguments ===
Actuals ::= "(" Actual_list ")"
Actual_list ::= {[[#Expressions|Expression]] "," ...}+
===Object test ===
Object_test ::= "{" [[#Identfiers|Identifier]] ":" [[#Types|Type]] "}" [[#Expressions|Expression]]
===Rescue clauses ===
Rescue ::= <code>rescue</code> [[#Instructions|Compound]]
Retry ::= <code>retry</code>
===Agents ===
Agent ::= Call_agent | Inline_agent
Call_agent ::= <code>agent</code> [[#Call agent bodies|Call_agent_body]]
Inline_agent ::= <code>agent</code> <nowiki>[</nowiki>[[#Formal argument and entity declarations|Formal_arguments]]<nowiki>]</nowiki> <nowiki>[</nowiki>[[#Feature declarations|Type_mark]]<nowiki>]</nowiki> <nowiki>[</nowiki>[[#Feature bodies|Attribute_or_routine]]<nowiki>]</nowiki> <nowiki>[</nowiki>[[#Call agent bodies|Agent_actuals]]<nowiki>]</nowiki>
===Call agent bodies ===
Call_agent_body ::= Agent_qualified | Agent_unqualified
Agent_qualified ::= Agent_target ". " Agent_unqualified
Agent_unqualified ::= [[#Feature names|Feature_name]] [Agent_actuals]
Agent_target ::= Entity | Parenthesized | [[#Manifest constants|Manifest_type]]
Agent_actuals ::= "(" Agent_actual_list ")"
Agent_actual_list ::= {Agent_actual "," ...}+
Agent_actual ::= [[#Expressions|Expression]] | Placeholder
Placeholder ::= <nowiki>[</nowiki>[[#Manifest constants|Manifest_type]]<nowiki>]</nowiki> "?"
===Expressions ===
Expression ::= Basic_expression | Special_expression
Basic_expression ::= [[#Entities and variables|Read_only]] | [[#Entities and variables|Local]] | [[#Feature calls|Call]] | [[#Precursor|Precursor]] | [[#Equality expressions|Equality]] | Parenthesized | [[#"Old" postcondition expressions|Old]] |
[[#Operator expressions|Operator_expression]] | [[#Bracket expressions|Bracket_expression]] | [[#Creation expression|Creation_expression]] | [[#Conditionals|Conditional_expression]]
Special_expression ::= [[#Manifest constants|Manifest_constant]] | [[#Manifest arrays|Manifest_array]] | [[#Manifest tuples|Manifest_tuple]] | [[#Agents|Agent]] | [[#Object test|Object_test]] | Once_string |
Address
Parenthesized ::= "(" Expression ")"
Address ::= "$" [[#Entities and variables|Variable]]
Once_string ::= <code>once</code> [[#Manifest strings|Manifest_string]]
Boolean_expression ::= Basic_expression | [[#Manifest constants|Boolean_constant]] | [[#Object test|Object_test]]
===Operator expressions ===
Operator_expression ::= Unary_expression | Binary_expression
Unary_expression ::= Unary Expression
Binary_expression ::= [[#Expressions|Expression]] [[#Operators|Binary]] [[#Expressions|Expression]]
===Bracket expressions ===
Bracket_expression ::= Bracket_target "[" [[#Actual arguments|Actuals]] "]"
Bracket_target ::= [[#Feature calls|Target]] | [[#Expressions|Once_string]] | [[#Manifest constants|Manifest_constant]] | [[#Manifest tuples|Manifest_tuple]]
===Constants ===
Constant ::= [[#Manifest constants|Manifest_constant]] | Constant_attribute
Constant_attribute ::= [[#Feature names|Feature_name]]
===Manifest constants ===
Manifest_constant ::= [Manifest_type] Manifest_value
Manifest_type ::= "{" [[#Types|Type]] "}"
Manifest_value ::= Boolean_constant |
Character_constant |
Integer_constant |
Real_constant |
[[#Manifest strings|Manifest_string]] |
Manifest_type
Sign ::= "+" | "-"
Integer_constant ::= <nowiki>[Sign]</nowiki> [[#Integers|Integer]]
Character_constant ::= " ' " [[#Characters|Character]] " ' "
Boolean_constant ::= <code>True</code> | <code>False</code>
Real_constant ::= <nowiki>[Sign]</nowiki> [[#Reals|Real]]
===Manifest strings ===
Manifest_string ::= Basic_manifest_string | Verbatim_string
Basic_manifest_string ::= ' " ' String_content ' " '
String_content ::= {[[#Simple strings|Simple_string]] [[#Line wrapping parts|Line_wrapping_part]] ...}+
Verbatim_string ::= Verbatim_string_opener Line_sequence Verbatim_string_closer
Verbatim_string_opener ::= ' " ' <nowiki>[</nowiki>[[#Simple strings|Simple_string]]<nowiki>]</nowiki> Open_bracket
Verbatim_string_closer ::= Close_bracket <nowiki>[</nowiki>[[#Simple strings|Simple_string]]<nowiki>]</nowiki> ' " '
Open_bracket ::= <nowiki>"[" | "{"</nowiki>
Close_bracket ::= "]" | "}"
Line_sequence ::= {[[#Simple strings|Simple_string]] [[#New line|New_line]] ...}+
{{Note|Exactly the same [[#Simple strings|Simple_string]] (including embedded white space, if any) should be used in ''Verbatim_string_opener'' and ''Verbatim_string_closer'' of the same verbatim string.}}
===External routines ===
External ::= <code>external</code> External_language <nowiki>[External_name]</nowiki>
External_language ::= Unregistered_language | [[#Registered languages|Registered_language]]
Unregistered_language ::= [[#Manifest strings|Manifest_string]]
External_name ::= <code>alias</code> [[#Manifest strings|Manifest_string]]
{{note|If the `inline` keyword is used in the Registered_language part, then External_name part is the inline code on the specified language.}}
===Registered languages ===
Registered_language ::= [[#C externals|C_external]] | [[#C++ externals|C++_external]] | [[#DLL externals|DLL_external]]
===External signatures ===
External_signature ::= <code>signature</code> <nowiki>[External_argument_types] [: External_type]</nowiki>
External_argument_types ::= "(" External_type_list ")"
External_type_list ::= {External_type "," ...}*
External_type ::= [[#Simple strings|Simple_string]]
===External file use ===
External_file_use ::= <code>use</code> External_file_list
External_file_list ::= {External_file "," <nowiki>... }+ </nowiki>
External_file ::= External_user_file | External_system_file
External_user_file ::= ' " ' [[#Simple strings|Simple_string]] ' " '
External_system_file ::= <nowiki>"<"</nowiki> [[#Simple strings|Simple_string]] <nowiki>">"</nowiki>
===C externals ===
C_external ::= ' " ' <code>C</code> <nowiki>[</nowiki><code>inline</code>] <nowiki>[</nowiki> [[#External signatures |External_signature]] <nowiki>] [</nowiki> [[#External file use |External_file_use]] <nowiki>] ' " '</nowiki>
===C++ externals ===
C++_external ::= ' " ' <code>C++</code> <code>inline</code> <nowiki>[</nowiki> [[#External signatures |External_signature]] <nowiki>] [</nowiki> [[#External file use |External_file_use]] <nowiki>] ' " '</nowiki>
===DLL externals ===
DLL_external ::= ' " ' <code>dll</code> <nowiki>[</nowiki><code>windows</code><nowiki>] DLL_identifier [DLL_index] [[</nowiki> [[#External signatures |External_signature]] <nowiki>] [</nowiki> [[#External file use |External_file_use]] <nowiki>] ' " ' </nowiki>
DLL_identifier ::= [[#Simple strings|Simple_string]]
DLL_index ::= [[#Integers|Integer]]
===Comments ===
Comment ::= "- -" <nowiki>{</nowiki>[[#Simple strings|Simple_string]] Comment_break ...}*
Comment_break ::= New_line <nowiki>[Blanks_or_tabs] "- -"</nowiki>
===Integers ===
Integer ::= <nowiki>[Integer_base]</nowiki> Digit_sequence
Integer_base ::= "0" Integer_base_letter
Integer_base_letter ::= "b" | "c" | "x" | "B" | "C" | "X"
Digit_sequence ::= Digit+
Digit ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" |
"a" | "b" | "c" | "d" | "e" | "f" |
"A" | "B" | "C" | "D" | "E" | "F" | "_"

View File

@@ -0,0 +1,16 @@
[[Property:title|Quick reference to the Eiffel programming language]]
[[Property:link_title|Quick Reference]]
[[Property:weight|4]]
[[Property:uuid|4f61365d-59f6-a394-678b-144bad8ec12f]]
The Quick Reference to the Eiffel programming language provides an informal guide to the syntax and reserved words of the language. The Eiffel programming language is described in detail in the '''ISO/ECMA''' standard document, available [http://www.ecma-international.org/publications/standards/Ecma-367.htm online].
Sometimes there are differences between the language as defined by the standard and that which is implemented by Eiffel Software. These differences are documented in the online documentation.
So, the final authority on Eiffel as implemented by Eiffel Software is the content of the standard document, amended by those variances cited in the [[Differences between standard ECMA-367 and Eiffel Software implementation|"differences" chapter of the online documentation]].
This reference is based on the June 2006 ISO/ECMA standard document.

View File

@@ -0,0 +1,88 @@
[[Property:title|Void-safe changes to Eiffel libraries]]
[[Property:weight|0]]
[[Property:uuid|dc993c0e-fbec-dc5a-82c8-fbfd9fa9bc3a]]
==Overview==
During the adoption of void-safety, the software libraries provided by Eiffel Software have been converted to be void-safe. The bulk of the changes made to these libraries will have little or no adverse effect on your existing software as you go through the process of void-safe conversion. However, there are a few changes to the library that we consider "breaking" changes, that is, important changes that might cause problems in existing systems that use certain library classes.
{{note|Many of these changes were in effect in the ''experimental'' mode of versions 6.4 and 6.5. With the release of version 6.6, the ''experimental'' mode of previous versions became the ''default'' mode and, consequently may have caused these changes to become more apparent to some users. A ''compatibility'' mode is available to ease transition. The ''compatibility'' mode is accessible using the <code>-compat</code> command line option or through the EiffelStudio choices provided through the Microsoft Windows ''Start'' button. }}
==Important changes to library classes==
===Class ARRAY===
====New preconditions====
Some additional preconditions are in force in <code>ARRAY</code> in void-safe mode.
In void-unsafe mode, the behavior is equivalent to that of previous versions.
====Feature make_from_special====
The signature of this routine has changed.
Current signature: <code>make_from_special (a: SPECIAL [G])</code>
Previous signature: <code>make_from_special (a: SPECIAL [G]; min_index, max_index: INTEGER)</code>
Using the current version will create an array with a range from 1 to the number of elements in the argument `a`.
====Feature auto_resize====
This implementation (private) feature has been removed.
===Class ARRAYED_LIST===
====Relationship to ARRAY====
Previously <code>ARRAYED_LIST</code> conformed to <code>ARRAY</code>. This is no longer the case. The feature <code>{ARRAYED_LIST}.to_array</code> can be used to produce an instance of <code>ARRAY</code> from an instance of <code>ARRAYED_LIST</code>.
====Features count and area====
Previously these two queries, <code>count</code> and <code>area</code>, were attributes. They are now functions.
===Class HASH_TABLE===
The internal implementation has changed in ways that cause the order of traversal to differ from previous versions.
===Classes SPECIAL and TO_SPECIAL===
====Feature {SPECIAL}.make====
This void-unsafe feature has been removed.
In its place, the creation procedures <code>{SPECIAL}.make_filled</code> and <code>{SPECIAL}.make_empty</code> can be used.
<code>{SPECIAL}.make_filled</code> is available in both ''default'' and ''compatible'' modes. Use this creation procedure if you want code that is compatible with both modes.
<code>{SPECIAL}.make_empty</code> is available in ''default'' mode only.
====Feature {TO_SPECIAL}.make_area====
In order to reflect the above change to class <code>SPECIAL</code>, the <code>make_area</code> feature of <code>TO_SPECIAL</code> has been removed in favor of <code>{TO_SPECIAL}.make_filled_area</code> and <code>{TO_SPECIAL}.make_empty_area</code>.
The availability of <code>{TO_SPECIAL}.make_filled_area</code> and <code>{TO_SPECIAL}.make_empty_area</code> corresponds to that noted above for the creation features of <code>SPECIAL</code>:
<code>{TO_SPECIAL}.make_filled_area</code> is available in both ''default'' and ''compatible'' modes. Use <code>make_filled_area</code> for code that needs to compile in both modes.
<code>{TO_SPECIAL}.make_empty_area</code> is available only in ''default'' mode.
====Relationship of feature {SPECIAL}.count to {SPECIAL}.capacity====
In previous versions, for a particular instance of <code>SPECIAL</code> the queries <code>count</code> and <code>capacity</code> yielded the same value.
This is no longer always true. If an instance of <code>SPECIAL</code> is created with, for example, <code>make_empty (10)</code>, although the <code>capacity</code> will be 10, the <code>count</code> will be zero.
However creating a <code>SPECIAL</code> using <code>make_filled</code> will produce an instance in which <code>count</code> and <code>capacity</code> are equal upon creation. So the behavior is similar to that of previous versions. Also, <code>make_filled</code> is available in both ''default'' and ''compatible'' modes.
If your code depends upon <code>count</code> and <code>capacity</code> having the same value, then you can use <code>make_filled</code> for creation. And then if you need resizing, use the "_with_default" versions of the "resized" features, specifically <code>resized_area_with_default</code> and <code>aliased_resized_area_with_default</code>.

View File

@@ -0,0 +1,335 @@
[[Property:title|Converting existing software to void-safety]]
[[Property:weight|6]]
[[Property:uuid|eb901272-d405-2277-005d-e37275b9baa4]]
If you have been using Eiffel for a while, you may be maintaining systems which were developed before Eiffel became void-safe. If that's the case, then you will probably want to make those systems void-safe.
In this section we will use the experience of converting a set of simple (but not too simple) legacy Eiffel classes to show the types of issues that you may encounter, and how to deal with them.
So in the discussion below, you will see references to these classes:
{| border="1"
|-
! Class name
! Description
|-
| APPLICATION
| Simple root class containing declarations of types NVP and NVP_LIST
|-
| NVP
| Class modeling name/value pairs of type STRING
|-
| NVP_LIST
| Class modeling a list of NVP's with specialized behavior; heir of TWO_WAY_LIST [NVP]
|}
It's not important that you know much about the details of these classes. We will, however, look at certain parts of the classes in enough detail to resolve the conversion issues.
=Conversion considerations=
==To redesign or not to redesign==
During the process of conversion of classes to void-safety, the compiler will point out problems which you will have to fix. Some of these will be straightforward, while others may be tricky. It is natural, or sometimes mandatory, at times to consider changing elements of the design of your software.
Also, as you sift through your existing software during the void-safe conversion, you may not get very far before you see things that you wish had been done differently. This occurs often during reviews of existing systems, not just because of the introduction of void-safety.
In the discussions that follow you will see these redesign opportunities arise, and the decisions that were made for these cases.
==Be aware of changes to Eiffel libraries==
The libraries distributed with EiffelStudio have been converted to support void-safety. Mostly the changes made will cause no problems for existing software. However a few changes have been identified as "breaking" changes. You may or may not encounter the effects of these changes, but you should be aware of how they could effect your software and what options you have for adapting to them. Breaking changes are described in the [[EiffelStudio release notes]] and in the page dedicated to [[Void-safe changes to Eiffel libraries]].
=Conversion process=
==Enable full class checking==
First make sure your project will compile correctly under the configuration of EiffelStudio that you intend to use to convert to void-safe.
Then set the project setting '''Full Class Checking''' to '''True'''. Do a ''[[Clean compile|clean compile]]'' of your system.
Full class checking will analyze your classes to make sure that in cases of inheritance, features of the parent classes are rechecked for validity in the heirs.
Here's an example of the kind of error you might expect when compiling with full class checking:
[[Image:VGCC error]]
The situation here is that the feature <code>split</code> has been inherited (from class <code>TWO_WAY_LIST [G]</code>) by our class <code>NVP_LIST</code>. Feature <code>split</code> includes code to create and attach feature <code>sublist</code> which is typed <code>attached like Current</code> which in this case means <code>attached NVP_LIST</code>. To do this creation, <code>split</code> uses a creation procedure <code>make_sublist</code>.
Now here's the rub: <code>NVP_LIST</code> has not named <code>make_sublist</code> as a creation procedure:
<code>
create
make, make_from_string, make_from_file_named
</code>
If we go to the <code>create</code> part of <code>NVP_LIST</code> and add <code>make_sublist</code> to its list of creation procedures, this will fix the problem:
<code>
create
make, make_from_string, make_from_file_named, make_sublist
</code>
So, fix any problems that arise out of turning on full class checking.
==Enable other project settings==
The second step in conversion of existing software is to change the values of the other void-safe related project settings and use the void-safe configurations for any delivered libraries and precompilations.
In the project settings for the target in which you are working, set '''Void safety''' to '''Complete''', '''Transitional''' , '''Initialization''' or '''Conformance'''.
{{note|Remember that during a transitional period starting with v6.4, there will be multiple versions of the configuration files for Eiffel libraries and precompiles. For example, base.ecf (void-unsafe) and base-safe.ecf (void-safe). Starting with v16.11 there is only one configuration file for libraries (e.g., base.ecf) that works with both void-safe and void-unsafe client software, but if you are using a precompile, there could be different versions for void-safe and void-unsafe precompiles.}}
If necessary, remove Eiffel libraries and any precompiled library that your project uses and re-add them with their void-safe configuration files. Because you've set your target to void-safety, when you click '''Add Library''', you should see only void-safe configurations by default.
You will see a check box on the dialog that you can uncheck if you want to see all available library configurations:
[[Image:VoidSafeAddLibraryDialog]]
Now do a [[Clean compile|clean compile]].
If you've replaced a precompiled library that you have not already built, EiffelStudio will offer to build it for you on the fly:
[[Image:VoidSafePrecompileOffer]]
Now you should see error messages representing any situation in your project in which the compiler determines that it cannot guarantee void-safety.
This is what our legacy system produced:
[[Image:VoidSafeErrorList]]
==Fix the issues==
Next you fix the problems that the compiler discovered. The compiler errors concerning void-safety typically will be of three varieties.
# VEVI: violations of the '''Variable initialization rule'''. An attached variable is not '''properly set'''.
# VUTA: violations of the '''Target rule'''. The target of a feature call is not attached.
# VJAR (and other related codes): violations of attached status considered in conformance. The attachment status of the source of an assignment (or an argument to a feature call) is not compatible with that of the target of the assignment (or the formal argument).
Let's look at some specific cases and how fixing them unfolds.
===Variables not properly set===
[[Image:VoidSafeVEVI1]]
There are two VEVI errors like this in class <code>APPLICATION</code> of our legacy system. They are probably the most obvious and easiest cases to handle.
<code>
feature {NONE} -- Initialization
make
-- Run application.
do
...
end
feature -- Access
my_nvp: NVP
-- NVP for testing
my_nvp_list: NVP_LIST
-- NVP_LIST for testing
</code>
Here attribute declarations for <code>my_nvp</code> and <code>my_nvp_list</code> are made. These are assumed to be attached because of the project setting. But the create routine <code>make</code> fails to create objects and attach them. So by adding those creations, as shown below, the compiler is satisfied.
<code>
make
-- Run application.
do
create my_nvp.make ("SomeName", "SomeValue")
create my_nvp_list.make
...
end
</code>
In a second case, there is also an Initialization rule violation (VEVI), this time on <code>Result</code>, in this routine:
<code>
at_first (nm: STRING): NVP
-- The first found NVP with name matching nm.
-- Or Void if not found
require
nm_valid: nm /= Void and then not nm.is_empty
local
tc: CURSOR
do
tc := cursor
start
name_search (nm)
if not exhausted then
Result := item
end
go_to (tc)
ensure
index_unchanged: index = old index
end
</code>
Here we cannot just ensure that <code>Result</code> is always attached, because, as indicated by the header comment, <code>Result</code> is allowed to be void by design.
So the least impact to this routine will be to declare its type as <code>detachable</code>:
<code>
at_first (nm: STRING): detachable NVP
-- The first found NVP with name matching nm.
-- Or Void if not found
</code>
The same change is made in other routines that can return void by design, particularly including a routine called <code>value_at_first</code>, which gets our attention next.
The case of <code>at_first</code> offered us an opportunity to redesign (or not). We might have been able to leave <code>at_first</code> attached. After all, in void-safe software, the fewer <code>detachable</code>s, the better. Maybe we could devise a way, possibly through preconditions and other queries, that would guarantee that <code>at_first</code> attempts to execute only when it can return a value.
But <code>at_first</code> is an exported query, so a consequence of such a change in the class design is that it would affect the class interface in such a way that existing clients would have to be modified to comply. In other words, it would be a "breaking" change.
===Source of assignment does not conform to target===
The change to <code>at_first</code> satisfies the VEVI issue in <code>at_first</code>, but it introduces a previously unseen conformance issue (VJAR) in the routine <code>value_at_first</code>:
[[Image:VoidSafeVJAR1]]
<code>value_at_first</code> looks like this:
<code>
value_at_first (nm: STRING): detachable STRING
-- Value from first found NVP with name matching nm
-- Or Void of not found
require
nm_valid: nm /= Void and then not nm.is_empty
local
tn: NVP
do
tn := at_first (nm)
if tn /= Void then
Result := tn.value
end
end
</code>
The problem is that the local variable <code>tn</code> is declared as <code>attached</code>, but we know that now the result of <code>at_first</code> is detachable, making this assignment invalid:
<code>
tn := at_first (nm)
</code>
Here the '''attached syntax''' can fix the problem and streamline the routine:
<code>
value_at_first (nm: STRING): detachable STRING
-- Value from first found NVP with name matching nm
-- Or Void of not found
require
nm_valid: nm /= Void and then not nm.is_empty
do
if attached at_first (nm) as tn then
Result := tn.value
end
end
</code>
In this version <code>tn</code> need not be declared as a local variable. Remember that the attached syntax provides a fresh local variable, if the expression is not void.
===Both VEVI and VJAR errors===
A design issue in class <code>NVP_LIST</code> causes both conformance and initialization compiler errors. In the original design, an instance of the class NVP_LIST could traverse its contents NVP-by-NVP with inherited functionality. Additionally, <code>NVP_LIST</code> has immediate functionality allowing an instance to traverse its contents in two different ways returning "sublists" based on recurring patterns of the <code>name</code> attributes of a sequence of name/value pairs.
These two traversal methods are referred to as "sequencing" and "segmenting". It's not important that you understand the details of what these traversals do. But it is important to know that a valid instance of <code>NVP_LIST</code> can either be in the process of sequencing or in the process of segmenting, or neither. It is invalid to be both sequencing ''and'' segmenting.
Two class attributes are maintained to store the recurring patterns of values of <code>{NVP}.name</code> that guide traversal:
<code>
feature {NONE} -- Implementation
sequence_array: ARRAY [STRING]
-- The current array of names being used for
-- sequence traversal
segment_array: ARRAY [STRING]
-- The current array of names being used to determine
-- the termination of list segments
</code>
In the original class design, each of these attributes would be void unless their corresponding traversal was active. So the class contains the following clauses in its invariant:
<code>
not_sequencing_and_segmenting: not (segment_readable and sequence_readable)
sequence_traversal_convention: (sequence_array = Void) = (not sequence_readable)
segment_traversal_convention: (segment_array = Void) = (not segment_readable)
</code>
Of course by default these attributes are considered to be attached. So, because they are not initialized during creation, we see initialization errors. Because elements of the class intentionally set them to <code>Void</code>, we see conformance errors.
Here we have another opportunity to redesign (or not). We could mark the two arrays as <code>detachable</code>, recompile and fix any problems this causes (in fact, it causes eight errors: six Target rule violations, and two conformance issues).
However, because these attributes are not exported, we may be able to leave them attached and make changes to the implementation design without making breaking changes to the interface.
Those exported features which take arguments of the type <code>ARRAY [STRING]</code> which will serve as sequencing or segmenting control also require that the array contain at least one element. For example, the contract for feature <code>segment_start</code> contains these preconditions:
<code>
segment_start (nms: ARRAY [STRING_8])
-- Place segment cursor on the first occurrence of a seqment of list which
-- begins at the current cursor position and
-- terminates in a sequence with names equivalent to and ordered the same as `nms'.
-- If no such sequence exists, then ensure exhausted
require
nms_valid: nms /= Void and then (nms.count > 0)
not_sequencing: not sequence_readable
</code>
Because the restriction always exists that a valid <code>sequence_array</code> or <code>segment_array</code> must contain at least one element, it is possible to redesign the implementation of the class such that an empty <code>sequence_array</code> and <code>segment_array</code> could serve the same purpose as a <code>Void</code> one does in the original design.
So the invariant clauses that we saw above would now become:
<code>
not_sequencing_and_segmenting: not (segment_readable and sequence_readable)
sequence_traversal_convention: (sequence_array.is_empty) = (not sequence_readable)
segment_traversal_convention: (segment_array.is_empty) = (not segment_readable)
</code>
We already have compiler errors (VJAR's) that point us to those places in which we have code that sets either <code>sequence_array</code> or <code>segment_array</code> to <code>Void</code>. Like this:
<code>
segment_array := Void
</code>
These instances need to be changed to attach an empty array, maybe like this:
<code>
create segment_array.make (1, 0)
</code>
Additionally, some postconditions which reference the implementation features <code>sequence_array</code> and/or <code>segment_array</code> would have to be changed. Looking at the postcondition clauses for <code>segment_start</code> we see that <code>segment_array</code> is expected (or not) to be <code>Void</code>:
<code>
ensure
started: (not exhausted) implies (segment_readable and (segment_array /= Void) and (last_segment_element_index > 0))
not_started: exhausted implies ((not segment_readable) and (segment_array = Void) and (last_segment_element_index = 0))
</code>
To support the "empty array" design, <code>segment_start</code>'s postcondition clauses would be:
<code>
ensure
started: (not exhausted) implies (segment_readable and (not segment_array.is_empty) and (last_segment_element_index > 0))
not_started: exhausted implies ((not segment_readable) and (segment_array.is_empty) and (last_segment_element_index = 0))
</code>
{{SeeAlso|<br/>[[Converting EiffelVision 2 Systems to Void-Safety]]<br/>[[Void-safe changes to Eiffel libraries]]}}

View File

@@ -0,0 +1,28 @@
[[Property:title|Mixing void-safe and void-unsafe software]]
[[Property:weight|3]]
[[Property:uuid|3446f214-3c77-ef41-98eb-92942298630c]]
{{underconstruction}}
=Introduction=
Eiffel Software recommends that any new development efforts be implemented using Eiffel's void-safe approach, thus eliminating one more common type of runtime failure. It is also recommended that existing software be converted to void-safety at the earliest opportunity.
Under some circumstances it is possible and even helpful to mix void-safe and void-unsafe libraries. During conversion to void-safety, for example, it can be helpful to compile and test a void-unsafe system with void-safe versions of the libraries it depends upon.
=Rule for mixing void-safety modes=
The rule for using void-safe and void-unsafe software together is fairly simple.
{{Rule|name=Mixing void-safe and void-unsafe software|text=<br/>
1) A class that is void-unsafe may depend upon other classes (as suppliers or ancestors) which are either void-safe or void-unsafe.<br/>
2) A class that is void-safe may depend only upon other classes that are void-safe.}}
This means that if the root class of a system is void-safe, then every other class in the system must also be void-safe.
However, if you are converting a system to void-safety, it's likely that your root class and the classes in the closely related clusters will be void-unsafe. The rule allows you to mix the void-safe versions of the Eiffel Software library classes from the EiffelStudio distribution with your void-unsafe system during conversion.

View File

@@ -0,0 +1,390 @@
[[Property:link_title|New void-safe project]]
[[Property:title|Creating a new void-safe project]]
[[Property:weight|2]]
[[Property:uuid|92cea2e9-b094-6380-2c5d-1cd1eb3038b4]]
{{TOC|limit=2}}
Now that we've been introduced to the Eiffel void-safe facilities, let's look at what it takes to set up a new void-safe software project. Here we'll look at the void-safety related project settings and how the can be used. Then we'll look deeper into the use of some of the void-safe tools.
==Project settings for void-safe projects==
There are two project settings that are related to void-safety. These settings can be set with great granularity throughout your project to allow you maximum flexibility, particularly when including classes or libraries that are void-unsafe or that have been converted to void-safety, but must do double duty in the void-safe and void-unsafe worlds.
===The ''"Void-safe"'' setting===
The '''Void-safe''' setting determines whether and how the Eiffel compiler checks your project against the void-safe related validity rules.
This is the essential void-safe project setting. It can assume one of the following values:
# '''No''': No checking against any of the void-safety validity rules. Attachment marks '''attached''' and '''detachable''' are simply ignored.
# '''Conformance''': The attachment marks are not ignored for type conformance checks (with respect to VJAR/VBAR and related validity rules).
# '''Initialization''': Validity rules are selectively checked. The initialization rule (VEVI) and the target rule (VUTA) are checked only for attached entities and attached call targets -- i.e., detachable cases are not checked.
# '''Transitional''': It is an obsolete level which is for users who have already migrated their code to void-safety using an old version of the compiler which did not implement all the void-safety validity rules (especially with agent initialization).
# '''Complete''': Complete checking against all void-safety validity rules.
So, for a new void-safe project, you would want to set this option first to '''Conformance''', then '''Initialization''' and finally to '''Complete'''. This will let you migrate your code progressively without much changes at each steps.
===The ''"Full class checking"'' setting===
This setting instructs the compiler to recheck inherited features in descendant classes. This setting is True and cannot be changed for projects with some void-safety level enabled.
==Void-safe libraries==
As of EiffelStudio version 13.11, all libraries distributed with EiffelStudio are void-safe except the EiffelCOM library.
{{note|During a period of transition, there are different Eiffel configuration files (.ecf's) for void-unsafe and void-safe projects (for example, base.ecf and base-safe.ecf). If you have set the '''Void-safe''' setting to check for void-safety, then when you add a library to your project in EiffelStudio, you will see only the void-safe configurations by default. Starting with version 16.11 there is only one version of each of the configuration files for each library. The single configuration files serve both void-unsafe and void-safe projects.}}
===Using generic classes===
Void-safety affects generic classes. Fortunately, from the viewpoint of those writing clients to the generic classes in the EiffelBase library, not much has changed. Still, you should understand the interplay between void-safety and [[ET: Genericity and Arrays|genericity]].
Consider a generic class like <code>LIST [G]</code>. The formal generic parameter <code>G</code> represents an arbitrary type. In a generic derivation of <code>LIST [G]</code>, say <code>LIST [STRING]</code>, the formal generic type is replaced by an actual generic type, in this case <code>STRING</code>.
Remember that unconstrained genericity, <code>LIST [G]</code>, for example, is really a case of [[ET: Inheritance#Constrained genericity|constrained genericity]] in which the generic parameter is constrained to <code>ANY</code>, that is, it could be written <code>LIST [G -> ANY]</code>.
With the advent of void-safe Eiffel, the unconstrained generic class name <code>LIST [G]</code> now equates to <code>LIST [G -> detachable ANY]</code>. Because any type, say <code>T</code>, (synonymous with <code>attached T</code> in void-safe Eiffel) conforms to <code>detachable T</code>, this change facilitates the production of generic classes, but has little effect on writers of clients to those classes.
This change works for all the generic classes in EiffelBase ... except for one: <code>ARRAY</code>. Arrays are a special case because we often create arrays with a pre-allocated number of elements. In the case of expanded types, there's not a problem. For example, in this code
<code>
my_array: ARRAY [INTEGER]
...
create my_array.make (1, 100)
</code>
we create <code>my_array</code> with one hundred <code>INTEGER</code> elements. <code>INTEGER</code> is an expanded type, and each element is initialized by applying the default initialization rule for <code>INTEGER</code>, i.e, the integer representation of zero.
However, if <code>my_array</code> had been declared of a type with reference semantics, say <code>STRING</code> (meaning, of course, <code>attached STRING</code>, the default rule would not work well, because the default initialization for references types is <code>Void</code> which would not be allowed in an array of elements of any attached type.
The solution to this challenge is fairly simple. For arrays of elements of detachable or expanded types, there is no different behavior. When dealing with arrays of elements of attached types, we must be careful.
Creating an array using <code>ARRAY</code>'s creation procedure <code>make</code> may still be safe in some cases. Specifically, <code>make</code> can be used with arrays of elements of attached types if the arguments have values such that an empty array will be created, that is, when
<code>
min_index = max_index + 1
</code>
In all other situations involving arrays of elements of attached types, <code>make</code> may not be used to do the creation. Rather, you should use the creation procedure <code>make_filled</code> which takes three arguments. The first is an object of the type of the array, and the second and third are the minimum and maximum indexes, respectively. When the array is created, each of the elements will be initialized with a reference to the object of the first argument.
So, a call using <code>make_filled</code> would look like this:
<code>
my_array: ARRAY [STRING]
...
create my_array.make_filled (" ", 1, 100)
</code>
Upon creation, each element of the array will reference the same object; an object of type <code>STRING</code> composed of one space character.
==Using the ''attribute'' keyword carefully==
The keyword <code>attribute</code> should be used with some care. You might be tempted to think that it would be convenient or add an extra element of safety to use [[Void-safety: Background, definition, and tools#Self-initializing attributes|self-initializing attributes]] widely. And in a way, you would be correct. But you should also understand that there is a price to pay for using self-initializing attributes and stable attributes. It is that upon every access, an evaluation of the state of the attribute must be made. So, as a general rule, you should avoid using self-initializing attributes only for the purpose of lazy initialization.
==More about the ''attached syntax''==
The complete attached syntax is:
<code>
attached {SOME_TYPE} exp as l_exp
</code>
In this section, we will see more ways in which to use this versatile language facility.
===As a CAP-like construct which yields a local variable===
In the introduction to the attached syntax, we used an example which showed how the attached syntax is directly relevant to void-safety. That is, the code:
<code>
if x /= Void then
-- ... Any other instructions here that do not assign to x
x.f (a)
end
</code>
is a CAP for <code>x</code> ... but that's only true if <code>x</code> is a local variable or a formal argument to the routine that contains the code.
So to access a detachable attribute safely, we could declare a local variable, make an assignment, and test for <code>Void</code> as above. Something like this:
<code>
my_detachable_attribute: detachable MY_TYPE
...
some_routine
local
x: like my_detachable_attribute
do
x := my_detachable_attribute
if x /= Void then
-- ... Any other instructions here that do not assign to x
x.f (a)
end
...
</code>
The attached syntax can both check the attached status of a detachable attribute and also provide a new local variable. So the routine becomes:
<code>
some_routine
do
if attached my_detachable_attribute as x then
-- ... Any other instructions here that do not assign to x
x.f (a)
end
...
</code>
===As a test for attachment===
In its simplest form, the attached syntax can be used to test attached status only:
<code>
if attached x then
do_something
else
do_something_different
end
</code>
So in this simple form, <code>attached x</code> can be used instead of <code>x /= Void</code>. The two are semantically equivalent, and which one you choose is a matter of personal preference.
===As a tool for "once per object"===
There is a code pattern for functions that exists in some Eiffel software to effect "once-per-object / lazy evaluation".
{{note|As of EiffelStudio version 6.6, the use of this code pattern effecting "once per object" is no longer necessary. V6.6 includes explicit support for <code>once</code> routines which can be adjusted by a [[ET: Once routines and shared objects#Adjusting once semantics with "once keys"|once key]] to specify once per object.}}
This "once-per-object" code pattern employs a cached value for some object which is not exported. When it is applied, the "once-per-object" function checks the attachment status of the cached value. If the cached value is void, then it is created and assigned to <code>Result</code>. If the cached value was found already to exist, then it is just assigned to <code>Result</code>.
Here's an example of this pattern used to produce some descriptive text of an instance of its class:
<code>
feature -- Access
descriptive_text: STRING
local
l_result: like descriptive_text_cache
do
l_result := descriptive_text_cache
if l_result = Void then
create Result.make_empty
-- ... Build Result with appropriate
-- descriptive text for Current.
descriptive_text_cache := Result
else
Result := l_result
end
ensure
result_attached: Result /= Void
result_not_empty: not Result.is_empty
result_consistent: Result = descriptive_text
end
feature {NONE} -- Implementation
descriptive_text_cache: like descriptive_text
</code>
This example will not compile in a void-safe project (class types are attached by default). The problem is that the attribute <code>descriptive_text_cache</code> is of an attached type, therefore will be flagged by the compiler as not properly set (VEVI). Of course, it will be ... that's the whole idea here: not to initialize <code>descriptive_text_cache</code> until it's actually used. So it sounds like <code>descriptive_text_cache</code> should be declared detachable. That is:
<code>
descriptive_text_cache: detachable like descriptive_text
</code>
This change will make this routine compile in a void-safe project. But you should notice that there is a ripple-down effect due to the change. Within the routine, <code>l_result</code> is typed <code>like descriptive_text_cache</code>, so it also will be detachable. Therefore we might expect trouble, because later in the routine we have:
<code>
Result := l_result
</code>
Because we know Result is attached and l_result is detachable, we might expect a compiler error in which the source of an assignment does not conform to its target (VJAR).
But we don't get such an error. The reason is two-fold. First, <code>l_result</code> is a local variable whose use can be protected by a CAP. Second, the CAP in this case is the check to ensure that <code>l_result</code> is not void. We only make the assignment to <code>Result</code> if <code>l_result</code> is not void. So the compiler can prove that <code>l_result</code> cannot be void at the point at which the assignment occurs ... therefore, no error.
Because the '''attached syntax''' can test attached status and provide a local variable, it can be used to remove some unnecessary code from this routine. The version of the routine that follows shows the attached syntax being used to test the attached status of <code>descriptive_text_cache</code> and yield the local variable <code>l_result</code> in the case that <code>descriptive_text_cache</code> is indeed attached.
<code>
descriptive_text: STRING
do
if attached descriptive_text_cache as l_result then
Result := l_result
else
create Result.make_empty
-- ... Build Result with appropriate
-- descriptive text for Current.
descriptive_text_cache := Result
end
ensure
result_attached: Result /= Void
result_not_empty: not Result.is_empty
result_consistent: Result = descriptive_text
end
feature {NONE} -- Implementation
descriptive_text_cache: like descriptive_text
</code>
===As a replacement for assignment attempt===
The assignment attempt ( <code>?=</code> ) has traditionally been used to deal with external objects (e.g., persistent objects from files and databases) and to narrow the type of an object in order to use more specific features. The latter is a process known by names such as "down casting" in some technological circles. A classic example is doing specific processing on some elements of a polymorphic data structure. Let's look at an example. Suppose we have a <code>LIST</code> of items of type <code>POLYGON</code>:
<code>
my_polygons: LIST [POLYGON]
</code>
<code>POLYGON</code>s could be of many specific types, and one of those could be <code>RECTANGLE</code>. Suppose too that we want to print the measurements of the diagonals of all the <code>RECTANGLE</code>s in the list. Class <code>RECTANGLE</code> might have a query <code>diagonal</code> returning such a measurement, but <code>POLYGON</code> would not, for the reason that the concept of diagonal is not meaningful for all <code>POLYGON</code>s, e.g., <code>TRIANGLE</code>s.
As we traverse the list we would use assignment attempt to try to attach each <code>POLYGON</code> to a variable typed as <code>RECTANGLE</code>. If successful, we can print the result of the application of <code>diagonal</code>.
<code>
l_my_rectangle: RECTANGLE
...
from
my_polygons.start
until
my_polygons.exhausted
loop
l_my_rectangle ?= my_polygons.item
if l_my_rectangle /= Void then
print (l_my_rectangle.diagonal)
print ("%N")
end
my_polygons.forth
end
</code>
The '''attached syntax''' allows us to check both attached status and type, and provides us with a fresh local variable when appropriate:
<code>
from
my_polygons.start
until
my_polygons.exhausted
loop
if attached {RECTANGLE} my_polygons.item as l_my_rectangle then
print (l_my_rectangle.diagonal)
print ("%N")
end
my_polygons.forth
end
</code>
As with the other examples of the '''attached syntax''', it is no longer necessary to make a declaration for the local variable, in this case <code>l_my_rectangle</code>.
==More about CAPs==
===Use of <code>check</code> instructions===
In void-safe mode, the compiler will accept code that it can prove will only apply features to attached references at runtime ... and you help this process along by using the tools of void-safety, like attached types and CAPs. On the other hand, the compiler will reject code that it cannot guarantee is void-safe. Sometimes this may cause you a problem. There may be subtle situations in which you feel quite certain that a section of code will be free of void calls at runtime, but the compiler doesn't see it the same way, and rejects your code. In cases like this, you can usually satisfy the compiler by using <code>check</code> instructions.
Technically speaking, <code>check</code> instructions are not CAPs. But they are useful in cases in which an entity is always expected to be attached at a certain point in the code. In the following example, the attribute <code>my_detachable_any</code> is detachable. But at the particular point at which it is the source of the assignment to <code>l_result</code>, it is expected always to be attached. If it is not attached at the time of the assignment, and therefore <code>l_result</code> becomes void, then an exception should occur. The <code>check</code> instruction provides this behavior.
The following sample shows the <code>check</code> instruction at work. There are reasons why this is not the best use use of <code>check</code> in this case, and we will discuss that next.
<code>
-- A not-so-good example of using check.
my_detachable_any: detachable ANY
...
my_attached_any: ANY
local
l_result: like my_detachable_any
do
l_result := my_detachable_any
check
attached l_result
end
Result := l_result
end
</code>
Here the assertion in the <code>check</code> guarantees that <code>l_result</code> is attached at the time of its assignment to <code>Result</code>. If <code>my_detachable_any</code> is ever not attached to an object, then an exception will be raised.
So what's wrong with the sample above? It would be fine in ''workbench'' code, but what happens if the code is in ''finalized'' mode, in which assertions are typically discarded?
The answer is that the <code>check</code> in the sample above would no longer be effective, and the resulting executable would no longer be void-safe.
The solution to this problem is found in a different form of the <code>check</code> instruction. Consider the same example, but this time using <code>check ... then ... end</code>:
<code>
-- A better way of using check.
my_detachable_any: detachable ANY
...
my_attached_any: ANY
do
check attached my_detachable_any as l_result then
Result := l_result
end
end
</code>
Here, in the improved version of the example, the <code>check ... then ... end</code> is used along with the <code>attached</code> syntax. This streamlines the code a bit by eliminating the need to declare a separate local entity, while achieving the same effect as the previous example. If <code>my_detachable_any</code> is attached at runtime, then the temporary variable <code>l_result</code> is created and attached to the same object. Then the body of the <code>check ... then ... end</code> is executed. If <code>my_detachable_any</code> is not attached, an exception occurs.
Another important benefit, one that solves the problem with the original example, comes from the way in which <code>check ... then ... end</code> is handled by the compiler. The <code>check ... then ... end</code> form '''is always monitored, even if assertion checking is turned off at all levels''', as is usually done in finalized code.
===Choosing CAPs versus the Attached Syntax===
The attached syntax is convenient because it can check attached status and deliver a new local variable at the same time. But there are cases in which you might choose instead to define a local variable and use a CAP. Suppose you had code acting on several similar and detachable expressions, and you use the attached syntax in each case:
<code>
foobar
do
if attached dictionary_entry ("abc") as l_abc then
l_abc.do_something
end
if attached dictionary_entry ("def") as l_def then
l_def.do_something
end
if attached dictionary_entry ("ghi") as l_ghi then
l_ghi.do_something
end
end
</code>
This routine causes three local variables to be allocated for the duration of routine <code>foobar</code>, one each for <code>l_abc</code>, <code>l_def</code>, and <code>l_ghi</code>. And it is no better to do this:
<code>
foobar
do
if attached dictionary_entry ("abc") as l_entry then
l_entry.do_something
end
if attached dictionary_entry ("def") as l_entry then
l_entry.do_something
end
if attached dictionary_entry ("ghi") as l_entry then
l_entry.do_something
end
end
</code>
Even though the names are the same, still three separate local variables are allocated for <code>foobar</code>.
In cases like this, you could effect a minor performance improvement by declaring one local variable and reusing it. In the following code, only one local variable is used and access to it is protected by the CAP <code>if l_entry /= Void then</code>.
<code>
foobar
local
l_entry: like dictionary_entry
do
l_entry := dictionary_entry ("abc")
if l_entry /= Void then
l_entry.do_something
end
l_entry := dictionary_entry ("def")
if l_entry /= Void then
l_entry.do_something
end
l_entry := dictionary_entry ("ghi")
if l_entry /= Void then
l_entry.do_something
end
end
</code>
==Stable attributes==
Remember that stable attributes are actually detachable attributes, with the difference that they can never be the target of an assignment in which the source is <code>Void</code> or anything that could have a value of <code>Void</code>.
Stable attributes are useful in situations in which there are valid object life scenarios in which some particular attribute will never need an object attached, or will only need an object attached late in the scenario. So in this case, the attribute is used only under certain runtime conditions. Declaring these attributes as stable eliminates the need to make attachments during object creation. Yet once needed, that is, once the attribute is attached, it will always be attached.
Also, you should remember that unlike other attributes, you can access stable attributes directly in a CAP:
<code>
my_stable_attribute: detachable SOME_TYPE
note
option: stable
attribute
end
...
if my_stable_attribute /= Void then
my_stable_attribute.do_something
end
...
</code>
{{SeeAlso| [[Void-safety: Background, definition, and tools#Types as "attached" or "detachable"|Types as "attached" or "detachable"]].}}

View File

@@ -0,0 +1,23 @@
[[Property:link_title|Void-safe programming]]
[[Property:title|Void-safe programming in Eiffel]]
[[Property:weight|10]]
[[Property:uuid|a03568e8-eb79-70d7-04a3-6fd3ed7ac2b3]]
=Void-safe software development using Eiffel: introduction=
When you develop software in Eiffel, you can be assured (at compile time) that your system will not attempt (at run time) to apply a feature to a void reference -- or, in the terminology of other languages such as C, "dereference a null pointer".
Throughout the history of Eiffel, new capabilities -- agents, the SCOOP concurrency mechanism and many others -- have added considerable expressive power to the languag,e while causing minimum impact on existing software. Void-safe Eiffel is such an innovation, which instead of adding new mechanisms ''removes'' a major source of instability in programs, present in all other major languages: null-pointer dereferencing. To say that Eiffel is void-safe means that such catastrophic yet common errors simply will not occur.
There is in fact no need to speak of "void-safe Eiffel". The language is just Eiffel... and it is void-safe, just as it is statically typed. We still occasionally refer to "Void-safe Eiffel" simply because until 2005 or so Eiffel was not void-safe (it had to start somewhere), and you may still encounter older documentation that talks about "calls on void targets" (null-pointer dereferences). But in today's Eiffel such an event is impossible.
The rest of this chapter explains void safety:
# How is void-safety defined?
# What are the specific elements of the mechanism?
# How do these relate to Eiffel before void-safety?
# What do I need to know to produce standard Eiffel software?
# What do I need to know to convert my existing systems to be standard?

View File

@@ -0,0 +1,287 @@
[[Property:link_title|Background and tools]]
[[Property:title|Void-safety: Background, definition, and tools]]
[[Property:weight|0]]
[[Property:uuid|689f62b2-5675-5ab6-cd47-d891cf3d484d]]
=Background=
The primary focus of Eiffel is on software quality. Void-safety, like static typing, is another facility for improving software quality. Void-safe software is protected from run time errors caused by calls to void references, and therefore will be more reliable than software in which calls to void targets can occur. The analogy to static typing is a useful one. In fact, void-safe capability could be seen as an extension to the type system, or a step beyond static typing, because the mechanism for ensuring void-safety is integrated into the type system.
==Static typing==
You know that static typing eliminates a whole class of software failures. This is done by making an assurance at compile time about a feature call of the form:
<code>
x.f (a)
</code>
Such a feature call is judged acceptable at compile time only if the type of <code>x</code> has a feature <code>f</code> and that any arguments, represented here by <code>a</code>, number the same as the formal arguments of <code>f</code>, and are compatible with the types of those formal arguments.
In statically typed languages like Eiffel, the compiler guarantees that you cannot, at run time, have a situation in which feature <code>f</code> is not applicable to the object attached to <code>x</code>. If you've ever been a Smalltalk programmer, you are certainly familiar with this most common of errors that manifests itself as "Message not understood." It happens because Smalltalk is not statically typed.
==Void-unsafe software==
Static typing will ensure that there is some feature <code>f</code> that can be applied at run time to <code>x</code> in the example above. But it does not assure us that, in the case in which <code>x</code> is a reference, that there will always be an object attached to <code>x</code> at any time <code>x.f (a)</code> is executed.
This problem is not unique to Eiffel. Other environments that allow or mandate reference semantics also allow the possibility of void-unsafe run time errors. If you've worked in Java or .NET you may have seen the NullReferenceException. Sometimes you might have experienced this rather poetic sounding message: "Object reference not set to an instance of an object". In Eiffel you would see "Feature call on void target". All these are the hallmarks of run time errors resulting from void-unsafe software.
{{note|If you need a review of difference between reference types and expanded types in Eiffel, see [[ET: The Dynamic Structure: Execution Model|the chapter of the Eiffel Tutorial dedicated to the Eiffel execution model]]. }}
Of course this is not an issue with instances of expanded types, because these instances are indeed "expanded" within their parent objects. But we could not imagine a world with expanded types only. References are important for performance reasons and for modeling purposes. For example, consider that a car has an engine and a manufacturer. When we model cars in software, it might be appropriate for engines to be expanded types, as each car has one engine. But certainly the same is not true for manufacturer. Many cars can share, through a reference, a single manufacturer.
So, references are necessary, but we want them to be trouble free.
==Void-safe software==
Void-safe software, then, is software in which the compiler can give assurance, through a static analysis of the code, that at run time whenever a feature is applied to a reference, that the reference in question will have an object attached. This means that the feature call
<code>
x.f (a)
</code>
is valid only if we are assured that <code>x</code> will be attached to an object when the call executes.
{{info|This validity rule is called the '''Target rule''', validity code VUTA, and is the primary rule for void-safety. In the following discussion, you will see that other validity rules are involved, too. You can see the formal definition of all validity rules in the [http://www.ecma-international.org/publications/standards/Ecma-367.htm ISO/ECMA standard document] available online. }}
Once we have committed ourselves to this validity rule, we must have a strategy for complying with the rule.
=Elements of the void-safe strategy=
Here are the tools of void-safe trade. They will each be addressed in more detail throughout the documentation that follows. As you look at these elements it helps to try to think about things from the compiler's viewpoint ... after all, it is the compiler that we expect to give us the guarantee that our code is indeed void-safe.
First let's look at a couple of approaches that won't work.
It might occur to us that we could enforce compliance with the target rule by simply eliminating the concept of void references. But this would not be practical. Void is a valuable abstraction that is useful in many situations, such as providing void links in structures. So, we must keep void ... but we want to keep it under control.
Another thought might be that we could just have the compiler do all the work for us. But would be impossibly time consuming for the compiler to investigate every conceivable execution path available to a system to make certain that every possible feature call was made on an attached reference.
So, all of this boils down to the fact that we have to take some actions that help the compiler along. That's what the following are about.
==Certified Attachment Patterns (CAPs)==
We know that in the context of certain code patterns, it is clear that it would be impossible for a reference to be void. These patterns are identified and we call them CAPs, short for Certified Attachment Patterns. Here is a very straightforward example expressed in a syntax that should be familiar to all Eiffel developers:
<code>
if x /= Void then
-- ... Any other instructions here that do not assign to x
x.f (a)
end
</code>
Here a check is made to ensure <code>x</code> is not void. Then as long as no assignments to <code>x</code> are made in the interim, a feature <code>f</code> can be applied to <code>x</code> with the certainty that <code>x</code> will be attached at the time ... and importantly, this can be determined at compile time. So, we say that this code pattern is a CAP for <code>x</code>.
It is important to understand that in this example (and with other CAPs), <code>x</code> is allowed to be a local variable or formal argument only. That is, <code>x</code> may not be an attribute or general expression (with one exception which we will see [[#Stable attributes|below]]). Direct access to class attribute references cannot be allowed via a CAP due to the fact that they could be set to void by a routine call in some execution path invoked by the intervening instructions or possibly even different process thread. In a later [[Void-safety: Background, definition, and tools#Types as "attached" or "detachable"|section]], we well see that this is not quite such a limitations as it may appear at this point.
{{note|You will find more useful information about CAPs in [[Creating a new void-safe project#More about CAPs|More about CAPs]]. Learn how certain code patterns are determined to be CAPs in [[What makes a Certified Attachment Pattern]]. }}
==The ''attached syntax'' (object test)==
For the purposes of void-safety, the '''attached syntax''' does double duty for us. It allows us to make certain that a reference is attached, and it provides us a safe way to access objects that are attached to class attributes.
We noted earlier that this code
<code>
if x /= Void then
-- ... Any other instructions here that do not assign to x
x.f (a)
end
</code>
creates a CAP for feature calls on <code>x</code>, but only if <code>x</code> is a local variable or a formal argument.
By using the '''attached syntax''', we can perform an '''object test''' on a variable. That is, the attached syntax is a <code>BOOLEAN</code> expression which provides an answer to the question "Is <code>x</code> attached to an object?" At the same time, if indeed <code>x</code> is attached to an object, the attached syntax will deliver to us a fresh local variable, also attached to <code>x</code>'s object, on which we can make feature calls.
<code>
if attached x as l_x then
l_x.f (a)
end
</code>
In the example above, <code>x</code> is tested to make certain that it is attached. If so, the new local <code>l_x</code> becomes attached to the same object as <code>x</code>. And so the object can be used safely even if <code>x</code> is a class attribute. So, the attached syntax, is really another CAP, because it provides a clearly verifiable place for the application of features to targets that are guaranteed not to be void.
{{note|The attached syntax has other syntax variations as well as other uses. These will be discussed [[Creating a new void-safe project#More about the attached syntax|later]]. }}
One way to make sure we comply with the target rule would be always use a CAP or the attached syntax every time we want to apply a feature to a referenced object. That might work, but it falls among the impractical approaches to the problem ... it would break a very high percentage of existing Eiffel code, not to mention cluttering things up quite a bit.
==Types as "attached" or "detachable"==
Rather than trying to protect every feature call, Eiffel allows us to declare any variable as being of an '''attached type'''. This is an important extension to the Eiffel type system.
In Eiffel prior to the introduction of void-safe facilities, any reference variable could be set to <code>Void</code>. So, all variables were considered '"detachable"'.
The current standard Eiffel supports a mixture of '''attached''' and '''detachable''' types. When a variable is declared of an attached type, as in the following example, then the compiler will prevent it from being set to <code>Void</code> or set to anything that can be set to <code>Void</code>.
<code>
my_attached_string: attached STRING
</code>
It is easy to imagine that the more declarations are of attached types, the easier it will be to guarantee that a call to a void target cannot take place at run time. In fact, if every declaration was guaranteed to be of an attached type, then that would be all that was needed to satisfy the Target rule.
However, it wouldn't be workable to have only attached types, because sometimes it's important to allow references to have a value of <code>Void</code>.
When it is necessary to allow <code>Void</code> as a value, a declaration can use the ''detachable mark'' as in the following.
<code>
my_detachable_string: detachable STRING
</code>
This doesn't mean that on every declaration you must put either an ''attached mark'' or a ''detachable mark''. Declarations that are unmarked are allowed. If a declaration contains neither '''attached''' nor '''detachable''', then it is assumed to be '''attached'''.
In Eiffel then, all declarations will have types that are either '''attached''' or '''detachable'''. As a result, we need only use CAPs and the attached syntax with detachable types. So the important thing to remember is that ''direct access to class attributes of detachable types is never void-safe.''
===Attachment and conformance===
The distinction between attached and detachable types results in a small but important addition to the rules of conformance. Because variables declared as attached types can never be void, then it is important not to allow any assignment of a detachable source to an attached target. However, assigning an attached source to a detachable target is permissible. The following code shows both cases (as described earlier, class types are attached by default).
<code>
my_attached_string: STRING
my_detachable_string: detachable STRING
...
my_attached_string := my_detachable_string -- Invalid
my_detachable_string := my_attached_string -- Valid
</code>
==Initialization rule==
If we have attached types, then we can assume variables declared of these types, once attached, will always be attached. But how do they get attached in the first place? That's what the initialization rule is all about.
The rule says that at any place in which a variable is accessed, it must be '''properly set'''. A variable's being properly set has a precise, but not particularly simple definition in the Eiffel standard.
{{info|You can find the formal definition of the '''Variable initialization rule''', validity code VEVI, and its related concepts such as '''properly set''' variables in the [http://www.ecma-international.org/publications/standards/Ecma-367.htm ISO/ECMA standard document]. }}
Still, it's not too hard to understand the basics of initializing variables of attached types:
* For the initialization of attributes of a class, we can apply a rule similar to that of the initial evaluation of class invariants ... that is, everything must be in order upon completion of a creation procedure. If a class attribute is of an attached type, then each of the class's creation procedures is responsible for making sure that the attribute is attached to an object upon its completion.
* A local variable is considered properly set if it is initialized at some point '''preceding''' its use in any execution path in which it is used. So immediately after its <code>create</code> instruction, the local variable would be considered properly set. But if the <code>create</code> occurred in the <code>then</code> part of an <code>if</code> instruction, the local variable would not be properly set in the <code>else</code> part of that same <code>if</code> instruction:
<code>
my_routine
-- Illustrate properly set local variable
local
l_my_string: STRING
do
if my_condition then
create l_my_string.make_empty
-- ... l_my_string is properly set here
else
-- ... l_my_string is not properly set here
end
end
</code>
* A variable is considered properly set if it is '''self-initializing'''. What it means to be self-initializing is explained below.
==Self-initializing attributes==
A self-initializing attribute is guaranteed to have a value when accessed at run time. Declarations of self-initializing attributes are characterized by the use of the code that follows the <code>attribute</code> keyword. The code is executed to initialize the attribute in the case that the attribute is accessed prior to being initialized in any other way.
So, self-initializing attributes are ordinary attributes, with the restriction that they are of both ''attached'' types and ''reference'' types (i.e., not expanded types or constants). Self-initializing attributes still can be, and typically will be initialized in the traditional ways. The difference is that the code in the attribute part serves as a kind of safety net guaranteeing that a self-initializing attribute will never be void, even if it is accessed prior to being initialized by one of the traditional means.
<code>
value: STRING
attribute
create Result.make_empty
end
</code>
In the example above, the attribute <code>value</code> will be attached to an object of type <code>STRING</code>, in fact, the empty string, if no other initialization occurs before the first access of <code>value</code>.
==Rule for conformance==
You will remember that the Eiffel type system dictates that an assignment instruction:
<code>
x := y
</code>
is valid only if the type of <code>y</code> is '''compatible''' with the type of <code>x</code>. Compatibility, in turn, means either '''conversion''' or '''conformance'''.
The fact that all types are either '''attached''' or '''detachable''' adds another dimension to rule for conformance:
*If x is of an attached type, then y must be of an attached type.
This prevents us from circumventing attached status at run time. If <code>x</code> is of a detachable type, then <code>y</code> could be either a detachable or attached type.
The same goes for routine calls. In a call:
<code>
z.r (y)
</code>
where <code>x</code> is the formal argument for <code>r</code>, then if x is of an attached type, then y must be of an attached type.
==Stable attributes==
Stable attributes are really stable ''detachable'' attributes, as adding the concept of stability is meaningful only for detachable attributes. Declaring a detachable attribute as stable, means that it behaves like a detachable attribute except that its assignment rules mimic those of attached attributes. In other words, a stable attribute does not need to be attached during object creation the way that attributes declared as attached must. But like attached type attributes, stable attributes can never be the target of an assignment in which the source is <code>Void</code> or a detachable type.
<code>
my_test: detachable TEST
note
option: stable
attribute
end
</code>
This means that even though stable attributes do not need to be initialized like attributes of attached types, once they are attached to an object, they can never be void again.
Stable attributes are also interesting in that they are the only exception to the rule given above in the [[Void-safety: Background, definition, and tools#Certified Attachment Patterns (CAPs)|CAPs section]] that stated that direct access to attributes cannot be protected by a CAP. A stable attribute can be used under the protection of a CAP. This is because once a stable attribute has an object attached, it can never again be set to <code>Void</code>. So there's no worry about having the attribute's state going unexpectedly from attached to non-attached because of the actions of other routines or threads.
==Rule for generic parameters==
Generic classes provide another question. A generic class like
<code>
class
C [G]
...
</code>
allows us to create a type by providing a specific actual generic parameter for the formal parameter <code>G</code>.
So, two valid derivations are:
<code>
my_integer_derivation: C [INTEGER]
</code>
and
<code>
my_employee_derivation: C [EMPLOYEE]
</code>
If class C contains a declaration:
<code>
x: G
</code>
What do we know about the void-safety of <code>x</code> ?
In the case of the <code>INTEGER</code> derivation above, we know <code>x</code> is safe because <code>INTEGER</code> is an expanded type. But often types like <code>EMPLOYEE</code> will be reference types which could be void at run time.
'''For a class like <code>C [G]</code>, <code>G</code> is considered detachable'''. As a result, because of the [[Void-safety: Background, definition, and tools#Rule for conformance|rule for conformance]], any class will work for an actual generic parameter. That means that both of the following are valid generic derivations:
<code>
my_detachable_string_derivation: C [detachable STRING]
my_attached_string_derivation: C [attached STRING]
</code>
If <code>C</code> contains a declaration <code>x: G</code>, the application of features to <code>x</code> must include verification of attachment (CAPs, attached syntax, etc).
Constrained genericity can be used to create generic classes in which the generic parameter represents an attached type. If class <code>C</code> had been defined as:
<code>
class C [G -> attached ANY]
...
</code>
then <code>x</code> in this class <code>G</code> represents an attached type. Consequently, the actual generic type in any derivation must be attached ... and feature calls on <code>x</code> are safe.
==Rule for ARRAYs==
The rule for generic parameters applies to all generic types ... except <code>ARRAYs</code>. In the typical creation of an <code>ARRAY</code>, we would provide a minimum and maximum index.
<code>
my_array: ARRAY [STRING]
...
create my_array.make (1, 100)
</code>
During creation, an area to store the appropriate number of entries is also created. And depending upon the actual generic parameter, these entries are either objects for expanded types or references for reference types.
In the case of an actual generic parameter of an attached reference type, all the elements must be attached to instances of type during the creation of the ARRAY. The <code>make</code> procedure would not do this. Creation of an <code>ARRAY</code> in which the actual generic parameter is attached must be done using the <code>make_filled</code> creation procedure.
<code>
create my_array.make_filled ("", 1, 100)
</code>
The first argument is an object of the actual generic type, in this case an empty <code>STRING</code>. Every entry in the newly created <code>ARRAY</code> will be initialized to reference this object.
For more detail on void-safe use of arrays and other generic classes, see the section: [[Creating a new void-safe project#Using generic classes|Using generic classes]].

View File

@@ -0,0 +1,182 @@
[[Property:title|What makes a Certified Attachment Pattern]]
[[Property:weight|8]]
[[Property:uuid|1a20197d-5a88-59c3-9a04-512399125661]]
==A little background on CAPs==
Certified Attachment Patterns (CAPs) were described in the section on [[Void-safety: Background, definition, and tools#Certified attachment patterns (CAPs)|void-safety tools]]. To review, a CAP is a code pattern for a certain expression, say <code>exp</code> of a detachable type that ensures that <code>exp</code> will never have a void run-time value within the covered scope.
A simple example is the familiar test for void reference:
<code>
if l_x /= Void then
l_x.do_something -- Valid for formal arguments, local variables, and stable attributes
end
</code>
We know that after the explicit check to make sure <code>l_x</code> is not <code>Void</code>, that the feature application <code>l_x.do_something</code> is void-safe.
Of course, you should remember from previous discussions that <code>l_x</code> must be a local variable, a formal argument, or a [[Void-safety: Background, definition, and tools#Stable attributes|stable attribute]].
When void-safety was first envisioned for Eiffel, it was intended that individual CAPs would be proven or certified and documented. This would produce a "catalog" of CAPs.
What happened instead is that the members of the Eiffel standard committee have been able to produce and publish as part of the [http://www.ecma-international.org/publications/standards/Ecma-367.htm standard] a definition of the nature of a CAP from which a determination can be made as to whether a particular code pattern is or is not a CAP.
The definition in the standard document is not easily readable by most developers. So, in this documentation, you will see various examples of CAPs and the rationale behind them.
==The standard CAP definition==
The Eiffel standard (2nd edition, June 2006) defines a CAP as follows:
----
'''''A Certified Attachment Pattern (or CAP) for an expression <code>exp</code> whose type is detachable is an occurrence of <code>exp</code> in one of the following contexts: '''''
'''''1. <code>exp</code> is an Object-Test Local and the occurrence is in its scope. '''''
'''''2. <code>exp</code> is a read-only entity and the occurrence is in the scope of a void test involving <code>exp</code>.'''''
----
The terminology used in the definition is precise. For example, terms like "read-only entity" and "scope of a void test" have specific meanings that are supported by their own definitions in the standard.
Still, the standard does contain informative text that gives us a guideline that a CAP is a scheme to ensure that a particular expression of a detachable type will never have void run-time value in the scope covered by the CAP.
The discussion here will follow that guideline, and, as such, will be less formal (and consequently less precise) than that in the standard, and is intended to be a practical guide. Of course, the [http://www.ecma-international.org/publications/standards/Ecma-367.htm standard document] is available for download if you wish to investigate the specifics.
==CAP-able expressions==
In the first context in the definition above, the expression <code>exp</code> can be an '''Object-Test Local'''. An Object-Test Local is the identifier specified for a fresh local entity in an '''object test'''. Remember, object tests are coded using the [[Void-safety: Background, definition, and tools#The attached syntax (object test)|attached syntax]].
<code>
attached x as l_x
</code>
In the object test expression above, the identifier '''<code>l_x</code>''' is an Object-Test Local.
In the second context, the expression can be a '''read-only entity'''. Read-only entities are:
# Constant attributes
# Formal arguments
# Object-Test Locals
# <code>Current</code>
Additionally, the Eiffel Software compiler allows for [[Void-safety: Background, definition, and tools#Stable attributes|stable attributes]] and local variables to be protected by a CAP.
===Stable attributes===
Stable attributes are the only class attributes which are CAP-able. This is because stable attributes, once attached at run-time, can never have a void value again. So, you use stable attributes safely by using them under the protection of a CAP. Consider this stable attribute:
<code>
my_stable_string: detachable STRING
note
option: stable
attribute
end
</code>
The detachable attribute <code>my_stable_string</code>, because it is stable, is not required to be initialized during the creation of instances of the class in which it is a feature. That means that for each instance, <code>my_stable_string</code> can be initialized later during the instance's life-cycle or not at all. But because it is detachable, <code>my_stable_string</code> cannot be accessed in any context in which it cannot be determined that it is currently attached. For ordinary attributes, this means either using an object test and accessing the object through an object test local, or using using a local variable under the protection of a CAP.
Stable attributes however, can be used directly in a CAP, as shown below:
<code>
if my_stable_string /= Void then
my_stable_string.append ("abc") -- Valid
...
</code>
So using stable attributes can reduce the need to initialize rarely used attributes, and the need to code object tests.
===Local variables===
Local variables can be used in a CAP as long as they are not the target of an assignment whose source is <code>Void</code> or some expression which could possibly be void.
So, for a local variable <code>l_string</code>, the following is valid:
<code>
local
l_string: detachable STRING
do
if l_string /= Void then
l_string.append ("abc") -- Valid
...
</code>
But, if <code>l_string</code> had been a target of an assignment in which the source could possibly have been void, then it could no longer be guaranteed that <code>l_string</code> is not void. So, assuming that <code>my_detachable_string</code> is an attribute declared as type <code>detachable STRING</code>, the second application of <code>append</code> in this example would be invalid:
<code>
local
l_string: detachable STRING
do
if l_string /= Void then
l_string.append ("abc") -- Valid
l_string := my_detachable_string
l_string.append ("xyz") -- Invalid: my_detachable_string might have been void
...
</code>
==Common CAPs==
We've already seen the simple test for void as a CAP:
<code>
local
l_str: detachable STRING
...
if l_str /= Void then
l_str.append ("xyz") -- Valid
end
</code>
Additionally, a creation instruction can serve as a CAP. After the execution of a creation instruction, the target of the creation instruction will be attached:
<code>
local
l_str: detachable STRING
do
create l_str.make_empty
l_str.append ("xyz") -- Valid
...
</code>
==Less obvious cases==
There are some situations that constitute CAPs that we might not think of immediately.
For example, the case of the non-strict boolean operator <code>and then</code>:
<code>
if x /= Void and not x.is_empty then -- Invalid
...
if x /= Void and then not x.is_empty then -- Valid
...
</code>
Assuming that <code>x</code> is CAP-able, the first line of code is invalid because the expression <code>x.is_empty</code> could always be evaluated even in the case in which <code>x</code> is void.
In the second line of code, the non-strict boolean is used, guaranteeing that <code>x.is_empty</code> will not be evaluated in cases in which <code>x</code> is void. Therefore, <code>x.is_empty</code> falls within the scope of the void test on <code>x</code>.
In contracts, multiple assertion clauses are treated as if they were separated by <code>and then</code>. This allows preconditions like the one in the following example:
<code>
my_routine (l_str: detachable STRING)
require
l_str /= Void
not l_str.is_empty -- Valid
...
</code>
Another not-so-obvious CAP is related to the use of the logical implication:
<code>
local
l_str: detachable STRING
do
if l_str /= Void implies some_expression then
...
else
l_str.append ("xyz") -- Valid
end
</code>
==The bottom line on CAPs==
In summary, CAPs provide void-safe protection for certain types of detachable expressions.
Possibly the characteristic of CAPs which is most important to developers is whether or not a particular CAP is supported by the compiler. In other words, from the developers viewpoint, the only opinion that matters in the argument of whether a particular pattern constitutes a CAP is that of the compiler.
If the compiler can provide assurance that a certain code pattern guarantees void-safe protection, then the developer will have that pattern available as a CAP. Likewise, even if a pattern can be shown logically to be a CAP, but for some reason it is not supported by the compiler, then that pattern will not available as a CAP and the compiler will not allow its use.

View File

@@ -0,0 +1,82 @@
[[Property:modification_date|Tue, 09 Jul 2019 09:42:22 GMT]]
[[Property:publication_date|Tue, 09 Jul 2019 09:42:22 GMT]]
[[Property:title|Common myths and misconceptions about Eiffel]]
[[Property:link_title|]]
[[Property:weight|4]]
[[Property:uuid|056c0ab0-8e44-571f-f126-0b1850980754]]
Often, when we speak about Eiffel to prospective users, we hear them repeat misinformation about the method, the language, or the tools. Most of the time, the stories are familiar to us … and untrue. Here are a few of the myths that we hear most often, as recounted and debunked by the series entitled [http://eiffel.com/developers/presentations/ "Where Eiffel Fits"].
==Eiffel is an "academic" language only: ''Whoa, wrong! Twice!''==
Recently, I was offered the opportunity to speak to a local technology group about Eiffel for Microsoft .Net. The leader of this group is part of a small commercially-oriented software development company. Concerning Eiffel, he said, “All I know about Eiffel is that its an academic language.”
We hear that one a lot … and its wrong … in two unrelated ways.
First, as you should know by now, Eiffel is a framework for software development. It has a full-lifecycle development method. The Eiffel method is supported by a notation we call the Eiffel programming language. The notation just happens to be designed such that when it contains sufficient detail, it can be compiled into a running software system. Additionally, the method and language are supported by a set of tools including an interactive development and compiler. So to refer to Eiffel only as a "language" is to do injustice to the complete framework of which the language is only one part.
Secondly, Im not sure what “academic language” means exactly, but if it means only used in an academic setting, or not fit for practical work, then this could not be farther from the truth. It is true that Bertrand Meyer who developed the original Eiffel concepts has academic background and is well-respected in the academic community. Its also true that many of those Eiffel ideas evolved from work that was done by other academic computer scientists and mathematicians. And its true that many colleges and universities use Eiffel to teach the best practices of software development.
But Eiffel is also used successfully in many commercial and government endeavors. If you have any doubts, pay a visit to [https://www.eiffel.com/company/customers/testimonials/ eiffel.com] and check out the success stories and customers testimonials.
==Eiffel is not for doing "real" work: ''That's a joke, right?''==
Occasionally weve heard people say that Eiffel is only suitable for building “toy” systems.
This is similar to the "academic language" argument and is just as false.
In actuality, we see Eiffel being used often in situations in which other technologies fail. If anything it is the other commonly used technologies that tend to break down under stress.
We see Eiffel being used instead of other technologies for systems in which scalability and reliability are essential.
One of our customers is an organization that has developed a payroll system using Eiffel that every week pays over two hundred thousand employees in twenty thousand different institutions … the people in this organization would assure you that Eiffel is indeed industrial grade.
==Not many people are using Eiffel: ''You wouldn't want to share an elevator with them all!''==
The answer to this one depends a bit upon your frame of reference. Some time ago Microsoft estimated that there were twenty million Visual Basic programmers world wide.
If this is true, then relatively speaking, we have to admit that Eiffels market share ''is'' considerably smaller than that of Visual Basic.
Despite that, its not correct to say that not many people use Eiffel. Eiffel licenses world wide number in the tens of thousands. If you use Eiffel, you are not alone. These license-holders have formed a lasting worldwide quorum. Many world-class organizations are committed now, and will continue to be committed to the Eiffel framework. There is support through your maintenance contract with Eiffel Software. Help and information are available online in the form of the [https://www.eiffel.com/company/customers/ Eiffel Software users list] and websites like [https://www.eiffel.org/ Eiffel.org].
Eiffel Software's dual licensing model gives developers the opportunity to learn Eiffel without a great initial financial commitment.
So, dont worry about it, plenty of people use Eiffel … and those numbers are increasing constantly.
==If we use Eiffel, we may not be able to find qualified programmers: ''Gimme a break.''==
Through the years some potential Eiffel users have expressed to us a concern that if they embrace Eiffel, that they may not be able to find a sufficient number of qualified developers.
This is of course incorrect.
First, almost all Eiffel people were proficient in some other technology before they became Eiffel people. It turns out that this really works to your advantage. You see, Eiffel people want to stay Eiffel people. So an Eiffel programmer on the job market will be searching for an Eiffel position first, and would probably rather have a root canal than to go back to working in his or her previous technology.
Additionally, it is important also to understand that Eiffel developers are easy to create. Because Eiffel is simple, clean, and elegant, it doesnt take long to get people going with it. I teach a five-day course that contains fifteen programming exercises. Each time Ive taught the course, almost every student has finished every exercise. Students leave with a good foundation for how to begin saving time and money for their organization by constructing quality software with Eiffel. These people can be fluent in Eiffel in as little as a couple of months. This can be contrasted with the other extreme ... a well-known Microsoft Windows expert told me a couple of years ago that he estimates it to take 5 to 7 years to become truly fluent in C++/COM programming on Windows. Programmers who are proficient in other technologies often experience Eiffel as a breath of fresh air.
==Eiffel might not be around in five/eight/ten (choose one) years: ''Better recalibrate your crystal ball, Nostradamus!''==
I think the first time I heard this one, it was about 1989.
And of course, Ive heard it many times in the years since.
And of course, its not true.
Eiffel is more complete and functionally superior in most ways to every other commercially viable software development technology … and there are enough people around who recognize this (that quorum of users I mentioned earlier) to ensure that Eiffel will be around for a long time to come.
Its possible that twenty-five years from now, there will be a significantly better software engineering idea … but certainly, there hasnt been anything thats come close since Eiffels original design in 1985. In most areas, other technologies are playing “catch-up” to Eiffel.
Besides, Eiffel constantly implements refinements and new capabilities with minimal impact on existing software. [[Void-safe programming in Eiffel|Void-safe programming]] is an excellent example of this.
You can get a feel for this issue by watching [http://channel9.msdn.com/posts/Charles/Emmanuel-Stapf-Eiffel-and-Contract-Oriented-Programming/ this video on Microsoft Developers Network Channel9]. Here you'll see Emmanuel Stapf, an engineer at Eiffel Software, speak with Mads Torgersen, one of Microsoft's C# language designers. You'll hear how Eiffel stays fresh and continues to set a technological standard worthy of the aspirations of other technologies.
So, dont worry about it. Eiffel will be here.

View File

@@ -0,0 +1,97 @@
[[Property:title|Two-Minute fact sheet]]
[[Property:weight|0]]
[[Property:uuid|f672bfb8-ddea-beb1-eaa6-e374a6a6bc92]]
If you are both curious about Eiffel and in a hurry, take a couple of minutes to read these facts about Eiffel. If anything here seems too good to be true, please suspend your disbelief. Press on to the more detailed documentation for the rationale, and our success stories for the evidence behind these facts.
===Eiffel is the most comprehensive approach to the construction of successful object-oriented software.===
Software produced with Eiffel is typically:
*Cheaper -- You spend less on development, debugging, maintenance
*Better -- You get the bugs before they get you
*Shorter time-to-market -- You release quality products ahead of your competitors
*Easier -- In every way: understanding, maintenance, reuse, and extension
===Systems developed using Eiffel can be made portable across major industry platforms.===
*Windows NT/2000/XP/Vista including CLS compliance on Microsoft .NET
*Major Unix versions
*Macintosh OS X
*Linux
*OpenVMS
===Eiffel is the only approach that covers analysis, design, implementation and maintenance in a single framework.===
Eiffel consists of:
====The Eiffel Method====
*Is Based on a small number of powerful ideas from computer science and software engineering
**An example of these is Design by Contract
***Defines a software system as a set of components interacting through precisely specified contracts
***Contracts are active and enforceable throughout the life-cycle
***Design by Contract promotes:
****Precise software specification
****Software reliability
****Safe, effective software reuse
*Uses a "single-product" model
**All life-cycle phases are supported by a single notation
***No need to switch, say, from "analysis language" to "design language"
**Products of all phases are recorded in a single document with multiple views
====The Eiffel Programming Language====
*Exists to express the products of the Eiffel Method
*Supports features not always available in competing technologies
**Contracts and contract monitoring
**Exception handling based on software specification (versus ad hoc try/catch)
**Void-safety: calls on void (null) references are eliminated at compile time
**Inheritance
***Includes multiple and repeated inheritance
***Safe and fully controllable
**Genericity (generic classes), including constrained genericity
**Platform independent concurrency ([[Concurrent programming with SCOOP|SCOOP]])
*Widely recognized as simultaneously the simplest and most complete implementation of object-oriented concepts
*Is clean, elegant, readable, easy to learn
====EiffelStudio and the Eiffel Libraries====
*'''EiffelStudio'''
**Runs on all major platforms (of course, it's built with Eiffel)
**Features lightning-fast compilation (Melting Ice Technology)
**Generates lightning-fast executables
***Final compilation generates standard C (MSIL in the case of .NET)
***Speed of executables rivals native C
**Provides multiple views of your product
***Views for different life-cycle phases and developer roles
***Graphical views
**Features automated generation of HTML and XML documentation
*'''The Eiffel Libraries'''
**Contain rich, time-tested, multi-platform components
**Include facilities for
***GUI building and graphics
***Web
***Networking
***Fundamental algorithms and data structures
***Object persistence and database access
***Multi-threading
***Lexical analysis and parsing
***Interfacing with other technologies
===Eiffel has a proven track record of successful projects===
*Some of the largest successful object-oriented projects ever built, including systems target to:
**Finance and securities
**Education
**Trading
**Manufacturing
**Telecommunications
**Government and national defense
**Science
For a more detailed overview see [[Invitation to Eiffel (I2E)|An Invitation to Eiffel]] .

View File

@@ -0,0 +1,5 @@
[[Property:title|Eiffel Overview]]
[[Property:link_title|Overview]]
[[Property:weight|1]]
[[Property:uuid|f65e67ed-0990-4638-b8f8-0fc85c28f0d8]]

View File

@@ -0,0 +1,59 @@
[[Property:modification_date|Thu, 19 Sep 2019 23:24:40 GMT]]
[[Property:publication_date|Fri, 22 Mar 2019 14:53:52 GMT]]
[[Property:title|Learning Eiffel]]
[[Property:weight|3]]
[[Property:uuid|a30e29fe-841d-4634-ded2-88ae1754e5fd]]
If you are new to Eiffel and are interested in learning the technology, you might consider some of the following resources. Remember that Eiffel, unlike other programming languages, is not just a programming language. Instead, it is a full life-cycle framework for software development. As a consequence, learning Eiffel implies learning the Eiffel Method and the Eiffel programming Language. Additionally, the Eiffel development environment EiffelStudio is specifically designed to support the method and language. So having an understanding of the method and language helps you to appreciate the capabilities and behavior of EiffelStudio.
=Online presentations=
Your first stop in getting acquainted with Eiffel might be the collection of [http://eiffel.com/developers/presentations/ online presentations] on the [http://eiffel.com eiffel.com] website. These presentations each usually take less than an hour to view, and give an introduction to Eiffel concepts including Design by Contract, the EiffelStudio development environment, and includes several presentations that describe selected Eiffel features in relation to those of other other development tools.
=Online documentation set=
The [http://eiffel.org/documentation|eiffel.org/documentation] section contains the online documentation for the Eiffel method, tools, and language. Within the documentation set are tutorials to help you learn about the Eiffel programming language and tools.
==The Eiffel Tutorial==
A [[An Eiffel Tutorial (ET)|tutorial]] that covers the Eiffel Method and much of the Eiffel programming language.
==The EiffelStudio Guided Tour==
This [[Introducing EiffelStudio]] page is good way to get a feel for what EiffelStudio can do.
=Academic materials available online=
Many colleges and universities use Eiffel to teach "best practices" in software engineering. Often the materials used in courses are available on the worldwide web. For example, the teaching materials for courses at the Swiss Federal Institute of Technology in Zurich are available at [http://se.inf.ethz.ch/courses/ this web address] (warning: old content).
If you search the web, you can find similar materials at other academic institutions.
<!--
=Learning maps=
For certain specific areas of learning, the eiffel.com website includes conceptual [http://eiffel.com/developers/learning_maps/ learning maps]. These are graphical maps that link concepts with their relationships. Each concept can have multiple learning resources attached to it. One of the most prevalent types of resources is the "Learnlet", a short online presentation (less than 30 minutes) covering a specific concept.
-->
=Books=
To find information about the most up-to-date books about Eiffel, look [[Books about the Eiffel Method and Language|here]].
=Examples and sample code=
Throughout the documentation site, there are many code snippets designed to illustrate certain language features or design principles. For example, the code snippet [[ET: Inheritance#Redefinition|here]] shows the mechanics of redefining an inherited feature.
In the EiffelStudio distribution you will find a subdirectory "<code>examples</code>" which contains many examples of using Eiffel, primarily with the Eiffel class libraries.
A third source of examples is the [[Examples]] book in the documentation pages.
=Eiffel Programming Language Syntax=
The documentation site includes a summary of the [[Quick reference to the Eiffel programming language|syntax of Eiffel]] the language. This summary is intended to reflect the state of the current official [[ECMA Standard 367|ISO/ECMA Eiffel standard document]].
However, usually you will find that there are differences in the syntax supported by EiffelStudio's compiler and that defined in the current standard. The differences between the standard and the EiffelStudio implementation are summarized in the [[EiffelStudio release notes]] and in a [[Differences between standard ECMA-367 and Eiffel Software implementation|documentation page]] that is specific to that purpose.
Another [[Differences_between_ETL_2nd_printing_and__Eiffel_Software__implementation|a documentation page]] summarizes changes to the pre-ECMA definition of Eiffel as described in [[Eiffel-_The_Language|ETL-2 "Eiffel: The Language"]].

View File

@@ -0,0 +1,185 @@
[[Property:title|Your next project in Eiffel]]
[[Property:weight|1]]
[[Property:uuid|038CDA4A-9ACA-46F6-AC10-06942FAE4529]]
(After an article in the special Eiffel issue of the ''Journal of Object-Oriented Programming'', May 1996.)
Over its ten-year life Eiffel has evolved into one of the most usable software development environments available today. Other articles discuss its theoretical contributions. This one addresses a more mundane subject: how practical software projects can benefit, today, from the power of Eiffel. In so doing it will largely rely on published assessments from both Eiffel users and book authors. In fact a quotation from one of the best-known books in the object-oriented field -- ''Object-Oriented Modeling and Design'' by James Rumbaugh and his colleagues, the text that introduced the OMT O-O analysis method -- provides a good start:
<blockquote>
''Eiffel is arguably the best commercial object-oriented language available today. [Jim Rumbaugh et al. in Object-Oriented Modeling and Design, Prentice Hall 1988]. ''
</blockquote>
==What is Eiffel?==
First we should define what the word "Eiffel" means. If you are thinking "a programming language" you are not wrong (and the preceding quotation shows that you are in good company). The programming language is indeed the most visible part, but it is only a reflection of something broader: a comprehensive approach to the production of quality software. As Richard Wiener wrote:
<blockquote>
''Eiffel is more than a language; it is a framework for thinking about, designing and implementing object-oriented software. [Richard Wiener in Software Development using Eiffel: There is life other than C++, Prentice Hall, 1995.] ''
</blockquote>
The Eiffel approach includes a method (a "methodology", as it is sometimes called) based on a number of pervasive ideas such as Design by Contract, seamlessness, reversibility, rigorous architectural rules, systematic use of single and multiple inheritance, static type checking and several others. Besides a method and a language Eiffel also means powerful graphical development environments, such as EiffelStudio, available across a wide number of industry-standard platforms and supporting analysis and design as well as implementation, maintenance and evolution.
The language itself, indeed (which Wiener calls an elegant and powerful language for object-oriented problem solving") is not just a programming language but extends to the phases of system construction that both precede and follow implementation. This is sometimes hard to accept if you have been raised in the view that software development must involve a sequence of separate steps; that one should initially use an analysis method and then at some point switch to a programming language, with perhaps a design method in-between. This view is detrimental to the software process and to the quality of the resulting product, as it does not support the inevitable back-and-forth hesitations that characterize real software development.
Wisdom sometimes blooms late in the season. However careful you may have been at the analysis stage, some great ideas will hit you - or your implementers - past the point at which you thought you had all the specifications right. Why renounce the benefit of such belated but valuable ideas? Eiffel and the associated Business Object Notation approach to analysis and design accommodate them naturally, by providing a single conceptual framework from the beginning to the end of the process.
Here Eiffel does not have much competition. The most bright-eyed Smalltalk or C++ enthusiast would not seriously claim that one can do design, let alone analysis, in his language of choice. And users of any of the popular O-O analysis notations know that at some stage they must stop working on their model and move on to the implementation in some programming language. Eiffel is unique in helping you for all of these tasks, without ever introducing the impedance mismatches that characterize other approaches.
As a reviewer wrote:
<blockquote>
''As a design language, Eiffel continues to be a better model for object- oriented programming than Ada. It is even better than the new Ada 9X standard. [Richard Riehle in HP Professional, October 1994, A Tour of Eiffel.] ''
</blockquote>
==The commercial and political context==
The next few sections give a glimpse of the technical contributions of Eiffel, or more precisely of what other people have written about them. But of course the best technology in the world requires infrastructure and support to succeed.
Eiffel has plenty of these. It has been around for more than a decade. Eiffel is available from several commercial and open-source providers. The number of licenses sold is in the tens of thousands. Reusable library classes are in the thousands.
The platforms covered range from Unix (all of Unix, the famous and the arcane) and Linux to OpenVMS, OS/2, Windows 3. 1, Windows NT, Windows 95/98.
Particularly impressive is the growth of Eiffel usage in education. Eiffel is quickly becoming the language of choice for teaching modern software technology, including, increasingly, introductory programming. A dozen of excellent textbooks are now available from Prentice Hall, Addison-Wesley, Macmillan and others, with about as many announced just for the coming months.
It is not just the professors who like the approach. Here is just one typical comment on student reaction, from an institution (Rochester Institute of Technology) having adopted Eiffel as its first-year introductory language on a massive scale:
<blockquote>
''We were pleased to discover many of our more skeptical students turning around and admitting that Eiffel was a "fun" language in which to work. [Jim Heliotis in the Proceedings of OOPSLA 95, Experiences teaching objects: A new curriculum for computer science students.] ''
</blockquote>
A Computer World article confirmed the need for Eiffel in training the high-powered software professionals of tomorrow. Quoting Amy Cody-Quinn from Management Recruiters International, the journalist writes
<blockquote>
''There is a big problem with people who say they know C++ - but they don't really know how to do objects. If they have Eiffel on their resume, then we know they really have the proper understanding of what they are doing. [Leslie Goff in ComputerWorld, Object Edge, December 18, 1995.] ''
</blockquote>
But it would be a mistake to think of Eiffel as an academic tool. A little-known fact is that some of the biggest object-oriented projects ever undertaken (at least the successful ones - other O-O languages have had their share of large-scale failures) are being done in Eiffel. The hot areas at the moment are banking and the financial industry (in particular some very large derivative trading and investment management systems), telecommunications, health care. These are all areas in which all that counts in the end is quality and time to market, so that projects need to select the best technology available. Quoting from an article by Philippe Stephan, the system architect of such a project (Rainbow, a major derivative trading system built with ISE Eiffel):
<blockquote>
''We evaluated three major object-oriented languages for the project - Smalltalk, C++ and Eiffel - and chose Eiffel. [...] Rainbow currently comprises over 400,000 lines of code, for about 3000 classes. [Current figures are way over these mid-1995 counts. ] The developers feel very productive. This was confirmed when Rainbow's financial backers brought in object professionals to audit the project. The auditors evaluated the project during July 1994 and were impressed with the productivity of the Rainbow development group. [Philippe Stephan in Object Magazine, July-August 1995, Building financial software with object technology.] ''
</blockquote>
The development group in question is remarkable for being made only for a third of software professionals. The others are professionals from other disciplines (such as trading and financial analysis), who, Stephan writes,
<blockquote>
''can express business concepts in Eiffel because they can focus on design and implementation, rather than struggling with memory management problems and debugging. ''
</blockquote>
The result has received lavish praise from such publications as ComputerWorld and analysts:
<blockquote>
''Industry experts briefed on Rainbow said they were impressed with the results. CALFP is "progressive" in [...] committing the organization's mission-critical systems development efforts to this architecture, said Richard Crone, senior manager of financial services at KPMG Peat Marwick in Los Angeles. "What's unique here is that [CALFP is] delivering this system end-to-end using object-oriented technologies", said Henry Morris, a research analyst at International Data Corporation (IDC) in Framingham, Mass. [Thomas Hoffmann in ComputerWorld, May 8, 1995, Object- Oriented financial package tames transactions.]''
</blockquote>
Along with these Eiffel mega-projects, you will also find myriad smaller endeavors. Many consultants, in particular, have found for themselves the key competitive advantage that they can gain from Eiffel's excellence. In ensuring this spread of Eiffel throughout the industry, the benefit of cheap yet complete environments such as EiffelStudio for Linux has been immeasurable.
Also crucial to the development of Eiffel has been the neutral status of its definition, now controlled by a consortium of vendors and users, NICE (the Nonprofit International Consortium for Eiffel). NICE has already produced a library standard and expects to produce soon the language standard that should shortly thereafter enjoy a smooth ride through ANSI and other international standards bodies.
The pace of Eiffel history has been accelerating in the past few months. This has been picked up by many journalists. As Dan Wilder wrote:
<blockquote>
''With an open specification for both the language and the kernel libraries, and support from multiple vendors, Eiffel now stands poised to take off. [Dan Wilder in Linux Journal, June 1995, Introduction to Eiffel.] ''
</blockquote>
==The criteria==
Eiffel - the method, the language, the environment - is based on a small set of goals, addressing the crucial needs of software quality and productivity. Quoting from an article in ''Byte'' magazine:
<blockquote>
''Developers who want an object-oriented language that adheres to the keystone principles of software engineering need look no further than Eiffel. [Peter Varhol in Byte Magazine, February 1996.] ''
</blockquote>
or, as Steve Bilow wrote in a review of Eiffel Software's Melting Ice compiling technology (which he calls "an outstanding marriage between portability and development speed"):
<blockquote>
''Eiffel was designed precisely for the purpose of enabling software developers to deliver high quality, reliable, efficient, reusable code. [Steve Bilow in The X Journal, The Eiffel alternative, July-August 1995.]''
</blockquote>
==Reliability==
The first goal is reliability. No other approach available today has made the effort to give developers all the tools that they need to produce bug-free software - software that will run without bugs the first time around. Crucial in this effort is the presence of static typing ( ''real'' static typing, not "a little bit typed" as in those languages that still keep C-like type conversions); assertions and the whole mechanism of Design by Contract, on which more than one Eiffel developer has said "this has changed my life" by enabling him or her to specify precisely what the software should do, and to track at run time that it does it; disciplined exception handling; automatic garbage collection, which eliminates a source of horrendous bugs in C++-based environments (and a large part of the code, tedious and error-prone); a clean approach to inheritance; the use of dynamic binding as the default policy, meaning the guarantee that all calls will use the right version of each operation; and the simplicity of the language design, which enables Eiffel developers to know '''all''' of Eiffel and feel in control.
The role of assertions and Design by Contract is particularly important here. According to the ''Journal of Object-Oriented Programming'':
<blockquote>
''The contribution of Eiffel is significant: it shows how invariants, preconditions, and postconditions can be incorporated into a practical developer's view of a class. Wider use of Eiffel [...] will encourage a greater use of simple but powerful mathematics during development. [Richard Mitchell et al. in Journal of Object-Oriented Programming, July-August 1995, As-a: a relationship to support code reuse.] ''
</blockquote>
==Reusability==
The second goal is reusability. This has become a catchword, but Eiffel is the only approach that has taken this requirement and its consequences all the way to the end. Quoting Roland Racko:
<blockquote>
''Everything about [Eiffel] is single-mindedly, unambiguously, gloriously focused on reusability - right down to the choice of reserved words and punctuation and right up to the compile time environment. [Roland Racko in Software Development, December 1994, In praise of Eiffel.] ''
</blockquote>
Eiffel benefits here from being a simple ("but not simplistic", writes Racko) and consistent design, not a transposition from older, unrelated technology. Beyond the language and the environment facilities (such as precompilation), the crucial help to reusability is of course the presence of thousands of high-quality library ''classes'', such as, in EiffelBase (a "Linnaean approach to the reconstruction of software fundamentals"), EiffelNet for client-server communication, EiffelStore for relational and O-O database manipulations, EiffelLex and EiffelParse for lexical analysis and parsing, EiffelMath for object-oriented numerical computation, EiffelVision for portable graphics, WEL (the Windows Eiffel Library) for Windows-specific graphics, EiffelWeb to process forms from the Web, and many others. Not even mentioning quality, the result is probably the biggest repository of object-oriented components available elsewhere. The care that has been applied to the production of these libraries also has considerable pedagogical benefits: the way people learn Eiffel is by learning the libraries - first to use them, then to adapt them if necessary, then to write their own software.
Part of the single-mindedness mentioned by acko is the emphasis on abstraction. In contrast with, say, Smalltalk, you do not read the source code of a class when you want to use it. This may be fine for a couple dozen classes, but not for a large, powerful library. Eiffel introduces the notion of '''short form''': an abstract version of the class, keeping only the interface information including assertions. This is an ideal tool for documenting classes but also for discussing designs and presenting them to outsiders - managers or customers - who need to know what is going on without getting bogged down in the details.
Let me mention just one of the unique reusability-supporting features of Eiffel, without which it is, in my experience, impossible to have a long-term reuse effort. Racko again:
<blockquote>
''The language's designer [...] recognized that no reusable library is ever perfect and, thus, that libraries are always in flux. So he built a kind of version-control system into the language. Specifically, there are language elements to demarcate obsolete code that is, however, still being supported. When these elements are referenced by someone unaware of such code's obsolescence, the compiler will issue a warning at compile time about the impending doom that awaits persons who continue the referencing. ''
</blockquote>
It is this kind of detail that can make or break the success of reuse in a company.
==Extendibility==
Next comes extendibility. With Eiffel, modifying software is part of the normal process. As Philippe Stephan writes of the external audit of his project:
<blockquote>
''The auditors rated the responsiveness of the development team as very high. ''
</blockquote>
Chief among the method's support for extendibility is the careful design of the inheritance mechanism. Unlike Smalltalk, which is fatally limited by the absence of multiple inheritance, the Eiffel approach fundamentally relies on multiple inheritance to combine various abstractions into one. As Dan Wilder notes:
<blockquote>
''Most object-oriented languages do not attempt multiple-inheritance. The literature is full of elaborate explanations why. This is sad. Eiffel demonstrates that multiple inheritance need not be difficult or complex, and it can also yield some quite practical results. ''
</blockquote>
The approach also enforces a strict form of information hiding, which means that a module (a '''client''' in Eiffel Design by Contract terminology) that uses another's facilities (its '''supplier''') is protected against many of the changes that can be made later on to these facilities. This is essential in preserving the coherent evolution of a large system - and the sanity of its developers.
==Efficiency==
Performance is almost as much an obsession in Eiffel as reusability. The software field is still, and will remain for a long time, largely driven by performance considerations. (Do not believe anyone who says that speed does not matter. If we get faster computers, it is to do things faster and especially to do more things - not to use more CPU cycles to run the same old applications at the same old visible speed. )
There is no reason whatsoever to leave the mantle of efficiency to the proponents of machine-oriented languages such as C/C++, or to follow the path of Smalltalk which sacrifices performance to object orientation. With Eiffel you can have the best of both worlds. Thanks to a performance-obsessed language design and ten years of research and competition on compiling algorithms, the speed of Eiffel-generated code (in such modes as what is known as "finalization" in Eiffel Software's implementation) is as good as that of hand-produced C code, or better.
Software producers should stand up to their ideas. That is what we do at Eiffel Software: apart from the run-time engine (a few thousand lines of C), all of our software - thousands of classes, hundreds of thousands of lines - is written in Eiffel, and it runs fast. Typical of the situation is a recent incident with the EiffelLex library: it still had a few C elements, remnants of an earlier design. We rewrote them in Eiffel - for a 30% performance gain.
Why these gains? The answer is simple. The /C++ approach of doing everything by hand, under tight programmer control, works well for small programs. Similarly, a good secretary has no equivalent for keeping one person's records. But in the same way that no humans can match the performance of a computer for managing, say, the records of a bank or a city, no programmer can beat a sophisticated Eiffel compiler for optimizing a large program. Against the automatic application of inlining, static binding, memory management and other optimizations, the human does not stand a chance.
To have one's cake and eat it also means not to have to choose between run-time and compilation-time performance. For programmers used to the contrast between a Smalltalk-like style of rapid turnaround and the interminable edit-compile-link cycle of most compiled environment, the following comments by Dan Wilder (in a separate article) will be a shock:
<blockquote>
''EiffelStudio uses "melting ice technology", which allows incremental changes to run in an interpreted mode. Only modified classes are recompiled. Changing one class and clicking the Melt button caused only a few seconds of compilation. [...] My test application took 20 seconds to compile from scratch in "melt" mode. [Dan Wilder in Linux Journal, September 1995, Two Eiffel implementations.] ''
</blockquote>
Steve Bilow provides further explanations:
<blockquote>
''Based on the observation that software development is an iterative process which is usually focused on constructing systems from code modifications, the folks at Eiffel Software have developed something that they call "Melting Ice Technology". Essentially, this means that when you make a [change] and you want to try it out, you simply "melt" it into the system. You don't need to regenerate a bunch of C code, so your changes are integrated into the system proportionally to the amount of code changed. Even in C and C++, `make` still has to relink. ''
</blockquote>
What this also indicates in passing is the technology choice made by Eiffel Software's implementation and all current implementations: using C as the portable implementation vehicle. By going through C, the compilers gain efficiency and portability. This also makes Eiffel one of the most open environments around; in contrast to the self-centered view that predominates in Smalltalk, Eiffel software is born with a sociable attitude, ready to interface with all kinds of other software written in C or other languages. This, needless to say, is a key to the success of realistic applications.
==With us, everything is the face==
A good way to think about Eiffel - the seamlessness of it, the insistence on getting everything right, the conviction that software should be beautiful in and out, specification and implementation - is this little anecdote stolen from Roman Jakobson's Essays on ''General Linguistics'':
<blockquote>
''In a far-away country, a missionary was scolding the natives. "You should not go around naked, showing your body like this!". One day a young girl spoke back, pointing at him: "But you, Father, you are also showing a part of your body!". "But of course", the missionary said in a dignified tone; "That is my face". The girl replied: "So you see, Father, it is really the same thing. Only, with us, everything is the face". ''
</blockquote>
So it is with Eiffel too. Everything is the face.
Hundreds of thousands of people have now been exposed to Eiffel through books, through courses, through hearing about other people's successes, and most importantly (for the most fortunate among them) through using it to complete a project on time, within budget, and to the satisfaction of their customers. Shouldn't your next project use Eiffel too?

View File

@@ -0,0 +1,38 @@
[[Property:modification_date|Wed, 18 Sep 2019 13:17:05 GMT]]
[[Property:publication_date|Thu, 12 Sep 2019 15:07:05 GMT]]
[[Property:uuid|BF3D5A25-A6C0-4645-956A-82807C41F073]]
[[Property:weight|10]]
[[Property:title|EiffelStudio: A Guided Tour - Eiffel Software Technical Report]]
[[Property:link_title|EiffelStudio Guided Tour]]
==Eiffel Software Technical Report TR-EI-68/GT ==
First published 1993 as ''First Steps with EiffelBench'' (TR-EI-38/EB) and revised as a chapter of ''Eiffel: The Environment'' also available as [[#An_Object-Oriented_Environment|An Object-Oriented Environment]] (below).
Version 3.3.8, 1995.
Version 4.1, 1997
This version: July 2001. Corresponds to release 5.0 of the EiffelStudio environment.
Full reference at [[Manual_identification_and_copyright|Manual identification and copyright]]
==An Object-Oriented Environment ==
:<big>'''Bertrand Meyer'''</big>
:Prentice Hall, 1994
:ISBN 0-13-245-507-2
The principles of object technology change the way we envision, design and use software development environments.
This book explains what it means for an environment to be truly object-oriented, not just by having a modern user interface but by applying to its full extent the concept of data abstraction. It will provide precious material to anyone who is interested in finding out how an environment can support O-O development in its quest for software quality and productivity.
''Content highlights: ''
Introduces five design principles for object-oriented environments; presents a complete set of tools applying these principles, based on development object types rather than functional units; describes a novel approach to compilation: the Melting Ice Technology, which combines the fast development turnaround of interpreters with the safety of compiled approaches, and generates high-performance final code; discusses how to use C as a target language for efficiency and portable cross-development, without impairing the benefits of the O-O method; takes the reader through a detailed demonstration of the environment's object-oriented tools, showing their application to compiling, browsing and symbolic debugging; explains the principles and application of GUI (Graphical User Interface) Application Building, going from mere 'interface builders' to the interactive construction of entire applications - interface and semantics; and introduces the Context-Events-Command-State model of GUI application building and applies it to the interactive development of a complete mini-application.
==The Guided Tour==
{{Note|[[EiffelStudio_tutorials|The Guided Tour to EiffelStudio starts here]]}}

View File

@@ -0,0 +1,33 @@
[[Property:modification_date|Wed, 18 Sep 2019 13:10:45 GMT]]
[[Property:publication_date|Wed, 11 Sep 2019 01:44:42 GMT]]
[[Property:uuid|8A382DA4-C45F-4CBB-A2B6-44447C63EFB0]]
[[Property:weight|5]]
[[Property:title|Reusable Software: The Base Object-Oriented Component Libraries]]
[[Property:link_title|OO Component Libraries]]
:[[Image:/files/uploads/OOComponentLibrariesSmall.jpg|OO Component Libraries]]
:<big>'''Bertrand Meyer'''</big>
:Prentice Hall, 1994
:xx, 514 p.
:Includes bibliographical references and index
:ISBN-10: 013-245-499-8
:ISBN-13: 978-013-245-499-5
First reviews the principles of library construction and the object-oriented techniques that make it possible to build high-quality libraries - e.g., finding the right objects and classes, choosing the proper names, using inheritance properly, determining the ideal class size, etc.
Then provides detailed usage descriptions of hundreds of reusable components, offering thousands of directly usable operations. The components, written in Eiffel, cover such areas as lists, chains, queues, stacks, trees of various kinds, sorted structures, lexical analysis, parsing, and many other fundamental data structures and algorithms.
For both the users of reusable software libraries and for developers who are interested in building their own libraries of reusable software.
''Content:''
1. Introduction to the Base libraries -- 2. Building libraries: techniques -- 3. Principles of library design -- 4. Abstract container structures: the taxonomy -- 5. Mathematical properties -- 6. Linear structures: sequences, chains, lists, circular chains -- 7. Dispenser structures: stacks, queues, priority lists -- 8. Trees -- 9. Sets and hash tables -- 10. Iteration -- 11. Lexical analysis: the Lex library -- 12. Parsing: The Parse Library -- 13. The Kernel Library -- 14. Classes for abstract container structures -- 15. Classes for mathematical properties -- 16. Classes for linear structures -- 17. Dispenser classes -- 18. Tree classes -- 19. Set and hash table classes -- 20. Iteration classes -- 21. Lexical analysis classes -- 22. Parsing classes -- 23. Kernel library classes
{{Caution|The last half of the book is taken up by a reprint of the contract form of the libraries as per printing time.
The most current documentation is found here as
[[ref:libraries/base/reference/index|EiffelBase Class Reference]] }}

View File

@@ -0,0 +1,16 @@
[[Property:title|ECMA Standard 367]]
[[Property:weight|1]]
[[Property:uuid|b49b0949-85fa-31da-555e-003b09f6213e]]
[[Image:ECMA-367 cover small|ECMA-367]]
==ECMA Standard 367 -- Eiffel: Analysis, Design, and Programming Language==
ECMA International
Standard Eiffel syntax, validity, and semantics are described in this document, which is available [http://www.ecma-international.org/publications/standards/Ecma-367.htm online].
ECMA-367 is a specification for the Eiffel programming language. Therefore, it can be useful as a reference, but it is definitely not a tutorial. That said, the document does contain occasional informative text and a general description chapter which can help readers understand the specification.

View File

@@ -0,0 +1,26 @@
[[Property:title|Eiffel: The Language]]
[[Property:weight|2]]
[[Property:uuid|dae5a248-29f5-02b2-d01f-371394aa75e9]]
[[Image:ETL]]
=='''''Eiffel: The Language''''' by Bertrand Meyer.==
Prentice Hall Object-Oriented Series.
594 pp.
Soft cover.
<nowiki>ISBN 0-13-247925-7</nowiki>
''Eiffel: The Language'' is one of the foundation volumes of Eiffel technology. It was originally published in 1992, and reprinted later with updates and corrections.
Because the language specification has changed since the last reprinting to incorporate new quality and productivity constructs, hardcopies of ''Eiffel: The Language'', although still available, will represent the bulk of Eiffel correctly, but will not reflect the latest important changes.
Currently ''Standard Eiffel'', the successor to ''Eiffel: The Language'', is a work-in-progress and is available in its current state online (See ''Standard Eiffel'', on [http://se.ethz.ch/~meyer/publications/#PSTE this page]).
The most current state of Eiffel syntax, validity, and semantics is described in the ISO/ECMA [http://www.ecma-international.org/publications/standards/Ecma-367.htm standard document], also available online.

View File

@@ -0,0 +1,6 @@
[[Property:title|Books about the Eiffel Method and Language]]
[[Property:link_title|Books]]
[[Property:weight|5]]
[[Property:uuid|721967da-6621-33f0-198f-9fc8ee26d37f]]

View File

@@ -0,0 +1,39 @@
[[Property:title|Object-Oriented Software Construction, 2nd Edition]]
[[Property:link_title|OOSC2]]
[[Property:weight|0]]
[[Property:uuid|496983ef-b86e-772e-16b9-39b37ef80e37]]
[[Image:OOSC2 small|OOSC2]]
=='''''Object-Oriented Software Construction, 2nd Edition''''' by Bertrand Meyer.==
Prentice Hall Professional Technical Reference.
1254 + xxviii pp.
Soft cover.
<nowiki>ISBN 0-13-629155-4</nowiki>
Click to [http://www.amazon.com/Object-Oriented-Software-Construction-Book-CD-ROM/dp/0136291554 buy from Amazon].
This Jolt Award winner takes the reader through the clear, logical, and comprehensive formation of a method for object-oriented software development ... the Eiffel method. During this journey, the author evolves a notation capable of expressing the products of each phase of development, from analysis through implementation. This notation is the Eiffel programming language.
==Praise for '''''Object-Oriented Software Construction, 2nd Edition'''''==
Roger Smith, on the Dr. Dobbs Journal website, writes:
:"In my unbiased opinion [...] it is destined to become the comprehensive and definitive reference for most methodological and technical questions raised by object technology. Its width and breadth of scope is impressive, from object-oriented techniques like Design by Contract and inheritance, to methodology issues like patterns and class design, to advanced issues like concurrency and persistence."
In ''Unix Review'', Stan Kelly-Bootle calls this book "The ultimate O-O guide."
Ian Graham, in ''Journal of Object-Oriented Programming'' calls it "Epoch-making".

View File

@@ -0,0 +1,38 @@
[[Property:modification_date|Wed, 11 Sep 2019 02:10:22 GMT]]
[[Property:publication_date|Wed, 11 Sep 2019 02:10:22 GMT]]
[[Property:link_title|Touch of Class]]
[[Property:title|Touch of Class: Learning to Program Well with Objects and Contracts]]
[[Property:weight|-1]]
[[Property:uuid|3b4afd2f-6433-c619-f9a4-602c430c6902]]
[[Image:Touch of Class cover small]]
=='''''Touch of Class: Learning to Program Well with Objects and Contracts''''' by Bertrand Meyer==
Springer-Verlag, 2009, 2nd corrected ed. 2013
876 + lxiv pp.
<nowiki>ISBN-13: 978-3540921448 </nowiki>
Full color printing; many color illustrations and photographs
Click to [http://www.amazon.com/Touch-Class-Learning-Program-Contracts/dp/3540921443 buy from Amazon].
Is this really a book about Eiffel? Perhaps in some senses it is not. It is a book about exactly what the subtitle indicates: ''Learning to Program Well with Objects and Contracts.'' (Primary emphasis should fall on the word "''Well''".)
Still, the Eiffel method and language are used in this journey as tools, the best tools known, to help those seeking excellence in software development become prepared to meet the types of challenges a career in software will present. In the rapidly changing software world, this is a tall order. As the preface (for instructors) states:
:'' It is not enough to present immediately applicable technology, for which in our globalized industry a cheaper programmer will always be available somewhere ... [Software professionals] must master software development as a professional endeavor, and by this distinguish themselves from the masses of occasional or amateur programmers.''
''Touch of Class'' imparts its message using techniques which have accumulated through decades of study of technical learning and have been applied for several years in courses at ETH Zurich. These techniques include the extensive study and reuse of libraries of high-quality software components, employment of the Eiffel object-oriented method and Design by Contract, an introduction to formal methods and a ubiquitous awareness for software engineering concerns.
A unique and refreshing aspect of ''Touch of Class'' is seen throughout the volume. Credit is given for ideas which form the foundation of modern software thinking, and in the process, those pioneers upon whose shoulders all software professionals stand, are made human and personal by photographs and historical vignettes.

View File

@@ -0,0 +1,20 @@
[[Property:title|Eiffel as an expression language]]
[[Property:weight|0]]
[[Property:uuid|61e93102-c558-42e7-7784-0b60b9257b5d]]
A functional-programming style, or more generally a style involving more expressions and fewer instructions, is possible in Eiffel. In particular, the agent mechanism embeds a full functional-programming mechanism in the object-oriented framework of the language.
To make the notations simpler, a number of extensions have been proposed. They involve no fundamental new language mechanisms, but provide new, more concise notations for existing mechanisms. Examples are:
*Conditional expressions
*Implicit tuple, a rule allowing the omission of brackets for an actual argument when it is a tuple and the last argument, e.g. f (a, b, c) as an abbreviation for f ([a, b, c]) (an example involving just one argument). Tuples already provided the equivalent of a variable-argument ("varargs") facility, but it is made simpler to use with this convention.
*Parenthesis alias, making it possible to write just f (x, y) when f is an agent (closure, lambda expression, delegate etc. in other terminologies), i.e. treating f as if it were a function; the notation is simply an abbreviation for f.item ([x, y]) (this example also takes advantage of implicit tuples). It has many other applications since a "parenthesis alias" can be defined for a feature of any class.
*Avoiding explicit assignments to '''Result'''.
*Type inference (to avoid explicitly specifying the type when it can be deduced from the context). This is a facility for the programmer, useful in particular for local variables, but does not affect the type system: Eiffel remains strongly typed, it is just that you can be lazy about writing the type when there is no ambiguity.
*In the same vein, omitting the entire list of generic parameters when it can be inferred.
see [[file:expression_language.pdf|document as pdf]].

View File

@@ -0,0 +1,9 @@
[[Property:title|Technical papers about Eiffel]]
[[Property:description|Background, foundation, or supplemental information about uncovered topics]]
[[Property:link_title|Papers]]
[[Property:weight|4]]
[[Property:uuid|d2b880d6-d1dc-9811-32b8-ed718ad4d4be]]
Occasionally papers are produced providing background, foundation, or supplemental information about the topics covered by the Eiffel documentation. Although the material in these papers might be of interest to many Eiffel users, they might not be suitable in their current form for inclusion in the mainstream documentation books.
You will find a collection of these papers in this book.

View File

@@ -0,0 +1,25 @@
[[Property:title|Void-safety: how Eiffel removes null-pointer dereferencing]]
[[Property:weight|0]]
[[Property:uuid|d9380464-4312-b76e-9bfd-e57df0f59b4a]]
This white paper (see [[file:void-safe-eiffel.pdf|document as pdf]]) presents the Eiffel void-safety mechanism, fully implemented in EiffelStudio 6.4.
In almost every program running today there is a ticking time bomb: the risk of a "void call". A void call is possible in programs written in almost any programming language; its effect is usually to crash the program. Many unexplained program failures and other abnormal behaviors result from void calls.
While extensive testing can decrease the likelihood of a void call, it cannot remove the possibility. The solution has to come from the programming language.
<!--break-->
Professor C.A.R. Hoare from Microsoft Research, winner of the Turing Award and the Kyoto Prize, calls the presence of void calls in modern programming languages the "billion-dollar mistake":
:"The invention of the null reference in 1965" [the source of void calls] "has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years."
(Citation at: [http://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare] )
The Eiffel solution relies on a combination of language mechanisms:
*"Certified Attachment Patterns" are code schemes that the EiffelStudio compiler guarantees to be void-safe.
*"Attached types" are types that are guaranteed to have non-void values.
*The "Object Test" instruction lets programmers treat void values in a special way.
The White Paper (see the link below) describes the theoretical and practical challenges of ensuring void-safety and presents the Eiffel mechanism.

View File

@@ -0,0 +1,17 @@
[[Property:modification_date|Mon, 10 Sep 2018 09:09:25 GMT]]
[[Property:publication_date|Mon, 10 Sep 2018 09:09:25 GMT]]
[[Property:uuid|B74D374E-895C-4F22-B95F-656BD78ECD03]]
[[Property:weight|1000]]
[[Property:title|Getting a STRING from a NUMERIC object]]
[[Property:link_title|NUMERIC to STRING]]
Every class has the `out` method that can be used to get a text version of the object. For a lot of classes, this method returns internal information that is not really useful for the end user. But for every `NUMERIC` class, the `out` method returns a text representation of the number that the `NUMERIC` object represents.
<code>
print_integer (a_integer: INTEGER)
-- Print the value of `a_integer`.
do
print (a_integer.out + "%N")
end
</code>
Note that for more advanced conversion, you can also use a conversion class like `FORMAT_DOUBLE`.

View File

@@ -0,0 +1,28 @@
[[Property:modification_date|Mon, 10 Sep 2018 09:06:41 GMT]]
[[Property:publication_date|Fri, 07 Sep 2018 12:13:00 GMT]]
[[Property:uuid|78393BBA-9B1E-4523-9881-3D83CEB6A952]]
[[Property:weight|3000]]
[[Property:title|Removing object while iterating on a LIST]]
If you already have the object that you want to remove from the `LIST` you can easily use `prune` and `prune_all`. But if you want to remove objects while iterating on that `LIST`, depending on criteria on the objects contained in the `LIST`, here is what you can do.
First of all, if you think about removing an object while iterating, I do not recommend using an `across` loop. If you iterate on the list using a `from until loop end`, just remember to use the `LIST.forth` only when you do not use `LIST.remove`.
For example, let's say we have class `MY_CLASS` with an attribute `has_stopped` and that I want to remove every object of a `LIST` that has this attribute set to `True`. Here is what the code will look like.
<code>
removing_stopped (a_list: LIST [MY_CLASS])
-- Removing every closed element of `a_list`
do
from
a_list.start
until
a_list.exhausted
loop
if a_list.item.has_stopped then
a_list.remove
else
a_list.forth
end
end
end
</code>

View File

@@ -0,0 +1,64 @@
[[Property:modification_date|Wed, 17 Apr 2019 14:09:18 GMT]]
[[Property:publication_date|Thu, 06 Sep 2018 15:17:57 GMT]]
[[Property:uuid|96077603-DD2D-4D8C-A486-AF4BD066613A]]
[[Property:weight|2000]]
[[Property:title|Iterating on a LIST]]
There are three Eiffel mechanisms to iterate on every element of a `LIST`.
=== the `across` loop ===
The `across` can be used on every `ITERABLE` object (including `LIST` objects).
<code>
print_elements (a_list: LIST[INTEGER])
-- Print every elements on `a_list`
do
across a_list as ic loop
print (ic.item.out + "%N")
end
end
</code>
Note that the temporary variable (`ic` in the example) represents an iterator of the `ITERABLE` object, and not directly an element like in many other languages (like the `for` structure in Python for example).
=== the `from until` loop syntax===
This syntax offer more possibilities than the `across` loop, but is riskier.
<code>
print_elements (a_list:LIST[INTEGER])
-- Print every elements on `a_list`
do
from
a_list.start
until
a_list.exhausted
loop
print (a_list.item.out + "%N")
a_list.forth
end
end
</code>
=== Using Eiffel agents and `{LIST}.do_all, ....` ===
It is possible to use agents in conjunction with the `LIST` features `do_all`, `do_if`, `there_exists`, and `for_all` which are inherited from the class `LINEAR`.
<code>
list_traversal_agents
-- Example of traversing a list with do_all
local
a_list: LINKED_LIST [STRING]
do
-- Insert some elements in a_list
create a_list.make
a_list.extend ("The Moon Is Full")
a_list.extend ("Master charge")
a_list.extend ("Black cat bone")
a_list.do_all (agent {STRING}.append (" - Albert Collins"))
a_list.do_all (agent print_element)
end
print_element (a_element: STRING)
-- Print `a_element` to standard output
do
io.put_string (a_element)
io.put_new_line
end
</code>

View File

@@ -0,0 +1,54 @@
[[Property:modification_date|Wed, 17 Apr 2019 14:06:41 GMT]]
[[Property:publication_date|Wed, 17 Apr 2019 14:02:25 GMT]]
[[Property:uuid|5CA34C5D-30F1-4D6F-9FE4-B555E541EA8C]]
[[Property:weight|4000]]
[[Property:title|Managing CTRL+C in console application]]
Normally, if the user uses the CTRL+C keys, the Eiffel application detect it as an error and throw an exception of type <code>OPERATING_SYSTEM_SIGNAL_FAILURE</code>.
To manage the CTRL+C keys, you can use a <code>rescue</code> clause to detect the exception and a <code>retry</code> mechanism to cancel the exception handling done by the Eiffel runtime.
To detect the exception, you can <code>inherit</code> from the <code>EXCEPTIONS</code> class and use an attachment test on <code>Exception_manager.last_exception</code>.
Note that this code does not work on Windows. If used on Windows, the application will quit, but the <code>rescue</code> call is not launched.
<code>
note
description: "Show how to quit an application using CTRL+C (without trace)."
author: "Louis Marchand"
date: "Wed, 25 Apr 2018 23:12:33 +0000"
revision: "0.1"
class
APPLICATION
inherit
EXCEPTIONS
create
make
feature {NONE} -- Initialization
make
-- Launch `Current'.
local
l_ctrl_c:BOOLEAN
do
if not l_ctrl_c then
from until False loop
io.standard_default.put_string ("Press CTRL+C%N")
io.input.read_line
end
else
io.standard_default.put_string ("%NClosing...%N")
end
rescue
if attached {OPERATING_SYSTEM_SIGNAL_FAILURE}
Exception_manager.last_exception then
l_ctrl_c := True
retry
end
end
end
</code>

View File

@@ -0,0 +1,10 @@
[[Property:modification_date|Mon, 10 Sep 2018 09:04:15 GMT]]
[[Property:publication_date|Mon, 10 Sep 2018 09:04:15 GMT]]
[[Property:link_title|Mini How-tos]]
[[Property:uuid|B2E4622A-2495-47DD-9C02-B9940A026EC1]]
[[Property:weight|0]]
[[Property:title|Mini How-tos]]
In this section, you will find little how-tos that you can use to learn some very specific mechanics in Eiffel. Those how-tos are small by design and can be used to show very fundamental, or more advanced, mechanisms for beginners.

View File

@@ -0,0 +1,252 @@
[[Property:modification_date|Wed, 01 Jul 2020 08:52:09 GMT]]
[[Property:publication_date|Wed, 01 Jul 2020 08:52:09 GMT]]
[[Property:title|ET: Agents]]
[[Property:weight|-3]]
[[Property:uuid|ba49a80d-5ddf-8b30-4943-528974fd0ddd]]
Our last mechanism, agents, adds one final level of expressive power to the framework describe so far. Agents apply object-oriented concepts to the modeling of operations.
==Objects for operations==
Operations are not objects; in fact, object technology starts from the decision to separate these two aspects, and to choose object types, rather than the operations, as the basis for modular organization of a system, attaching each operation to the resulting modules -- the classes.
In a number of applications, however, we may need objects that represent operations, so that we can include them in object structures that some other piece of the software will later traverse to uncover the operations and, usually, execute them. Such "operation wrapper" objects, called agents, are useful in a number of application areas such as: <br/>
* GUI (Graphical User Interface) programming, where we may associate an agent with a certain event of the interface, such as a mouse click at a certain place on the screen, to prescribe that if the event occurs -- a user clicks there -- it must cause execution of the agent's associated operation.
* Iteration on data structures, where we may define a general-purpose routine that can apply an arbitrary operation to all the elements of a structure such as a list; to specify a particular operation to iterate, we will pass to the iteration mechanism an agent representing that operation.
* Numerical computation, where we may define a routine that computes the integral of any applicable function on any applicable interval; to represent that function and pass its representation to the integration routine, we will use an agent.
Operations in Eiffel are expressed as routines, and indeed every agent will have an associated routine. Remember, however, that the fundamental distinction between objects and operations remains: an agent is an object, and it is not a routine; it represents a routine. As further evidence that this is a proper data abstraction, note that the procedure <code>call</code>, available on all agents to call the associated routine, is only one of the features of agents. Other features may denote properties such as the class to which the routine belongs, its precondition and postcondition, the result of the last call for a function, the number of arguments.
==Building an agent==
In the simplest form, also one of the most common, you obtain an agent just by writing
<code>
agent r
</code>
where <code>r</code> is the name of a routine of the enclosing class. This is an expression, which you may assign to a writable entity, or pass as argument to a routine. Here for example is how you will specify event handling in the style of the EiffelVision 2 GUI library:
<code>
your_icon.click_actions.extend (agent your_routine)
</code>
This adds to the end of <code>your_icon.click_actions</code> -- the list of agents associated with the "click" event for <code>your_icon</code>, denoting an icon in the application's user interface -- an agent representing <code>your_routine</code>. Then when a user clicks on the associated icon at execution, the EiffelVision 2 mechanisms will call the procedure <code>call</code> on every agent of the list, which for this agent will execute <code>your_routine</code>. This is a simple way to associate elements of your application, more precisely its "business model" (the processing that you have defined, directly connected to the application's business domain), with elements of its GUI.
Similarly although in a completely different area, you may request the integration of a function <code>your_function</code> over the interval <code>0..1</code> through a call such as
<code>
your_integrator.integral (agent your_function, 0, 1)
</code>
In the third example area cited above, you may call an iterator of EiffelBase through
<code>
your_list.do_all (agent your_proc)
</code>
with <code>your_list</code> of a type such as <code>LIST [YOUR_TYPE]</code>. This will apply <code>your_proc</code> to every element of the list in turn.
The agent mechanism is type-checked like the rest of Eiffel; so the last example is valid if and only if <code>your_proc</code> is a procedure with one argument of type <code>YOUR_TYPE</code>.
==Operations on agents==
An agent <code>agent</code> <code>r</code> built from a procedure <code>r</code> is of type <code>PROCEDURE [T, ARGS]</code> where <code>T</code> represents the class to which <code>r</code> belongs and <code>ARGS</code> the type of its arguments. If <code>r</code> is a function of result type <code>RES</code>, the type is <code>FUNCTION [T, ARGS, RES]</code>. Classes <code>PROCEDURE</code> and <code>FUNCTION</code> are from the Kernel Library of EiffelBase, both inheriting from <code>ROUTINE [T, ARGS]</code>.
Among the features of <code>ROUTINE</code> and its descendants the most important are <code>call</code>, already noted, which calls the associated routine, and <code>item</code>, appearing only in <code>FUNCTION</code> and yielding the result of the associated function, which it obtains by calling <code>call</code>.
As an example of using these mechanisms, here is how the function <code>integral</code> could look like in our <code>INTEGRATOR</code> example class. The details of the integration algorithm (straight forward, and making no claims to numerical sophistication) do not matter, but you see the place were we evaluate the mathematical function associated with <code>f</code>, by calling <code>item</code> on <code>f</code>:
<code>
integral (f: FUNCTION [TUPLE [REAL], REAL]; low, high: REAL): REAL
-- Integral of `f' over the interval [`low', `high']
require
meaningful_interval: low <= high
local
x: REAL
do
from
x := low
invariant
x >= low
x <= high + step
-- Result approximates the integral over
-- the interval [low, low.max (x - step)]
until
x > high
loop
Result := Result + step * f.item ([x]) -- Here item is applied to f
x := x + step
end
end
</code>
Function <code>integral</code> takes three arguments: the agent <code>f</code> representing the function to be integrated, and the two interval bounds. When we need to evaluate that function for the value <code>x</code>, in the line
<code>
Result := Result + step * f.item ([x])
</code>
we don't directly pass <code>x</code> to <code>item</code>; instead, we pass a one-element tuple <code>[x]</code>, using the syntax for manifest tuples introduced in [[ET: Other Mechanisms#Tuple_types|"Tuple types"]] . You will always use tuples for the argument to <code>call</code> and <code>item</code>, because these features must be applicable to any routine, and so cannot rely on a fixed number of arguments. Instead they take a single tuple intended to contain all the arguments. This property is reflected in the type of the second actual generic parameter to <code>f</code>, corresponding to <code>ARGS</code> (the formal generic parameter of <code>FUNCTION</code>): here it's <code>TUPLE [REAL]</code> to require an argument such as <code>[x]</code>, where <code>x</code> is of type <code>REAL</code>.
Similarly, consider the agent that the call seen above:
<code>
your_icon.click_actions.extend (agent your_routine)
</code>
added to an EiffelVision list. When the EiffelVision mechanism detects a mouse click event, it will apply to each element <code>item</code> of the list of agents, <code>your_icon.click_actions</code>, an instruction such as
<code>
item.call ([x, y])
</code>
where <code>x</code> and <code>y</code> are the coordinates of the mouse clicking position. If <code>item</code> denotes the list element <code>agent</code> your_routine, inserted by the above call to <code>extend</code>, the effect will be the same as that of calling
<code>
your_routine (x, y)
</code>
assuming that <code>your_routine</code> indeed takes arguments of the appropriate type, here <code>INTEGER</code> representing a coordinate in pixels. (Otherwise type checking would have rejected the call to <code>extend</code>.)
==Open and closed arguments==
In the examples so far, execution of the agent's associated routine, through <code>item</code> or <code>call</code>, passed exactly the arguments that a direct call to the routine would expect. You can have more flexibility. In particular, you may build an agent from a routine with more arguments than expected in the final call, and you may set the values of some arguments at the time you define the agent.
Assume for example that a cartographical application lets a user record the location of a city by clicking on the corresponding position on the map. The application may do this through a procedure
<code>
record_city (cn: STRING; pop: INTEGER; x, y: INTEGER)
-- Record that the city of name `cn' is at coordinates
-- `x' and `y' with population `pop'.
</code>
Then you can associate it with the GUI through a call such as
<code>
map.click_actions.extend (agent record_city (name, population, ?, ?))
</code>
assuming that the information on the <code>name</code> and the <code>population</code> has already been determined. What the agent denotes is the same as <code>agent</code> <code>your_routine</code> as given before, where <code>your_routine</code> would be a fictitious two-argument routine obtained from <code>record_city</code> -- a four-argument routine -- by setting the first two arguments once and for all to the values given, <code>name</code> and <code>population</code>.
In the agent <code>agent record_city (name, population, ?, ?)</code>, we say that these first two arguments, with their set values, are '''closed'''; the last two are '''open'''. The question mark syntax introduced by this example may only appear in agent expressions; it denotes open arguments. This means, by the way, that you may view the basic form used in the preceding examples, <code>agent your_routine</code>, as an abbreviation -- assuming your_routine has two arguments -- for <code>agent your_routine (?, ?)</code>. It is indeed permitted, to define an agent with all arguments open, to omit the argument list altogether; no ambiguity may result.
For type checking, <code>agent record_city (name, population, ?, ?)</code> and <code>agent your_routine (?, ?)</code> are acceptable in exactly the same situations, since both represent routines with two arguments. The type of both is
<code>
PROCEDURE [TUPLE [INTEGER, INTEGER]]
</code>
where the tuple type specifies the open operands.
A completely closed agent, such as <code>agent your_routine (25, 32)</code> or <code>agent record_city (name, population, 25, 32)</code>, has the type <code>TUPLE</code>, with no parameters; you will call it with <code>call ([ ])</code>, using an empty tuple as argument.
The freedom to start from a routine with an arbitrary number of arguments, and choose which ones you want to close and which ones to leave open, provides a good part of the attraction of the agent mechanism. It means in particular that in GUI applications you can limit to the strict minimum the "glue" code (sometimes called the controller in the so-called MVC, Model-View Controller, scheme of GUI design) between the user interface and "business model" parts of a system. A routine such as <code>record_city</code> is a typical example of an element of the business model, uninfluenced -- as it should be -- by considerations of user interface design. Yet by passing it in the form of an agent with partially open and partially closed arguments, you may be able to use it directly in the GUI, as shown above, without any "controller" code.
As another example of the mechanism's versatility, we saw above an integral function that could integrate a function of one variable over an interval, as in
<code>
your_integrator.integral (agent your_function, 0, 1)
</code>
Now assume that <code>function3</code> takes three arguments. To integrate <code>function3</code> with two arguments fixed, you don't need a new <code>integral</code> function; just use the same <code>integral</code> as before, judiciously selecting what to close and what to leave open:
<code>
your_integrator.integral (agent function3 (3.5, ?, 6.0), 0, 1)
</code>
==Open targets==
All the agent examples seen so far were based on routines of the enclosing class. This is not required. Feature calls, as you remember, were either unqualified, as in <code>f (x, y)</code>, or qualified, as in <code>a.g (x, y)</code>. Agents, too, have a qualified variant as in
<code>
agent a.g
</code>
which is closed on its target <code>a</code> and open on the arguments. Variants such as <code>agent a.g (x, y)</code>, all closed, and <code>agent a.g (?, y)</code>, open on one argument, are all valid.
You may also want to make the target open. The question mark syntax could not work here, since it wouldn't tell us the class to which feature <code>g</code> belongs, known in the preceding examples from the type of <code>a</code>. As in creation expressions, we must list the type explicitly; the convention is the same: write the types in braces, as in
<code>
agent {SOME_TYPE}.g
agent {SOME_TYPE}.g (?, ?)
agent {SOME_TYPE}.g (?, y)
</code>
The first two of these examples are open on the target and both operands; they mean the same. The third is closed on one argument, open on the other and on the target.
These possibilities give even more flexibility to the mechanism because they mean that an operation that needs agents with certain arguments open doesn't care whether they come from an argument or an operand of the original routine. This is particularly useful for iterators and means that if you have two lists
<code>
your_account_list: LIST [ACCOUNT]
your_integer_list: LIST [INTEGER]
</code>
you may write both
<code>
your_account_list.do_all (agent {ACCOUNT}.deposit_one_grand)
your_integer_list.do_all (agent add_to_total)
</code>
even though the two procedures used in the agents have quite different forms. We are assuming here that the first one, a feature of class <code>ACCOUNT</code>, is something like
<code>
deposit_one_grand
-- Deposit one thousand into `Current'.
do
deposit (1000)
end
</code>
The procedure <code>deposit_one_grand</code> takes no arguments. In the <code>do_all</code> example above, its target is open. The target will be, in turn, each instance of <code>ACCOUNT</code> in <code>your_account_list</code>.
In contrast, the other routine, assumed to be a feature of the calling class, does take an argument <code>x</code>:
<code>
add_to_total (x: INTEGER)
-- Add `x' to the value of `total'.
do
total := total + x
end
</code>
Here, <code>total</code> is assumed to be an integer attribute of the enclosing class. In the <code>do_all</code> example, each instance of <code>your_integer_list</code> will fill the argument <code>x</code> left open in <code>add_to_total</code>.
Without the versatility of playing with open and closed arguments for both the original arguments and target, you would have to write separate iteration mechanisms for these two cases. Here you can use a single iteration routine of <code>LIST</code> and similar classes of EiffelBase, <code>do_all</code>, for both purposes: <br/>
* Depositing money on every account in a list of accounts.
* Adding all the integers in a list of integers.
==Inline agents==
In the agent discussion above, it has been assumed that there already exists some routine that we wish to represent with an agent. However, sometimes the only usage of such a routine could be as an agent ... that is, the routine does not make sense as a feature of the class in question. In these cases, we can use '''inline agents'''. With an inline agent we write the routine within the agent declaration.
If we consider the use of agents instead of class features in the two <code>do_all</code> examples in the previous section, the agents would be coded as follows:
<code>
your_account_list.do_all
(agent (a: ACCOUNT)
do
a.deposit (1000)
end)
</code>
and
<code>
your_integer_list.do_all
(agent (i: INTEGER)
do
total := total + i
end)
</code>
The syntax of the inline agent corresponds to the syntax of a routine. Immediately following the <code>agent</code> keyword are the formal arguments and in the case of functions the type for <code>Result</code>. Inline agents can have <code>local</code> entities, preconditions, and postconditions, just like any routine.
Inline agents do not have access to the local entities of the routine in which they are coded. So, if it is necessary to use the routine's local variables, they must be passed as arguments to the inline agent.
Here's an example of an inline agent which is a function. It is used in the context of a check to see if every element of <code>your_integer_list</code> is positive:
<code>
your_integer_list.for_all
(agent (i: INTEGER): BOOLEAN
do
Result := (i > 0)
ensure
definition: Result = (i > 0)
end)
</code>
Inline agents are interesting also as an implementation of the notion of [http://en.wikipedia.org/wiki/Closure_(computer_science) closures] in computer science.
Agents provide a welcome complement to the other mechanisms of Eiffel. They do not conflict with them but, when appropriate -- as in the examples sketched in this section -- provide clear and expressive programming schemes, superior to the alternatives.
Compatibility note: earlier versions of the agent classes (ROUTINE, PROCEDURE, FUNCTION, PREDICATE) had an extra initial generic parameter, for which ANY was generally used. The compiler has been engineered to accept the old style in most cases.
{{SeeAlso|[[Event Programming with Agents]] }}

View File

@@ -0,0 +1,337 @@
[[Property:title|ET: Design by Contract (tm), Assertions and Exceptions]]
[[Property:weight|-8]]
[[Property:uuid|2ef367c9-34d9-d45e-a722-163b39581405]]
Eiffel directly implements the ideas of Design by Contract&#153; , which enhance software reliability and provide a sound basis for software specification, documentation and testing, as well as exception handling and the proper use of inheritance.
==Design by Contract&#153; basics==
A system -- a software system in particular, but the ideas are more general -- is made of a number of cooperating components. Design by Contract&#153; states that their cooperation should be based on precise specifications -- contracts -- describing each party's expectations and guarantees.
An Eiffel contract is similar to a real-life contract between two people or two companies, which it is convenient to express in the form of tables listing the expectations and guarantees. Here for example is how we could sketch the contract between a homeowner and the telephone company:
{| border="1"
|-
| style="width=10%" |provide telephone service
| style="width=35%" |'''OBLIGATIONS'''
| style="width=35%" |'''BENEFITS'''
|-
| '''Client'''
| (Satisfy precondition:) <br/>
Pay bill.
| (From postcondition:) <br/>
Receive telephone service from Supplier.
|-
| '''Supplier'''
| (Satisfy precondition:) <br/>
Provide telephone service.
| (From postcondition:) <br/>
No need to provide anything if bill not paid.
|}
Note how the obligation for each of the parties maps onto a benefit for the other. This will be a general pattern.
The client's obligation, which protects the supplier, is called a '''precondition'''. It states what the client must satisfy before requesting a certain service. The client's benefit, which describes what the supplier must do (assuming the precondition was satisfied), is called a '''postcondition'''.
In addition to preconditions and postconditions, contract clauses include '''class invariants''', which apply to a class as a whole. More precisely a class invariant must be ensured by every creation procedure (or by the default initialization if there is no creation procedure), and maintained by every exported routine of the class.
==Expressing assertions==
Eiffel provides syntax for expressing preconditions (<code>require</code>), postconditions (<code>ensure</code>) and class invariants (<code>invariant</code>), as well as other assertion constructs studied later (see "[[ET: Instructions|Instructions]]" ): loop invariants and variants, check instructions.
Here is a partial update of class <code>ACCOUNT</code> with more assertions:
<code>
note
description: "Simple bank accounts"
class
ACCOUNT
feature -- Access
balance: INTEGER
-- Current balance
deposit_count: INTEGER
-- Number of deposits made since opening
do
... As before ...
end
feature -- Element change
deposit (sum: INTEGER)
-- Add `sum' to account.
require
non_negative: sum >= 0
do
... As before ...
ensure
one_more_deposit: deposit_count = old deposit_count + 1
updated: balance = old balance + sum
end
feature {NONE} -- Implementation
all_deposits: DEPOSIT_LIST
-- List of deposits since account's opening.
invariant
consistent_balance: (all_deposits /= Void) implies
(balance = all_deposits . total)
zero_if_no_deposits: (all_deposits = Void) implies
(balance = 0)
end -- class ACCOUNT
</code>
Each assertion is made of one or more subclauses, each of them a boolean expression (with the additional possibility of the <code>old</code> construct). The effect of including more than one sub clause, as in the postcondition of <code>deposit</code> and in the invariant, is the same as connecting them through an <code>and</code>. Each clause may be preceded by a label, such as <code>consistent_balance</code> in the invariant, and a colon; the label is optional and does not affect the assertion's semantics, except for error reporting as explained in the next section, but including it systematically is part of the recommended style. The value of the boolean expression <code>a implies b</code> is true except if <code>a</code> is true and <code>b</code> false.
Because assertions benefit from the full power of boolean expressions, they may include function calls. This makes it possible to express sophisticated consistency conditions, such as " the graph contains no cycle", which would not be otherwise expressible through simple expressions, or even through first-order predicate calculus, but which are easy to implement as Eiffel functions returning boolean results.
===Preconditions===
The precondition of a routine expresses conditions that the routine is imposing on its clients. Here a call to <code>deposit</code> is correct if and only if the value of the argument is non-negative. The routine does not guarantee anything for a call that does not satisfy the precondition. It is in fact part of the Eiffel method that a routine body should '''never''' test for the precondition, since it is the client's responsibility to ensure it. (An apparent paradox of Design by Contract&#153;, which is reflected in the bottom-right entries of the preceding and following contract tables, and should not be a paradox any more at the end of this discussion, is that one can get more reliable software by having fewer explicit checks in the software text.)
===Postconditions===
The postcondition of a routine expresses what the routine guaranteed to its clients for calls satisfying the precondition. The notation <code>old expression</code>, valid in postconditions ( <code>ensure</code> clauses) only, denotes the value that <code>expression</code> had on entry to the routine.
The precondition and postcondition state the terms of the contract between the routine and its clients, similar to the earlier example of a human contract:
{| border="1"
|-
| style="width=10%" |<code>deposit</code>
| style="width=35%"| '''OBLIGATIONS'''
| style="width=35%" | '''BENEFITS'''
|-
| '''Client'''
| (Satisfy precondition:) <br/>
Use a non-negative argument.
| (From postcondition:) <br/>
Get deposits list and balance updated.
|-
| '''Supplier'''
| (Satisfy precondition:) <br/>
Update deposits list and balance.
| (From postcondition:) <br/>
No need to handle negative arguments.
|}
===Class invariants===
The class invariant, as noted, applies to all features. It must be satisfied on exit by any creation procedure, and is implicitly added to both the precondition and postcondition of every exported routine. In this respect it is both good news and bad news for the routine implementer: good news because it guarantees that the object will initially be in a stable state, averting the need in the example to check that the total of <code>all_deposits</code> is compatible with the <code>balance</code>; bad news because, in addition to its official contract as expressed by its specific postcondition, every routine must take care of restoring the invariant on exit.
A requirement on meaningful contracts is that they should be in good faith: satisfiable by an honest partner. This implies a consistency rule: if a routine is exported to a client (either generally or selectively), any feature appearing in its precondition must also be available to that client. Otherwise -- for example if the precondition included <code>require n > 0</code>, where <code>n</code> is a secret attribute -- the supplier would be making demands that a good-faith client cannot possibly check for.
Note in this respect that guaranteeing a precondition does not necessarily mean, for the client, testing for it. Assuming <code>n</code> is exported, a call may test for the precondition
<code>
if x.n > 0 then
x.r
end
</code>
possibly with an <code>else</code> part. But if the context of the call, in the client's code, implies that <code>n</code> is positive -- perhaps because some preceding call set it to the sum of two squares -- then there is no need for an <code>if</code> or similar construct.
{{note|In such a case, a <code>check</code> instruction as introduced later ( "[[ET: Instructions|Instructions]]" ) is recommended if the reason for omitting the test is non-trivial. }}
==Using contracts for built-in reliability==
What are contracts good for? Their first use is purely methodological. By applying a discipline of expressing, as precisely as possible, the logical assumptions behind software elements, you can write software whose reliability is built-in: software that is developed hand-in-hand with the rationale for its correctness.
This simple observation -- usually not clear to people until they have practiced Design by Contract&#153; thoroughly on a large-scale project -- brings as much change to software practices and quality as the rest of object technology.
==Run-time assertion monitoring==
Contracts in Eiffel are not just wishful thinking. They can be monitored at run time under the control of compilation options.
It should be clear from the preceding discussion that contracts are not a mechanism to test for special conditions, for example erroneous user input. For that purpose, the usual control structures ( <code>if deposit_sum > 0 then</code> ...) are available, complemented in applicable cases by the exception handling mechanism reviewed next. An assertion is instead a '''correctness condition''' governing the relationship between two software modules (not a software module and a human, or a software module and an external device). If <code>sum</code> is negative on entry to <code>deposit</code>, violating the precondition, the culprit is some other software element, whose author was not careful enough to observe the terms of the deal. Bluntly:
{{rule|name=Assertion Violation|text=A run-time assertion violation is the manifestation of a bug. }}
To be more precise: <br/>
* A precondition violation signals a bug in the client, which did not observe its part of the deal.
* A postcondition (or invariant) violation signals a bug in the supplier -- the routine -- which did not do its job.
That violations indicate bugs explains why it is legitimate to enable or disable assertion monitoring through mere compilation options: for a correct system -- one without bugs -- assertions will always hold, so the compilation option makes no difference to the semantics of the system.
But of course for an incorrect system the best way to find out where the bug is -- or just that there is a bug -- is often to monitor the assertions during development and testing. Hence the presence of the compilation options, which EiffelStudio lets you set separately for each class, with defaults at the system and cluster levels: <br/>
* <code>no</code> : assertions have no run-time effect.
* <code>require</code> : monitor preconditions only, on routine entry.
* <code>ensure</code> : preconditions on entry, postconditions on exit.
* <code>invariant</code> : same as <code>ensure</code>, plus class invariant on both entry and exit for qualified calls.
* <code>all</code> : same as <code>invariant</code>, plus <code>check</code> instructions, loop invariants and loop variants.
An assertion violation, if detected at run time under one of these options other than the first, will cause an exception ( [[ET: Design by Contract (tm), Assertions and Exceptions#exception_handling|"Exception handling"]] ). Unless the software has an explicit "retry" plan as explained in the discussion of exceptions, the violation will produce an exception trace and cause termination (or, in EiffelStudio, a return to the environment's browsing and debugging facilities at the point of failure). If present, the label of the violated sub clause will be displayed, to help identify the problem.
The default is <code>require</code>. This is particularly interesting in connection with the Eiffel method's insistence on reuse: with libraries such as EiffelBase, richly equipped with preconditions expressing terms of use, an error in the '''client software''' will often lead, for example through an incorrect argument, to violating one of these preconditions. A somewhat paradoxical consequence is that even an application developer who does not apply the method too well (out of carelessness, haste, indifference or ignorance) will still benefit from the presence of contracts in someone else's library code.
During development and testing, assertion monitoring should be turned on at the highest possible level. Combined with static typing and the immediate feedback of compilation techniques such as the Melting Ice Technology, this permits the development process mentioned in the section [[ET: The Software Process in Eiffel#Quality_and_functionality|"Quality and functionality"]], where errors are exterminated at birth. No one who has not practiced the method in a real project can imagine how many mistakes are found in this way; surprisingly often, a violation will turn out to affect an assertion that was just included for goodness' sake, the developer being convinced that it could never "possibly" fail to be satisfied.
By providing a precise reference (the description of what the software is supposed to do) against which to assess the reality (what the software actually does), Design by Contract&#153; profoundly transforms the activities of debugging, testing and quality assurance.
When releasing the final version of a system, it is usually appropriate to turn off assertion monitoring, or bring it down to the <code>require</code> level. The exact policy depends on the circumstances; it is a trade off between efficiency considerations, the potential cost of mistakes, and how much the developers and quality assurance team trust the product. When developing the software, however, you should always assume -- to avoid loosening your guard -- that in the end monitoring will be turned off.
==The contract form of a class==
Another application of assertions governs documentation. Environment mechanisms, such as clicking the <code>Form Contract</code> icon in Eiffelstudio, will produce, from a class text, an abstracted version which only includes the information relevant for client authors. Here is the contract form of class <code>ACCOUNT</code> in the latest version given:
<code>
note
description: "Simple bank accounts"
class interface
ACCOUNT
feature -- Access
balance: INTEGER
-- Current balance
deposit_count: INTEGER
-- Number of deposits made since opening
feature -- Element change
deposit (sum: INTEGER)
-- Add `sum' to account.
require
non_negative: sum >= 0
ensure
one_more_deposit: deposit_count = old deposit_count + 1
updated: balance = old balance + sum
invariant
consistent_balance: balance = all_deposits.total
end -- class interface ACCOUNT
</code>
The words <code>class interface</code> are used instead of just <code>class</code> to avoid any confusion with actual Eiffel text, since this is documentation, not executable software. (It is in fact possible to generate a compilable variant of the Contract Form in the form of a deferred class, a notion defined later.)
Compared to the full text, the Contract Form of a class (also called its "short form") retains all its interface properties, relevant to client authors: <br/>
* Names and signatures (argument and result type information) for exported features.
* Header comments of these features, which carry informal descriptions of their purpose. (Hence the importance, mentioned in "[[ET: Hello World|Hello World]]", of always including such comments and writing them carefully.)
* Preconditions and postconditions of these features (at least the subclauses involving only exported features).
* Class invariant (same observation).
The following elements, however, are not in the Contract Form: any information about non-exported features; all the routine bodies (<code>do</code> clauses, or the <code>external</code> and <code>once</code> variants seen in [[ET: The Static Picture: System Organization#External_software|"External software"]] above and [[ET: Other Mechanisms#Once_routines_and_shared_objects|"Once routines and shared objects"]] below); assertion subclauses involving non-exported features; and some keywords not useful in the documentation.
In accordance with the Uniform Access principle (described in [[ET: The Dynamic Structure: Execution Model|"Objects, fields, values, and references"]] ), the Contract Form does not distinguish between attributes and argument-less queries. In the above example, <code>balance</code> could be one or the other, as it makes no difference to clients, except possibly for performance.
The Contract Form is the fundamental tool for using supplier classes in the Eiffel method. It enables client authors to reuse software elements without having to read their source code. This is a crucial requirement in large-scale industrial developments.
The Contract Form satisfies two key requirements of good software documentation: <br/>
* It is truly abstract, free from the implementation details of what it describes and concentrating instead on its functionality.
* Rather than being developed separately -- an unrealistic requirement, hard to impose on developers initially and becoming impossible in practice if we expect the documentation to remain up to date as the software evolves -- the documentation is extracted from the software itself. It is not a separate product but a different view of the same product. This prolongs the '''Single Product''' principle that lies at the basis of Eiffel's seamless development model (shown in [[ET: The Software Process in Eiffel|The Software Process in Eiffel]] ).
The Contract Form is only one of the relevant views. EiffelStudio, for example, generates graphical representations of system structures, to show classes and their relations -- client, inheritance -- according to the conventions of BON (the Business Object Notation). In accordance with the principles of seamlessness and reversibility, EiffelStudio lets you both work on the text, producing the graphics on the fly, or work on the graphics, updating the text on the fly; you can alternate as you wish between these two modes. The resulting process is quite different from more traditional approaches based on separate tools: an analysis and CASE workbench, often based on UML, to deal with an initial "bubble-and-arrow" description; and a separate programming environment, to deal with implementation aspects only. In Eiffel the environment provides consistent, seamless support from beginning to end.
The Contract Form -- or its variant the Flat-Contract Form, which takes account of inheritance ( [[ET: Inheritance#Flat_and_Flat-Contract_Forms|"Flat and Flat-Contract Forms"]] ) are the standard form of library documentation, used extensively, for example, in the book <span> [http://www.eiffel.com/services/training/books.html Reusable Software] </span> (see bibliography). Assertions play a central role in such documentation by expressing the terms of the contract. As demonstrated a contrario by the widely publicized $500-million crash of the Ariane-5 rocket launcher in June of 1996, due to the incorrect reuse of a software module from the Ariane-4 project, '''reuse without a contract documentation''' is the path to disaster. Non-reuse would, in fact, be preferable.
==Exception handling==
Another application of Design by Contract&#153; governs the handling of unexpected cases. The vagueness of many discussions of this topic follows from the lack of a precise definition of terms such as "exception". With Design by Contract&#153; we are in a position to be specific: <br/>
* Any routine has a contract to achieve.
* Its body defines a strategy to achieve it -- a sequence of operations, or some other control structure involving operations. Some of these operations are calls to routines, with their own contracts; but even an atomic operation, such as the computation of an arithmetic operation, has an implicit contract, stating that the result will be representable.
* Any one of these operations may <code>fail</code>, that is to say be unable to meet its contract; for example an arithmetic operation may produce an overflow (a non-representable result).
* The failure of an operation is an '''exception''' for the routine that needed the operation.
* As a result the routine may fail too -- causing an exception in its own caller.
Note the precise definitions of the two key concepts, failure and exception. Although failure is the more basic one -- since it is defined for atomic, non-routine operations -- the definitions are mutually recursive, since an exception may cause a failure of the recipient routine, and a routine's failure causes an exception in its own caller.
Why state that an exception "may" cause a failure? It is indeed possible to "rescue" a routine from failure in the case of an exception, by equipping it with a clause labeled <code>rescue</code>, as in:
<code>
read_next_character (f: FILE)
-- Make next character available in last_character.
-- If impossible, set failed to True.
require
readable: file.readable
local
impossible: BOOLEAN
do
if impossible then
failed := True
else
last_character := low_level_read_function (f)
end
rescue
impossible := True
retry
end
</code>
This example includes the only two constructs needed for exception handling: <code>rescue</code> and <code>retry</code>. A <code>retry</code> instruction is only permitted in a rescue clause; its effect is to start again the execution of the routine, without repeating the initialization of local entities (such as <code>impossible</code> in the example, which was initialized to <code>False</code> on first entry). Features <code>failed</code> and <code>last_character</code> are assumed to be attributes of the enclosing class.
This example is typical of the use of exceptions: as a last resort, for situations that should not occur. The routine has a precondition, <code>file.readable</code>, which ascertains that the file exists and is accessible for reading characters. So clients should check that everything is fine before calling the routine. Although this check is almost always a guarantee of success, a rare combination of circumstances could cause a change of file status (because a user or some other system is manipulating the file) between the check for <code>readable</code> and the call to <code>low_level_read_function</code>. If we assume this latter function will fail if the file is not readable, we must catch the exception.
A variant would be
<code>
local
attempts: INTEGER
do
if attempts < Max_attempts then
last_character := low_level_read_function (f)
else
failed := True
end
rescue
attempts := attempts + 1
retry
end
</code>
which would try again up to <code>Max_attempts</code> times before giving up.
The above routine, in either variant, never fails: it always fulfills its contract, which states that it should either read a character or set <code>failed</code> to record its inability to do so. In contrast, consider the new variant
<code>
local
attempts: INTEGER
do
last_character := low_level_read_function (f)
rescue
attempts := attempts + 1
if attempts < Max_attempts then
retry
end
end
</code>
with no more role for <code>failed</code>. In this case, after <code>Max_attempts</code> unsuccessful attempts, the routine will execute its <code>rescue</code> clause to the end, with no <code>retry</code> (the <code>if</code> having no <code>else</code> clause). This is how a routine '''fails'''. It will, as noted, pass on the exception to its caller.
Such a rescue clause should, before terminating, restore the invariant of the class so that the caller and possible subsequent <code>retry</code>attempts from higher up find the objects in a consistent state. As a result, the rule for an absent <code>rescue</code> clause -- the case for the vast majority of routines in most systems -- is that it is equivalent to
<code>
rescue
default_rescue
</code>
where procedure <code>default_rescue</code> comes from <code>ANY</code>, where it is defined to do nothing; in a system built for robustness, classes subject to non-explicitly-rescued exceptions should redefine <code>default_rescue</code> (perhaps using a creation procedure, which is bound by the same formal requirement) so that it will always restore the invariant.
Behind Eiffel's exception handling scheme lies the principle -- at first an apparent platitude, but violated by many existing mechanisms -- that a routine should '''either succeed or fail'''. This is in turn a consequence of Design by Contract&#153; principles: succeeding means being able to fulfill the contract, possibly after one or more <code>retry</code>; failure is the other case, which must always trigger an exception in the caller. Otherwise it would be possible for a routine to miss its contract and yet return to its caller in a seemingly normal state. That is the worst possible way to handle an exception.
Concretely, exceptions may result from the following events: <br/>
* A routine failure ( <code>rescue</code> clause executed to the end with no <code>retry</code>), as just seen.
* Assertion violation, if for a system that runs with assertion monitoring on.
* Attempt to call a feature on a void reference: <code>x.f (...)</code>, the fundamental computational mechanism, can only work if <code>x</code> is attached to an object, and will cause an exception otherwise.
* Developer exception, as seen next.
* Operating system signal:arithmetic overfolow; no memory available for a requested creation or twin -- even after garbage collection has rummaged everything to find some space. (But no C/C++-like "wrong pointer address", which cannot occur thanks to the statically typed nature of Eiffel.)
It is sometimes useful, when handling exceptions in <code>rescue</code> clauses, to ascertain the exact nature of the exception that got the execution there. For this it is suffices to inherit from the Kernel Library class <code>EXCEPTIONS</code>, which provides queries such as <code>exception</code>, giving the code for the last exception, and symbolic names ( [[ET: Other Mechanisms#Constant_attributes|"Constant attributes"]] ) for all such codes, such as <code>No_more_memory</code>. You can then process different exceptions differently by testing <code>exception</code> against various possibilities. The method strongly suggests, however, that exception handling code should remain simple; a complicated algorithm in a <code>rescue</code> clause is usually a sign that the mechanism is being misused. Class <code>EXCEPTIONS</code> also provides various facilities for fine-tuning the exception facilities, such as a procedure <code>raise</code> that will explicitly trigger a "developer exception" with a code that can then be detected and processed. Exception handling helps produce Eiffel software that is not just correct but robust, by planning for cases that should not normally arise, but might out of Murphy's law, and ensuring they do not affect the software's basic safety and simplicity.
==Other applications of Design by Contract&#153;==
The Design by Contract&#153; ideas pervade the Eiffel method. In addition to the applications just mentioned, they have two particularly important consequences: <br/>
* They make it possible to use Eiffel for analysis and design. At a high level of abstraction, it is necessary to be precise too. With the exception of BON, object-oriented analysis and design methods tend to favor abstraction over precision. Thanks to assertions, it is possible to express precise properties of a system ("At what speed should the alarm start sounding?") without making any commitment to implementation. The discussion of deferred classes ( [[ET: Inheritance#Applications_of_deferred_classes|"Applications of deferred classes"]] ) will show how to write a purely descriptive, non-software model in Eiffel, using contracts to describe the essential properties of a system without any computer or software aspect.
* Assertions also serve to control the power of inheritance-related mechanisms -- redeclaration, polymorphism, dynamic binding -- and channel them to correct uses by assigning the proper semantic limits. See [[ET: Inheritance#Inheritance_and_contracts|"Inheritance and contracts"]] .

View File

@@ -0,0 +1,697 @@
[[Property:title|ET: The Dynamic Structure: Execution Model]]
[[Property:weight|-10]]
[[Property:uuid|1f3f2707-9129-4dca-76c7-157143d7ae74]]
A system with a certain static structure describes a set of possible executions. The run-time model governs the structure of the data (objects) created during such executions.
The properties of the run-time model are not just of interest to implementers; they also involve concepts directly relevant to the needs of system modelers and analysts at the most abstract levels.
==Objects, fields, values, and references==
A class was defined as the static description of a type of run-time data structures. The data structures described by a ca class are called '''instances''' of the class, which in turn is called their '''generating class''' (or just "generator"). An instance of <code>ACCOUNT</code> is a data structure representing a bank account; an instance of <code>LINKED_LIST</code> is a data structure representing a linked list.
An '''object''', as may be created during the execution of a system, is an instance of some class of the system.
Classes and objects belong to different worlds: a class is an element of the software text; an object is a data structure created during execution. Although is possible to define a class whose instances represent classes, this does not eliminate the distinction between a static, compile-time notion, class, and a dynamic, run-time notion, object.
An object is either an atomic object (integer, real, boolean, double) or a composite object made of a number of '''fields''', represented by adjacent rectangles on the conventional run-time diagrams:
[[Image:tutorial-5]]
Each field is a '''value'''. A value can be either an object or an object reference: <br/>
* When a field is an object, it will in most cases be an atomic object, as on the figure where the first field from the top is an integer and the third a character. But a field can also be a composite object, in which case it is called a '''subobject'''.
* A '''reference''' is either void or uniquely identifies an object, to which it is said to be '''attached'''. In the preceding figure the second field from the top is a reference -- attached in this case, as represented by the arrow, to the enclosing object itself. The bottom field is a void reference.
==Features==
[[Image:tutorial-6]]
A feature, as noted, is an operation available on instances of a class. A feature can be either an '''attribute''' or a '''routine'''. This classification, which you can follow by starting from the right on the figure above, is based on implementation considerations:
* An attribute is a feature implemented through memory: it describes a field that will be found in all instances of the class. For example class <code>ACCOUNT</code> may have an attribute <code>balance</code>; then all instances of the class will have a corresponding field containing each account's current balance.
* A routine describes a computation applicable to all instances of the class. <code>ACCOUNT</code> may have a routine <code>withdraw</code> .
* Routines are further classified into '''functions''', which will return a result, and '''procedures''', which will not. Routine <code>withdraw</code> will be a procedure; an example of function may be <code>highest_deposit</code>, which returns the highest deposit made so far to the account.
If we instead take the viewpoint of the '''clients''' of a class (the classes relying on its feature), you can see the relevant classification by starting from the left on the figure:
* '''Commands''' have no result, and may modify an object. They may only be procedures.
* '''Queries''' have a result: they return information about an object. You may implement a query as either an attribute (by reserving space for the corresponding information in each instance of the class, a memory-based solution) or a function (a computation-based solution). An attribute is only possible for a query without argument, such as <code>balance</code>; a query with arguments, such as <code>balance_on (d)</code> , returning the balance at date <code>d</code>, can only be a function.
From the outside, there is no difference between a query implemented as an attribute and one implemented as a function: to obtain the balance of an account <code>a</code>, you will always write <code>a.balance</code>. In the implementation suggested above, <code>a</code> is an attribute, so that the notation denotes an access to the corresponding object field. But it is also possible to implement <code>a</code> as a function, whose algorithm will explore the lists of deposits and withdrawals and compute their accumulated value. To the clients of the class, and in the official class documentation as produced by the environment tools, the difference is not visible.
This principle of '''Uniform Access''' is central to Eiffel's goals of extendibility, reusability and maintainability: you can change the implementation without affecting clients; and you can reuse a class without having to know the details of its features' implementations. Most object-oriented languages force clients to use a different notation for a function call and an attribute access. This violates Uniform Access and is an impediment to software evolution, turning internal representation changes into interface changes that may disrupt large parts of a system.
==A simple class==
The following simple class text illustrates the preceding concepts
<code>
note
description: "Simple bank accounts"
class
ACCOUNT
feature -- Access
balance: INTEGER
-- Current balance
deposit_count: INTEGER
-- Number of deposits made since opening
do
if all_deposits /= Void then
Result := all_deposits.count
end
end
feature -- Element change
deposit (sum: INTEGER)
-- Add `sum' to account.
do
if all_deposits = Void then
create all_deposits
end
all_deposits.extend (sum)
balance := balance + sum
end
feature {NONE} -- Implementation
all_deposits: DEPOSIT_LIST
-- List of deposits since account's opening.
invariant
consistent_balance:
(all_deposits /= Void) implies (balance = all_deposits.total)
zero_if_no_deposits:
(all_deposits = Void) implies (balance = 0)
end -- class ACCOUNT
</code>
(The <code>{NONE}</code> qualifier and the <code>invariant</code> clause, used here to make the example closer to a real class, will be explained shortly. <code>DEPOSIT_LIST</code> refers to another class, which can be written separately using library classes.)
It's easy to deduce, from a feature's syntactic appearance, the category to which it belongs. Here:
* Only <code>deposit</code> and <code>deposit_count</code>, which include a <code>do</code> ... clause, are routines.
* <code>balance</code> and <code>all_deposits</code>, which are simply declared with a type, are attributes. Note that even for attributes it is recommended to have a header comment.
* Routine <code>deposit_count</code> is declared as returning a result (of type <code>INTEGER</code>); so it is a function.
* Routine <code>deposit</code> has no such result and hence is a procedure.
==Creating and initializing objects==
Classes, as noted, are a static notion. Objects appear at run time; they are created explicitly. Here is the basic instruction to create an object of type <code>ACCOUNT</code> and attach it to <code>x</code>:
<code>
create x
</code>
assuming that <code>x</code> has been declared of type <code>ACCOUNT</code>. Such an instruction must be in a routine of some class -- the only place where instructions can appear -- and its effect at run time will be threefold: create a new object of type <code>ACCOUNT</code>; initialize its fields to default values; and attach the value of <code>x</code> to it. Here the object will have two fields corresponding to the two attributes of the generating class: an integer for <code>balance</code>, which will be initialized to 0, and a reference for <code>all_deposits</code>, which will be initialized to a void reference:
[[Image:tutorial-7]]
The language specifies default initialization values for all possible types:
{|
|-
|
'''Type'''
| &nbsp;
|
'''Default value'''
|-
|
<code>INTEGER</code>, <code>REAL</code>, <code>DOUBLE</code>
| &nbsp;&nbsp;&nbsp;
|
Zero
|-
|
<code>BOOLEAN</code>
| &nbsp;
|
False
|-
|
<code>CHARACTER</code>
| &nbsp;
|
Null
|-
|
Reference types (such as ACCOUNT and <code>DEPOSIT_LIST</code>)
| &nbsp;
|
Void reference
|-
|
Composite expanded types (see next)
| &nbsp;
|
Same rules, applied recursively to all fields
|}
It is possible to override the initialization values by providing -- as in the earlier example of class <code>HELLO</code> -- one or more creation procedures. For example we might change <code>ACCOUNT</code> to make sure that every account is created with an initial deposit:
<code>
note
description : "Simple bank accounts, initialized with a first deposit"
class
ACCOUNT1
create
make
feature -- Initialization
make (sum: INTEGER)
-- Initialize account with `sum' .
do
deposit (sum)
end
-- The rest of the class as for ACCOUNT
end -- class ACCOUNT1
</code>
A <code>create</code> clause may list zero or more (here just one) procedures of the class.
{{info|Note the use of the same keyword, <code>create</code> , for both a creation clause, as here, and creation instructions such as <code>create x</code> . }}
In this case the original form of creation instruction, <code>create x</code> , is not valid any more for creating an instance of <code>ACCOUNT1</code>; you must use the form
<code>
create x.make (2000)</code>
known as a creation call. Such a creation call will have the same effect as the original form -- creation, initialization, attachment to -- <code>x</code> followed by the effect of calling the selected creation procedure, which here will call <code>deposit</code> with the given argument.
Note that in this example all that <code>make</code> does is to call <code>deposit</code>. So an alternative to introducing a new procedure <code>make</code> would have been simply to introduce a creation clause of the form <code>create deposit</code> , elevating <code>deposit</code> to the status of creation procedure. Then a creation call would be of the form <code>create x.deposit (2000)</code> .
{{info|Some variants of the basic creation instruction will be reviewed later: instruction with an explicit type; creation expressions. See [[ET: Other Mechanisms#Creation_variants|"Creation variants"]] . }}
==Entities==
The example assumed <code>x</code> declared of type <code>ACCOUNT</code> (or <code>ACCOUNT1</code>). Such an <code>x</code> is an example of '''entity''', a notion generalizing the well-known concept of variable. An entity is a name that appears in a class text to represent possible run-time values (a value being, as defined earlier, an object or a reference). An entity is one of the following: <br/>
* An attribute of the enclosing class, such as <code>balance</code> and <code>all_deposits</code>.
* A formal argument of a routine, such as <code>sum</code> for <code>deposit</code> and <code>make</code>.
* A local entity declared for the internal needs of a routine.
* The special entity <code>Result</code> in a function.
The third case, local entities, arises when a routine needs some auxiliary values for its computation. Here is an example of the syntax:
<code>
deposit (sum: INTEGER)
-- Add sum to account.
local
new: AMOUNT
do
create new.make (sum)
all_deposits.extend (new)
balance := balance + sum
end
</code>
This example is a variant of <code> deposit </code> for which we assume that the elements of a <code>DEPOSIT_LIST</code> such as <code>all_deposits</code> are no longer just integers, but objects, instances of a new class, <code>AMOUNT</code>. Such an object will contain an integer value, but possibly other information as well. So for the purpose of procedure <code>deposit</code> we create an instance of <code>AMOUNT</code> and insert it, using procedure <code>extend</code>, into the list <code>all_deposits</code>. The object is identified through the local entity <code>new</code>, which is only needed within each execution of the routine (as opposed to an attribute, which yields an object field that will remain in existence for as long as the object).
The last case of entity, <code>Result</code>, serves to denote, within the body of a function, the final result to be returned by that function. This was illustrated by the function <code>deposit_count</code>, which read
<code>
deposit_count: INTEGER
-- Number of deposits made since opening (provisional version)
do
if all_deposits /= Void then
Result := all_deposits.count
end
end
</code>
The value returned by any call will be the value of the expression <code>all_deposits.count</code> (to be explained in detail shortly) for that call, unless <code>all_deposits</code> is a <code>Void</code> reference ( <code>/=</code> means "not equal").
The default initialization rules seen earlier for attributes (see the table above) also serve to initialize local entities and <code>Result</code> on routine entry. So in the last example, if <code>all_deposits</code> is void (as in the case on initialization with the class as given so far), <code>Result</code> keeps its default value of 0, which will be returned as the result of the function.
==Calls==
Apart from object creation, the basic computational mechanism, in the object-oriented style of computation represented by Eiffel, is feature call. In its basic form, it appears as
<code lang="text">
target.feature (argument1, ...)
</code>
where <code>target</code> is an entity or more generally an expression, <code lang="text">feature</code> is a feature name, and there may be zero or more <code>argument</code> expressions. In the absence of any <code>argument</code> the part in parentheses should be removed.
We have already seen such calls. If the <code lang="text">feature</code> denotes a procedure, the call is an instruction, as in
<code>
all_deposits.extend (new)
</code>
If <code lang="text">feature</code> denotes a query (function or attribute), the call is an expression, as in the right-hand side of
<code>
Result := all_deposits.count
</code>
Following the principle of Uniform Access (mentioned earlier in the section ''Objects, fields, values, and references''), this form is the same for calls to attributes and to functions without arguments. In this example, feature <code>count</code> from class <code>DEPOSIT_LIST</code> may indeed be implemented in either of these two ways: we can keep a <code>count </code> field in each list, updating it for each insertion and removal; or we can compute <code>count</code>, whenever requested, by traversing the list and counting the number of items.
In the case of a routine with arguments -- procedure or function -- the routine will be declared, in its class, as
<code>
some_feature (formal_1: TYPE_1; ...)
do
...
end
</code>
meaning that, at the time of each call, the value of each formal will be set to the corresponding actual (<code>formal_1</code> to <code>argument_1</code> and so on).
In the routine body, it is not permitted to change the value of a formal argument, although it is possible to change the value of an attached object through a procedure call such as <code>formal_1.some_procedure ( ... )</code> .
==Infix and prefix notations==
Basic types such as <code>INTEGER</code> are, as noted, full-status citizens of Eiffel's type system, and so are declared as classes (part of the Kernel Library). <code>INTEGER</code>, for example, is characterized by the features describing integer operations: plus, minus, times, division, less than, and so on.
With the dot notation seen so far, this would imply that simple arithmetic operations would have to be written with a syntax such as
<code>
i.plus (j)
</code>
instead of the usual
<code>
i + j
</code>
This would be awkward. Infix and prefix notations solve the problem, reconciling the object-oriented view of computation with common notational practices of mathematics. The addition function is declared in class <code>INTEGER</code> as
<code>
plus alias "+" (other: INTEGER): INTEGER
do
...
end
</code>
Such a feature has all the properties and prerogatives of both normal "identifier-dot" notation and infix notation. This allowing invoking <code>plus</code> using either notation: <code>i.plus (j)</code> or <code>i + j</code> . A feature such as <code>plus</code> allowing infix notation must be a function, and take exactly one argument.
Prefix notation is allowed as well. A function can be declared as <code>opposite alias "-" </code>, with no argument, permitting calls of the form <code>-3</code> rather than <code>(3).opposite</code> .
Predefined library classes covering basic types such as <code>INTEGER</code>, <code>CHARACTER</code>, <code>BOOLEAN</code>, <code>REAL</code>, <code>DOUBLE</code> are known to the Eiffel compiler, so that a call of the form <code>j + i</code>, although conceptually equivalent to a routine call, can be processed just as efficiently as the corresponding arithmetic expression in an ordinary programming language. This brings the best of both worlds: conceptual simplicity, enabling Eiffel developers, when they want to, to think of integers and the like as objects; and efficiency as good as in lower-level approaches.
Infix and prefix notations are available to any class, not just the basic types' predefined classes. For example a graphics class could use the name <code>distance alias "|-|"</code> for a function computing the distance between two points, to be used in expressions such as
<code>
point1 |-| point2
</code>
==Type declaration==
Every entity appearing in an Eiffel text is declared as being of a certain type, using the syntax already encountered in the above examples:
<code>
entity_name: TYPE_NAME
</code>
This applies to attributes, formal arguments of routines and local entities. You will also declare the result type for a function, as in the earlier example
<code>
deposit_count: INTEGER ...
</code>
Specifying such a function result type also declares, implicitly, the type for <code>Result</code> as used in the function's body.
What is a type? With the elements seen so far, every type is a <code>class</code> . <code>INTEGER</code>, used in the declaration of <code>deposits_count</code>, is, as we have seen, a library class; and the declaration <code>all_deposits: DEPOSIT_LIST</code> assumes the existence of a class <code>DEPOSIT_LIST</code> .
Three mechanisms introduced below -- expanded types, genericity, and anchored declarations -- will generalize the notion of type slightly. But they do not change the fundamental property that '''every type is based on a class''', called the type's '''base class'''. In the examples seen so far, each type is a class, serving as its own base class.
An instance of a class <code>C</code> is also called "an object of type <code>C</code>".
==Type categories==
It was noted above that a value is either an object or a reference. This corresponds to two kinds of type: reference types and expanded types.
If a class is declared as just
<code>
class CLASS_NAME ...
</code>
it defines a reference type. The entities declared of that type will denote references. So in the declaration
<code>
x: ACCOUNT
</code>
the possible run-time values for <code> x </code> are references, which will be either void or attached to instances of class <code>ACCOUNT</code> .
Instead of <code>class</code>, however, you may use the double keyword <code>expanded class</code> , as in the EiffelBase class definition
<code>
note
description : "Integer values"
expanded class
INTEGER
feature -- Basic operations
plus alias "+" (other: INTEGER): INTEGER
do
...
end
... Other feature declarations ...
end -- class INTEGER
</code>
In this case the value of an entity declared as <code>n: INTEGER</code> is not a reference to an object, but the object itself -- in this case an atomic object, an integer value.
Expanded classes make it possible to construct composite objects with subobjects. Suppose that two classes, <code>ENGINE</code> and <code>PLANT</code>, are suppliers to the class <code>CAR</code>. Further, <code>ENGINE</code> is defined as <code>expanded</code>, and <code>PLANT</code> is ''not'' defined as <code>expanded</code>. So, here's an abbreviated class declaration (<code>note</code> clause and routines omitted) for <code>CAR</code>:
<code>
class CAR
feature
engine: ENGINE
originating_plant: PLANT
end -- class CAR
</code>
We can illustrate the structure of a typical instance of <code>CAR</code> like this:
[[Image:tutorial-8]]
The field for the attribute <code>originating_plant</code> is a reference to an object of type <code>PLANT</code> external to the instance of <code>CAR</code>. But in the case of the attribute <code>engine</code>, the fields for the instance of <code>ENGINE</code> exist as a subobject within the instance of <code>CAR</code>, because of class <code>ENGINE</code>'s expanded nature.
This example also illustrates that the distinction between expanded and reference types is important not just for system implementation purposes but for high-level system modeling as well. Consider the example of a class covering the notion of car. Many cars share the same <code>originating_plant</code>, but an <code>engine</code> belongs to just one car. References represent the modeling relation "knows about"; subobjects, as permitted by expanded types, represent the relation "has part", also known as aggregation. The key difference is that sharing is possible in the former case but not in the latter.
==Basic operations==
To assign, copy and compare values, you can rely on a number of mechanisms. Two of them, assignment and equality testing, are language constructs; the others are library features, coming from the top-level class <code>ANY</code> seen earlier.
Assignment uses the symbol <code> := </code>. The assignment instruction
<code>
x := y
</code>
updates the value of <code>x</code> to be the same as that of <code>y</code>. This means that for entities of reference types, the value of <code>x</code> will be a void reference if the value of <code>y</code> is void, and otherwise <code>x</code> will be attached to the same object OBJ2 as <code>y</code>:
[[Image:tutorial-9]]
For entities of expanded types, the values are objects; the object attached to <code>x</code> will be overwritten with the contents of the object attached to <code>y</code>. In the case of atomic objects, as in <code>n := 3</code> with the declaration <code> n: INTEGER</code> , this has the expected effect of assigning to <code>n</code> the integer value <code>3</code>; in the case of composite objects, this overwrites the fields for <code>x</code>, one by one, with the corresponding <code>y</code> fields.
To copy an object, use
<code>
x.copy (y)
</code>
which assumes that both <code>x</code> and <code>y</code> are non-void, and copies the contents of <code>y</code>'s attached object onto those of <code>x</code>'s. For expanded entities the effect is the same as that of the assignment <code>x := y</code>.
An operation performing similar duty to <code>copy</code> is <code>twin</code> . The assignment
<code>
x := y.twin
</code>
produces a newly created object (provided that <code>y</code> is non-void), initialized with a copy of the object attached to <code>y</code> and attaches the result to <code>x</code> . This means we may view <code>twin</code> as a function that performs the following two steps:
<code>
create Result
Result.copy (Current)
</code>
The new object is created, then its content is updated to match the content of <code>y</code> to which the <code>twin</code> call is targeted.
So, assuming both entities of reference types and <code>y</code> not void, the assignment above will attach <code>x</code> to a '''new object''' identical to <code>y</code>'s attached object, as opposed to the assignment <code>x := y</code> which attaches <code>x</code> to the '''same object''' as <code>y</code>.
To determine whether two values are equal, use the expression:
<code>
x = y
</code>
For references, this comparison will yield true if the values are either both void or both attached to the same object; this is the case in the last figure in the state after the assignment, but not before. The symbol for not equal is <code> /= </code>, as in:
<code>
x /= y
</code>
As with assignment, there is also a form that works on objects rather than references:
<code>
x.is_equal (y)
</code>
will return true when <code>x</code> and <code>y</code> are both non-void and attached to field-by-field identical objects. This can be true even when <code>x = y</code> is not, for example, in the figure, ''before'' the assignment, if the two objects shown are field-by-field equal.
The expression <code>x.is_equal (y)</code> can be written alternatively, using the ''tilde'' ('~') character, in a notation similar in form to <code>x = y</code> . The expression:
x ~ y
will be true only in cases in which <code>x</code> and <code>y</code> are the same type and <code>x.is_equal (y)</code> is true.
A more general variant of <code>is_equal</code> is used under the form:
<code>
equal (x, y)
</code>
This is always defined, even if <code>x</code> is void, returning true whenever <code>is_equal</code> would but also if <code>x</code> and <code>y</code> are both void. (In contrast, <code>x.is_equal (y)</code> is not defined for void <code>x</code> and would, if evaluated, yield an exception as explained in [[ET: Design by Contract (tm), Assertions and Exceptions#Exception_handling|"Exception handling"]] below.)
{{note|The ~ operator performs an object equality comparison, using the (possibly redefined) version of feature <code>is_equal</code> that is appropriate for the operand types. The operand types must be the same, or the result will be <code>False</code>. As such, the use of ~ is preferred to over the use of direct use of either <code>x.is_equal (y)</code> or <code>equal (x, y)</code>, which can be susceptible to [[ET: Inheritance#Catcalls|catcalls]].}}
<code>Void</code> denotes a void reference. So you can make <code>x</code> void through the assignment
<code>
x := Void
</code>
and test whether it is void through:
<code>
if x = Void then ...</code>
Note that the assignment, <code>:=</code> , and the equality operators, <code>=</code>, <code>~</code>, <code>/~</code>, and <code>/=</code> , are language constructions, whereas <code>copy</code>, <code>twin</code>, <code>is_equal</code>, and <code>equal</code> are '''library features''' coming from class <code>ANY</code> .
<code>Void</code> is a language keyword with built-in characteristics, but it is not harmful to imagine <code>Void</code> as another feature declared in class <code>ANY</code>, with type of <code>NONE</code>, the "bottom" type. This convenience allows any assignment of the for <code>x := Void</code> to be valid without any making exceptions to the type rules, regardless of the type of <code>x</code> .
Using the redefinition mechanisms to be seen in the discussion of inheritance, a class can redefine <code>copy</code> and <code>is_equal</code> to cover specific notions of copy and equality. The assertions will ensure that the two remain compatible: after <code>x.copy (y)</code> , the property <code>x .is_equal (y)</code> must always be true. The effect of <code>twin</code> will automatically follow a redefinition of <code>copy</code>, and <code>equal</code> will follow <code>is_equal</code>.
To guarantee the original, non-redefined semantics you may use the variants <code>standard_copy</code>, <code>standard_twin</code>, <code>standard_equal</code>, all defined in <code>ANY</code> as "frozen", that is to say non-redefinable.
==Deep operations and persistence==
Feature <code>twin</code> only duplicates one object. If some of the object's fields are references to other objects, the references themselves will be copied, not those other objects.
It is useful, in some cases, to duplicate not just one object but an entire object structure. The expression <code>y.deep_twin</code> achieves this goal: assuming non-void <code>y</code>, it will produce a duplicate not just of the object attached to <code>y</code> but of the entire object structure starting at that object. The mechanism respects all the possible details of that structure, such as cyclic reference chains. Like the preceding features, <code>deep_twin</code> comes from class <code>ANY</code>.
A related mechanism provides a powerful '''persistence''' facility. A call of the form
<code>
x.store (Some_file_or_network_connection)
</code>
will store a copy of the entire object structure starting at <code> x </code>, under a suitable representation. Like <code>deep_twin</code>, procedure <code>store</code> will follow all references to the end and maintain the properties of the structure. The function <code>retrieved</code> can then be used -- in the same system, or another -- to recreate the structure from the stored version.
As the name suggests, <code>Some_file_or_network_connection</code> can be an external medium of various possible kinds, not just a file but possibly a database or network. The EiffelNet client-server library indeed uses the <code> store </code>-<code> retrieved </code> mechanism to exchange object structures over a network, between compatible or different machine architectures, for example a Windows client and a Unix server.
==Memory management==
Reference reattachments, <code>x := y</code> , of the form illustrated by the figure just above can cause objects to become unreachable. This is the case for the object identified as OBJ1 on that figure (the object to which <code>x</code> was attached before the assignment) if no other reference was attached to it.
In all but toy systems, it is essential to reclaim the memory that has been allocated for such objects; otherwise memory usage could grow forever, as a result of creation instructions <code>create x</code> ... and calls to <code>twin</code> and the like, leading to thrashing and eventually to catastrophic termination.
The Eiffel method suggests that the task of detecting and reclaiming such unused object space should be handled by an automatic mechanism (part of the Eiffel run-time environment), not manually by developers (through calls to procedures such as Pascal's <code>dispose</code> and C/C++'s <code>free</code>). The arguments for this view are:
'''Simplicity''' : handling memory reclamation manually can add enormous complication to the software, especially when -- as is often the case in object-oriented development -- the system manipulates complex run-time data structures with many links and cycles.
'''Reliability''' : memory management errors, such as the incorrect reclamation of an object that is still referenced by a distant part of the structure, are a notorious source of dangerous and hard-to-correct bugs.
The Eiffel Software's implementation of Eiffel provides a sophisticated '''garbage collector''' which efficiently handles the automatic reclamation process, while causing no visible degradation of a system's performance and response time.
==Information hiding and the call rule==
The basic form of computation, it has been noted, is a call of the form <code lang="text">target.feature (...)</code> . This is only meaningful if <code lang="text">feature</code> denotes a feature of the generating class of the object to which <code>target</code> (assumed to be non-void) is attached. The precise rule is the following:
{{rule|name=Feature Call|text=A call of the form <code lang="text">target.feature (...)</code> appearing in a class C is only valid if <code lang="text">feature</code> is a feature of the base class of <code>target</code>'s type, and is available to C.}}
The first condition simply expresses that if <code>target</code> has been declared as <code>target: A</code> then <code lang="text">feature</code> must be the name of one of the features of <code>A</code>. The second condition reflects Eiffel's application of the principles of information hiding. A <code>feature</code> clause, introducing one or more feature declarations, may appear not only as
<code>
feature -- Comment identifying the feature category
... Feature declaration ...
... Feature declaration ...
...
</code>
but may also include a list of classes in braces, <code>feature {A, B, ... }</code> , as was illustrated for <code>ACCOUNT</code>:
<code>
feature {NONE} -- Implementation
all_deposits: DEPOSIT_LIST
-- List of deposits since account's opening.
</code>
This form indicates that the features appearing in that clause are only '''available''' -- in the sense of available for calls, as used in the Feature Call rule -- to the classes listed. In the example feature <code> all_deposits </code> is only available to <code> NONE </code>. Because of the [[ET: The Static Picture: System Organization#The_global_inheritance_structure|global inheritance structure]], this means it is in fact available to no useful client at all, and is equivalent in practice to <code>feature { }</code> with an empty class list, although the form listing <code> NONE </code> explicitly is more visible and hence preferred.
With this specification a class text including the declaration <code>acc: ACCOUNT</code> and a call of the form
<code>
acc.all_deposits
</code>
violates the Feature Call rule and will be rejected by the EiffelStudio compiler.
Besides fully exported features (introduced by <code>feature ... </code>; without further qualification) and fully secret ones (<code>feature { }</code> or <code>feature {NONE}</code> ), it is possible to export features selectively to some specified classes, using the specification
<code>
feature {A, B, ...}
</code>
for arbitrary classes <code>A, B</code>, ... This enables a group of related classes to provide each other with privileged access, without requiring the introduction of a special module category above the class level (see [[ET: The Static Picture: System Organization#Clusters|"Clusters"]] ).
Exporting features selectively to a set of classes <code>A, B</code>, ... also makes them available to the descendants of these classes. So a feature clause beginning with just <code>feature</code> is equivalent to one starting with <code>feature {ANY}</code> .
These rules enable successive feature clauses to specify exports to different clients. In addition, the recommended style, illustrated in the examples of this chapter, suggests writing separate feature clauses -- regardless of their use for specifying export privileges -- to group features into separate categories. The standard style rules define a number of fundamental categories and the order in which they should appear; they include: <code>Initialization</code> for creation procedures, <code>Access</code> for general queries, <code>Status report</code> for boolean-valued queries, <code>Status setting</code>, <code>Element change</code>, <code>Implementation</code> (for selectively exported or secret features. Every feature in the EiffelBase library classes belongs to one of the predefined categories.
The Feature Call rule is the first of the rules that make Eiffel a '''statically typed''' approach, where the applicability of operations to objects is verified at compile time rather than during execution. Static typing is one of the principal components of Eiffel's support for reliability in software development.
==Execution scenario==
The preceding elements make it possible to understand the overall scheme of an Eiffel system's execution.
At any time during the execution of a system, one object is the '''current object''' of the execution, and one of the routines of the system, the '''current routine''', is being executed, with the current object as its target. (We will see below how the current object and current routine are determined.) The text of a class, in particular its routines, make constant implicit references to the current object. For example in the instruction
<code>
balance := balance + sum
</code>
appearing in the body of procedure <code>deposit</code> of class <code>ACCOUNT</code>, the name of the attribute <code>balance</code>, in both occurrences, denotes the <code>balance</code> field of the current object, assumed to be an instance of <code>ACCOUNT</code>. In the same way, the procedure body that we used for the creation procedure <code>make</code> in the <code>ACCOUNT1</code> variant
<code>
make (sum: INTEGER)
-- Initialize account with sum .
do
deposit (sum)
end
</code>
contains a call to the procedure <code>deposit</code>. Contrary to earlier calls written in dot notation as <code>target.feature (...)</code>, the call to <code>deposit</code> has no explicit target; this means its target is the current object, an instance of <code>ACCOUNT1</code>. Such a call is said to be '''unqualified'''; those using dot notations are '''qualified''' calls.
Although most uses of the current object are implicit, a class may need to name it explicitly. The predefined expression <code>Current</code> is available for that purpose. A typical use, in a routine <code>merge (other: ACCOUNT )</code> of class <code>ACCOUNT</code>, would be a test of the form
<code>
if other = Current then
report_error ("Error: trying to merge an account with itself!")
else
... Normal processing (merging two different account) ...
end
</code>
With these notions it is not hard to define precisely the overall scenario of a system execution by defining which object and routine will, at each instant, be the current object and the current routine:
Starting a system execution, as we have seen, consists in creating an instance of the root class, the root object, and executing a designated creation procedure, the root procedure, with the root object as its target. The root object is the initial current object, and the root procedure is the initial current procedure.
From then on only two events can change the current object and current procedure: a qualified routine call; and the termination of a routine.
In a call of the form <code>target.routine (...)</code> , <code>target</code> denotes a certain object TC. (If not, that is to say, if the value of target is void, attempting to execute the call will trigger an exception, as studied below.) The generating class of TC must, as per the Feature Call rule, contain a routine of name <code>routine</code>. As the call starts, TC becomes the new current object and <code>routine</code> becomes the new current routine.
When a routine execution terminates, the target object and routine of the most recent non-terminated call -- which, just before the terminated call, were the current object and the current routine -- assume again the role of current object and current routine.
The only exception to the last rule is termination of the original root procedure call; in this case the entire execution terminates.
==Abstraction==
===Restriction of assignment targets===
The description of assignments stated that in <code>x := y</code> the target <code>x</code> must be an entity. More precisely it must be a '''writable''' entity. This notion excludes formal routine arguments: as noted, a routine <code>r (arg: SOME_TYPE)</code> may not assign to <code>arg</code> (reattaching it to a different object), although it can change the attached objects through calls of the form <code>arg.procedure (...)</code> .
Allowing only entities to be the targets of assignments precludes assignments of the form
<code>
obj.some_attribute := some_value
-- This syntax is disallowed (except in the presence of an `assigner command', see below)
</code>
This is because the left-hand side <code>obj.some_attribute</code> is an expression (a feature call), not an entity: you may no more assign to <code>obj.some_attribute</code> than to, say, <code>b + a</code> -- another expression that is also, formally, a feature call.
To obtain the intended effect of such an assignment you may use a procedure call, where the base class of <code>obj</code>'s type has defined the procedure
<code>
set_some_attribute (v: VALUE_TYPE)
-- Set value of some_attribute to `v'.
do
some_attribute := v
end
</code>
So instead of the disallowed assignment shown above, you would code:
<code>
obj.set_some_attribute (some_value)
</code>
This rule is essential to enforcing the method. Permitting direct assignments to an object's fields -- as in C++ and Java -- would violate all the tenets of information hiding by letting clients circumvent the interface carefully crafted by the author of a supplier class.
===Assigner commands===
However, many developers have become accustomed to reading and writing code in other languages which do allow assignments of the form:
<code>
obj.some_attribute := some_value
</code>
For this reason, it is possible in Eiffel to allow such a syntax without actually enabling an end-run around the constraints of the class. It is done by using a facility called an '''assigner command'''. In the example shown in the previous section, we might expect <code>some_attribute</code> to be declared something like this:
<code>
some_attribute: SOME_TYPE
</code>
If this were the case the assignment above would cause a syntax error at compile time. But if the declaration included the specification of an assigner command, as shown below, then the assignment syntax would be valid.
<code>
some_attribute: SOME_TYPE assign set_some_attribute
</code>
The assigner command then is the procedure <code>set_some_attribute</code> coded as shown in the previous section. In the presence of the assigner command, the previously invalid assignment syntax is now valid. But it is translated by the compiler as a call to <code>set_some_attribute</code>, using the source of the assignment as an argument.
===Controlling modification of class fields===
It is the responsibility of each class author to define the exact privileges that the class gives to each of its clients, in particular field modification rights. Building a class is like building a machine: you design the internals, to give yourself the appropriate mechanisms; and you design the control panel, letting users (clients) access the desired subset of these mechanisms, safely and conveniently.
The levels of privilege available to the class author include, for any field:
* Hide the field completely from clients, by exporting the corresponding attribute to <code>NONE</code>.
* Export it, but in read-only mode, by not exporting any procedure that modifies it.
* Export it for free read and write by any client, by also exporting a procedure of the <code>set_attribute</code> kind.
* Export it in '''restricted-write''' mode, by exporting a procedure such as <code>deposit</code> of class <code>ACCOUNT</code>, which adds a specified amount to the <code>balance</code> field, rather than directly setting the balance.
The last case is particularly interesting is that it allows the class designer to set the precise way in which clients will manipulate the class instances, respecting the properties of the class and its integrity. The exported routines may, through the Design by Contract mechanism reviewed later in ( [[ET: Design by Contract (tm), Assertions and Exceptions]] ), place some further restrictions on the permitted modifications, for example by requiring the withdrawn amount to be positive.
These rules follow directly from the more general goals (reusability, extendibility, reliability) and principles (Uniform Access, information hiding) underlying Eiffel software design. They reflect a view that each class must denote a well-understood abstraction, defined by a set of exported features chosen by the class designer -- the "control panel".
The class documentation (see [[ET: Design by Contract (tm), Assertions and Exceptions#The_contract_form_of_a_class|the contract form of a class]] ) makes this view clear to client authors; no violation of that interface is permitted. This approach also paves the way for future '''generalization''' -- the final step of the cluster lifecycle, seen earlier in the section [[ET: The Software Process in Eiffel#Generalization_and_reuse|Generalization and reuse]] -- of the most promising components, and their inclusion into reusable libraries.
===Attribute specializations===
In certain situations it is beneficial to be able to declare class attributes which behave in specialized ways.
====Attribute specializations useful in void-safe programming====
Part of the strategy to ensure void-safety makes it necessary to be able to declare attributes as either [[Void-safety: Background, definition, and tools#Types as "attached" or "detachable"|'''detachable''' or '''attached''']].
'''[[Void-safety: Background, definition, and tools#Self-initializing attributes|Self-initializing attributes]]''' and '''[[Void-safety: Background, definition, and tools#Stable attributes|stable attributes]]''' are other tools for making void-safe programming more convenient.
These attribute specializations are presented in the [[Void-safe programming in Eiffel|void-safe programming]] chapter.
====Transient attributes====
Another special type of attribute supported by Eiffel Software's compiler is the '''transient attribute'''. When an instance of a class to which a transient attribute belongs is saved to persistent storage, the field for the transient attribute is not included. So, transient attributes are transient in the sense that they are part of the object at runtime, but not when the object is stored on disk.
This type of attribute has benefits when using the persistence mechanisms provided with EiffelStudio, like [http://eiffel.com/developers/learning_maps/Training/Maps/PersistenceCanPayOff/Serialization.html SED]. Because transient attributes are not stored, they need not be accounted for upon retrieval. So, objects stored before changes to a class that only affect transient attributes will still be retrievable using the new class definition (whereas, if non-transient attributes were changed, a mismatch would occur during retrieval).
An attribute is marked as transient by including a note option in its declaration:
<code>
transient_attribute: detachable STRING
note
option: transient
attribute
end
</code>
Only certain attributes can be marked as transient. Specifically, if attribute ''a'' is declared of type '''T''', it can be marked as transient only if it satisfies the following conditions:
# If '''T''' is a reference type, '''T''' must be detachable
# '''T''' is not a formal generic parameter
# '''T''' is not a user defined expanded type
# ''a'' is not an attribute of a user defined expanded class.
The EiffelBase class <code>INTERNAL</code> includes features which are used to distinguish object fields as either persistent or transient and to reveal how many transient fields an object has.
{{note|Prior to version 6.6, support for transient attributes was limited to the C storable mechanism. In version 6.6, support was added for the Eiffel storable mechanism (SED) on both classic and .NET system targets.}}

View File

@@ -0,0 +1,34 @@
[[Property:title|ET: Eiffel Tutorial Copyright]]
[[Property:weight|0]]
[[Property:uuid|105e9956-f168-b060-a6be-e78b221f269a]]
====MANUAL IDENTIFICATION AND COPYRIGHT====
Title: An Eiffel Tutorial, Eiffel Software Technical Report TR-EI-66/TU.
Publication history
First published July 2001. Corresponds to release 5.0 of the EiffelStudio environment.
Author
Software credits
See acknowledgments in book <span>[[Eiffel: The Language]]</span>.
Cover design
Rich Ayling.
Copyright notice and proprietary information
Copyright Interactive Software Engineering Inc. (Eiffel Software), 2001. May not be reproduced in any form (including electronic storage) without the written permission of Eiffel Software . "Eiffel Power" and the Eiffel Power logo are trademarks of Eiffel Software .
All uses of the product documented here are subject to the terms and conditions of the Eiffel Software Eiffel user license. Any other use or duplication is a violation of the applicable laws on copyright, trade secrets and intellectual property.
Special duplication permission for educational institutions
Degree-granting educational institutions using Eiffel Software Eiffel for teaching purposes as part of the <span> [http://www.eiffel.com/educators/resources.html Eiffel University Partnership Program] </span> may be permitted under certain conditions to copy specific parts of this book. Contact Eiffel Software for details.

View File

@@ -0,0 +1,49 @@
[[Property:title|ET: General Properties]]
[[Property:weight|-14]]
[[Property:uuid|1ad0b1d5-7ac6-9f55-92ec-ba6f42aee690]]
Here is an overview of the facilities supported by Eiffel: <br/>
* Completely ''object-oriented'' approach. Eiffel is a full-fledged application of object technology, not a "hybrid" of O-O and traditional concepts.
* ''External interfaces''. Eiffel is a software composition tool and is easily interfaced with software written in such languages as C, C++, Java and C#.
* ''Full lifecycle support''. Eiffel is applicable throughout the development process, including analysis, design, implementation and maintenance.
* ''Classes'' as the basic structuring tool. A class is the description of a set of run-time objects, specified through the applicable operations and abstract properties. An Eiffel system is made entirely of classes, serving as the only module mechanism.
* ''Consistent type system''. Every type is based on a class, including basic types such as integer, boolean, real, character, string, array.
* ''Design by Contract''. Every system component can be accompanied by a precise specification of its abstract properties, governing its internal operation and its interaction with other components.
* ''Assertions''. The method and notation support writing the logical properties of object states, to express the terms of the contracts. These properties, known as assertions, can be monitored at run-time for testing and quality assurance. They also serve as documentation mechanism. Assertions include preconditions, postconditions, class invariants, loop invariants, and also appear in "check" instructions.
* ''Exception handling''. You can set up your software to detect abnormal conditions, such as unexpected operating system signals and contract violations, correct them, and recover
* ''Information hiding''. Each class author decides, for each feature, whether it is available to all client classes, to specific clients only, or just for internal purposes.
* ''Self-documentation''. The notation is designed to enable environment tools to produce abstract views of classes and systems, textual or graphical, and suitable for reusers, maintainers and client authors.
* ''Inheritance''. You can define a class as extension or specialization of others.
* ''Redefinition''. An inherited feature (operation) can be given a different implementation or signature.
* ''Explicit redefinition''. Any feature redefinition must be explicitly stated.
* ''Subcontracting''. Redefinition rules require new assertions to be compatible with inherited ones.
* ''Deferred features and classes''. It is possible for a feature, and the enclosing class, to be specified -- including with assertions -- but not implemented. Deferred classes are also known as abstract classes.
* ''Polymorphism''. An entity (variable, argument etc.) can become attached to objects of many different types.
* ''Dynamic binding''. Calling a feature on an object always triggers the version of the feature specifically adapted to that object, even in the presence of polymorphism and redefinition.
* ''Static typing''. A compiler can check statically that all type combinations will be valid, so that no run-time situation will occur in which an attempt will be made to apply an inexistent feature to an object.
* ''Object test'' ("type narrowing"). It is possible to check at run time whether the type of an object conforms to a certain expectation, for example if the object comes from a database or a network.
* ''Multiple inheritance''. A class can inherit from any number of others.
* ''Feature renaming''. To remove name clashes under multiple inheritance, or to give locally better names, a class can give a new name to an inherited feature.
* ''Repeated inheritance'': ''sharing and replication''. If, as a result of multiple inheritance, a class inherits from another through two or more paths, the class author can specify, for each repeatedly inherited feature, that it yields either one feature (sharing) or two (replication).
* ''No ambiguity under repeated inheritance''. Conflicting redefinitions under repeated inheritance are resolved through a "selection" mechanism.
* ''Unconstrained genericity''. A class can be parameterized, or "generic", to describe containers of objects of an arbitrary type.
* ''Constrained genericity''. A generic class can be declared with a generic constraint, to indicate that the corresponding types must satisfy some properties, such as the presence of a particular operation.
* ''Garbage collection''. The dynamic model is designed so that memory reclamation, in a supporting environment, can be automatic rather than programmer-controlled.
* ''No-leak modular structure''. All software is built out of classes, with only two inter-class relations, client and inheritance.
* ''Once routines''. A feature can be declared s "once", so that it is executed only for its first call, subsequently returning always the same result (if required). This serves as a convenient initialization mechanism, and for shared objects.
* ''Standardized library''. The Kernel Library, providing essential abstractions, is standardized across implementations.
* ''Other libraries''. Eiffel development is largely based on high-quality libraries covering many common needs of software development, from general algorithms and data structures to networking and databases.
It is also useful, as in any design, to list some of what is '''not''' present in Eiffel. The approach is indeed based on a small number of coherent concepts so as to remain easy to master. Eiffel typically takes a few hours to a few days to learn, and users seldom need to return to the reference manual once they have understood the basic concepts. Part of this simplicity results from the explicit decision to exclude a number of possible facilities: <br/>
* ''No global variables'', which would break the modularity of systems and hamper extendibility, reusability and reliability.
* ''No union types'' (or record type with variants), which force the explicit enumeration of all variants; in contrast, inheritance is an open mechanism which permits the addition of variants at any time without changing existing code.
* ''No in-class overloading'', which by assigning the same name to different features within a single context, causes confusions, errors, and conflicts with object-oriented mechanisms such as dynamic binding. (Dynamic binding itself is a powerful form of inter-class overloading, without any of these dangers.)
* ''No goto instructions'' or similar control structures (break, exit, multiple-exit loops) which break the simplicity of the control flow and make it harder or impossible to reason about the software (in particular through loop invariants and variants).
* ''No exceptions to the type rules''. To be credible, a type system must not allow unchecked "casts" converting from a type to another. (Safe cast-like operations are available through object test.)
* ''No side-effect expression operators'' confusing computation and modification.
* ''No low-level pointers, no pointer arithmetic'', a well-known source of bugs. (There is however a type ''POINTER'', used for interfacing Eiffel with C and other languages.)

View File

@@ -0,0 +1,67 @@
[[Property:title|ET: Genericity and Arrays]]
[[Property:weight|-9]]
[[Property:uuid|7f3bd1d7-357e-031d-9faa-b00594aa9ae0]]
Some of the classes that we will need, particularly in libraries, are '''container''' classes, describing data structures made of a number of objects of the same or similar types. Examples of containers include arrays, stacks and lists. The class <code>DEPOSIT_LIST</code> posited in earlier examples describes containers.
It is not hard, with the mechanisms seen so far, to write the class <code>DEPOSIT_LIST</code>, which would include such features as <code>count</code> (query returning the number of deposit objects in the list) and <code>put</code> (command to insert a new deposit object).
Most of the operations, however, would be the same for lists of objects other than deposits. To avoid undue replication of efforts and promote reuse, we need a way to describe '''generic''' container classes, which we can use to describe containers containing elements of many different types.
==Making a class generic==
The notation
<code>
class C [G]
... The rest as for any other class declaration ...</code>
introduces a generic class. A name such as <code>G</code> appearing in brackets after the class name is known as a '''formal generic parameter'''; it represents an arbitrary type.
Within the class text, feature declarations can freely use <code>G</code> even though it is not known what type <code>G</code> stands for. Class <code>LIST</code> of EiffelBase, for example, includes features
<code>
first: G
-- Value of first list item
extend (val: G)
-- Add a new item of value val at end of list
...
</code>
The operations available on an entity such as <code>first</code> and <code>val</code>, whose type is a formal generic parameter, are the operations available on all types: use as source <code>y</code> of an assignment <code>x := y</code>, use as target <code>x</code> of such an assignment (although not for <code>val</code>, which as a formal routine argument is not writable), use in equality comparisons <code>x = y</code> or <code>x /= y</code>, and application of universal features from <code>ANY</code> such as <code>twin</code>, <code>is_equal</code> and <code>copy</code>.
To use a generic class such as list, a client will provide a type name as '''actual generic parameter'''. So instead of relying on a special purpose class <code>DEPOSIT_LIST</code>, the class <code>ACCOUNT</code> could include the declaration
<code>all_deposits: LIST [DEPOSIT]</code>
using <code>LIST</code> as a generic class and <code>DEPOSIT</code> as the actual generic parameter. Then all features declared in <code>LIST</code> as working on values of type <code>G</code> will work, when called on the target <code>all_deposits</code>, on values of type <code>DEPOSIT</code>. With the target
<code>all_accounts: LIST [ACCOUNT]</code>
these features would work on values of type <code>ACCOUNT</code>.
{{info|A note of terminology: to avoid confusion, Eiffel always uses the word '''argument''' for routine arguments, reserving '''parameter''' for the generic parameters of classes. }}
Genericity reconciles extendibility and reusability with the static type checking demanded by reliability. A typical error, such as confusing an account and a deposit, will be detected immediately at compile time, since the call <code>all_accounts</code>. <code>extend</code> <code>(</code> <code>dep</code> <code>)</code> is invalid for <code>dep</code> declared of type <code>DEPOSIT</code>. What is valid is something like <code>all_accounts</code>. <code>extend</code> <code>(</code> <code>acc</code> <code>)</code> for <code>acc</code> of type <code>ACCOUNT</code>. In other approaches, the same effect might require costly run-time checks (as in Java, C# or Smalltalk), with the risk of run-time errors.
{{info|This form of genericity is known as '''unconstrained''' because the formal generic parameter, <code>G</code> in the example, represents an arbitrary type. You may also want to use types that are guaranteed to have certain operations available. This is known as '''constrained''' genericity and will be studied with inheritance. }}
==Arrays==
An example of generic class from the Kernel Library is <code>ARRAY</code> <code>[G]</code>, which describes direct-access arrays. Features include:
* <code>put</code> to replace an element's value, as in <code>my_array.put (val, 25)</code> which replaces by <code>val</code> the value of the array entry at index 25.
* <code>item</code> to access an entry, as in <code>my_array.item (25)</code> yielding the entry at index 25. A synonym is <code>infix</code> <code>"@"</code>, so that you may also write more tersely, for the same result, <code>my_array</code> <code>@</code> <code>25</code> .
* <code>lower</code>, <code>upper</code> and <code>count</code>: queries yielding the bounds and the number of entries.
* The creation procedure <code>make</code>, as in <code>create my_array.make (1, 50)</code> which creates an array with the given index bounds. It is also possible to resize an array through <code>resize</code>, retaining the old elements. In general, the Eiffel method abhors built-in limits, favoring instead structures that resize themselves when needed, either from explicit client request or automatically.
The comment made about <code>INTEGER</code> and other basic classes applies to <code>ARRAY</code> too: Eiffel compilers know about this class, and will be able to process expressions of the form <code>my_array.put (val, 25)</code> and <code>my_array</code> <code>@</code> <code>25</code> in essentially the same way as a C or Fortran array access -- <code>my_array</code> <code>[25]</code> in C. But it is consistent and practical to let developers treat <code>ARRAY</code> as a class and arrays as objects; many library classes in EiffelBase, for example, inherit from <code>ARRAY</code>. Once again the idea is to get the best of both worlds: the convenience and uniformity of the object-oriented way of thinking; and the efficiency of traditional approaches.
A similar technique applies to another Kernel Library class, that one not generic: <code>STRING</code>, describing character strings with a rich set of string manipulation features.
==Generic derivation==
The introduction of genericity brings up a small difference between classes and types. A generic class <code>C</code> is not directly a type since you cannot declare an entity as being of type <code>C</code>: you must use some actual generic parameter <code>T</code> -- itself a type. <code>C</code> <code>[T]</code> is indeed a type, but class <code>C</code> by itself is only a type template.
The process of obtaining a type <code>C</code> <code>[T]</code> from a general class <code>C</code> is known as a '''generic derivation'''; <code>C</code> <code>[T]</code> is a '''generically derived type'''. Type <code>T</code> itself is, recursively, either a non-generic class or again a generically derived type <code>D</code> <code>[U]</code> for some <code>D</code> and <code>U</code>, as in <code>LIST</code> <code>[ARRAY [INTEGER]]</code>.)
It remains true, however, that every type is based on a class. The base class of a generically derived type <code>C</code> <code>[T]</code> is <code>C</code>.

View File

@@ -0,0 +1,80 @@
[[Property:title|ET: Hello World]]
[[Property:weight|-12]]
[[Property:uuid|5b286f94-dd63-1169-a64e-74b5f8c5ef14]]
When discovering any approach to software construction, however ambitious its goals, it is reassuring to see first a small example of the big picture -- a complete program to print the famous "Hello World" string. Here is how to perform this fascinating task in the Eiffel notation.
You write a class <code>HELLO</code> with a single procedure, say <code>make</code>, also serving as creation procedure. If you like short texts, here is a minimal version:
<code>
class
HELLO
create
make
feature
make
do
print ("Hello World%N")
end
end
</code>
In practice, however, the Eiffel style rules suggest a better documented version:
<code>
note
description: "Root for trivial system printing a message"
author: "Elizabeth W. Brown"
class
HELLO
create
make
feature
make
-- Print a simple message.
do
io.put_string ("Hello World")
io.put_new_line
end
end -- class HELLO
</code>
The two versions perform identically; the following comments will cover the more complete second one.
Note the absence of semicolons and other syntactic clatter or clutter. You may in fact use semicolons to separate instructions and declarations. But the language's syntax is designed to make the semicolon optional (regardless of text layout) and it's best for readability to omit it, except in the special case of successive elements on a single line.
The <code>note</code> clause does not affect execution semantics; you may use it to associate documentation with the class, so that browsers and other indexing and retrieval tools can help users in search of reusable components satisfying certain properties. Here we see two notes, labeled <code>description</code> and <code>author</code>.
The name of the class is <code>HELLO</code>. Any class may contain "features"; <code>HELLO </code>has just one, called <code>make</code>. The <code>create</code> clause indicates that <code>make</code> is a "creation procedure", that is to say an operation to be executed at class instantiation time. The class could have any number of creation procedures.
The definition of <code>make</code> appears in a <code>feature</code> clause. There may be any number of such clauses (to separate features into logical categories), and each may contain any number of feature declarations. Here we have only one.
The line starting with <code>--</code> (two hyphen signs) is a comment; more precisely it is a "header comment", which style rules invite software developers to write for every such feature, just after the point at which the feature is named. As will be seen in [[ET: Design by Contract (tm), Assertions and Exceptions#The_contract_form_of_a_class|"The contract form of a class"]], the tools of EiffelStudio know about this convention and use it to include the header comment in the automatically generated class documentation.
The body of the feature is introduced by the <code>do</code> keyword and terminated by <code>end</code>. It consists of two output instructions. They both use <code>io</code>, a generally available reference to an object that provides access to standard input and output mechanisms; the notation <code>io.f</code>, for some feature <code>f</code> of the corresponding library class (<code>STD_FILES</code>, in this case), means "apply <code>f</code> to <code>io</code>". Here we use two such features:
* <code>put_string</code> outputs a string, passed as argument, here <code>"Hello World"</code>.
* <code>put_new_line</code> terminates the line.
Rather than using a call to <code>put_new_line</code>, the first version of the class simply includes a new-line character, denoted as <code>%N</code> (the percent sign is used to introduce codes for [[Eiffel programming language syntax#Special characters|special characters]]), at the end of the string. Either technique is acceptable.
You may have noticed another difference between the two versions. The first version uses a call to <code>print</code> where the second uses <code>io.put_string</code> . Here too, the effect is identical and either technique is acceptable. In the next section, you will begin to see how things like <code>io</code> and <code>print</code> become available for use in a class like <code>HELLO</code>.
To build the system and execute it:
* Start EiffelStudio
* Create a new ''Basic application'' project
* Specify <code>HELLO</code> as the "root class" and <code>make</code> as the "root procedure".
* You can either use EiffelStudio to type in the above class text, or you may use any text editor and store the result into a file <code>hello.e</code> in the current directory.
* Click the "Compile" icon.
* Click the "Run" icon.
Execution starts and outputs <code>Hello World</code> on the appropriate medium: under Windows, a Console; under Unix or OpenVMS, the windows from which you started EiffelStudio.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,410 @@
[[Property:modification_date|Wed, 01 Jul 2020 08:48:12 GMT]]
[[Property:publication_date|Tue, 10 Sep 2019 21:54:55 GMT]]
[[Property:title|ET: Instructions]]
[[Property:weight|-6]]
[[Property:uuid|628bf3db-728f-0b3c-bdbb-fe52deaae5b7]]
==Instructions==
Eiffel has a remarkably small set of instructions. The basic computational instructions have been seen: creation, assignment, procedure call, retry. They are complemented by control structures: conditional, multi-branch, loop, as well as debug and check.
===Assignment and attachment===
As noted above we have already introduced assignment. But let's take another look at the assignment in the context of the more abstract concept of '''attachment'''. Attachment can occur with reference types by assignment such as:
<code>
x := y
</code>
In this assignment, <code>x</code> is the target of the assignment and <code>y</code> is the source. The object associated with <code>y</code> becomes ''attached'' to the entity <code>x</code>.
Attachment also occurs in other contexts. For example, when actual arguments are substituted for formal arguments in a call to a routine.
<code>
f (w)
</code>
In the call to <code>f</code> above, the object associated with the actual argument <code>w</code> will be ''attached'' to the formal argument for the duration of the execution of <code>f</code>. So, in this case, <code>w</code> can be viewed as the source of the attachment and the formal argument of <code>f</code> is the target.
Other situations in which attachment occurs include [[ET: The Dynamic Structure: Execution Model#Creating and initializing objects|creation instructions]], attachment of [[Void-safety: Background, definition, and tools#The attached syntax (object test)|object test local variables]], and the attachment of local iteration cursors in the iteration form of the [[ET: Instructions#Loop|loop construct]].
We learned in the section on [[ET: Inheritance#Polymorphism|polymorphism]], that the type of the source of an assignment must conform to the type of the assignment's target.
The rule that governs validity of assignments expands upon this and is generalized to apply to all attachments.
{{Rule|name=Assignment|text=An assignment is valid if and only if the type of its source expression is '''compatible''' with the type of its target entity. }}
The phrase "'''compatible with'''" in this rule means that either it "'''conforms to'''" or "'''converts to'''".
We saw conformance defined in the section on [[ET: Inheritance#Polymorphism|Polymorphism]]. [[ET: Other Mechanisms#Convertibility|Convertibility]] is explained in the section on [[ET: Other Mechanisms#Convertibility|Other Mechanisms]].
===Conditional===
A conditional instruction has the form
<code>
if ... then
...
elseif ... then
...
else
...
end
</code>
The <code>elseif</code> ... <code>then</code> ... part (of which there may be more than one) and the <code>else</code> ... part are optional. After <code>if</code> and <code>elseif</code> comes a boolean expression; after <code>then</code> and <code>else</code> come zero or more instructions.
===Multi-branch===
A multi-branch instruction has the form
<code>
inspect
exp
when v1 then
inst
when v2 then
inst2
...
else
inst0
end
</code>
where the <code>else inst0</code> part is optional, <code>exp</code> is a character or integer expression, <code>v1</code>, <code>v1</code>, ... are constant values of the same type as <code>exp</code>, all different, and <code>inst0</code>, <code>inst1</code>, <code>inst2</code>, ... are sequences of zero or more instructions.
The effect of such a multi-branch instruction, if the value of <code>exp</code> is one of the <code>vi</code>, is to execute the corresponding <code>insti</code>. If none of the <code>vi</code> matches, the instruction executes <code>inst0</code>, unless there is no <code>else</code> part, in which case it triggers an exception.
{{note|Raising an exception is the proper behavior, since the absence of an <code>else</code> indicates that the author asserts that one of the values will match. If you want an instruction that does nothing in this case, rather than cause an exception, use an <code>else</code> part with an empty <code>inst0</code>. In contrast, <code>if c then</code> <code>inst</code> <code>end</code> with no <code>else</code> part does nothing in the absence of an <code>else</code> part, since in this case there is no implied claim that <code>c</code> must hold. }}
===Loop===
The loop construct provides a flexible framework for iterative computation. Its flexibility lies in how the complete form can be tailored and simplified for certain purposes by including or omitting optional parts.
You'll learn that the loop construct is always used in one of two forms: a '''base''' form which allows precise control over details of all loop aspects, and an '''iteration''' form which abstracts many of the details and provides a concise notation, ideal for traversing data structures and other objects which support iteration.
We will explore the entire mechanism, but let's approach things a little at a time.
====Two forms -- two examples====
First let's take a look at two examples. These examples accomplish the same goal: they both use a loop to visit and print the content of each node of a linked list of character strings. So, the list in question might be declared like this:
<code>
my_list: LINKED_LIST [STRING]
</code>
Here's one example:
<code>
from
my_list.start
until
my_list.off
loop
print (my_list.item)
my_list.forth
end
</code>
''Loop example 1.''
and the other:
<code>
across my_list as ic loop print (ic.item) end
</code>
''Loop example 2.''
At first observation, it may not appear that both of these examples are using the same language construct. But, indeed, they are simply two different forms of a single language construct, as you will see.
Incidentally, there is no requirement that ''Loop example 1'' occupy multiple lines, and ''Loop example 2'' occupy only one line. ''Loop example 1'' could have been written like this:
<code>
from my_list.start until my_list.off
loop print (my_list.item) my_list.forth end
</code>
just as ''Loop example 2'' could have been written to take multiple lines. It comes down to a matter of balance among traditional style, conciseness, and readability.
In fact, these two examples illustrate the two basic usage forms of the loop construct in Eiffel. The two basic forms can be differentiated by the parts of the construct with which they begin.
The form shown in ''Loop example 1'' begins with an ''Initialization part'' ( <code>from my_list.start</code> ), which starts with the keyword <code>from</code>. Let's call this form the '''base''' form. So, the type of loop you see in ''Loop example 1'' has been the traditional mechanism for accomplishing iterative computation, including iterating across data structures. However, extensions to Eiffel's loop construct have provided a more concise way of expressing traversing "iterable" structures.
This is the form shown in ''Loop example 2''. It begins with an ''Iteration part'' ( <code>across my_list as c</code> ), which starts with the keyword <code>across</code>. We'll call this form the '''iteration''' form.
====A closer look at the ''base'' form====
What is happening in ''Loop example 1''? Let's dissect it and see.
First there is the ''initialization'' part:
<code>
from
my_list.start
</code>
''Initialization part.''
The first thing to occur in the execution of the base loop is the execution of any instructions in the initialization part (it is permissible for the initialization part to be empty of instructions, but the keyword <code>from</code> must be present to distinguish the base loop form). In our example, the feature <code>start</code> is applied to <code>my_list</code> which will attempt to set the list cursor to the first element in <code>my_list</code>.
The ''Exit condition part'':
<code>
until
my_list.off
</code>
''Exit condition part.''
The exit condition part of the loop construct defines the conditions under which the loop body (explained below) should no longer be executed. In our example, the loop will no longer execute if the cursor is "off", that is, there is no current item. So, if the list is empty, the loop body will not execute at all.
The ''<code>loop</code> body'' part:
<code>
loop
print (my_list.item)
my_list.forth
</code>
''<code>loop</code> body part.''
The loop body part contains the sequence of instructions to be executed during each iteration. In the example, that includes printing the current list item and then advancing the cursor. At some point, the cursor will pass the last item in the list, causing the exit condition to become true and stop the loop's execution. So, at the risk of stating the obvious, the key to loops that always complete is to ensure that there is something in the loop body that is guaranteed always to cause the exit condition eventually to become true. Loop correctness will discussed in more detail [[#Loop invariants and variants|later]].
And finally, there's the ''End'' part:
<code>
end
</code>
''<code>end</code> part.''
====A closer look at the ''iteration'' form====
Now let's examine the iteration form (sometimes called the "across syntax") used in ''Loop example 2.''
The example begins with an iteration part:
<code>
across my_list as ic
</code>
''Iteration part.''
The iteration form is special in the sense that it is designed to work with objects which are ''iterable'', usually data structures. The iteration form always targets a particular object (usually a data structure) based on a class that inherits, either directly or indirectly from the library class <code>ITERABLE</code>. The iteration part specifies such a target for the iteration, in the case of our example, the target is <code>my_list</code>.
The "<code>as ic</code>" indicates that a local iteration cursor object referenced by the name <code>ic</code>, and available only for the scope of the iteration, will be created to effect the iteration. The element of <code>my_list</code> which is currently referenced by the cursor <code>ic</code> is accessed through <code>ic.item</code> as you see in the loop body:
<code>
loop print (ic.item)
</code>
''<code>loop</code> body part''.
Notice that the loop body does not contain the call to the structure's <code>forth</code> feature, as our example in base form did. Neither do you see the call to <code>start</code> nor the check of <code>off</code> in the exit condition. The iteration form abstracts these for you, relieving you of their burden ... while eliminating some opportunities for error.
Notice also that the call "<code>print (ic.item)"</code>" accesses the current item as "<code>ic.item"</code>" versus "<code>my_list.item"</code>" in the base form. This is because in the iteration form, access to the current item is through the cursor variable, "<code>ic</code>" in the case of ''Loop example 2''.
Concerning cursors, both ways of using the loop construct to traverse a structure employ a cursor. In the base form, the cursor is internal to the structure object. In the case of the example, that would be the instance of <code>LINKED_LIST [STRING]</code> called <code>my_list</code>. Applying the feature <code>item</code> to <code>my_list</code> retrieves the list element currently referenced by the cursor. In the iteration version of traversal, the variable <code>ic</code> holds the iteration cursor, external to the list object. So, you apply <code>ic.item</code> to get the current list element. The advantage to the external cursor is that multiple traversals of the structure can occur simultaneously without interfering with one another. This is possible in the base form, but only by saving and restoring the structure's cursor.
{{recommended|The ''iteration'' form of the loop construct is not appropriate for use in cases in which the target structure may be changed during the traversal. Therefore, if you choose to alter the structure during traversal, you must use the ''base'' loop form with explicit cursor manipulation. This is still tricky business, so you should be certain to protect your work with appropriate contracts.}}
Lastly, of course, the iteration form includes an ''<code>end</code> part'' ... at the end.
====The ''iteration'' form as a boolean expression====
In ''Loop example 2'', the loop behaves as an instruction. But it is possible to have the iteration loop form behave as a boolean expression. This is helpful in cases in which you might want to ask a question that can be answered by traversing all or part of a structure.
To get this effect, you use the iteration form with one of two alternative body notations, the ''<code>all</code> body part'' or the ''<code>some</code> body part'' in place of the ''<code>loop</code> body''. When you use either of these notations, the ''body'' is a boolean expression. So, the forms for these body parts are:
<code>
all boolean_expression
</code>
''<code>all</code> body part.''
<code>
some boolean_expression
</code>
''<code>some</code> body part.''
So, to know if all the strings in <code>my_list</code> have lengths greater than three characters, we could code:
<code>
across my_list as ic all ic.item.count > 3 end
</code>
''Loop example 3.''
To know if at least one string in <code>my_list</code> has a length greater than three characters, we would use the ''<code>some</code> body part'':
<code>
across my_list as ic some ic.item.count > 3 end
</code>
''Loop example 4.''
Of course you can use iteration loops with "<code>all</code>" or "<code>some</code>" bodies in the same way that you would any other boolean expression; in [[#Conditional|conditionals]], for example.
====Loop anatomy and rules for constructing loops====
Now that we've seen examples of the two forms of loops and broken down their component parts, we're ready to examine the anatomy of the entire construct in more detail. You may remember from the beginning of this discussion that the flexibility of the loop construct lies in its ability to use or omit its various parts to gain certain effects.
Here are all the possible loop parts, most of which we've seen in examples, in the order in which they must appear when we code them:
{| border="2" cellpadding="8"
! This loop part:
! Has this pattern:
|-
| ''Iteration part'' || <code>across expression as identifier</code>
|-
| ''Initialization part'' || <code>from zero_or_more_instructions</code>
|-
| ''Invariant part'' || <code>invariant assertion</code>
|-
| ''Exit condition part'' || <code>until boolean_expression</code>
|-
| rowspan="3" | ''Body part'' || <code>loop</code> ''<code>zero_or_more_instructions </code>'' '''or'''
|-
| <code>all</code> ''<code>boolean_expression</code>'' '''or'''
|-
| <code>some</code> ''<code>boolean_expression</code>''
|-
| ''Variant part'' || <code>variant optional_tag: integer_expression</code>
|-
| ''<code>end</code> part'' || <code>end</code>
|}
Apart from seeing examples, it is useful to understand some of the rules of constructing loops from these parts. Here's an informal summary of what you should know about putting together valid loops:
# Any loop parts being used must appear in the order shown in the table above.
# Every loop used will assume one of the two forms mentioned early. As a result, every loop will begin either with the <code>across</code> keyword (''iteration'' form) or the <code>from</code> keyword (''base'' form).
# A ''Body part'' and an ''End part'' are both required for every loop.
## ''Body parts'' using either the <code>all</code> keyword or the <code>some</code> keyword are only allowed in the absence of an ''initialization part''.
# An ''exit condition part'' is required for all loops of ''base'' form.
# The expression you use in an ''iteration'' part, must have a type that is based on a class that inherits from the library class <code>ITERABLE</code>.
# The identifier you choose for the internal cursor used in loops of the ''iteration'' form shouldn't be the same as another identifier you are using.
There are implications of these rules that are worth understanding. Let's look at some of them.
Consider that all parts must appear in order (1) and that every loop starts with one of two keywords: either <code>across</code> or <code>from</code> (2). Taken together, these imply that it would be invalid for a loop in ''base'' form to include an ''iteration part''. However, the opposite is not true. Because the ''initialization part'' falls after the ''iteration part'' it is possible for a loop in ''iteration'' form to contain an ''initialization'' part. Imagine for example, that we wanted to compute the sum of the number of characters in all elements of the list of strings in our examples. The ''initialization'' part could be used to initialize the sum entity before starting the iteration:
<code>
across
my_list as ic
from
sum := 0
loop
sum := sum + ic.item.count
end
</code>
Loops of the ''base'' form require an ''exit condition part'' (4). This allows the possibility that ''Iteration'' loops ''may'' contain an ''exit condition part''. Indeed they may, but it is not required. Using an ''exit condition part'' in a loop of the ''iteration'' can be useful if you want to impose an early exit condition on an iteration. So, extending the previous example, if we wanted to sum the length of elements, but only until we reached an element whose content matched a certain criterion, we could add the ''exit condition part'':
<code>
across
my_list as ic
from
sum := 0
until
ic.item ~ "Stop now"
loop
sum := sum + ic.item.count
end
</code>
For loops of the ''iteration'' form, types of iteration targets must be based on classes inheriting from <code>ITERABLE</code> (5). What classes meet this criterion? All the appropriate classes in the EiffelBase library: lists, hash tables, arrays, intervals, etc. Although the details are beyond the scope of this tutorial, you also should recognize the implication that your own classes could be made iterable.
One useful descendant of <code>ITERABLE</code> is the integer interval. The general operator "<code>|..|</code>" provides a concise way of creating the interval between two integers. So, you can use this to loop across a range of integers without a lot of setup. This example:
<code>
across
5 |..| 15 as ic
loop
print (ic.item.out+"%N")
end
</code>
prints the integers in the interval 5 through 15.
Also descending from <code>ITERABLE</code> are the iteration cursors themselves. This means that a cursor can be the target of a loop of the ''iteration'' form. Consider this example that prints the items in <code>my_list</code> in reverse order:
<code>
across
my_list.new_cursor.reversed as ic
loop
print (ic.item)
end
</code>
Here the feature <code>new_cursor</code> is applied to <code>my_list</code>. The result is a new iteration cursor for traversing <code>my_list</code>. Then the <code>reversed</code> feature is applied to that result, which itself results in an iteration cursor having the order of the elements reversed. It is this cursor that is used for <code>ic</code> in the traversal.
====Loop invariants and variants====
The only loop parts that we have yet to address are the ''invariant part'' and the ''variant part''. These two optional loop parts exist to help guarantee the correctness of loops. The ''invariant part'' expresses a loop invariant (not to be confused with [[ET: Design by Contract (tm), Assertions and Exceptions#Class invariants|class invariants]]). For the loop to be correct, the instructions in ''initialization part'' must ensure that the loop invariant assertion is true, and then every execution of the loop body must preserve the invariant; so the effect of the loop is to yield a state, eventually, in which both the loop invariant and the exit condition are true.
The loop must terminate after a finite number of iterations, of course. This can be guaranteed by including the loop ''variant part''. The ''variant part'' provides an integer expression whose value is non-negative after the execution of the instructions in the ''initialization part''. The value of the variant is then decreased by at least one, while remaining non-negative, by any execution of the loop body. Because a non-negative integer cannot be decreased forever, this guarantees that the loop will terminate.
When assertion monitoring is enabled for loop invariants and variants, the integrity of these properties is checked after initialization and after each loop iteration. An exception will be triggered if the loop invariant does not hold, or if the variant either becomes negative or does not decrease.
===Debug===
An occasionally useful instruction is <code>debug</code> <code>(</code>''Debug_key'', ... <code>)</code> ''instructions'' <code>end</code> where ''instructions'' is a sequence of zero or more instructions and the part in parentheses is optional, containing if present one or more strings, called debug keys. The EiffelStudio compiler lets you specify the corresponding <code>debug</code> compilation option: <code>yes</code>, <code>no</code>, or an explicit debug key. The ''instructions'' will be executed if and only if the corresponding option is on. The obvious use is for instructions that should be part of the system but executed only in some circumstances, for example to provide extra debugging information.
===Check===
The final instruction is connected with Design by Contract&#153;. The instruction
<code>
check
Assertion
end
</code>where Assertion is a sequence of zero or more assertions, will have no effect unless assertion monitoring is turned on at the <code>Check</code> level or higher. If so it will evaluate all the assertions listed, having no further effect if they are all satisfied; if any one of them does not hold, the instruction will trigger an exception.
This instruction serves to state properties that are expected to be satisfied at some stages of the computation -- other than the specific stages, such as routine entry and exit, already covered by the other assertion mechanisms such as preconditions, postconditions and invariants. A recommended use of <code>check</code> involves calling a routine with a precondition, where the call, for good reason, does not explicitly test for the precondition. Consider a routine of the form
<code>
r (a_count: INTEGER)
require
valid_count: a_count >= minimum_allowable
do
...
end
</code>
This routine will only work if its precondition is satisfied on entry. To guarantee this precondition, the caller may protect it by the corresponding test, as in
<code>
if my_count >= a.minimum_allowable then
a.r (my_count)
end
</code>
In effect, this says that if the value of <code>my_count</code> meets <code>r</code>'s precondition requirement, then call <code>r</code>, otherwise continue execution. This implies that there is something useful to be done in the case that the call to <code>r</code> could not be executed because the value of <code>my_count</code> did not meet the precondition.
But suppose that due to previous processing, it is reasonably expected that <code>my_count</code> should always have a value that complies with <code>r</code>'s precondition. In other words, it would always be expected that the call to <code>r</code> should proceed without failure. In this case it might be a good idea to use a <code>check</code> to document this property,
<code>
check
my_count_is_large_enough: my_count >= a.minimum_allowable
-- Should always be large enough because ...
end
</code>
if only to make sure that a reader of the code will realize that the omission of an explicit test was not a mistake.
In production (finalized) mode, when assertion monitoring is typically turned off, this instruction will have no effect. But it will be precious for a maintainer of the software who is trying to figure out what it does, and in the process to reconstruct the original developer's reasoning. (The maintainer might of course be the same person as the developer, six months later.) And if the rationale is wrong somewhere, turning assertion checking on will immediately uncover the bug.
There is, however, one form of <code>check</code> that continues to be monitored even when assertion monitoring is turned off.
<code>
check Assertion then
Compound
end
</code>
Here <code>Assertion</code> is a list of assertions as above, and <code>Compound</code> is a list of zero or more executable instructions.
This variant is used often when ensuring [[Void-safe programming in Eiffel|void-safety]]. It is used to make certain that certain detachable entities are actually attached to objects when expected, and to create a new void-safe scope for accessing the objects. For example:
<code>
check attached my_detachable as l_temp then
l_temp.do_something
end
</code>
In cases in which <code>my_detachable</code> is attached to an object (as is expected), the local entity l_temp will allow controlled access to the object during the scope of the <code>check</code> instruction. If a case occurs in which <code>my_detachable</code> is not attached to an object, then an exception is triggered. As noted above, for this variant of <code>check</code>, assertion monitoring is always in effect, even if it has been turned off for other cases.
So, the form <code>check ... then ... end</code> is somewhat similar to <code>if ... then ... end</code>. The difference is that the <code>if ... then ... end</code> allows the possibility that valid cases might occur in which the boolean expression is not true, and processing continues. The <code>check ... then ... end</code> does not allow such a possibility. The boolean expression is expected always to hold. In fact, if the expression is not true, then like other assertion violations, this is indicative of a bug, and will cause an exception to be raised.
{{recommended|An extra indentation of the <code>check</code> part to separate it from the algorithm proper; and inclusion of a comment listing the rationale behind the developer's decision not to check explicitly for the precondition. }}

View File

@@ -0,0 +1,15 @@
[[Property:title|ET: To Learn More]]
[[Property:weight|-1]]
[[Property:uuid|74a5c826-8f21-8cf2-4f2c-dee4ee28ead5]]
Beyond this introduction, you will find the following books essential to a mastery of the method and language: <br/>
* [[Touch of class: Learning to Program Well with Objects and Contracts]], Bertrand Meyer, Springer-Verlag, 2009. A modern guide to developing durable skills for software professionals.
* [[Object-Oriented Software Construction, 2nd Edition]], Bertrand Meyer, Prentice Hall, 2nd edition 1997. (Be sure to get the second edition.) About object technology in general; presents the method behind Eiffel.
* [[Eiffel: The Language]], Bertrand Meyer, Prentice Hall, 1992. Language manual and reference.

View File

@@ -0,0 +1,110 @@
[[Property:modification_date|Wed, 01 Jul 2020 08:44:12 GMT]]
[[Property:publication_date|Wed, 01 Jul 2020 08:44:12 GMT]]
[[Property:title|ET: Lexical Conventions and Style Rules]]
[[Property:weight|-2]]
[[Property:uuid|60fdf029-8626-166d-cc4f-9069aacdda7f]]
Eiffel software texts are free-format: distribution into lines is not semantically significant, and any number of successive space and line-return characters is equivalent to just one space. The style rules suggest indenting software texts as illustrated by the examples in this chapter.
Successive declarations or instructions may be separated by semicolons. Eiffel's syntax has been so designed, however, that (except in rare cases) '''the semicolon is optional'''. Omitting semicolons for elements appearing on separate lines lightens text and is the recommended practice since semicolons, as used by most programming languages, just obscure the text by distracting attention from the actual contents. Do use semicolons if you occasionally include successive elements on a single line.
56 names -- all unabbreviated single English words, except for <code>elseif</code> which is made of two words -- are reserved, meaning that you cannot use them to declare new entities. Here is the list:
{| border="1"
|-
| <code>agent</code>
| <code>alias</code>
| <code>all</code>
| <code>and</code>
| <code>as</code>
| <code>assign</code>
| <code>check</code>
|-
| <code>class</code>
| <code>convert</code>
| <code>create</code>
| <code>Current</code>
| <code>debug</code>
| <code>deferred</code>
| <code>do</code>
|-
| <code>else</code>
| <code>elseif</code>
| <code>end</code>
| <code>ensure</code>
| <code>expanded</code>
| <code>export</code>
| <code>external</code>
|-
| <code>False</code>
| <code>feature</code>
| <code>from</code>
| <code>frozen</code>
| <code>if</code>
| <code>implies</code>
| <del><code>indexing</code></del>
|-
| <del><code>infix</code></del>
| <code>inherit</code>
| <code>inspect</code>
| <code>invariant</code>
| <code>is</code>
| <code>like</code>
| <code>local</code>
|-
| <code>loop</code>
| <code>not</code>
| <code>obsolete</code>
| <code>old</code>
| <code>once</code>
| <code>or</code>
| <del><code>prefix</code></del>
|-
| <code>Precursor</code>
| <code>pure</code>
| <code>redefine</code>
| <code>reference</code>
| <code>rename</code>
| <code>require</code>
| <code>rescue</code>
|-
| <code>Result</code>
| <code>retry</code>
| <code>separate</code>
| <code>then</code>
| <code>True</code>
| <code>TUPLE</code>
| <code>undefine</code>
|}
note: `infix`, `prefix` are not anymore reserved since version 19.12 , and `indexing` as well even before.
Since this tutorial has covered all the essential mechanisms, you may ignore the keywords not encountered; they are reserved for future use.
Most of the reserved words are keywords, serving only as syntactic markers, and written in boldface in typeset texts such as the present one: <code>class</code>, <code>feature</code>, <code>inherit</code>. The others, such as <code>Current</code>, directly carry a semantic denotation; they start with an upper-case letter and are typeset in boldface.
These conventions about letter case are only style rules. Eiffel is case-insensitive, since it is foolish to assume that two identifiers denote two different things just on the basis of a letter written in lower or upper case. The obvious exception is manifest character constants (appearing in single quotes, such as <code>'A'</code>) and manifest character strings (appearing in double quotes, such as <code>"UPPER and lower"</code>).
The style rules, however, are precise, and any serious Eiffel project will enforce them; the tools of EiffelStudio also observe them in the texts they output (although they will not mess up with your source text unless you ask them to reformat it). Here are the conventions, illustrated by the examples of this tutorial:
* Class names in upper case, as <code>ACCOUNT</code>.
* Non-constant feature names and keywords in lower case, as <code>balance</code> and <code>class</code>.
* Constant features and predefined entities and expressions with an initial upper case, as <code>Avogadro</code> and <code>Result</code>.
In typeset documents including Eiffel texts, the standard for font styles is also precise. You should use <code>bold face</code> for keywords and <code>italics</code> for all other Eiffel elements. Comments, however, are typeset in <code>roman</code>. This lets a software element, such as an identifier, stand out clearly in what is otherwise a comment text expressed in English or another human language, as in the earlier example
<code>
-- Add `sum' to account.
</code>
which makes clear that <code>sum</code> is a software element, not the English word.
There is also an Eiffel style to the choice of identifiers. For features, stay away from abbreviations and use full words. In multi-word identifiers, separate the constituents by underscores, as in <code>LINKED_LIST</code> and <code>set_owner</code>. The competing style of no separation but mid-identifier upper-case, as in <code>linkedList</code> or <code>setOwner</code>, is less readable and not in line with standard Eiffel practices.
Features of reusable classes should use consistent names. A set of standard names -- <code>put</code> for the basic command to add or replace an element, <code>count</code> for the query that returns the number of element in a structure, <code>item</code> to access an element -- is part of the style rules, and used systematically in EiffelBase. Use them in your classes too.
For local entities and formal arguments of routines, it is all right to use abbreviated names, since these identifiers only have a local scope, and choosing a loud name would give them too much pretense, leading to potential conflicts with features.
The complete set of style rules applied by ISE is available on the web in both <span> [http://archive.eiffel.com/doc/manuals/language/style/page.html HTML] </span> and <span> [http://archive.eiffel.com/doc/manuals/language/style/style.pdf PDF] </span> forms. These rules are an integral part of the Eiffel method; in quality software, there is no such thing as a detail. Applying them systematically promotes consistency between projects in the Eiffel world, enhances reusability, and facilitates everyone's work.

View File

@@ -0,0 +1,91 @@
[[Property:title|ET: Once routines and shared objects]]
[[Property:weight|-5]]
[[Property:uuid|bc42c52f-c668-6036-9540-55d0f48b05cb]]
==About ''once'' routines==
The Eiffel's method obsession with extendibility, reusability and maintainability yields, as has been seen, modular and decentralized architectures, where inter-module coupling is limited to the strictly necessary, interfaces are clearly delimited, and all the temptations to introduce obscure dependencies, in particular global variables, have been removed. There is a need, however, to let various components of a system access common objects, without requiring their routines to pass these objects around as arguments (which would only be slightly better than global variables). For example various classes may need to perform output to a common "console window", represented by a shared object.
Eiffel addresses this need through an original mechanism that also takes care of another important issue, poorly addressed by many design and programming approaches: initialization. The idea is simple: if instead of <code>do</code> the implementation of an effective routine starts with the keyword <code>once</code>, it will only be executed the first time the routine is called during a system execution (or, in a multi-threaded environment, the first time in each thread), regardless of what the caller was. Subsequent calls from the same caller or others will have no effect; if the routine is a function, it will always return the result computed by the first call -- object if an expanded type, reference otherwise.
In the case of procedures, this provides a convenient initialization mechanism. A delicate problem in the absence of a <code>once</code> mechanism is how to provide the users of a library with a set of routines which they can call in any order, but which all need, to function properly, the guarantee that some context had been properly set up. Asking the library clients to precede the first call with a call to an initialization procedure <code>setup</code> is not only user-unfriendly but silly: in a well-engineered system we will want to check proper set-up in every one of the routines, and report an error if necessary; but then if we were able to detect improper set-up we might as well shut up and set up ourselves (by calling <code>setup</code>). This is not easy, however, since the object on which we call <code>setup</code> must itself be properly initialized, so we are only pushing the problem further. Making <code>setup</code> a <code>once</code> procedure solves it: we can simply include a call
<code>
setup
</code>
at the beginning of each affected routine; the first one to come in will perform the needed initializations; subsequent calls will have, as desired, no effect.
Once functions will give us shared objects. A common scheme is
<code>
console: WINDOW
-- Shared console window
once
create Result.make (...)
end
</code>
Whatever client first calls this function will create the appropriate window and return a reference to it. Subsequent calls, from anywhere in the system, will return that same reference. The simplest way to make this function available to a set of classes is to include it in a class <code>SHARED_STRUCTURES</code> which the classes needing a set of related shared objects will simply inherit.
For the classes using it, <code>console</code>, although a function, looks very much as if it were an attribute -- only one referring to a shared object.
The "[[ET: Hello World|Hello World]]" system at the beginning of this discussion used an output instruction of the form <code>io</code>. <code>put_string (some_string)</code>. This is another example of the general scheme illustrated by <code>console</code>. Feature <code>io</code>, declared in <code>ANY</code> and hence usable by all classes, is a once function that returns an object of type <code>STANDARD_FILES</code> (another Kernel Library class) providing access to basic input and output features, one of which is procedure <code>put_string</code>. Because basic input and output must all work on the same files, <code>io</code> should clearly be a <code>once</code> function, shared by all classes that need these mechanisms.
==Adjusting once semantics with "once keys"==
Sometimes it is helpful to adjust the way that once routines work, and that is done by applying '''once keys'''. For example, in multithreaded mode, it is reasonable most often for once routines to be executed once per ''thread'', versus once per ''process''. Therefore, the default <code>once</code> syntax, as shown in the example above, would behave as once per thread in multithreaded mode.
Sometimes, however, it is useful in multithreaded mode to create an object which can be shared among threads. To do this, once per process is needed. To create effects like this which are outside the default behavior, we can use once "keys". In following example, a once key is used to specify that the once routine is executed only once per process:
<code>
shared_object: SOME_TYPE
-- An object that can be shared among threads
-- without being reinitialized.
once ("PROCESS")
create Result.make (...)
end
</code>
Other valid once keys are "THREAD" and "OBJECT". Of course, "THREAD" ensures that the once routine executes only the first time it is called during the execution of a particular process thread. "OBJECT" is used when it is desirable to have a once routine executed on a once per object basis.
{| border="2"
|+ '''How once keys affect once routine execution'''
! Once key ... !! Routine executed the first time it is called ...
|-
| PROCESS || During process execution
|-
| THREAD || During each process thread execution
|-
| OBJECT || By each instance
|}
THREAD is the default once key if none is specified (which for single threaded systems will have the same effect as PROCESS).
The concept of once keys is open ended, so additional keys may become supported in the future to allow even finer grained control of once routine behavior.
==Once per object internal implementation warning ==
{{warning|As of version 6.6, once per object is implemented using 2 or 3 implementation attributes (these are used to store whether the once routine has already called or not, the eventual exception if any, and the result value if any).<br/><br/>The implementation attributes are named starting with an underscore '_', and if you use the class <code>INTERNAL</code>, the implementation attributes will be included in the <code>field_count</code>, and available through the <code>INTERNAL</code> features. <br/>However this might change in the future, and the implementation attributes might be hidden, so you should not rely on them for your applications. <br/>One last technical detail is that for now a once per object is transient (i.e the associated implementation attributes are [[ET: The Dynamic Structure: Execution Model#Transient attributes|transient]]).<br/>}}
==Once routines and exceptions==
It is possible that during the execution that happens when a once routine is called for the first time, an exception may occur. If this happens, then the '''same exception will be raised on each subsequent''' call to the once routine.
==Syntax from previous versions==
The syntax shown above is the current standard syntax. However in Eiffel code written for previous versions, you may run across once keys for multithreaded systems which are expressed in a different syntax. Specifically, the older syntax used a feature's <code>note</code> clause to specify a once key, as in the following example.
<code>
shared_object: SOME_TYPE
-- Obsolete syntax
-- An object that can be shared among threads
-- without being reinitialized.
note
once_status: global
once
create Result.make (...)
end
</code>

View File

@@ -0,0 +1,372 @@
[[Property:modification_date|Thu, 02 Jul 2020 10:00:15 GMT]]
[[Property:publication_date|Tue, 10 Sep 2019 23:07:44 GMT]]
[[Property:title|ET: Other Mechanisms]]
[[Property:weight|-4]]
[[Property:uuid|c0a01664-194c-4e84-0517-8e7c1ca61dec]]
We now examine a few important mechanisms that complement the preceding picture.
==Manifest constants==
Sometimes we want to provide in software text a self-denoting value of a particular type. In Eiffel this is what we call a '''manifest constant'''. For example, if we are searching an indexed structure, we might have an integer variable that we would want to initialize to reference the first item in the structure:
<code>
my_index := 1
</code>
In this case we used a manifest constant, <code>1</code>, to provide an initial value for <code>my_index</code>. In particular, this is a manifest integer.
Eiffel also supports [[Eiffel_programming_language_syntax#Manifest_constants|manifest constants]] for real (and double) numbers (ex: <code>3.1415</code>), boolean values (ex: <code>True</code>, <code>False</code>), and characters (ex: <code>'A'</code>, with [[Eiffel programming language syntax#Special characters|special characters]] expressed using a percent sign as in <code>'%N'</code> for new line, <code>'%B'</code> for backspace, <code>'%"'</code> for double quote, and <code>'%U'</code> for null).
Manifest constants are also available for strings, using double quotes as in: <code>"Hello world!"</code>. As with character constants, special characters are denoted using the <code>%</code> codes.
===Verbatim strings===
You may occasionally have a need for a manifest string that represents a multi-line formatted string. In Eiffel we call this type of manifest string a '''verbatim string''', and there is a special syntax for specifying verbatim strings in Eiffel code. Verbatim strings are either '''aligned''' or '''non-aligned'''. Aligned verbatim strings will automatically be adjusted so that their leftmost line (the line with text characters closest to the left margin) contains no "white space" to the left of the first text character. For non-aligned verbatim strings, the white space is left untouched. You use a slightly different way of specifying each type of string. For example, this aligned verbatim string:
<code>
my_aligned_string: STRING =
"[
Thrice hail the still unconquered King of Song!
For all adore and love the Master Art
That reareth his throne in temple of the heart;
And smiteth chords of passion full and strong
Till music sweet allures the sorrowing throng!
]"
</code>
will print like this:
<code lang="text">
Thrice hail the still unconquered King of Song!
For all adore and love the Master Art
That reareth his throne in temple of the heart;
And smiteth chords of passion full and strong
Till music sweet allures the sorrowing throng!
</code>
The same string, declared as a non-aligned verbatim string:
<code>
my_non_aligned_string: STRING =
"{
Thrice hail the still unconquered King of Song!
For all adore and love the Master Art
That reareth his throne in temple of the heart;
And smiteth chords of passion full and strong
Till music sweet allures the sorrowing throng!
}"
</code>
will print like this:
<code lang="text">
Thrice hail the still unconquered King of Song!
For all adore and love the Master Art
That reareth his throne in temple of the heart;
And smiteth chords of passion full and strong
Till music sweet allures the sorrowing throng!
</code>
The difference in declaration is that the aligned verbatim string uses as its "opener" the double-quote plus bracket combination, " <code>"[</code> ", and the bracket plus double quote, " <code>]"</code> ", as its "closer". The non-aligned verbatim string uses braces, " <code>{</code> " and " <code>}</code> " instead of the bracket.
The syntax for specifying verbatim strings allows an option for the situation in which the specified string might conflict with the "closer". You can include a simple string between the double quote and the bracket on each end of the verbatim string to guarantee uniqueness. Here's our aligned verbatim string with the simple string " <code>*?</code> " inserted in the opener and closer:
<code>
my_aligned_string: STRING =
"*?[
Thrice hail the still unconquered King of Song!
For all adore and love the Master Art
That reareth his throne in temple of the heart;
And smiteth chords of passion full and strong
Till music sweet allures the sorrowing throng!
]*?"
</code>
==Constant attributes==
The attributes studied earlier were variable: each represents a field present in each instance of the class and changeable by its routines.
It is also possible to declare '''constant attributes''', as in
<code>
Solar_system_planet_count: INTEGER = 8
</code>
These will have the same value for every instance and hence do not need to occupy any space in objects at execution time. (In other approaches similar needs would be addressed by symbolic constants, as in Pascal or Ada, or macros, as in C.)
What comes after the <code>=</code> is a manifest constant. So you can declare a constant attribute for any type for which there is a manifest constant.
==Obsolete features and classes==
One of the conditions for producing truly great reusable software is to recognize that although you should try to get everything right the first time around you won't always succeed. But if "good enough" may be good enough for application software, it's not good enough, in the long term, for reusable software. The aim is to get ever closer to the asymptote of perfection. If you find a better way, you must implement it. The activity of generalization, discussed as part of the lifecycle, doesn't stop at the first release of a reusable library.
This raises the issue of backward compatibility: how to move forward with a better design, without compromising existing applications that used the previous version?
The notion of obsolete class and feature helps address this issue. By declaring a feature as <code>obsolete</code>, using the syntax
<code>
enter (i: INTEGER; x: G)
obsolete
"Use ` put (x, i)' instead "
require
...
do
put (x, i)
end
</code>
you state that you are now advising against using it, and suggest a replacement through the message that follows the keyword <code>obsolete</code>, a mere string. The obsolete feature is still there, however; using it will cause no other harm than a warning message when someone compiles a system that includes a call to it. Indeed, you don't want to hold a gun to your client authors' forehead (''"Upgrade now or die !"''); but you do want to let them know that there is a new version and that they should upgrade at their leisure.
Besides routines, you may also mark classes as obsolete.
The example above is a historical one, involving an early change of interface for the EiffelBase library class <code>ARRAY</code>; the change affected both the feature's name, with a new name ensuring better consistency with other classes, and the order of arguments, again for consistency. It shows the recommended style for using <code>obsolete</code>: <br/>
* In the message following the keyword, explain the recommended replacement. This message will be part of the warning produced by the compiler for a system that includes the obsolete element.
* In the body of the routine, it is usually appropriate, as here, to replace the original implementation by a call to the new version. This may imply a small performance overhead, but simplifies maintenance and avoids errors.
It is good discipline not to let obsolete elements linger around for too long. The next major new release, after a suitable grace period, should remove them.
The design flexibility afforded by the <code>obsolete</code> keyword is critical to ensure the harmonious long-term development of ambitious reusable software.
==Creation variants==
The basic forms of creation instruction, and the one most commonly used, are the two illustrated earlier ( [[ET: The Dynamic Structure: Execution Model#Creating_and_initializing_objects|"Creating and initializing objects"]] ):
<code>
create x.make (2000)
create x
</code>
the first one if the corresponding class has a <code>create</code> clause, the second one if not. In either form you may include a type name in braces, as in
<code>
create {SAVINGS_ACCOUNT} x.make (2000)
</code>
which is valid only if the type listed, here <code>SAVINGS_ACCOUNT</code>, conforms to the type of <code>x</code>, assumed here to be <code>ACCOUNT</code>. This avoids introducing a local entity, as in
<code>
local
xs: SAVINGS_ACCOUNT
do
create xs.make (2000)
x := xs
...
</code>
and has exactly the same effect. Another variant is the '''creation expression''', which always lists the type, but returns a value instead of being an instruction. It is useful in the following context:
<code>
some_routine (create {ACCOUNT}.make (2000))
</code>
which you may again view as an abbreviation for a more verbose form that would need a local entity, using a creation instruction:
<code>
local
x: ACCOUNT
do
create x.make (2000)
some_routine (x)
...
</code>
Unlike creation instructions, creation expressions must always list the type explicitly, <code>{ACCOUNT}</code> in the example. They are useful in the case shown: creating an object that only serves as an argument to be passed to a routine. If you need to retain access to the object through an entity, the instruction <code>create x</code> ... is the appropriate construct.
The creation mechanism gets an extra degree of flexibility through the notion of <code>default_create</code>. The simplest form of creation instruction, <code>create x</code> without an explicit creation procedure, is actually an abbreviation for <code>create x.default_create</code>, where <code>default_create</code> is a procedure defined in class <code>ANY</code> to do nothing. By redefining <code>default_create</code> in one of your classes, you can ensure that <code>create x</code> will take care of non-default initialization (and ensure the invariant if needed). When a class has no <code>create</code> clause, it's considered to have one that lists only <code>default_create</code>. If you want to allow <code>create x</code> as well as the use of some explicit creation procedures, simply list <code>default_create</code> along with these procedures in the <code>create</code> clause. To disallow creation altogether, include an empty <code>create</code> clause, although this technique is seldom needed since most non-creatable classes are deferred, and one can't instantiate a deferred class.
One final twist is the mechanism for creating instances of formal generic parameters. For <code>x</code> of type <code>G</code> in a class <code>C [G]</code>, it wouldn't be safe to allow <code>create x</code>, since <code>G</code> stands for many possible types, all of which may have their own creation procedures. To allow such creation instructions, we rely on constrained genericity. You may declare a class as
<code>
[G -> T create cp end]
</code>
to make <code>G</code> constrained by <code>T</code>, as we learned before, and specify that any actual generic parameter must have <code>cp</code> among its creation procedures. Then it's permitted to use <code>create x.cp</code>, with arguments if required by <code>cp</code>, since it is guaranteed to be safe. The mechanism is very general since you may use <code>ANY</code> for <code>T</code> and <code>default_create</code> for <code>cp</code>. The only requirement on <code>cp</code> is that it must be a procedure of <code>T</code>, not necessarily a creation procedure; this permits using the mechanism even if <code>T</code> is deferred, a common occurrence. It's only descendants of <code>T</code> that must make <code>cp</code> a creation procedure, by listing it in the <code>create</code> clause, if they want to serve as actual generic parameters for <code>C</code>.
==Non-object calls==
The Eiffel model for object-oriented computation involves the application of some feature <code>f</code> to some object <code>x</code>, and possibly passing arguments <code>a</code>:
<code>
x.f (a)
</code>
This type of feature call is known as an '''object call''' because it applies the feature to a target object, in this case <code>x</code>. However, under certain circumstances we may apply a feature of a class in a fashion that does not involve a target object. This type of call is a '''non-object call'''. In place of the target object, the syntax of the non-object call uses the type on which the feature can be found.
<code>
circumference := radius * 2.0 * {MATH_CONST}.pi
</code>
In the sample above, the call to feature <code>{MATH_CONST}.Pi</code> is a non-object call. This case illustrates one of the primary uses of non-object calls: constants. The library class <code>MATH_CONST</code> contains commonly used mathematical constants. Non-object calls make it possible to use the constants in <code>MATH_CONST</code> without having to create an instance of <code>MATH_CONST</code> or inherit from it.
The other primary use is for external features. One example is when we use Microsoft .NET classes from Eiffel code and have to access mechanisms for which there is no direct analog in Eiffel. Microsoft .NET supports so-called "static" methods and enumeration types. To access these, we use non-object calls. In the example below, a non-object call is used to access the enumeration <code lang="text">CreateNew</code> from the .NET enumeration type <code lang="text">System.IO.FileMode</code>.
<code>
create my_file_stream.make ("my_file.txt", {FILE_MODE}.create_new)
</code>
The validity of a non-object call is restricted in ways that mirror these primary uses. That is, any feature called in a non-object call must be either a constant attribute, an external feature, or a class feature. (See the [[ECMA Standard 367|ISO/ECMA Eiffel standard document]] for additional details.)
=== Class feature ===
A feature with a class postcondition is known as a class feature and can be used in non-object calls. A class postcondition consists of a single keyword <code lang="eiffel">class</code> (with an optional leading tag):
<code>
disc_area (radius: REAL_32): REAL_32
-- Area of a disk of radius `radius`.
do
Result := radius * radius * {MATH_CONST}.pi
ensure
instance_free: class
end
</code>
A class feature can be used not only in object calls, but also in non-object calls. For example, assuming the feature above is defined in class <code lang="eiffel">GEOMETRY</code>, it can be called without creating an object:
<code>
area := {GEOMETRY}.disc_area (r)
</code>
A class feature is valid only when it does not
* access <code lang="eiffel">Current</code>;
* access a variable attribute;
* declare an unqualified agent;
* make an unqualified call to a non-class feature.
Although an external feature without assertions can be used in non-object calls, it is a good practice to add a class postcondition if such usage is expected. This guarantees that no added or inherited assertion violates the validity rule for a class feature.
==Convertibility==
It is useful at times to designate that instances of one type can be created through the controlled conversion of instances of some other type. This can be done through a safe Eiffel type conversion mechanism called '''convertibility'''.
Convertibility is useful when refactoring, moving from one design to another, or, as you will see in the example, accommodating external technologies over which we have no control.
{{Definition|Convertibility: converts to, converts from|<br/>
<br/>
A type U based on a class CU '''converts to''' a type T based on a class CT (and T '''converts from''' U) if either<br/>
<br/>
CT has a ''conversion procedure'' using U as a conversion type, or <br/>
<br/>
CU has a ''conversion query'' listing T as a conversion type,<br/>
<br/>
but not both.}}
Before we get into an example of convertibility, let's list some of its underlying principles:
# Conversion Principle: No type may both ''conform'' and ''convert'' to another.
# Conversion Asymmetry Principle: No type may convert to another through both a ''conversion procedure'' and a ''conversion query''.
# Conversion Non-transitivity Principle: That V converts to U and U converts to T does not imply that V converts to T.
Let's look at an example with which you may already be familiar.
<code>
my_string: STRING_8 -- Native Eiffel string
my_system_string: SYSTEM_STRING -- Native Microsoft .Net string
my_string := my_system_string
</code>
In the snippet above, we have attributes declared of type <code>STRING_8</code> and <code>SYSTEM_STRING</code>.
We know that if we have a attribute of type <code>STRING_8</code> that we can make a direct assignment of a .Net type of string (that is, the .Net type <code>System.String</code> which we see as class <code>SYSTEM_STRING</code>) to our <code>STRING_8</code> attribute.
We know also that <code>SYSTEM_STRING</code> does not conform to <code>STRING_8</code>, so according to the definition of [[ET: Instructions#Assignment and attachment|compatibility]], this must happen through conversion.
Therefore <code>SYSTEM_STRING</code> converts to <code>STRING_8</code>. And according to the definition above this means that either:
# Class <code>SYSTEM_STRING</code> has a conversion query listing <code>STRING_8</code> as a conversion type, or
# Class <code>STRING_8</code> has a conversion procedure listing <code>SYSTEM_STRING</code> as a conversion type
In this case <code>STRING_8</code> has a conversion procedure for objects of type <code>SYSTEM_STRING</code>. Conversion procedures are always [[ET: The Dynamic Structure: Execution Model#Creating and initializing objects|creation procedures]]. So they appear in both the <code>create</code> and the <code>convert</code> parts of the class.
<code>
class STRING_8
create
make_from_cil
convert
make_from_cil ({SYSTEM_STRING})
</code>
We won't show the implementation of the conversion procedure, but as you can imagine, it initializes its target with the content of its argument.
Because of convertibility, this code:
<code>
my_string := my_system_string
</code>
is equivalent to:
<code>
create my_string.make_from_cil (my_system_string)
</code>
So, we've seen how <code>SYSTEM_STRING</code> converts to <code>STRING_8</code>. But, in the context of our example, we could also do this:
<code>
my_system_string := my_string
</code>
Which means that <code>STRING_8</code> converts to <code>SYSTEM_STRING</code>. The <code>convert</code> part of class <code>STRING_8</code> also has a conversion query listing <code>SYSTEM_STRING</code> as a conversion type:
<code>
class STRING_8
create
make_from_cil
convert
make_from_cil ({SYSTEM_STRING})
to_cil: {SYSTEM_STRING}
</code>
Because of convertibility, this code:
<code>
my_system_string := my_string
</code>
is equivalent to:
<code>
my_system_string := my_string.to_cil
</code>
You should bear in mind that assignments are not the only situation in which conversions take place. Convertibility works for other types of attachments as well. For example, if a routine calls for an argument of type <code>SYSTEM_STRING</code>, and you supply an actual argument of type <code>STRING_8</code>, this constitutes an attachment, and the conversion from <code>STRING</code> to <code>SYSTEM_STRING</code> will occur.
==Tuple types==
The study of genericity described arrays. Another common kind of container objects bears some resemblance to arrays: sequences, or "tuples", of elements of specified types. The difference is that all elements of an array were of the same type, or a conforming one, whereas for tuples you will specify the types we want for each relevant element. A typical tuple type is of the form
<code>
TUPLE [X, Y, Z]
</code>
denoting a tuple of at least three elements, such that the type of the first conforms to <code>X</code>, the second to <code>Y</code>, and the third to <code>Z</code>.
You may list any number of types in brackets, including none at all: <code>TUPLE</code>, with no types in brackets, denotes tuples of arbitrary length.
{{info|The syntax, with brackets, is intentionally reminiscent of generic classes, but <code>TUPLE</code> is a reserved word, not the name of a class; making it a class would not work since a generic class has a fixed number of generic parameters. You may indeed use <code>TUPLE</code> to obtain the effect of a generic class with a variable number of parameters. }}
To write the tuples themselves -- the sequences of elements, instances of a tuple type -- you will also use square brackets; for example
<code>
[x1, y1, z1]
</code>
with <code>x1</code> of type <code>X</code> and so on is a tuple of type <code>TUPLE [X, Y, Z]</code>.
The definition of tuple types states that <code>TUPLE [X1 ... Xn]</code> denotes sequences of at least <code>n</code> elements, of which the first <code>n</code> have types respectively conforming to <code>X1, ..., Xn</code>. Such a sequence may have more than <code>n</code> elements.
Features available on tuple types include <code>count: INTEGER</code>, yielding the number of elements in a tuple, <code>item (i: INTEGER): ANY</code> which returns the <code>i</code>-th element, and <code>put</code> which replaces an element.
Tuples are appropriate when these are the only operations you need, that is to say, you are using sequences with no further structure or properties. Tuples give you "anonymous classes" with predefined features <code>count</code>, <code>item</code> and <code>put</code>. A typical example is a general-purpose output procedure that takes an arbitrary sequence of values, of arbitrary types, and prints them. It may simply take an argument of type <code>TUPLE</code>, so that clients can call it under the form
<code>
write ([your_integer, your_real, your_account])
</code>
As soon as you need a type with more specific features, you should define a class.

View File

@@ -0,0 +1,24 @@
[[Property:title|ET: Overview]]
[[Property:weight|-15]]
[[Property:uuid|0eaddff9-5d72-87fc-663a-2fc8a9152c25]]
Eiffel is a method and language for the efficient description and development of quality systems.
As a language, Eiffel is more than a programming language. It covers not just programming in the restricted sense of implementation but the whole spectrum of software development: <br/>
* ''Analysis, modeling and specification'', where Eiffel can be used as a purely descriptive tool to analyze and document the structure and properties of complex systems (even non-software systems).
* ''Design and architecture'', where Eiffel can be used to build solid, flexible system structures.
* ''Implementation'', where Eiffel provides practical software solutions with an efficiency comparable to solutions based on such traditional approaches as C and Fortran.
* ''Maintenance'', where Eiffel helps thanks to the architectural flexibility of the resulting systems.
* ''Documentation'', where Eiffel permits automatic generation of documentation, textual and graphical, from the software itself, as a partial substitute for separately developed and maintained software documentation.
Although the language is the most visible part, Eiffel is best viewed as a '''method''', which guides system analysts and developers through the process of software construction. The Eiffel method is focused on both productivity (the ability to produce systems on time and within budget) and quality, with particular emphasis on the following quality factors: <br/>
* ''Reliability:'' producing bug-free systems, which perform as expected.
* ''Reusability:'' making it possible to develop systems from prepackaged, high-quality components, and to transform software elements into such reusable components for future reuse.
* ''Extendibility:'' developing software that is truly soft -- easy to adapt to the inevitable and frequent changes of requirements and other constraints.
* ''Portability:'' freeing developers from machine and operating system peculiarities, and enabling them to produce software that will run on many different platforms.
* ''Maintainability:'' yielding software that is clear, readable, well structured, and easy to continue enhancing and adapting.

View File

@@ -0,0 +1,66 @@
[[Property:title|ET: The Software Process in Eiffel]]
[[Property:weight|-13]]
[[Property:uuid|eef7f31a-25de-93cc-9a33-41d991c51ccb]]
Eiffel, as noted, supports the entire lifecycle. The underlying view of the system development lifecycle is radically different not only from the traditional "Waterfall" model (implying a sequence of discrete steps, such as analysis, global design, detailed design, implementation, separated by major changes of method and notation) but also from its more recent variants such as the spiral model or "rapid prototyping", which remain predicated on a synchronous, full-product process, and retain the gaps between successive steps.
Clearly, not everyone using Eiffel will follow to the letter the principles outlined below; in fact, some highly competent and successful Eiffel developers may disagree with some of them and use a different process model. In the author's mind, however, these principles fit best with the language and the rest of the method, even if practical developments may fall short of applying their ideal form.
==Clusters and the cluster model==
Unlike earlier approaches, the Eiffel model assumes that the system is divided into a number of subsystems or '''clusters'''. It keeps from the Waterfall a sequential approach to the development of each cluster (without the gaps), but promotes '''concurrent engineering''' for the overall process, as suggested by the following picture:
[[Image:tutorial-2]]
The Eiffel techniques developed below, in particular information hiding and Design by Contract, make the concurrent engineering process possible by letting the clusters rely on each other through clearly defined interfaces, strictly limiting the amount of knowledge that one must acquire to use the cluster, and permitting separate testing. When the inevitable surprises of a project happen, the project leader can take advantage of the model's flexibility, advancing or delaying various clusters and steps through dynamic reallocation of resources.
==The Single Product Principle==
Each of the individual cluster life cycles is based on a continuous progression of activities, from the more abstract to the more implementation-oriented:
[[Image:tutorial-3]]
You may view this picture as describing a process of accretion (as with a stalactite), where each steps enriches the results of the previous one. Unlike traditional views, which emphasize the multiplicity of software products -- analysis document, global and detailed design documents, program, maintenance reports... --, the principle is here to treat the software as a '''single product''' which will be repeatedly refined, extended and improved. The Eiffel programming language supports this view by providing high-level notations that can be used throughout the lifecycle, from the most general and software-independent activities of system modeling to the most exacting details of implementation tuned for optimal run-time performance.
These properties make Eiffel span the scope of both "object-oriented methods", with their associated notations such as UML and supporting CASE tools (whereas most such solutions do not yield an executable result), and "programming languages" (whereas most such languages are not suitable for design and analysis).
Additionally, within the EiffelStudio development environment, the concept of '''single product''' is extended to documents external to the software itself, by the [[Eiffel Information System|Eiffel Information System (EIS)]] which allows the linking elements of the software text to portions of external documents and vice versa.
==Seamlessness and reversibility==
The preceding ideas define the '''seamless approach''' embodied by Eiffel. With seamlessness goes '''reversibility''': the ability to go back, even late in the process, to earlier stages. Because the developers work on a single product, they can take advantages of bouts of late wisdom -- such as a great idea for adding a new function, discovered only at implementation time -- and integrate them in the product. Traditional approaches tend to discourage reversibility because it is difficult to guarantee that the analysis and design will be updated with the late changes. With the single-product principle, this is much easier to achieve.
Seamlessness and reversibility enhance extendibility by providing a direct mapping from the structure of the solution to the structure of the problem description, making it easier to take care of customers' change requests quickly and efficiently. They promote reliability, by avoiding possible misunderstandings between customers' and developers' views. They are a boost to maintainability. More generally, they yield a smooth, consistent software process that helps both quality and productivity.
==Generalization and reuse==
The last step of the cluster, Generalization, is unheard of in traditional models. Its task is to prepare the results of a cluster for reuse across projects by looking for elements of general applicability, and transform them for inclusion in libraries.
Recent object-oriented literature has used the term "refactoring" to describe a process of continuous improvement of released software. Generalization includes refactoring, but also pursues a more ambitious goal: helping turn program elements (software modules useful only as part of a certain program) into software components -- reusable parts with a value of their own, ready to be used by diverse programs that can benefit from their capabilities.
Of course not all companies using the method will be ready to include a Generalization phase in their. But those which do will see the reusability of their software greatly improved.
==Constant availability==
Complementing the preceding principles is the idea that, in the cluster lifecycle, the development team (under the responsibility of the project leader) should at all times maintain a current working demo which, although covering only a part of the final system, works well, and can be demonstrated or -- starting at a suitable time -- shipped as an early release. It is not a "prototype" in the sense of a meant to be thrown away, but an initial iteration towards the final product; the successive iterations will progress continuously towards until they become that final product.
==Compilation technology==
The preceding goals benefit from the ability to check frequently that the current iteration is correct and robust. Eiffel supports efficient compilation mechanisms through such mechanisms as the '''Melting Ice Technology''' in EiffelStudio. The Melting Ice achieves immediate recompilation after a change, guaranteeing a recompilation time that's a function of the size of the changes, not of the system's overall size. Even for a system of several thousand classes and several hundred thousand lines, the time to get restarted after a change to a few classes is, on a typical modern computer, a few seconds.
Such a "melt" (recompilation) will immediately catch (along with any syntax errors) the type errors -- often the symptoms of conceptual errors that, if left undetected, could cause grave damage later in the process or even during operation. Once the type errors have been corrected, the developers should start testing the new functionalities, relying on the power of '''assertions''' -- explained in [[ET: Design by Contract (tm), Assertions and Exceptions|"Design By Contract&#153; Assertions, Exceptions"]] -- to kill the bugs while they are still larvae. Such extensive unit and system testing, constantly interleaved with development, plays an important part in making sure that the "current demo" is trustworthy and will eventually yield a correct and robust product.
==Quality and functionality==
Throughout the process, the method suggests maintaining a constant '''quality''' level: apply all the style rules, put in all the assertions, handle erroneous cases (rather than the all too common practice of thinking that one will "make the product robust" later on), enforce the proper architecture. This applies to all the quality factors except possibly reusability (since one may not know ahead of time how best to generalize a component, and trying to make everything fully general may conflict with solving the specific problem at hand quickly). All that varies is '''functionality''': as the project progresses and clusters come into place, more and more of the final product's intended coverage becomes available. The project's most common question, "Can we ship something yet?", translates into "Do we cover enough?", not "Is it good enough?" (as in "Will it not crash?").
Of course not everyone using Eiffel can, any more than in another approach, guarantee that the ideal just presented will always hold. But it is theoretical scheme to which the method tends. It explains Eiffel's emphasis on getting everything right: the grandiose and the mundane, the structure and the details. Regarding the details, the Eiffel books cited in the bibliography include many rules, some petty at first sight, about such low-level aspects as the choice of names for classes and features (including their grammatical categories), the indentation of software texts, the style for comments (including the presence or absence of a final period), the use of spaces. Applying these rules does not, of course, guarantee quality; but they are part of a quality-oriented process, along with the more ambitious principles of design. In addition they are particularly important for the construction of quality libraries, one of the central goals of Eiffel.
Whenever they are compatible with the space constraints, the present chapter and the rest of this book apply these rules to their Eiffel examples.

View File

@@ -0,0 +1,76 @@
[[Property:title|ET: The Static Picture: System Organization]]
[[Property:weight|-11]]
[[Property:uuid|46d3f41e-d41c-a443-4574-403dfebb60aa]]
We now look at the overall organization of Eiffel software.
References to Eiffel Software's libraries appearing in subsequent examples include: '''EiffelBase''', the fundamental open-source library covering data structures and algorithms; the '''kernel library''', a subset of EiffelBase covering the most basic notions such as arrays and strings; and '''EiffelVision 2''', an advanced graphics and GUI library providing full compatibility across platforms (Unix, Windows, OpenVMS) with native look-and-feel on each.
==Systems==
An Eiffel system is a collection of classes, one of which is designated as the root class. One of the features of the root class, which must be one of its creation procedures, is designated as the root procedure.
To execute such a system is to create an instance of the root class (an object created according to the class description) and to execute the root procedure. In anything more significant than "Hello World" systems, this will create new objects and apply features to them, in turn triggering further creations and feature calls.
For the system to make sense, it must contains all the classes on which the root '''depends''' directly or indirectly. A class <code>B</code> depends on a class <code>A</code> if it is either a '''client''' of <code>A</code>, that is to say uses objects of type <code>A</code>, or an '''heir''' of <code>A</code>, that is to say extends or specializes <code>A</code>. (These two relations, client and inheritance, are covered below.)
==Classes==
The notion of class is central to the Eiffel approach. A class is the description of a type of run-time data structures (objects), characterized by common operations features) and properties. Examples of classes include:
* In a banking system, a class <code>ACCOUNT</code> may have features such as <code>deposit</code>, adding a certain amount to an account, <code>all_deposits</code>, yielding the list of deposits since the account's opening, and <code>balance</code>, yielding the current balance, with properties stating that <code>deposit</code> must add an element to the <code>all_deposits</code> list and update <code>balance</code> by adding the sum deposited, and that the current value of <code>balance</code> must be consistent with the lists of deposits and withdrawals.
* A class <code>COMMAND</code> in an interactive system of any kind may have features such as <code>execute</code> and <code>undo</code> , as well as a feature <code>undoable</code> which indicates whether a command can be undone, with the property that <code>undo</code> is only applicable if <code>undoable</code> yields the value true.
* A class <code>LINKED_LIST</code> may have features such as <code>put</code>, which adds an element to a list, and <code>count</code>, yielding the number of elements in the list, with properties stating that <code>put</code> increases <code>count</code> by one and that <code>count</code> is always non-negative.
We may characterize the first of these examples as an analysis class, directly modeling objects from the application domain; the second one as a design class, describing a high-level solution; and the third as an implementation class, reused whenever possible from a library such as EiffelBase. In Eiffel, however, there is no strict distinction between these categories; it is part of the approaches seamlessness that the same notion of class, and the associated concepts, may be used at all levels of the software development process.
==Class relations==
Two relations may exist between classes:
* You can define a class <code>C</code> as a '''client''' of a class <code>A</code> to enable the features of <code>C</code> to rely on objects of type <code>A</code>.
* You may define a class <code>B</code> as an '''heir''' of a class <code>A</code> to provide <code>B</code> with all the features and properties of <code>A</code>, letting <code>B</code> add its own features and properties and modify some of the inherited features if appropriate.
If <code>C</code> is a client of <code>A</code>, <code>A</code> is a '''supplier''' of <code>C</code>. If <code>B</code> is an heir of <code>A</code>, <code>A</code> is a '''parent''' of <code>B</code>. A '''descendant''' of <code>A</code> is either <code>A</code> itself or, recursively, a descendant of an heir of <code>A</code>; in more informal terms a descendant is a direct or indirect heir, or the class itself. To exclude <code>A</code> itself we talk of '''proper descendant'''. In the reverse direction the terms are '''ancestor''' and '''proper ancestor'''.
The client relation can be cyclic; an example involving a cycle would be classes <code>PERSON</code> and <code>HOUSE</code>, modeling the corresponding informal everyday "object" types and expressing the properties that every person has a home and every home has an architect. The inheritance (heir) relation may not include any cycle.
In modeling terms, client roughly represents the relation "has" and heir roughly represents "is". For example we may use Eiffel classes to model a certain system and express that every child <code>has</code> a birth date (client relation) and is a person (inheritance).
Distinctive of Eiffel is the rule that classes can only be connected through these two relations. This excludes the behind-the-scenes dependencies often found in other approaches, such as the use of global variables, which jeopardize the modularity of a system. Only through a strict policy of limited and explicit inter-class relations can we achieve the goals of reusability and extendibility.
==The global inheritance structure==
An Eiffel class that you write does not come into a vacuum but fits in a preordained structure, shown in the figure and involving two library classes: <code>ANY</code> and <code>NONE</code>.
[[Image:tutorial-4]]
Any class that does not explicitly inherit from another is considered to inherit from <code>ANY</code>, so that every class is a descendant, direct or indirect, of <code>ANY</code>. <code>ANY</code> introduces a number of general-purpose features useful everywhere, such as copying, cloning and equality testing operations (see [[ET: The Dynamic Structure: Execution Model|The Dynamic Structure: Execution Model]] ) and default input-output. The procedure <code>print</code> used in the first version of our "[[ET: Hello World|Hello World]]" comes from <code>ANY</code>.
<code>NONE</code> inherits from any class that has no explicit heir. Since inheritance has no cycles, <code>NONE</code> cannot have proper descendants. This makes it useful, as we will see, to specify non-exported features, and to denote the type of void values. Unlike <code>ANY</code>, class <code>NONE</code> doesn't have an actual class text; instead, it's a convenient fiction.
==Clusters==
Classes are the only form of module in Eiffel. As will be explained in more detail, they also provide the basis for the only form of type. This module-type identification is at the heart of object technology and of the fundamental simplicity of the Eiffel method.
Above classes, you will find the concept of cluster. A cluster is a group of related classes. Clusters are a property of the method, enabling managers to organize the development into teams. As we have already seen (in [[ET: The Software Process in Eiffel|The Software Process in Eiffel]] ) they also play a central role in the lifecycle model. Clusters are an organizational concept, not a form of module, and do not require an Eiffel programming language construct.
==External software==
The subsequent sections will show how to write Eiffel classes with their features. In an Eiffel system, however, not everything has to be written in Eiffel: some features may be '''external''' , coming from languages such as C, C++, Java, C# Fortran and others. For example a feature declaration may appear (in lieu of the forms seen later) as
<code>
file_status (filedesc: INTEGER): INTEGER
-- Status indicator for filedesc
external
"C" alias "_fstat"
end
</code>
to indicate that it is actually an encapsulation of a C function whose original name is <code>_fstat</code>. The <code>alias</code> clause is optional, but here it is needed because the C name, starting with an underscore, is not valid as an Eiffel identifier.
Similar syntax exists to interface with C++ classes. EiffelStudio includes a tool called Legacy++ which will automatically produce, from a C++ class, an Eiffel class that encapsulates its facilities, making them available to the rest of the Eiffel software as bona fide Eiffel features.
These mechanisms illustrate one of the roles of Eiffel: as an system architecturing and software composition tool, used at the highest level to produce systems with robust, flexible structures ready for extendibility, reusability and maintainability. In these structures not everything must be written in the Eiffel programming language: existing software elements and library components can play their part, with the structuring capabilities of Eiffel (classes, information hiding, inheritance, clusters, contracts and other techniques seen in this presentation) serving as the overall wrapping mechanism.

View File

@@ -0,0 +1,6 @@
[[Property:title|An Eiffel Tutorial (ET)]]
[[Property:link_title|Tutorial]]
[[Property:weight|2]]
[[Property:uuid|4dbc41e2-ecfc-8c50-9288-fce30f4abd90]]
This Eiffel Tutorial (ET) should provide you with a broad understanding of what Eiffel is all about and why it is different from other technologies. Still more detail is available in [[Object-Oriented Software Construction, 2nd Edition]].

View File

@@ -0,0 +1,13 @@
[[Property:title|Eiffel Tutorials]]
[[Property:link_title|Tutorials]]
[[Property:weight|2]]
[[Property:uuid|f443f10d-9dbc-4d6b-b9fb-c59af76abde9]]
== Tutorials about Eiffel ==
* [[Invitation to Eiffel (I2E)]]
* [[An Eiffel Tutorial (ET)]]
* [https://webcourses.inf.ethz.ch/se_courses/edx/eiffel_tutorial/] from Marco Piccioni
* ...
{{Note|Please, don't hesitate to comment this page to add link to other existing tutorials on the web.This list is for now far from being complete.}}

View File

@@ -0,0 +1,110 @@
[[Property:title|I2E: Classes]]
[[Property:weight|-11]]
[[Property:uuid|218bead9-428e-f61d-1e45-7eea4291d895]]
A class, it was said above, is an implementation of an abstract data type. This means that it describes a set of run-time objects, characterized by the ''' features''' (operations) applicable to them, and by the formal properties of these features.
Such objects are called the '''direct instances''' of the class. Classes and objects should not be confused: "class" is a compile-time notion, whereas objects only exist at run time. This is similar to the difference that exists in classical programming between a program and one execution of that program, or between a type and a run-time value of that type.
{{info|"Object-Oriented" is a misnomer; "Class-Oriented Analysis, Design and Programming" would be a more accurate description of the method. }}
To see what a class looks like, let us look at a simple example, <code>ACCOUNT</code>, which describes bank accounts. But before exploring the class itself it is useful to study how it may be used by other classes, called its '''clients'''.
A class <code>X</code> may become a client of <code>ACCOUNT</code> by declaring one or more '''entities''' of type <code>ACCOUNT</code>. Such a declaration is of the form:
<code>acc: ACCOUNT</code>
The term "entity" generalizes the more common notion of "variable". An entity declared of a reference type, such as <code>acc</code>, may at any time during execution become " '''attached to''' " an object; the type rules imply that this object must be a direct instance of <code>ACCOUNT</code> -- or, as seen below, of a "descendant" of that class.
[[Image:invitation-2]]
An entity is said to be void if it is not attached to any object. By default, entities are void at initialization. To obtain objects at run-time, a routine <code>r</code> appearing in the client class <code>X</code> may use a '''creation instruction''' of the form
<code>
create acc</code>
which creates a new direct instance of <code> ACCOUNT</code>, attaches <code>acc</code> to that instance, and initializes all its fields to default values. A variant of this notation, studied below, makes it possible to override the default initializations.
Once the client has attached <code>acc</code> to an object, it may call on this object the features defined in class <code>ACCOUNT</code>. Here is an extract with some feature calls using <code>acc</code> as their target:
<code>
acc.open ("Jill")
acc.deposit (5000)
if acc.may_withdraw (3000) then
acc.withdraw (3000)
print (acc.balance)
end
</code>
These feature calls use dot notation, of the form <code>target_name.feature_name</code>, possibly followed by a list of arguments in parentheses. Features are of two kinds:
* '''Routines''', such as <code>open</code>, <code>deposit</code>, <code>may_withdraw</code>, <code>withdraw</code>, represent computations applicable to instances of the class.
* '''Attributes''' represent data items associated with these instances.
Routines are further divided into '''procedures''' (commands, which do not return a value) and '''functions''' (queries, returning a value). Here <code>may_withdraw</code> is a function returning a boolean; the other three-routines called are procedures.
{{info|A note on syntax: you may separate instructions by semicolons, and indeed you should when, as on the next-to-last line of the example, two or more instructions appear on a line. But the language's syntax has been designed so that the semicolon is almost always optional, regardless of the layout. Indeed the practice is to omit it between instructions or declarations on separate lines, as this results in lighter, clearer software texts. }}
In class <code>ACCOUNT</code>, is feature <code>balance</code> an attribute, or is it a function with no argument? The above extract of the client class <code>X</code> doesn't say, and this ambiguity is intentional. A client of <code>ACCOUNT</code> must not need to know how class <code>ACCOUNT</code> delivers an account's balance when requested: by looking up a field present in each account object, or by calling a function that computes the balance from other fields. Choosing between these techniques is the business of class <code>ACCOUNT</code>, not anybody else's. Because such implementation choices are often changed over the lifetime of a project, it is essential to protect clients against their effects. This is known as the '''Uniform Access Principle''', stating that the choice between representing a property through memory (an attribute) or through an algorithm (function) shall not affect how clients use it.
So much for how client classes will typically use <code>ACCOUNT. </code> Below is a first sketch of how class <code>ACCOUNT</code> itself might look. Line segments beginning with <code>--</code> are comments. The class includes two <code>feature</code> clauses, introducing its features. The first begins with just the keyword <code>feature</code>, without further qualification; this means that the features declared in this clause are available (or "exported") to all clients of the class. The second clause is introduced by <code>feature {NONE}</code> to indicate that the feature that follows, called <code>add</code>, is available to no client. What appears between the braces is a list of client classes to which the corresponding features are available; <code>NONE</code> is a special class of the Kernel Library, which has no instances, so that <code>add</code> is in effect a secret feature, available only locally to the other routines of class <code>ACCOUNT</code>. So in a client class such as <code>X</code>, the call <code>acc.add ( -3000 )</code> would be invalid.
<code>
class
ACCOUNT
feature
balance: INTEGER
owner: PERSON
minimum_balance: INTEGER = 1000
open (who: PERSON)
-- Assign the account to owner who.
do
owner := who
end
deposit (sum: INTEGER)
-- Deposit sum into the account.
do
add (sum)
end
withdraw (sum: INTEGER)
-- Withdraw sum from the account.
do
add (-sum)
end
may_withdraw (sum: INTEGER): BOOLEAN
-- Is there enough money to withdraw sum?
do
Result := (balance >= sum + minimum_balance)
end
feature {NONE}
add (sum: INTEGER)
-- Add sum to the balance
do
balance := balance + sum
end
end -- ACCOUNT
</code>
Let us examine the features in sequence. The <code>do</code> <code>...</code> <code>end</code> distinguishes routines from attributes. So here the class has implemented <code>balance</code> as an attribute, although, as noted, a function would also have been acceptable. Feature <code>owner</code> is also an attribute.
The language definition guarantees automatic initialization, so that the initial balance of an account object will be zero after a creation instruction. Each type has a default initial value: zero for <code>INTEGER</code> and <code>REAL</code>, false for <code>BOOLEAN</code>, null character for <code>CHARACTER</code>, and a void reference for reference types. The class designer may also provide clients with different initialization options, as will be seen below in a revised version of this example.
The other public features, <code>withdraw, deposit, open,</code> and <code>may_withdraw</code> are straight-forward routines. The special entity <code>Result</code>, used in <code>may_withdraw</code>, denotes the function result; it is initialized on function entry to the default value of the function's result type. You may only use <code>Result</code> in functions.
The secret procedure <code>add</code> serves for the implementation of the public procedures <code>deposit</code> and <code>withdraw</code>; the designer of <code>ACCOUNT</code> judged it too general to be exported by itself. The clause "<code>= 1000</code>" introduces <code>minimum_balance</code> as a constant attribute, which will not occupy any space in instances of the class; in contrast, every instance has a field for every non-constant attribute such as <code>balance</code>.
In Eiffel's object-oriented programming style any operation is relative to a certain object. A client invoking the operation specifies this object by writing the corresponding entity on the left of the dot, as <code>acc</code> in <code>acc.open ("Jill")</code>. Within the class, however, the "current" instance to which operations apply usually remains implicit, so that unqualified feature names, such as <code>owner</code> in procedure <code>open</code> or <code>add</code> in <code> deposit</code>, mean "the <code>owner</code> attribute or <code>add</code> routine relative to the current instance".
If you need to denote the current object explicitly, you may use the special entity <code>Current</code>. For example the unqualified occurrences of <code>add</code> appearing in the class text above are equivalent to <code>Current</code>. <code>add</code>.
In some cases, infix or prefix notation will be more convenient than dot notation. For example, if a class <code>VECTOR</code> offers an addition routine, most people will feel more comfortable with calls of the form <code>v + w</code> than with the dot-notation call <code>v.plus (w)</code>. To make this possible it suffices to give the routine a "<code>+</code>" alias. The operation is still a normal routine call which can be invoked with either the infix form or the dot-notation.
The above simple example has shown the basic structuring mechanism of the language: the class. A class describes objects accessible to clients through an official interface comprising some of the class features. Features are implemented as attributes or routines; the implementation of exported features may rely on other, secret ones.

View File

@@ -0,0 +1,34 @@
[[Property:title|I2E: Combining Genericity and Inheritance]]
[[Property:weight|-3]]
[[Property:uuid|912e4c38-9add-e478-59c3-5c10aa75d784]]
Genericity and inheritance, the two fundamental mechanisms for generalizing classes, may be combined in two fruitful ways.
The first technique yields '''polymorphic data structures'''. Assume that in the generic class <code>LIST [G]</code> the insertion procedure <code>put</code> has a formal argument of type <code>G</code>, representing the element to be inserted. Then with a declaration such as
<code>
pl: LIST [POLYGON]</code>
the type rules imply that in a call <code>pl.put (p)</code> the permitted types for the argument <code>p</code> include not just <code>POLYGON</code>, but also <code>RECTANGLE</code> (an heir of <code>POLYGON</code>) or any other type conforming to <code>POLYGON</code> through inheritance.
The basic conformance requirement used here is the inheritance-based type compatibility rule: <code>V</code> conforms to <code>T</code> if <code>V</code> is a descendant of <code>T</code>.
Structures such as <code>pl</code> may contain objects of different types, hence the name "polymorphic data structure". Such polymorphism is, again, made safe by the type rules: by choosing an actual generic parameter ( <code>POLYGON</code> in the example) based higher or lower in the inheritance graph, you extend or restrict the permissible types of objects in <code>pl</code>. A fully general list would be declared as
<code>
LIST [ANY]</code>
where <code>ANY</code>, a Kernel Library class, is automatically an ancestor of any class that you may write.
The other mechanism for combining genericity and inheritance is '''constrained genericity'''. By indicating a class name after a formal generic parameter, as in
<code>
VECTOR [T -> NUMERIC]</code>
you express that only descendants of that class (here <code>NUMERIC</code>) may be used as the corresponding actual generic parameters. This makes it possible to use the corresponding operations. Here, for example, class <code>VECTOR</code> may define a routine <code>infix</code> "+" for adding vectors, based on the corresponding routine from <code>NUMERIC</code> for adding vector elements. Then by making <code>VECTOR</code> itself inherit from <code>NUMERIC</code>, you ensure that it satisfies its own generic constraint and enable the definition of types such as <code>VECTOR [VECTOR [T]]</code> .
As you have perhaps guessed, unconstrained genericity, as in <code>LIST [G]</code> , may be viewed as an abbreviation for genericity constrained by <code>ANY</code>, as in
<code>
LIST [G -> ANY]</code>
Something else you may have guessed: if <code>ANY</code>, introduced in this session, is the top of the inheritance structure -- providing all classes with universal features such as <code>equal</code> to compare arbitrary objects and <code>twin</code> to duplicate objects -- then <code>NONE</code>, seen earlier in the notation <code>feature {NONE}</code>, is its bottom. <code>NONE</code> indeed conceptually inherits from all other classes. <code>NONE</code> is, among other things, the perceived type of the <code>Void</code> keyword which represents a void reference.

View File

@@ -0,0 +1,64 @@
[[Property:title|I2E: Deferred Classes and Seamless Development]]
[[Property:weight|-2]]
[[Property:uuid|b3264238-f160-a6fc-0b03-adcd80b1f55a]]
The inheritance mechanism includes one more major notion: deferred features and classes.
Declaring a feature <code>f</code> as deferred in a class <code>C</code> expresses that there is no default implementation of <code>f</code> in <code>C</code>; such implementations will appear in eventual descendants of <code>C</code>. A class that has one or more deferred routines is itself said to be deferred. A non-deferred routine or class -- like all those seen until now -- is said to be '''effective'''.
For example, a system used by a Department of Motor Vehicles to register vehicles might include a class of the form
<code>
deferred class
VEHICLE
feature
dues_paid (year: INTEGER): BOOLEAN
do ... end
valid_plate (year: INTEGER): BOOLEAN
do ... end
register (year: INTEGER)
-- Register vehicle for year.
require
dues_paid (year)
deferred
ensure
valid_plate (year)
end
... Other features, deferred or effective ...
end -- VEHICLE
</code>
This example assumes that no single registration algorithm applies to all kinds of vehicle; passenger cars, motorcycles, trucks etc. are all registered differently. But the same precondition and postcondition apply in all cases. The solution is to treat register as a deferred routine, making VEHICLE a deferred class. Descendants of class VEHICLE, such as CAR or TRUCK, effect this routine, that is to say, give effective versions. An effecting is similar to a redefinition; only here there is no effective definition in the original class, just a specification in the form of a deferred routine. The term '''redeclaration''' covers both redefinition and effecting.
[[Image:invitation-5]]
Whereas an effective class described an implementation of an abstract data types, a deferred class describes a set of possible implementations. You may not instantiate a deferred class: create v is invalid if v is declared of type VEHICLE. But you may assign to v a reference to an instance of an effective descendant of VEHICLE. For example, assuming CAR and TRUCK provide effective definitions for all deferred routines of VEHICLE, the following will be valid:
<code>
v: VEHICLE
c: CAR
t: TRUCK
...
create c
create t
...
if "Some test" then
v := c
else
v := t
end
v.register (2008)</code>
This example fully exploits polymorphism: depending on the outcome of "Some test", <code>v</code> will be treated as a car or a truck, and the appropriate registration algorithm will be applied. Also, "Some test" may depend on some event whose outcome is impossible to predict until run-time, for example the user clicking with the mouse to select one among several vehicle icons displayed on the screen.
Deferred classes are particularly useful at the design stage. The first version of a module may be a deferred class, which will later be refined into one or more effective classes. Eiffel's Design by Contract&#153; mechanisms are essential here: you may a precondition and a postcondition with a routine even though it is a deferred routine (as with register above), and an invariant with a class even though it is a deferred class. This enables you, as a designer, to attach precise semantics to a module at the design stage long before you will make any implementation choices.
Beyond design and implementation, these techniques extend to the earliest stage of development, analysis. Deferred classes written at that stage describe not software objects, but objects from the external world being modeled -- documents, airplanes, investments. Here again the presence of contracts to express constraints, and the language's other structuring facilities, provide an attractive combination.
Eiffel appears here in its full role of a lifecycle approach, covering areas traditionally considered separate: program implementation, the traditional province of development environments; system modeling and architecture, the traditional province of CASE tools based on UML or similar notations disconnected from the rest of the lifecycle. Eiffel instead emphasizes the fundamental unity of the software process and the usefulness of a single set of notations, concepts and tools applicable throughout. Such a seamless approach is indispensable to support the inevitable reversals that occur during the process of building software, such as detecting at implementation time a problem that leads to a change in the system's functionality, set at analysis time. The use of separate tools and notations, such as UML on one side and a programming language on the other, makes such round-trips difficult at best and often leads to monolithic, hard-to-change software. Eiffel lets you focus on the issues, without interposing artificial barriers between different software development activities. You'll use the fundamental problem-solving techniques -- data abstraction through classes, precise specification through contracts, modularity through information hiding, rational organization through inheritance, decentralized architecture through dynamic binding, parameterization of the solution through genericity, reusability through all these techniques -- all along; only the level of abstraction changes.

View File

@@ -0,0 +1,150 @@
[[Property:title|I2E: Design by Contract and Assertions]]
[[Property:weight|-9]]
[[Property:uuid|f563aa75-3a5a-5110-b4f1-07da5448f668]]
If classes are to deserve their definition as abstract data type implementations, they must be known not just by the available operations, but also by the formal properties of these operations, which did not yet appear in the preceding example.
==The role of assertions==
Eiffel encourages software developers to express formal properties of classes by writing '''assertions''', which may in particular appear in the following roles: <br/>
* Routine '''preconditions''' express the requirements that clients must satisfy whenever they call a routine. For example the designer of <code>ACCOUNT</code> may wish to permit a withdrawal operation only if it keeps the account's balance at or above the minimum. Preconditions are introduced by the keyword <code>require</code>.
* Routine '''postconditions''', introduced by the keyword <code>ensure</code>, express conditions that the routine (the supplier) guarantees on return, if the precondition was satisfied on entry.
* A class '''invariant''' must be satisfied by every instance of the class whenever the instance is externally accessible: after creation, and after any call to an exported routine of the class. The invariant appears in a clause introduced by the keyword <code>invariant</code>, and represents a general consistency constraint imposed on all routines of the class.
With appropriate assertions, the class <code>ACCOUNT</code> becomes:
<code>
class
ACCOUNT
create
make
feature
... Attributes as before:
balance , minimum_balance , owner , open ...
deposit (sum: INTEGER)
-- Deposit sum into the account.
require
sum >= 0
do
add (sum)
ensure
balance = old balance + sum
end
withdraw (sum: INTEGER)
-- Withdraw sum from the account.
require
sum >= 0
sum <= balance - minimum_balance
do
add (-sum)
ensure
balance = old balance - sum
end
may_withdraw ... -- As before
feature {NONE}
add ...
make (initial: INTEGER)
-- Initialize account with balance initial.
require
initial >= minimum_balance
do
balance := initial
end
invariant
balance >= minimum_balance
end -- ACCOUNT
</code>
The notation <code>old</code> <code>expression</code> is only valid in a routine postcondition. It denotes the value the <code>expression</code> had on routine entry.
==Creation procedures==
In its last version above, the class now includes a creation procedure, <code>make</code>. With the first version, clients used creation instructions such as <code>create </code> <code>acc1</code> to create accounts; but then the default initialization, setting balance to zero, violated the invariant. By having one or more creation procedures, listed in the <code>create</code> clause at the beginning of the class text, a class offers a way to override the default initializations. The effect of
<code>
create acc1.make (5_500)</code>
is to allocate the object (as with the default creation) and to call procedure <code>make</code> on this object, with the argument given. This call is correct since it satisfies the precondition; it will ensure the invariant.
{{info|The underscore <code>_</code> in the integer constant ''5_500'' has no semantic effect. The general rule is that you can group digits by sets of three from the right to improve the readability of integer constants. }}
Note that the same keyword, <code>create</code>, serves both to introduce creation instructions and the creation clause listing creation procedures at the beginning of the class.
A procedure listed in the creation clause, such as <code>make</code>, otherwise enjoys the same properties as other routines, especially for calls. Here the procedure <code>make</code> is secret since it appears in a clause starting with
<code>
feature {NONE}</code>
so it would be invalid for a client to include a call such as
<code>
acc.make (8_000)</code>
To make such a call valid, it would suffice to move the declaration of <code>make</code> to the first <code>feature</code> clause of class <code>ACCOUNT</code>, which carries no export restriction. Such a call does not create any new object, but simply resets the balance of a previously created account.
==Design by Contract&#153;==
Syntactically, assertions are boolean expressions, with a few extensions such as the <code>old </code>notation. Also, you may split an assertion into two or more clauses, as here with the precondition of <code>withdraw</code>; this is as if you had separated the clauses with an <code>and</code>, but makes the assertion clearer, especially if it includes many conditions.
Assertions play a central part in the Eiffel method for building reliable object-oriented software. They serve to make explicit the assumptions on which programmers rely when they write software elements that they believe are correct. Writing assertions amounts to spelling out the terms of the '''contract''' which governs the relationship between a routine and its callers. The precondition binds the callers; the postcondition binds the routine.
The underlying theory of Design by Contract&#153;, the centerpiece of the Eiffel method, views software construction as based on contracts between clients (callers) and suppliers (routines), relying on mutual obligations and benefits made explicit by the assertions.
==The Contract Form==
Assertions are also an indispensable tool for the documentation of reusable software components: one cannot expect large-scale reuse without a precise documentation of what every component expects (precondition), what it guarantees in return (postcondition) and what general conditions it maintains (invariant).
Documentation tools in EiffelStudio use assertions to produce information for client programmers, describing classes in terms of observable behavior, not implementation. In particular the '''Contract Form''' of a class, also called its "short form", which serves as its interface documentation, is obtained from the full text by removing all non-exported features and all implementation information such as <code>do</code> clauses of routines, but keeping interface information and in particular assertions. Here is the Contract Form of the above class:
<code>
class interface ACCOUNT
create
make
feature
balance: INTEGER
...
deposit (sum: INTEGER)
-- Deposit sum into the account.
require
sum >= 0
ensure
balance = old balance + sum
withdraw (sum: INTEGER)
-- Withdraw sum from the account.
require
sum >= 0
sum <= balance - minimum_balance
ensure
balance = old balance - sum
may_withdraw ...
end -- ACCOUNT
</code>
This is not actual Eiffel, only documentation of Eiffel classes, hence the use of slightly different syntax to avoid any confusion ( <code>interface class</code> rather than <code>class</code>). In accordance with the Uniform Access Principle (in [[I2E: Classes|Classes]]), the output for <code>balance</code> would be the same if this feature were a function rather than an attribute.
You will find in EiffelStudio automatic tools to produce the Contract Form of a class. You can also get the '''Flat Contract''' form, based on the same ideas but including inherited features along with those introduced in the class itself. EiffelStudio can produce these forms, and other documentation views of a class, in a variety of output formats including HTML, so that collaborative projects can automatically post the latest versions of their class interfaces on the Internet or an Intranet.
==Contracts for testing and debugging==
Under EiffelStudio you may also set up compilation options, for the whole system or specific classes only, to evaluate assertions at run time, to uncover potential errors ("bugs"). EiffelStudio provides several levels of assertion monitoring: preconditions only, postconditions etc. When monitoring is on, an assertion which evaluates to true has no further effect on the execution. An assertion that evaluates to false will trigger an exception, as described next; unless you have written an appropriate exception handler, the exception will cause an error message and termination with a precise message and a call trace.
This ability to check assertions provides a powerful testing and debugging mechanism, in particular because the classes of the EiffelBase Libraries, widely used in Eiffel software development, are protected by carefully written assertions.
Run-time monitoring, however, is only one application of assertions, whose role as design and documentation aids, as part of the theory of Design by Contract&#153;, exerts a pervasive influence on the Eiffel style of software development.

View File

@@ -0,0 +1,22 @@
[[Property:title|I2E: Design Principles]]
[[Property:weight|-13]]
[[Property:uuid|529659bd-ec13-5805-87f2-2fd9318ad442]]
The aim of Eiffel is to help specify, design, implement and modify quality software. This goal of quality in software is a combination of many factors; the language design concentrated on the three factors which, in the current state of the industry, are in direct need of improvements: reusability, extendibility and reliability. Also important were other factors such as efficiency, openness and portability.
'''Reusability''' is the ability to produce components that may serve in many different applications. Central to the Eiffel approach is the presence of predefined libraries such as EiffelBase, and the language's support for the production of new libraries.
'''Extendibility''' is the ability to produce easily modifiable software. "Soft" as software is supposed to be, it is notoriously hard to modify software systems, especially large ones.
Among quality factors, reusability and extendibility play a special role: satisfying them means having less software to write -- and hence more time to devote to other important goals such as efficiency, ease of use or integrity.
The third fundamental factor is '''reliability, ''' the ability to produce software that is correct and robust -- that is to say, bug-free. Eiffel techniques such as static typing, assertions, disciplined exception handling and automatic garbage collection are essential here.
Three other factors are also part of Eiffel's principal goals: <br/>
* The language enables implementers to produce high '''efficiency''' compilers, so that systems developed with Professional Eiffel may run under speed and space conditions similar to those of programs written in lower-level languages.
* Ensuring '''openness''', so that Eiffel software may cooperate with programs written in other languages.
* Guaranteeing '''portability''' by a platform-independent language definition, so that the same semantics may be supported on many different platforms.

View File

@@ -0,0 +1,42 @@
[[Property:title|I2E: Event-Driven Programming and Agents]]
[[Property:weight|-7]]
[[Property:uuid|16fdab60-ae42-1bb8-f4bb-89e34d18a842]]
The division of roles in object technology is clear: of the two principal constituents of a system, object types and operations, the first dominates. Classes, representing object types, determines the structure of the software; every routine, representing an operation, belongs to a class.
In some circumstances it is useful to define an object that denotes an operation. This is especially useful if you want to build an object structure that refers to operations, so that you can later traverse the structure and execute the operations encountered. A typical application is '''event-driven programming''' for Graphical User Interfaces (GUI), including Web programming. In GUI programming you will want to record properties of the form
<code>
"When the user clicks this OK button, the system must update the file"
</code>
each involves a '''control''' (here the OK button), an '''event''' (mouse click) and an '''operation''' (update the file). This can be programmed by having an "event loop", triggered for each event, which performs massive decision-making (<code>if "The latest event was `left mouse click on button 23'" then "Appropriate instructions" else if </code>... and so on with many branches); but this leads to bulky software architectures where introducing any new control or event requires updating a central part of the code. It's preferable to let any element of the system that encounters a new control-event-operation association
<code>
[control, event, operation]
</code>
store it as a triple of objects into an object structure, such as an array or a list. Triples in that structure may come from different parts of the system; there is no central know-it-all structure. The only central element is a simple mechanism which can explore the object structure to execute each <code>operation</code> associated with a certain <code>control</code> and a certain <code>event</code>. The mechanism is not just simple; it's also independent of your application, since it doesn't need to know about any particular control, event or operation (it will find them in the object structure). So it can be programmed once and for all, as part of a library such as EiffelVision 2 for platform-independent graphics.
To build an object structure, we need objects. A <code>control</code>, an <code>event</code> are indeed objects. But an <code>operation</code> is not: it's program code -- a routine of a certain class.
Agents address this issue. An agent is an object that represents a routine, which can then be kept in an object structure. The simplest form of agent is written <code>agent r</code>, where <code>r</code> is a routine. This denotes an object. If <code>your_agent</code> is such an agent object, the call
<code>
your_agent.call ([a, b])
</code>
where <code>a</code> and <code>b</code> are valid arguments for <code>r</code>, will have the same effect as a direct call to <code>r</code> with arguments <code>a</code> and <code>b</code>. Of course, if you know that you want to call <code>r</code> with those arguments, you don't need any agents; just use the direct call <code>r (a, b)</code>. The benefit of using an agent is that you can store it into an object structure to be called '''later''', for example when an event-driven mechanism finds the agent in the object structure, associated with a certain control and a certain event. For this reason agents are also called '''delayed calls'''.
{{info|The notation <code>[a, b]</code> denotes a sequence of elements, or '''tuple'''. The reason <code>call</code> needs a tuple as argument, whereas the direct call <code>r (a, b)</code> doesn't, is that <code>call</code> is a general routine (from the EiffelBase class <code>ROUTINE</code>, representing agents) applicable to any agent, whereas the direct call refers explicitly to <code>r</code> and hence requires arguments <code>a</code> and <code>b</code> of specific types. The agent mechanism, however, is statically typed like the rest of the language; when you call <code>call</code>, the type checking mechanism ensures that the tuple you pass as argument contains elements <code>a</code> and <code>b</code> of the appropriate types. }}
A typical use of agents with EiffelVision 2 is
<code>
ok_button.select_actions.extend (agent your_routine)</code>
which says: "add <code>your_routine</code> to the list of operations to be performed whenever a <code>select</code> event (left click) happens on <code>ok_button</code>". <code>ok_button.select_actions</code> is the list of agents associated with the button and the event; in list classes, procedure <code>extend</code> adds an item at the end of a list. Here, the object to be added is the agent.
This enables the EiffelVision 2 event-handling mechanism to find the appropriate agent when it processes an event, and call <code>call</code> on that agent to trigger the appropriate routine. EiffelVision 2 doesn't know that it's <code>your_routine</code>; in fact, it doesn't know anything about your application. It simply finds an agent in the list, and calls <code>call</code> on it. For your part, as the author of a graphical application, you don't need to know how EiffelVision 2 handles events; you simply associate the desired agents with the desired controls and events, and let EiffelVision 2 do the rest.
Agents extend to many areas beyond GUIs. In '''numerical computation''', you may use an agent to pass to an "integrator" object a numerical function to be integrated over a certain interval. In yet another area, you can use agents (as in the iteration library of EiffelBase) to program '''iterators''' : mechanisms that repetitively apply an arbitrary operation -- represented by an agent -- to every element of a list, tree or other object structure. More generally, agent embody properties of the associated routines, opening the way to mechanism for '''reflection''', also called "introspection": the ability, during software execution, to discover properties of the software itself.

View File

@@ -0,0 +1,47 @@
[[Property:title|I2E: Exceptions]]
[[Property:weight|-8]]
[[Property:uuid|e3e10dac-0dd7-bbe1-240c-6a6985c7376a]]
Whenever there is a contract, the risk exists that someone will break it. This is where exceptions come in.
Exceptions -- contract violations -- may arise from several causes. One is an assertion violation, if you've selected run-time assertion monitoring. Another is a signal triggered by the hardware or operating system to indicate an abnormal condition such as arithmetic overflow, or an attempt to create a new object when there's not enough memory available.
Unless a routine has made specific provision to handle exceptions, it will '''fail''' if an exception arises during its execution. This in turn provides one more source of exceptions: a routine that fails triggers an exception in its caller.
A routine may, however, handle an exception through a <code>rescue</code> clause. This optional clause attempts to "patch things up" by bringing the current object to a stable state (one satisfying the class invariant). Then it can terminate in either of two ways:<br/>
* The <code>rescue</code> clause may execute a <code>retry</code> instruction, which causes the routine to restart its execution from the beginning, attempting again to fulfill its contract, usually through another strategy. This assumes that the instructions of the <code>rescue</code> clause, before the <code>retry</code>, have attempted to correct the cause of the exception.
* If the <code>rescue</code> clause does not end with <code>retry</code>, then the routine fails: it returns to its caller, immediately triggering an exception. (The caller's <code>rescue</code> clause will be executed according to the same rules.)
The principle is that '''a routine must either succeed or fail''': it either fulfills its contract, or not; in the latter case it must notify its caller by triggering an exception.
Usually, only a few routines of a system will explicitly include a <code>rescue </code>clause. A routine that doesn't have an explicit <code>rescue</code> is considered to have an implicit one, which calls a routine <code>default_rescue</code> that by default does nothing, so that an exception will cause the routine to fail immediately, propagating the exception to the caller.
An example using the exception mechanism is a routine <code>attempt_transmission</code> that tries to transmit a message over a phone line. The actual transmission is performed by an external, low-level routine <code>transmit</code>; once started, however, <code>transmit</code> may abruptly fail, triggering an exception, if the line is disconnected. Routine <code>attempt_transmission</code> tries the transmission at most 50 times; before returning to its caller, it sets a boolean attribute <code>successful</code> to <code>True</code> or <code>False</code> depending on the outcome. Here is the text of the routine:
<code>
attempt_transmission (message: STRING)
-- Try to transmit message, at most 50 times.
-- Set successful accordingly.
local
failures: INTEGER
do
if failures < 50 then
transmit (message)
successful := True
else
successful := False
end
rescue
failures := failures + 1
retry
end
</code>
Initialization rules ensure that <code>failures</code>, a local entity, is set to zero on entry.
This example illustrates the simplicity of the mechanism: the <code>rescue</code> clause never attempts to achieve the routine's original intent; this is the sole responsibility of the body (the <code>do</code> clause). The only role of the <code>rescue</code> clause is to clean up the objects involved, and then either to fail or to retry.
This disciplined exception mechanism is essential for software developers, who need protection against unexpected events, but cannot be expected to sacrifice safety and simplicity to pay for this protection.

View File

@@ -0,0 +1,28 @@
[[Property:title|I2E: Genericity]]
[[Property:weight|-6]]
[[Property:uuid|091c0b65-73de-b454-b3f2-d8752983780e]]
Building software components (classes) as implementations of abstract data types yields systems with a solid architecture but does not in itself ensure reusability and extendibility. Two key techniques address the problem: genericity (unconstrained or constrained) and inheritance. Let us look first at the unconstrained form.
To make a class generic is to give it '''formal generic parameters''' representing as unknown types, as in these examples from EiffelBase, an open-source library covering basic data structures and algorithms:
<code>
ARRAY [G]
LIST [G]
LINKED_LIST [G]</code>
These classes describe data structures -- arrays, lists without commitment to a specific representation, lists in linked representation -- containing objects of a certain type. The formal generic parameter <code>G</code> denotes this type.
A class such as these doesn't quite yet describe a type, but a type template, since <code> G </code> itself denotes an unknown type. To derive a directly usable list or array type, you must provide a type corresponding to <code>G</code>, called an '''actual generic parameter'''; this may be either an expanded type, including basic types such as <code>INTEGER</code>, or a reference type. Here are some possible generic derivations:
<code>
il: LIST [INTEGER]
aa: ARRAY [ACCOUNT]
aal: LIST [ARRAY [ACCOUNT]]</code>
As the last example indicates, an actual generic parameter may itself be generically derived.
It would not be possible, without genericity, to have static type checking in a realistic object-oriented language.
A variant of this mechanism, constrained genericity, will enable a class to place specific requirements on possible actual generic parameters. Constrained genericity will be described after inheritance.

View File

@@ -0,0 +1,72 @@
[[Property:title|I2E: Inheritance]]
[[Property:weight|-5]]
[[Property:uuid|acf84989-0e7c-f2f7-427a-19e7fce404ce]]
Inheritance, the other fundamental generalization mechanism, makes it possible to define a new class by combination and specialization of existing classes rather than from scratch.
The following simple example, from the Data Structure Library in EiffelBase, is typical. <code>LIST</code>, as noted, describes lists in any representation. One such representation if the lists have a fixed number of elements uses an array. We may define the corresponding class by combination of <code>LIST</code> and <code>ARRAY</code>, as follows:
<code>
class ARRAYED_LIST [G]
inherit
LIST [G]
ARRAY [G]
export ... See below ... end
feature
... Specific features of fixed-size lists ...
end -- ARRAYED_LIST
</code>
The <code>inherit</code> ... clause lists all the "parents" of the new class, which is said to be their "heir". (The "ancestors" of a class include the class itself, its parents, grandparents etc.; the reverse term is "descendant".) Declaring <code>ARRAYED_LIST</code> as shown ensures that all the features and properties of lists and arrays are applicable to arrayed lists as well. Since the class has more than one parent, this is a case of multiple inheritance.
Standard graphical conventions -- drawn from the Business Object Notation or BON, a graphical object-oriented notation based on concepts close to those of Eiffel, and directly supported by EiffelStudio -- illustrate such inheritance structures:
[[Image:invitation-4]]
An heir class such as <code>ARRAYED_LIST</code> needs the ability to define its own export policy. By default, inherited features keep their export status (publicly available, secret, available to selected classes only); but this may be changed in the heir. Here, for example, <code>ARRAYED_LIST</code> will export only the exported features of <code>LIST</code>, making those of <code>ARRAY</code> unavailable directly to <code>ARRAYED_LIST</code> 's clients. The syntax to achieve this is straightforward:
<code>
class ARRAYED_LIST [G]
inherit
LIST [G]
ARRAY [G]
export {NONE} all end
... The rest as above ...
</code>
Another example of multiple inheritance comes from a windowing system based on a class <code>WINDOW</code>, close to actual classes in EiffelVision 2. Windows have '''graphical''' features: a height, a width, a position, routines to scale windows, move them, and other graphical operations. The system permits windows to be nested, so that a window also has '''hierarchical''' features: access to sub windows and the parent window, adding a sub window, deleting a sub window, attaching to another parent and so on. Rather than writing complex class that would contain specific implementations for all of these features, it is preferable to inherit all hierarchical features from <code>TREE</code> (a class in EiffelBase describing trees), and all graphical features from a class <code>RECTANGLE</code>.
Inheritance complements the "client" relation by providing another form of reuse that yields remarkable economies of effort -- for analysis, design, implementation, evolution -- and has a profound effect on the entire software development process.
The very power of inheritance demands adequate means to keep it under control. Multiple inheritance, in particular, raises the question of name conflicts between features inherited from different parents; this case will inevitably arise in practice, especially for classes contributed by independent developers. You may remove such a name conflict through '''renaming''', as in
<code>
class C
inherit
A
rename
x as x1,
y as y1
end
B
rename
x as x2,
y as y2
end
feature ...
</code>
Here, if both <code>A</code> and <code>B</code> have features named <code>x</code> and <code>y</code>, class <code>C</code> would be invalid without the renaming.
Renaming also serves to provide more appropriate feature names in descendants. For example, class <code>WINDOW</code> may inherit a routine <code>insert_subtree</code> from <code>TREE</code>. For clients of <code>WINDOW</code>, however, such a routine name is no longer appropriate. An application that uses this class needs coherent window terminology, and should have to concern itself with the inheritance structure that led to the class. So you may wish to rename <code>insert_subtree</code> as <code>add_subwindow</code> in the inheritance clause of <code>WINDOW</code>.
As a further protection against misusing multiple inheritance, the invariants of all parent classes automatically apply to a newly defined class. So classes may not be combined if their invariants are incompatible.

View File

@@ -0,0 +1,37 @@
[[Property:title|I2E: Invitation to Eiffel Copyright]]
[[Property:weight|0]]
[[Property:uuid|ce7b4af4-b669-9fec-92e1-c24c4f089336]]
Title: Invitation to Eiffel, Eiffel Software Technical Report TR-EI-67/IV.
==Publication history==
First published 1987. Some revisions (in particular Web versions) have used the title "Eiffel in a Nutshell" <br/>
This version: July 2001. Introduces coverage of agents; several other improvements. Corresponds to release 5.0 of the EiffelStudio environment.
==Author==
Bertrand Meyer
==Software Credits==
See acknowledgments in book ''[[Eiffel: The Language]]''.
==Cover Design==
Rich Ayling.
==Copyright notice and proprietary information==
Copyright Interactive Software Engineering Inc. (Eiffel Software), 2001. May not be reproduced in any form (including electronic storage) without the written permission of Eiffel Software . "Eiffel Power" and the Eiffel Power logo are trademarks of Eiffel Software . All uses of the product documented here are subject to the terms and conditions of the Eiffel Software Eiffel user license. Any other use or duplication is a violation of the applicable laws on copyright, trade secrets and intellectual property.
==Special duplication permission for educational institutions==
Degree-granting educational institutions using Eiffel Software Eiffel for teaching purposes as part of the [http://www.eiffel.com/educators/resources.html Eiffel University Partnership Program] may be permitted under certain conditions to copy specific parts of this book. Contact Eiffel Software for details.
{{info|About Eiffel Software (Interactive Software Engineering) helps you produce software better, faster and cheaper. Eiffel Software provides a wide range of products and services based on object technology, including Eiffel Software Eiffel, a complete development environment for the full system life cycle. Eiffel Software's training courses, available worldwide, cover key management and technical topics. Eiffel Software's consultants are available to address your project needs at all levels. Eiffel Software's TOOLS (Technology of Object-Oriented Languages and Systems) conferences, [http://www.tools-conferences.com http://www.tools-conferences.com] , are the meeting point for anyone interested in the software technologies of the future. Eiffel Software originated one of the earliest . NET products and offers a full range of . NET services and training at [http://www.dotnetexperts.com http://www.dotnetexperts.com] . }}
==For more information==
Interactive Software Engineering Inc. <br/>
Eiffel Software Building, <br/>
356 Storke Road, <br/>
Goleta, <br/>
CA, 93117 <br/>
USA. <br/>
<br/>
Telephone 805-685-1006, <br/>
Fax 805-685-6869
==Internet and email==
Eiffel Software maintains a rich source of information at [http://eiffel.com http://eiffel.com] , with more than 1200 Web pages including online documentation, downloadable files, product descriptions, links to Eiffel Software partners, University Partnership program, mailing list archives, announcements, press coverage, Frequently Asked Questions, Support pages, and much more. Visit [http://www.eiffel.com/general/contact_details.html http://www.eiffel.com/general/contact_details.html] to request information about products and services. To subscribe to the Eiffel Software Eiffel user list, go to [http://groups.eiffel.com/join http://groups.eiffel.com/join] .
==Support programs==
Eiffel Software offers a variety of support options tailored to the diverse needs of its customers. See [http://support.eiffel.com http://support.eiffel.com] for details.

View File

@@ -0,0 +1,25 @@
[[Property:title|I2E: Object-Oriented Design]]
[[Property:weight|-12]]
[[Property:uuid|e0a1f24e-5dd7-e5f8-8be8-8da32cc6a91c]]
To achieve reusability, extendibility and reliability, the principles of object-oriented design provide the best known technical answer.
An in-depth discussion of these principles fall beyond the scope of this introduction but here is a short definition:
{{info|Object-oriented design is the construction of software systems as structured collections of abstract data type implementations, or "classes". }}
The following points are worth noting in this definition:<br/>
* The emphasis is on structuring a system around the types of objects it manipulates (not the functions it performs on them) and on reusing whole data structures together with the associated operations (not isolated routines).
* Objects are described as instances of abstract data types -- that is to say, data structures known from an official interface rather than through their representation.
* The basic modular unit, called the class, describes one implementation of an abstract data type (or, in the case of "deferred" classes, as studied below, a set of possible implementations of the same abstract data type).
* The word ''collection'' reflects how classes should be designed: as units which are interesting and useful on their own, independently of the systems to which they belong, and may be reused by many different systems. Software construction is viewed as the assembly of existing classes, not as a top-down process starting from scratch.
* Finally, the word ''structured'' reflects the existence of two important relations between classes: the client and inheritance relations.
Eiffel makes these techniques available to developers in a simple and practical way.
As a language, Eiffel includes more than presented in this introduction, but not much more; it is a small language, not much bigger (by such a measure as the number of keywords) than Pascal. It was meant to be a member of the class of languages which programmers can master entirely -- as opposed to languages of which most programmers know only a subset. Yet it is appropriate for the development of industrial software systems, as has by now been shown by many full-scale projects, some in the thousands of classes and hundreds of thousands of lines, in companies around the world.

View File

@@ -0,0 +1,71 @@
[[Property:title|I2E: Polymorphism and Dynamic Binding]]
[[Property:weight|-4]]
[[Property:uuid|1c3221be-0237-1c9a-407d-652a4084de12]]
Inheritance is not just a module combination and enrichment mechanism. It also enables the definition of flexible entities that may become attached to objects of various forms at run time, a property known as polymorphism.
This remarkable facility must be reconciled with static typing. The language convention is simple: an assignment of the form <code>a : = b</code> is permitted not only if <code>a</code> and <code>b</code> are of the same type, but more generally if <code>a</code> and <code>b</code> are of reference types <code>A</code> and <code>B</code>, based on classes <code>A</code> and <code>B</code> such that <code>B</code> is a descendant of <code>A</code>.
This corresponds to the intuitive idea that a value of a more specialized type may be assigned to an entity of a less specialized type -- but not the reverse. (As an analogy, consider that if you request vegetables, getting green vegetables is fine, but if you ask for green vegetables, receiving a dish labeled just "vegetables" is not acceptable, as it could include, say, carrots.)
What makes this possibility particularly powerful is the complementary facility: '''feature redefinition'''. A class may redefine some or all of the features which it inherits from its parents. For an attribute or function, the redefinition may affect the type, replacing the original by a descendant; for a routine it may also affect the implementation, replacing the original routine body by a new one.
Assume for example a class <code>POLYGON</code>, describing polygons, whose features include an array of points representing the vertices and a function <code>perimeter</code> which computes a polygon's perimeter by summing the successive distances between adjacent vertices. An heir of <code>POLYGON</code> may begin as:
<code>
class RECTANGLE
inherit
POLYGON
redefine
perimeter
end
feature -- Specific features of rectangles, such as:
side1: REAL
side2: REAL
perimeter: REAL
-- Rectangle-specific version
do
Result := 2 * (side1 + side2)
end
... Other RECTANGLE features ...
</code>
Here it is appropriate to redefine <code>perimeter</code> for rectangles as there is a simpler and more efficient algorithm. Note the explicit <code>redefine</code> sub clause (which would come after the <code>rename</code> if present).
Other descendants of <code>POLYGON</code> may also have their own redefinitions of <code>perimeter</code>. The version to use in any call is determined by the run-time form of the target. Consider the following class fragment:
<code>
p: POLYGON
r: RECTANGLE
...
create p
create r
...
if c then
p := r
end
print (p.perimeter)</code>
The polymorphic assignment <code>p := r</code> is valid because of the above rule. If condition <code>c</code> is false, <code>p</code> will be attached to an object of type <code>POLYGON</code> for the computation of <code>p</code>. <code>perimeter</code>, which will thus use the polygon algorithm. In the opposite case, however, <code>p</code> will be attached to a rectangle; then the computation will use the version redefined for <code>RECTANGLE</code>. This is known as '''dynamic binding'''.
Dynamic binding provides a high degree of flexibility. The advantage for clients is the ability to request an operation (such as perimeter computation) without explicitly selecting one of its variants; the choice only occurs at run-time. This is essential in large systems, where many variants may be available; dynamic binding protects each component against changes in other components.
This technique is particularly attractive when compared to its closest equivalent in traditional approaches, where you would need records with variant components, or union types (C), together with <code>case</code> (switch) instructions to discriminate between variants. This means that every client must know about every possible case, and that any extension may invalidate a large body of existing software.
The combination of inheritance, feature redefinition, polymorphism and dynamic binding supports a development mode in which every module is open and incremental. When you want to reuse an existing class but need to adapt it to a new context, you can define a new descendant of that class (with new features, redefined ones, or both) without any change to the original. This facility is of great importance in software development, an activity that -- by design or circumstance -- is invariably incremental.
The power of these techniques demands adequate controls. First, feature redefinition, as seen above, is explicit. Second, because the language is typed, a compiler can check statically whether a feature application <code>a.f</code> is correct. In contrast, dynamically typed object-oriented languages defer checks until run-time and hope for the best: if an object "sends a message" to another (that is to say, calls one of its routines) one just expects that the corresponding class, or one of its ancestors, will happen to include an appropriate routine; if not, a run-time error will occur. Such errors will not happen during the execution of a type-checked Eiffel system.
In other words, the language reconciles dynamic binding with static typing. Dynamic binding guarantees that whenever more than one version of a routine is applicable the right version (the one most directly adapted to the target object) will be selected. Static typing means that the compiler makes sure there is at least one such version.
This policy also yields an important performance benefit: in contrast with the costly run-time searches that may be needed with dynamic typing (since a requested routine may not be defined in the class of the target object but inherited from a possibly remote ancestor), the EiffelStudio implementation always finds the appropriate routine in constant-bounded time.
Assertions provide a further mechanism for controlling the power of redefinition. In the absence of specific precautions, redefinition may be dangerous: how can a client be sure that evaluation of <code>p.perimeter</code> will not in some cases return, say, the area? Preconditions and postconditions provide the answer by limiting the amount of freedom granted to eventual redefiners. The rule is that any redefined version must satisfy a weaker or equal precondition and ensure a stronger or equal postcondition than in the original. This means that it must stay within the semantic boundaries set by the original assertions.
The rules on redefinition and assertions are part of the Design by Contract&#153; theory, where redefinition and dynamic binding introduce subcontracting. <code>POLYGON</code>, for example, subcontracts the implementation of perimeter to <code>RECTANGLE</code> when applied to any entity that is attached at run-time to a rectangle object. An honest subcontractor is bound to honor the contract accepted by the prime contractor. This means that it may not impose stronger requirements on the clients, but may accept more general requests: weaker precondition; and that it must achieve at least as much as promised by the prime contractor, but may achieve more: stronger postcondition.

View File

@@ -0,0 +1,33 @@
[[Property:title|I2E: Putting a System Together]]
[[Property:weight|-1]]
[[Property:uuid|97460714-8ae1-a7cb-8216-235827045ea6]]
We have now studied the constituents of Eiffel software. It remains to see how you can combine these elements into executable '''systems''' (the Eiffel concept closest to the traditional notion of program) and libraries.
How do you get an executable system? All you need is to <br/>
* Provide a set of classes, called a '''universe'''.
* Designate one of these classes as the '''root class'''.
* Designate one of its creation procedures as the '''root procedure'''.
This defines what it means to execute the system: create one direct instance of the root class (the execution's '''root object'''); and call the root procedure on it. That's all.
In any practical case, the root procedure will create other objects, call other routines on them, leading to further creations and calls.
For the system to be valid, it must include all the classes which the root '''needs''' directly or indirectly; a class "needs" another if it is one of its heirs or clients.
For a library we don't need to specify a root. If we want to make sure that every class in a library compiles fine we can specify that we want all classes to be the root.
The Eiffel method suggests grouping related classes (typically 5 to 40 classes) into collections called '''clusters'''. A universe is then a set of clusters. For example the EiffelBase library is divided into clusters corresponding each to a major category of data structure: <code>lists</code>, <code>tables</code>, <code>iteration</code>, and so on. You can nest clusters, using for example EiffelBase, with its own subclusters as listed, as a cluster of your system.
How will you specify a universe? Any Eiffel implementation can use its own conventions. EiffelStudio applies a simple policy: <br/>
* Store each class in a single file, called its class file, with a name of the form <code>name</code>.<code>e</code> . For clarity, <code>name</code> should be the lower-case version of the class name, although this is a style rule, not a requirement.
* Put all the class files of a cluster into a single directory (folder on Windows), called its cluster directory.
{{note|It is desirable for clarity, as a style rule, to separate clusters that directly contain classes ("terminal clusters") from those that have subclusters. Cluster directories will then contain class files or cluster subdirectories, but not both. }}
* To specify a system, it suffices to provide a list of cluster directories, along with the name of the root class and root procedure. The universe consists of the classes contained in all the class files in the listed cluster directories.
Such a system specification is written in an ecf (eiffel configuration file) which is an xml based file format. It can be created by using the project settings in EiffelStudio.

View File

@@ -0,0 +1,24 @@
[[Property:title|I2E: Types]]
[[Property:weight|-10]]
[[Property:uuid|344a9fdc-3346-5e2d-5fdd-77464e92f72f]]
Eiffel is strongly typed for readability and reliability. Every entity is declared of a certain type, which may be either a reference type or an expanded type.
Any type <code>T</code> is based on a class, which defines the operations that will be applicable to instances of <code>T</code>. The difference between the two categories of type affects the semantics of an entity <code>x</code> declared of type <code>T</code>: for a reference type, the most common case, possible values for <code>x</code> are references to objects; for an expanded type, the values are objects. In both cases, the type rules guarantee that the objects will be instances of <code>T</code>.
A non-expanded class such as <code>ACCOUNT</code> yields a reference type. As a result, an entity of type <code>ACCOUNT</code>, such as <code>acc</code> in the earlier client example (see the declaration of <code>acc</code> and the accompanying picture as given in [[I2E: Classes]] ), denotes possible run-time references to objects of type <code>ACCOUNT</code>.
In contrast, the value of an entity <code>acc</code> declared of type <code>expanded ACCOUNT</code> is an object such as the one shown on the figure below, with no reference. The only difference with the earlier figure is that the value of <code>acc</code> is now an <code>ACCOUNT</code> object, not a reference to such an object. No creation instruction is needed in this case. (The figure does not show the <code>PERSON</code> object to which the <code>owner</code> field of the <code>ACCOUNT</code> object -- itself a reference -- is attached.)
[[Image:invitation-3]]
An important group of expanded types, based on library classes, includes the basic types <code>CHARACTER, DOUBLE, REAL, INTEGER,</code> and <code>BOOLEAN</code>. Clearly, the value of an entity declared of type <code>INTEGER</code> should be an integer, not a reference to an object containing an integer value. Operations on these types are defined by prefix and infix operators such as "+" and "<".
As a result of these conventions, the type system is uniform and consistent: all types, including the basic types, are defined from classes, either as reference types or as expanded types.
In the case of basic types, for obvious reasons of efficiency, the compilation mechanism implements the standard arithmetic and boolean operations directly through the corresponding machine operations, not through routine calls. But this is only a compiler optimization, which does not hamper the conceptual homogeneity of the type edifice.

View File

@@ -0,0 +1,10 @@
[[Property:title|I2E: What Must I Know First?]]
[[Property:weight|-14]]
[[Property:uuid|f40b4a30-87f7-2c27-b6e7-ef2f2a74661b]]
This Invitation assumes that you have some experience of software development, but that's all. Previous exposure to object technology is not required. If you've had it, it will help; but if it has all been to notations like UML or programming languages like C++ and Java, you should not let it guide your study of this Invitation. Although Eiffel shares a number of properties with these other approaches, it takes a fresh path to object technology, based on a small number of simple, far-reaching concepts.
Once you are familiar with the basic ideas you may want to try them with EiffelStudio, which provides a direct implementation of the Eiffel concepts, available in a completely portable way across Windows, Linux, many versions of Unix and OpenVMS.

View File

@@ -0,0 +1,6 @@
[[Property:title|Invitation to Eiffel (I2E)]]
[[Property:link_title|Invitation to Eiffel]]
[[Property:weight|-15]]
[[Property:uuid|7a606387-2653-b122-b4ef-e283a389656e]]
The Invitation to Eiffel (I2E) is a short set of pages that should provide you with the essence of the Eiffel way, without taking too much of your time. Enjoy this profoundly different way of thinking about developing software! When you are done, move on to the more detailed Eiffel tutorial.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,3 @@
title=Catcall example class diagram
author=halw
path=content/catcall-example-class-diagram

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -0,0 +1,3 @@
title=Catcall compiler warning
author=halw
path=content/catcall-compiler-warning

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,3 @@
title=ECMA-367 cover small
author=halw
path=content/ecma-367-cover-small

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,3 @@
title=ETL
author=halw
path=content/etl

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -0,0 +1,3 @@
title=OOSC2 small
author=halw
path=content/oosc2-small

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@@ -0,0 +1,3 @@
title=Touch of Class cover small
author=halw
path=content/touch-class-cover-small

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,3 @@
title=tutorial-4
author=halw
path=content/tutorial-4

Some files were not shown because too many files have changed in this diff Show More