General
-
The name of the class clearly reflects the role it plays.
-
The description of the class clearly conveys the purpose of the class.
-
The class represents a single well-defined abstraction.
-
The class's attributes and operations are all essential to fulfilling the responsibilities of the class.
-
Each class represents a small, consistent and unique set of responsibilities.
-
The responsibilities of the class are well-defined, clearly stated, and clearly related to the purpose of the
class.
-
Each class is relatively self-contained, and is loosely coupled to other classes.
-
The responsibilities of the class are at a consistent level of abstraction (i.e. high-level (application-level)
and low-level (implementation-level) responsibilities are not mixed).
-
Classes in the same inheritance hierarchy possess unique class attributes, operations and relationships (i.e.
they inherit all common attributes, operations and relationships).
-
The complete life-cycle of an instance of the class is accounted for. Each object is created, used, and removed
by one or more use-case realizations.
-
The class satisfies the behavioral requirements established by the use-case realizations.
-
All requirements on the class in the requirement specification are addressed.
-
The demands on the class (as reflected in the class description and by the objects in sequence diagrams) are
consistent with the class's state machine.
-
All responsibilities of the class are related, such that it is not possible for the class to exist in a system
where some of its responsibilities are used, but not others.
-
No two classes have essentially the same purpose.
|
Generalization/Specialization
-
The generalization hierarchy is balanced, such that there are no classes for which the hierarchy is unusually
flat or deep.
-
Obvious commonality has been reflected in the inheritance hierarchy.
-
There are no superclasses which appear to be merges of the attributes of the subclasses.
-
There are no intermediate abstract classes in the inheritance hierarchy with orthogonal properties, examples of
which include duplicated subclasses on both sides of an inheritance tree.
-
Inheritance is used to capture common design abstractions, not primarily for implementation considerations,
i.e. to reuse bits of code or class structure.
|
Naming Conventions
-
Class names indicate purpose.
-
Class names follow the naming conventions specified in project design guidelines.
|
Operations
-
The name of each operation is descriptive and understandable.
-
The state machine and the operations are consistent.
-
The state machine and operations completely describe the behavior of the class.
-
The parameters of each operation are correct in terms of both number, name and type.
-
Implementation specifications for each operation, where defined, are correct.
-
Operation signatures conform to the standards of the target programming language.
-
Each operation is used by at least one use-case realization.
|
Attributes
-
All relationships of the class are required to support some operation of the class.
-
Each attribute represents a single conceptual thing.
-
The name of each attribute is descriptive, and correctly conveys the information it stores.
|
Relationships
-
The role names of aggregations and associations describe the relationship between the associating and
associated classes.
-
The multiplicities of the relationships are correct.
|
State Machines
-
The state machine is as simple as possible while still expressing the required behavior.
-
The state machine does not contain any superfluous states or transitions.
-
The state machine has a clear context.
-
All referenced objects are visible to the enclosing object.
-
The state machine is efficient, and carries out its behavior with an optimal balance of time and resources as
defined by the actions it dispatches.
-
The state machine is understandable.
-
-
The state and transition names are understandable in the context of the domain of the system.
-
The state names indicate what is being waited for or what is happening, rather than what has happened.
-
The state and transition names are unique within the state machine (although not a strict requirements,
it aids in debugging to enforce unique names).
-
Logical groupings of states are contained in composite states.
-
Composite states have been used effectively to reduce complexity?
-
Transition labels reflect the underlying cause of the transition.
-
There are no code fragments on state transitions which are more than 25 lines of detail code; instead,
functions have been used effectively to reduce transition code complexity.
-
State machine nesting has been examined to ensure that nesting depth is not too deep to be
understandable; one or two levels of substates are usually sufficient for most complex behaviors.
-
Active classes have been used instead of concurrent substates; active classes are nearly always a better
alternative and more understandable than concurrent substates.
-
In real-time systems, capsules have been used to represent logical threads of control.
-
Error or maintenance states have been accounted for.
-
Substates have been used in lieu of extended state variables; there is no evidence of transition guard
conditions testing several variables to determine which to state the transition should occur.
-
The state machine does not resemble a flow chart.
-
The state machine does not appear to have been overly de-composed, consisting of nested state machines with a
single sub-state. In cases where the nested sub-state is a placeholder for future design work or subclassing,
this may be temporarily acceptable providing that the choice has been a conscious one.
|
|