500 likes | 516 Views
UML Distilled. Design by contract. Object-Oriented Software Construction by Bertrand Meyer, Prentice Hall The presence of a precondition or postcondition in a routine is viewed as a contract. Rights and obligations. Parties in the contract: class and clients
E N D
Design by contract • Object-Oriented Software Construction by Bertrand Meyer, Prentice Hall • The presence of a precondition or postcondition in a routine is viewed as a contract.
Rights and obligations • Parties in the contract: class and clients • require pre, ensure post with method r: If you promise to call r with pre satisfied then I, in return, promise to deliver a final state in which post is satisfied. • Contract: entails benefits and obligations for both parties
Rights and obligations • Precondition binds clients • Postcondition binds class
If precondition is not satisfied • If client’s part of the contract is not fulfilled, class can do what it pleases: return any value, loop indefinitely, terminate in some wild way. • Advantage of convention: simplifies significantly the programming style.
Source of complexity • Does data passed to a method satisfy requirement for correct processing? • Problem: no checking at all or: multiple checking. • Multiple checking: conceptual pollution: redundancy; complicates maintenance • Recommended approach: use preconditions
Class invariants and class correctness • Preconditions and postconditions describe properties of individual methods • Need for global properties of instances which must be preserved by all routines • 0<=nb_elements; nb_elements<=max_size • empty=(nb_elements=0);
Class invariants and class correctness • A class invariant is an assertion appearing in the invariant clause of the class. • Must be satisfied by all instances of the class at all “stable” times (instance in stable state): • on instance creation • before and after every remote call to a routine (may be violated during call)
Class invariants and class correctness • A class invariant only applies to public methods; private methods are not required to maintain the invariant.
Invariant Rule • An assertion I is a correct class invariant for a class C iff the following two conditions hold: • The constructor of C, when applied to arguments satisfying the constructor’s precondition in a state where the attributes have their default values, yields a state satisfying I. • Every public method of the class, when applied to arguments and a state satisfying both I and the method’s precondition, yields a state satisfying I.
Invariant Rule • Precondition of a method may involve the initial state and the arguments • Postcondition of a method may only involve the final state, the initial state (through old) and in the case of a function, the returned value. • The class invariant may only involve the state
Invariant Rule • The class invariant is implicitly added (anded) to both the precondition and postcondition of every exported routine • Could do, in principle, without class invariants. But they give valuable information. • Class invariant acts as control on evolution of class • A class invariant applies to all contracts between a method of the class and a client
Resource Allocation reqs <JobCategory> <Facility> 0..* type provides 0..* <Job> when: TimeInterval schedule allocated <Resource> 0..* 0..1 inv Job::allocated<>0 ==> allocated.provides->includesAll(type.reqs) --Any allocated resource must have the required facilities inv Resource::jo1, jo2: Job:: (schedule->includesAll({jo1,jo2}) ==> jo1.when.noOverlap(jo2.when) -- no double-booking of resources
Collaborations in UMLUML Distilled: page 113 • A collaboration is a name given to the interaction among two or more classes. • You can also add a class diagram to show the classes that participate in the collaboration.
Collaborations • Use them to show common behavior. • Often you may find that the same collaboration is used by different classes in the system. • You can illustrate this by parameterizing the collaboration.
Roles • Show roles that objects play in collaboration. • UML also uses the term pattern for a parameterized collaboration.
Collaboration basics collaboration checkDef { roleCd_graph { out check(){}; // out: provided getClasses(){}; // local method in getAll = // in: expected from Cd_graph bypassing Neighbors to Vertex; } roleNeighbors { } roleVertex { } } A collaboration is self-contained and parameterized by roles and expected members.
Java Code: What is the collaboration? Cd_graph{{ void isDefined(ClassGraph cg){ checkDefined(cg, getClasses(cg));} HashSet getClasses(ClassGraph cg){ Strategy getAll = new Strategy( "from Cd_graph bypassing Neighbors to Vertex"); TraversalGraph tg = new TraversalGraph(getAll, cg); Visitor v = new Visitor(){ HashSet return_val = new HashSet(); void before(Vertex v){ return_val.add(v.get_vertex_name());} public Object getReturnValue(){return return_val;}}; tg.traverse(this,v); return (HashSet)v.getReturnValue(); }
Java Code: What is the collaboration? void checkDefined(ClassGraph cg, HashSet tempClassSet){ final HashSet classHash = tempClassSet; Strategy checkAll = new Strategy(” from Cd_graph through Neighbors to Vertex"); TraversalGraph tg = new TraversalGraph(checkAll, cg); tg.traverse(this, new Visitor(){ void before(Vertex v){ if(!classHash.contains(v.get_vertex_name())){ System.out.println("The class "+ v.get_vertex_name() + " is undefined."); }}});} }}
Find undefined classes vertices getAll * Cd_graph * Vertex checkAll neighbors * * vertices Neighbors getAll = from Cd_graph bypassing Neighbors to Vertex checkAll = from Cd_graph through Neighbors to Vertex
High-level description • It is useful to have a high-level description of the collaboration besides the Java source code. Useful documentation. • Ultimately we are interested in the executable form of the collaboration (Java source code).
Collaboration 1: with strategies collaboration checkDef { participantCd_graph { out check(){(uses getClasses, checkDefined)}; getClasses(){(uses getAll)}; checkDefined(){(uses checkAll)}; in getAll = from Cd_graph bypassing Neighbors to Vertex; incheckAll = from Cd_graph through Neighbors to Vertex; } participantNeighbors { } participantVertex { } }
Collaboration 2: with accessors collaboration checkDef { participantCd_graph { out check(){(uses getClasses, checkDefined)}; getClasses(){(uses getAll)}; checkDefined(){(uses checkAll)}; in getNeighbors(); in getVertices(); getAll(){return getVertices()}; // from Cd_graph bypassing Neighbors to Vertex; checkAll(){return getNeighbors().getVertices();} // from Cd_graph through Neighbors to Vertex; participantNeighbors { in getVertices(); } participantVertex { } }
Use of 2. collaboration Need to provide the expected methods (in methods) and provide name map (identity in this case): Cd_graph: in getNeighbors(); Cd_graph: in getVertices(); Neighbors: in getVertices(); Cd_graph:getNeighbors(){ return cg.gather(this,”from Cd_graph to Neighbors”);} Cd_graph:getVertices(){ return cg.gather(this, ”from Cd_graph bypassing Neighbors to Vertex;”);} Neighbors:getVertices(){ return cg.gather(this,”from Neighbors to Vertex”);}
Use of 1. collaboration Need to provide the expected methods (in methods) and provide name map (identity in this case): Cd_graph: in getAll // use default incheckAll // use default
The Collaboration in Action • Computer Science • Project • Smaller class graph for class graphs • Mathematics
Class dictionary (part 1) Cd_graph = <adjacencies> Nlist(Adjacency) EOF. Adjacency = < source > Vertex < ns > Neighbors "." . Neighbors : Neighbors_wc . Neighbors_wc :Construct_ns | Alternat_ns common < construct_ns > List(Any_vertex). Construct_ns = "=". Alternat_ns = ":" < alternat_ns > Bar_list(Term) [<common> Common]. Common = "common". Any_vertex : Opt_labeled_term | Optional_term | Syntax_vertex .
Class dictionary (part 2) Vertex = < vertex_name > Ident. Syntax_vertex : Regular_syntax common. Regular_syntax = < string > String . Opt_labeled_term : Labeled | Regular common <vertex> Term. Regular = . Labeled = "<" < label_name > Ident ">" . Term : Normal common <vertex> Vertex. Normal = . Optional_term = "[" <opt> Sandwich(Opt_labeled_term) "]".
getAll = from Cd_graph bypassing Neighbors to Vertex checkAll = from Cd_graph through Neighbors to Vertex Class dictionary (part 1) Cd_graph = <adjacencies> Nlist(Adjacency) EOF. Adjacency = < source > Vertex < ns > Neighbors "." . Neighbors : Neighbors_wc . Neighbors_wc :Construct_ns | Alternat_ns common < construct_ns > List(Any_vertex). Construct_ns = "=". Alternat_ns = ":" < alternat_ns > Bar_list(Term) [<common> Common]. Common = "common". Any_vertex : Opt_labeled_term | Optional_term | Syntax_vertex .
getAll = from Cd_graph bypassing Neighbors to Vertex checkAll = from Cd_graph through Neighbors to Vertex Class dictionary (part 1) Cd_graph =<adjacencies> Nlist(Adjacency) EOF. Adjacency= < source > Vertex < ns > Neighbors "." . Neighbors : Neighbors_wc . Neighbors_wc :Construct_ns | Alternat_ns common < construct_ns > List(Any_vertex). Construct_ns = "=". Alternat_ns = ":" < alternat_ns > Bar_list(Term) [<common> Common]. Common = "common". Any_vertex : Opt_labeled_term | Optional_term | Syntax_vertex .
getAll = from Cd_graph bypassing Neighbors to Vertex checkAll = from Cd_graph through Neighbors to Vertex Class dictionary (part 2) Vertex = < vertex_name > Ident. Syntax_vertex : Regular_syntax common. Regular_syntax = < string > String . Opt_labeled_term : Labeled | Regular common <vertex> Term. Regular = . Labeled = "<" < label_name > Ident ">" . Term : Normal common <vertex> Vertex. Normal = . Optional_term = "[" <opt> Sandwich(Opt_labeled_term) "]".
getAll = from ClassG bypassing Body to ClassName UML class diagram ClassG 0..* Entry EParse entries ClassG BParse ClassDef Body parts Part className 0..* ClassName Concrete Abstract AOO / UML / OCL/Strategies
checkAll = from ClassG through Body to ClassName UML class diagram ClassG 0..* Entry EParse entries ClassG BParse ClassDef Body parts Part className 0..* ClassName Concrete Abstract AOO / UML / OCL/Strategies
change of domain: from Computer Science to Mathematics Example: x = 1.0 . y = (+ x 4.0). z = (* x y). Equation System EquationSystem = <equations> List(Equation). Equation = <lhs> Variable “=“ <rhs> Expression “.”. Variable = Ident. Expression : Simple | Compound. Simple : Variable | Numerical. Compound = “(“ Op <args> List(Expression) “)”. Op : Add | Mul. Add = “+”. Mul = “*”. Numerical = float. Write a program for: Are all variables in an equation system defined? (disregard order of equations)
Make More Reusable Cd_graph{{ String vi = “from Vertex to edu.neu.ccs.demeter.Ident”; void isDefined(ClassGraph cg){ checkDefined(cg, getClasses(cg));} HashSet getClasses(ClassGraph cg){ Strategy getAll = new Strategy( "from Cd_graph bypassing Neighbors to Vertex"); TraversalGraph tg = new TraversalGraph(getAll, cg); Visitor v = new Visitor(){ HashSet return_val = new HashSet(); void before(Vertex v){ return_val.add(cg.fetch(v, vi) );} public Object getReturnValue(){return return_val;}}; tg.traverse(this,v); return (HashSet)v.getReturnValue(); }
Make More Reusable void checkDefined(ClassGraph cg, HashSet tempClassSet){ final HashSet classHash = tempClassSet; Strategy checkAll = new Strategy(” from Cd_graph through Neighbors to Vertex"); TraversalGraph tg = new TraversalGraph(checkAll, cg); tg.traverse(this, new Visitor(){ void before(Vertex v){ Ident vn = cg.fetch(v, vi); if (!classHash.contains(vn)){ System.out.println("The object "+ vn + " is undefined."); }}});} }}
Example: x = 1.0 . y = (+ x 4.0). z = (* x y). Equation System EquationSystem = <equations> List(Equation). Equation = <lhs> Variable “=“ <rhs> Expression “.”. Variable = Ident. Expression : Simple | Compound. Simple : Variable | Numerical. Compound = “(“ Op <args> List(Expression) “)”. Op : Add | Mul. Add = “+”. Mul = “*”. Numerical = float. Write a program for: Are all variables in an equation system defined? (disregard order of equations)
Adaptive Object-Oriented Design Find undefined things definedThings * System * Thing usedThings * * * UsedThingsHolder definedThings= from System bypassing UsedThingsHolder to Thing usedThings = from System through UsedThingsHolder to Thing
usedThings = from EquationSystem through Expression to Variable Example: x = 1.0 . y = (+ x 4.0). z = (* x y). Equation System EquationSystem = <equations> List(Equation). Equation = <lhs> Variable “=“ <rhs> Expression “.”. Variable = Ident. Expression : Simple | Compound. Simple : Variable | Numerical. Compound = “(“ Op <args> List(Expression) “)”. Op : Add | Mul. Add = “+”. Mul = “*”. Numerical = float.
definedThings= from EquationSystem bypassing Expression to Variable Example: x = 1.0 . y = (+ x 4.0). z = (* x y). Equation System EquationSystem = <equations> List(Equation). Equation =<lhs> Variable “=“ <rhs> Expression “.”. Variable = Ident. Expression : Simple | Compound. Simple : Variable | Numerical. Compound = “(“ Op <args> List(Expression) “)”. Op : Add | Mul. Add = “+”. Mul = “*”. Numerical = float.
Conclusion Collaborations • Collaborations are an important architectural element in object-oriented design. • Separate collaboration from its use.
Collaboration CheckUnique:3 Roles //checks for unique parts. // Collaboration CheckUnique // role System // out void checkUnique(final ClassGraph cg) // in Strategy getAllUnitsToBeChecked // role UnitToBeChecked // in Strategy checkAllParts // role NotDuplicated // System = List(UnitToBeChecked). // UnitToBeChecked = List(NotDuplicated). // NotDuplicated = Ident.
Collaboration CheckUniquewith role play //checks for unique parts. // Collaboration CheckUnique // role System played by Grammar // out void checkUnique(final ClassGraph cg) // in Strategy getAllUnitsToBeChecked // role UnitToBeChecked played by Statement // in Strategy checkAllParts // role NotDuplicated played by NonTerminal // System = List(UnitToBeChecked). // UnitToBeChecked = List(NotDuplicated). // NotDuplicated = Ident.
Collaboration CheckUniquewith role play 2 //checks for unique parts. // Collaboration CheckUnique // role System played by Cd_graph // out void checkUnique(final ClassGraph cg) // in Strategy getAllUnitsToBeChecked // role UnitToBeChecked played by Adjacency // in Strategy checkAllParts // role NotDuplicated played by Vertex // System = List(UnitToBeChecked). // UnitToBeChecked = List(NotDuplicated). // NotDuplicated = Ident.
Program part 1 System{ {{ Strategy getAllUnitsToBeChecked = … from System to UnitToBeChecked … void checkUnique(final ClassGraph cg){ cg.traverse(this, getAllUnitsToBeChecked, new Visitor(){ void before(UnitToBeChecked a){ a.checkDuplicateParts(cg);} });}}}}
Program part 2 UnitToBeChecked{ {{ Strategy checkAllParts = … from UnitToBeChecked to NotDuplicated … void checkDuplicateParts(ClassGraph cg){ cg.traverse(this, checkAllParts, new Visitor(){ HashSet hParts = new HashSet(); void before(NotDuplicated l){ if(!hParts.add(l.get_ident())){ System.out.println("Element "+ l.get_ident() + " is not unique."); }}});}}}}
Generic System UnitToBeChecked NotDuplicated Project Cd_graph Adjacency Vertex Map