Académique Documents
Professionnel Documents
Culture Documents
Overview
Object design is situated between system design and implementation. Object design is not very well understood and if not well done, leads to a bad system implementation. In this lecture, we describe a selection of transformations to illustrate a disciplined approach to implementation to avoid system degradation.
1. Operations on the object model: Optimizations to address performance requirements 2. Implementation of class model components: Realization of associations Realization of operation contracts 3. Realizing entity objects based on selected storage strategy Mapping the class model to a storage schema
Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 2
Developers perform transformations to the object model to improve its modularity and performance. Developers transform the associations of the object model into collections of object references, because programming languages do not support the concept of association. If the programming language does not support contracts, the developer needs to write code for detecting and handling contract violations. Developers often revise the interface specification to accommodate new requirements from the client. All these activities are intellectually not challenging
However, they have a repetitive and mechanical flavor that makes them error prone.
Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 3
The Vision
During object design we would like to implement a system that realizes the use cases specified during requirements elicitation and system design.
The Reality
Different developers usually handle contract violations differently. Undocumented parameters are often added to the API to address a requirement change. Additional attributes are usually added to the object model, but are not handled by the persistent data management system, possibly because of a miscommunication. Many improvised code changes and workarounds that eventually yield to the degradation of the system.
Model transformations
Forward engineering
Refactoring
Model transformation Reverse engineering Model space Source code space
+email:Address
+email:Address
User +email:Address
LeagueOwner
Bernd Bruegge & Allen H. Dutoit
Advertiser
Object-Oriented Software Engineering: Using UML, Patterns, and Java
Player
6
public class LeagueOwner extends User { //... } public class Advertiser extends User { //... }
7
public class LeagueOwner extends User { private int maxNumLeagues; public int getMaxNumLeagues() { return maxNumLeagues; } public void setMaxNumLeagues (int value) { maxNumLeagues = value; } /* Other methods omitted */ }
9
Optimizing the Object Design Model Mapping Associations Mapping Contracts to Exceptions Mapping Object Models to Tables
10
Person
SocialSecurity number:String
Person
SSN:String
11
?
Image
filename:String paint()
0..1
Optimizing the Object Design Model Mapping Associations Mapping Contracts to Exceptions Mapping Object Models to Tables
13
Account
public class Advertiser { private Account account; public Advertiser() { account = new Account(); } public Account getAccount() { return account; } }
Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 14
Account
public class Account { /* The owner field is initialized * during the constructor and * never modified. */ private Advertiser owner; public Account(owner:Advertiser) { this.owner = owner; } public Advertiser getOwner() { return owner; } }
15
18
public void addPlayer (String nickName, Player p) { if (!players.containsKey(nickName)) { players.put(nickName, p); p.addLeague(nickName, this); } }
} }
public void addLeague (String nickName, League l) { if (!leagues.containsKey(l)) { leagues.put(l, nickName); l.addPlayer(nickName, this); } }
19
Object design model after transformation: 1 class and two binary associations
Statistics
Player
20
Optimizing the Object Design Model Mapping Associations Mapping Contracts to Exceptions Mapping Object Models to Tables
21
Many object-oriented languages, including Java do not include built-in support for contracts. However, we can use their exception mechanisms as building blocks for signaling and handling contract violations In Java we use the try-throw-catch mechanism Example:
Let us assume the acceptPlayer() operation of TournamentControl is invoked with a player who is already part of the Tournament. In this case acceptPlayer() should throw an exception of type KnownPlayer. See source code on next slide
22
Implementing a contract
For each operation in the contract, do the following Check precondition: Check the precondition before the beginning of the method with a test that raises an exception if the precondition is false. Check postcondition: Check the postcondition at the end of the method and raise an exception if the contract is violoated. If more than one postcondition is not satisfied, raise an exception only for the first violation. Check invariant: Check invariants at the same time as postconditions. Deal with inheritance: Encapsulate the checking code for preconditions and postconditions into separate methods that can be called from subclasses.
Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 24
precondition !isPlayerAccepted(p)
postcondition isPlayerAccepted(p)
25
Omit the checking code for private and protected methods. Focus on components with the longest life
Focus on Entity objects, not on boundary objects associated with the user interface.
Optimizing the Object Design Model Mapping Associations Mapping Contracts to Exceptions Mapping Object Models to Tables
27
UML mappings
Each class is mapped to a table Each class attribute is mapped onto a column in the table An instance of a class represents a row in the table A many-to-many association is mapped into its own table A one-to-many association is implemented as buried foreign key
28
29
Any set of attributes that could be used to uniquely identify any data record in a relational table is called a candidate key. The actual candidate key that is used in the application to identify the records is called the primary key.
The primary key of a table is a set of attributes whose values uniquely identify the data records in the table.
A foreign key is an attribute (or a set of attributes) that references the primary key of another table.
30
League table
chessNovice
js289
Foreign key referencing User table
31
Buried Association
Associations with multiplicity one can be implemented using a foreign key. For one-to-many associations we add a foreign key to the table representing the class on the many end. For all other associations we can select either class at the end of the association.
32
Buried Association
Associations with multiplicity one can be implemented using a foreign key. Because the association vanishes in the table, we call this a buried association. For one-to-many associations we add the foreign key to the table representing the class on the many end. For all other associations we can select either class at the end of the association.
LeagueOwner 1 *
League
33
Transaction
* Foreign Key
transactionID
34
cityName
Primary Key City Table cityName Houston Albany Munich Hamburg Airport Table airportCode IAH HOU ALB MUC HAM airportName Intercontinental Hobby Albany County Munich Airport Hamburg Airport Serves Table cityName airportCode IAH Houston HOU Houston ALB Albany MUC Munich HAM Hamburg
35
Tournament *
Player
Tournament table id 23 24 name novice exper t ... TournamentPlayerAssociation table tournament 23 23 player 56 79 id 56 79
36
Realizing Inheritance
Relational databases do not support inheritance Two possibilities to map UML inheritance relationships to a database schema
With a separate table (vertical mapping) The attributes of the superclass and the subclasses are mapped to different tables By duplicating columns (horizontal mapping) There is no table for the superclass Each subclass is mapped to a table containing the attributes of the subclass and the attributes of the superclass
37
LeagueOwner maxNumLeagues
Player credits
...
...
User name
LeagueOwner maxNumLeagues
Player credits
39
Duplicated columns
Modifying the database schema is more complex and error-prone Individual objects are not fragmented across a number of tables, resulting in faster queries
40
Keep the contracts in the source code, not in the object design model
By keeping the specification as a source code comment, they are more likely to be updated when the source code changes.
Summary
Undisciplined changes => degradation of the system model Four mapping concepts were introduced
Model transformation improves the compliance of the object design model with a design goal Forward engineering improves the consistency of the code with respect to the object design model Refactoring improves the readability or modifiability of the code Reverse engineering attempts to discover the design from the code.
Additional Slides
43
More Terminology
Roundtrip Engineering
Forward Engineering + reverse engineering Inventory analysis: Determine the Delta between Object Model and Code Together-J and Rationale provide tools for reverse engineering
Reengineering
Used in the context of project management: Provding new functionality (customer dreams up new stuff) in the context of new technology (technology enablers)
44
TicTacToeGame
ChessGame
Statistics
update() getStat()
TTTStatistics
Bernd Bruegge & Allen H. Dutoit
ChessStatistics
DefaultStatistics
45
N-ary association class Statistics Statistics relates League, Tournament, and Player
Statistics
46
TournamentControl StatisticsView
Game createStatistics()
Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 47
StatisticsVault as a Facade
TournamentControl StatisticsView
48
public double getStat(String name, Tournament t, Player p) throws UnknownStatistic, InvalidScope {...}
}
Bernd Bruegge & Allen H. Dutoit Object-Oriented Software Engineering: Using UML, Patterns, and Java 49
Game table
League table
Tournament table
id:long
...
id:long
...
id:long
...
50
Restructuring Activities
Realizing associations Revisiting inheritance to increase reuse Revising inheritance to remove implementation dependencies
51
Realizing Associations
Role names are treated like attributes in the classes and translate to references "Ordered many" : Translate to Vector "Unordered many" : Translate to Set Translate to Hash table
1-to-many association:
Qualified association:
52
53
MapArea
MapArea
-zoomIn:ZoomInAction +getZoomInAction() +setZoomInAction(action)
54
1-to-Many Association
55
Qualification
0..1
SimulationRun
56
Increase Inheritance
Rearrange and adjust classes and operations to prepare for inheritance Abstract common behavior out of groups of classes
If a set of operations or attributes are repeated in 2 classes the classes might be special instances of a more general class.
57
Prepare for inheritance. All operations must have the same signature but often the signatures do not match:
Some operations have fewer arguments than others: Use overloading (Possible in Java) Similar attributes in the classes have different names: Rename attribute and change all the operations. Operations defined in one class but no in the other: Use virtual functions and class function overriding.
Abstract out the common behavior (set of operations with same signature) and create a superclass out of it. Superclasses are desirable. They
increase modularity, extensibility and reusability improve configuration management
2. Component selection
Identify off-the-shelf components and additional solution objects
59
Design Optimizations
As an object designer you must strike a balance between efficiency and clarity.
Optimizations will make your models more obscure
60
61
Associations are more flexible than attributes but often introduce unnecessary indirection. Abbott's textual analysis rules Every student receives a number at the first day in in the university.
62
Student Matrikelnumber:String
63
Collapse a class into an attribute if the only operations defined on the attributes are Set() and Get().
64
Explicit code: Implementor determines affected derived attributes (push) Periodic computation: Recompute derived attribute occasionally (pull) Active value: An attribute can designate set of dependent values which are automatically updated when active value is changed (notification, data trigger)
65
image
ImageProxy
filename:String width() height() paint()
0..1
66
Increase Inheritance
Generalization is a common modeling activity. It allows to abstract common behavior out of a group of classes
If a set of operations or attributes are repeated in 2 classes the classes might be special instances of a more general class.
Always check if it is possible to change a subsystem (collection of classes) into a superclass in an inheritance hierarchy.
Object-Oriented Software Engineering: Conquering Complex and Changing Systems 67
Some operations have fewer arguments than others: Use overloading (Possible in Java) Similar attributes in the classes have different names: Rename attribute and change all the operations. Operations defined in one class but no in the other: Use virtual functions and class function overriding.
Try to retrofit an existing model to allow the use of a design pattern Bernd Bruegge & Allen Dutoit Object-Oriented Software Engineering: Conquering Complex and Changing Systems 68
Implement Associations
Role names are treated like attributes in the classes and translate to references Always Translate into a Vector Always translate into to Hash table
1-to-many association:
Qualified association:
69