[[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 ''a_'' and nothing more. The prefix ''a_'' 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:
perform (a_string: STRING; a_integer: STRING): CHARACTER
-- An example using routine argument variable names.
do
end
Here, the second argument ''a_integer'', is not considered ''A Integer'' but ''The Argument Integer'', hence the use if a_ instead of ''_an_''.
=== 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 ''other'' embedded in the variable name would suffice for most cases.
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
=== In-line Agent Routine Arguments ===
When working with an in-line agent, to prevent conflicts with the enclosing routine's arguments, the prefix ''ia_'' should be used. The same rules regarding English language rules apply here as they do to routine arguments. The ''ia_'' prefix represents an ''In-line Argument''.
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
==== 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 ''ia_'' prefix or use ''i1a_'', the former being preferred. A second-level (first nested level) in-line agent should use the prefix ''i2a_'', third-level ''i3a_'' and so forth.
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
== Local Declarations ==
Routine local declaration should also be prefixed to prevent potential conflicts between routine arguments or class attributes. The prefix ''l_'' 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 ''i'' should be use to indicate it is an index variable. Additional index variables should follow alphabetically from ''i'' 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 ''l_count'', a number-of-items variable will use a well-known contracted variable name 'nb''.
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
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 NEXT x
instruction:
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
==== Other Well-Known Names ====
There are a number of other well know and simpler to use local variable names:
* ''c'' for any type of character.
* ''e'' for any type of exception (descendant of EXCEPTION).
* ''s'' for any type of string (descendant of READABLE_STRING_GENERAL).
* ''uc'' for a Unicode character.
* ''us'' for a Unicode string (descendant of READABLE_STRING_32).
* ''nb'' 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 retry 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 ''retried'':
perform
-- An example using a rescue/retry local variable name.
local
retried: BOOLEAN
do
if not retried then
...
end
rescue
retried := True
retry
end
=== Object Tests ===
Object test locals obey the same rules and other standard local declarations, that it, prefixing a variable moniker with ''l_''. However, due to the current scoping rules of object-tests, where no object test local may be reused, extraneous guidelines need to be defined.
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
==== 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 ''l_'' 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:
* ''rl_'' for require
* ''el_'' for ensure
* ''cl_'' for check
* ''ll_'' for loop
* ''il_'' for loop invariant
* ''vl_'' for loop variant
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
No prefix, other than ''l_'' 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 ''l_'' prefix should be used if possible. However, for clarity this cannot always be such the case. When such as scenario arises the use of ''il_'' (in-line local) is preferred. It is recommended that all locals utilize the same prefix and '''not''' mix ''l_'' and il_''!
l_action := agent (ia_string: READABLE_STRING_GENERAL)
local
il_i, il_count: INTEGER
do
....
end
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 ''i'' prefix. For a second level in-line agent, this would be ''i2l_''.
== 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 ''_1''. To better illustrate, the following code examples are both valid uses of natural indexing:
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
or
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
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.