Orthogonality:
- In geometry, orthogonal means
"involving right angles", but the term has been extended to general
use, meaning the property of being independent (relative to
something else)
- Language constructs should not
behave differently in different contexts.
- The language constructs can be
combined in a meaningful way.
- The interactions of constructs, or
the context of use, should not cause unexpected restrictions or
behavior.
- There should be no strange
interactions!
In the context of a programming
language, a set of features/constructs is said to be
orthogonal if those features can be used freely in
combination with each other. In particular, the degree of
orthogonality is lessened if
- particular combinations are forbidden (as exceptional cases)
or
- the meaning of a particular combination is not evident from the
meanings of its component parts, each one considered without regard
to context.
Examples of non-orthogonality :
- C passes all parameters by value, except arrays, which are
passed by reference.
- In Java, primitive data types are passed by value, the rest by
reference, yet they look the same! (This is also
non-uniformity)
- In Java, assigning objects is an assignment of references,
while assigning primitive data types is done by value.
- In C and C++, values of all data types, except array types, can
be returned from a function.
- In C, local variables must be defined at the beginning of a
block, in C++ variable definitions can occur anywhere inside a
block, but before use of course.
Example from assembly languages:
- In VAX assembler, the instruction for 32-bit integer addition
is of the form
ADDL op1 op2
where each of the opi's can refer to either a
register or a memory location. This is nicely orthogonal.
- In contrast, in the assembly languages for IBM mainframes,
there are two separate analogous ADD instructions, one of which
requires op1 to refer to a register and op2
to refer to a memory location, the other of which requires both to
refer to registers. This is lacking in orthogonality.
Generality:
- Avoiding special cases in the availability or use of
constructs.
- Combining closely related constructs into a single more general
one.
- Too much generality is bad!
Examples of Lack of Generality:
- C lacks nested function definitions.
- Pascal has no variable-length arrays, arrays lack
generality.
- In C, two structures or arrays cannot be directly compared
using the equality (==) operator, but must be compared element by
element. Ada on the other hand allows totally new operators to be
defined. C++ can overload operators.
- In Pascal, constants may not be expressions, opposite to
Ada.
- Java does not have multiple inheritance, but interface
inheritance implementation is a good enough substitute.
Uniformity:
- Similar things should look similar and have similar
meanings
- Inversely, different things should look different i.e.
consistency of appearance and behavior.
- Non-uniformity and non-orthogonality may be very closely
related in some instances.
Examples of lack of uniformity:
- In C++, a semicolon is necessary after a class definition but
forbidden after a function definition. class A { … }; int f() { …
}
- This non-uniformity was forced to allow C++ to be compatible
with C.
- Returned values from functions in Pascal look like
assignments
function f : boolean;
begin
…
f :=true;
end;