Interface specification includes the following activities:
- Identify missing attributes and operations
- Specify visibility and signatures
- Specify contracts
Principal concepts of interface specification:
- Class Implementor, Class Extender, and Class User ( 9.3.1 )
- Types, Signatures, and Visibility ( 9.3.2 )
- Contracts: Invariants, Preconditions, and Postconditions ( 9.3.3 )
- Object Constraint Language ( 9.3.4 )
- OCL Collections: Sets, Bags, and Sequences ( 9.3.5 )
- OCL Quantifiers: forAll and exists ( 9.3.6 )
9.3.1 - Class Implementor, Class Extender, and Class User
- The class implementor is responsible for implementing ( writing ) the class, and needs to know what services and interface to provide.
- The class extender writes specializations of the class, and needs to know the services and data members accessible to sub-classes.
- The class user uses the class, and needs to know what services and interface are publicly available.
9.3.2 - Types, Signatures, and Visibility
- Types indicate the data types of members and method parameters, such as ints, floats, doubles, etc.
- A signature of a method documents the number and types of its parameters, and its return value.
- The visibility of a method or data member documents what class of accessor has what access to the item:
- ( - ) Private members are only accessible by members of the class. ( implementor )
- ( + ) Public members are accessible by any method or function that wants access. ( anyone )
- ( # ) Protected members are accessible only to members of the class and its descendants. ( implementors and extenders )
- ( ~ ) Package members are accessible only to members of the nearest enclosing package. ( implementors of closely affiliated classes. )
Note that Java has the concept of Packages, and C++ has the concept of Friendship, which are similar but different means of implementing accessibiltiy to a limited group of closely related classes.9.3.3 - Contracts: Invariants, Preconditions, and Postconditions
- An invariant is a predicate that is always true for all instances of a class.
- A precondition is a predicate that must be true before an operation is invoked.
- A postcondition is a predicate that must be true after an operation is completed.
The contract paradigm of programming states that those who invoke ( call ) an operation are responsible for ensuring the pre-conditions, and the implementor of the operation is responisble for ensuring the post-conditions only when the pre-conditions are met. The class implementor has no responsibiltiy for handling cases in which the pre-conditions are not met, and anything could "legally" happen in that case. Obviously the class implementor is responsible for clearly documenting the necessary pre-conditions for the class. This approach to programming eliminates redundant error checking, and clearly identifies who is responsible for what, but can lead to uncaught errors if the pre-conditions are not specified clearly or if the programmer who invokes the method does not check the pre-conditions carefully. ( It also requires that the method invoking the class method be able to check the pre-conditions. )
9.3.4 - Object Constraint Language
Boolean expressions which evaluate to true or false. OCL can be attached to class diagrams as notes:
Or as text expressions:
9.3.5 - OCL Collections: Sets, Bags, and Sequences
- A set is a collection of unique items, without regard to order
- A sequence is an ordered set
- A bag is a set that may contain duplicates.
Special operations for working on collections:
- size - The number of elements in the collection.
- includes( object ) - True if the collection includes the object.
- select( expression ) - A subset of the collection for which the expression is true.
- union( collection ) - The set of elements in either one of two collections
- intersection( collection ) - The set of elements in both of two collections.
- asSet( collection ) - generates a set from a bag.
The length of a Tournament must not exceed one week: ( attribute, Dot notation )
Only players enrolled in the League may play in a Tournament: ( collection, Arrow notation )
The active players in a League are all players playing in at least one Tournament: ( collection, Arrow notation )
9.3.6 - OCL Quantifiers: forAll and exists
- Every Match within a Tournament must start and end during the tournament:
- At least one Match must start on the first day of a Tournament:
9.4.1 - Identifying Missing Attributes and Operations
9.4.2 - Specifying Types, Signatures, and Visibility
9.4.3 - Specifying Pre- and Post conditions
9.4.4 - Specifying Invariants
- Invariants are much harder to write than pre-and post- conditions, because they must hold true over the entire lifetime of the class, and are potentially affected by many different operations.
- On the other hand, invariants do a better job of documenting the overall requirements of the class, as opposed to requirement that only apply to specific methods.
9.4.5 - Inheriting Contracts
- Post conditions and invariants can only be strengthened in inherited classes.
- Pre-conditions can only be weakened in inherited classes.
- In the following example, if it is determined that Spectators do not need to provide an e-mail address, then either the constraint needs to be removed from the User class or else Spectator can no longer be a descendant of User, since is no longer fulfills all the requirements of a User:
9.5.1 - Documenting Object Design
Two primary challenges:
- Increased communication complexity, as the number of people involved in the project increases.
- Consistency with prior decisions and documents. The new people were not involved in requirements development or system analysis, so it is up to management to make sure that current work is consistent with past efforts, and/or to make sure that previously developed documents are modified to reflect new changes. ( And to consider the ramifications of current changes to other parts of the system. )
Three main approaches to developing the Object Design Document:
- Self-contained ODD developed from the model.
- ODD as an extension of the RAD ( Requirements Analysis Document )
- ODD embedded into source code, e.g. JavaDoc.
9.5.2 - Assigning Responsibilities
- The core architect develops coding guidelines and conventions.
- The architecture liaisons document the public subsystem interfaces.
- Object designers refine and detail the interface specifications of particular classes or subsystems they implement.
- The configuration manager releases changes to the interfaces and ODD as available.
- Technical writers finalize the documents.
9.5.3 - Using Contracts During Requirements Analysis
Tradeoffs to consider regarding how early to introduce constraints into the development process:
- Communication among stakeholders.
- Level of detail and rate of change.
- Level of detail and elicitation effort.
- Testing requirements.
9.6.1 - Identifying Missing Operations in TournamentStyle and Round
Different styles of tournaments have different rules for assigning players to matches. For example a knock out style cannot assign players to matches in the next round until the winners of the current round are known, whereas round robin style can assign all players to all matches as soon as the number of players is known. Either style may or may not have restrictions on the number of players, such as requiring a power of two for knockout style.
New requirements:
This leads to a new class, Round, and a new set of methods in the TournamentStyle class.
- Schedule representation - the graph of matches needs to be represented in a fashion that works for all tournament styles.
- Incremental planning - TournamentStyle needs methods that allow matches to be planned incrementally as the Tournament proceeds.
- Game independence - The graph of matches and the planning of matches need to be independent of a particular game, even though they are generated by the Game abstract factory.
9.6.2 - Specifying the TournamentStyle and Round Contracts
9.6.3 - Specifying the KnockOutStyle and KnockOutRound Contracts
Note that these inherit from TournamentStyle and Round classes. They may strengthen the invariants and post-conditions, and weaken the pre-conditions.
Sample Problem
- Problem:
- Solution ( Try to work out the problem yourself before looking at the solution. )
9.6.4 - Lessons Learned