1 / 60

Overview of This Lecture

CS251 – Software Engineering Lectures 15 Implementing UML Models in Code Slides are borrowed from the net. Overview of This Lecture. Basic Implementation Steps. Implementing Classes: Class Association: Navigation direction; Multiplicity constraint; Qualified associations;

jsmail
Download Presentation

Overview of This Lecture

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CS251 – Software EngineeringLectures 15 Implementing UML Models in CodeSlides are borrowed from the net

  2. Overview of This Lecture • Basic Implementation Steps. • Implementing Classes: • Class Association: • Navigation direction; • Multiplicity constraint; • Qualified associations; • Association classes. • Implementing Statecharts

  3. Requirement Analysis Design Implement Testing Where are we now? • Translate Design into Code Software Process Software Version Control

  4. Implementation: Overview • Inputs: • Detailed UML Class Diagram; • UML Sequence Diagram; • UML Statechart. • Activities: • Implementation of class diagram; • Reminder: • Sequence diagrams show the basic behavior of some of the operations. • A statechart describes a complete lifetime for classes with complex behavior

  5. 1. Basic Steps in Implementation • Define methodinterface: • Give a formal/informal description of the functionality of an operation; • Useful in reducingmisunderstanding; • Allows splitting the workload. • Decide the order of implementation: • Which class/subsystem to start. • Implement the design using a suitable programming language.

  6. Step 1. Defining Method Interface • During design: • Detailed information of the method header are defined: • Returned Type, Parameter Type; • Accessibility. • public, private, protected • However, the functionality is not formally defined: • What should the method do? What is the algorithm? • What are acceptable values for the parameter? • Etc…

  7. Operation Contract • Writing the operation contract is one possible way to define the functionality. • Define the precondition: • Express the constraint regarding the attributes of the class and the actual parameter. • Define the postcondition: • Express the effect of an operation: • Instance Creation/Deletion; • Attribute Modification; • Association Formed/Broken. • Description can scale in formality.

  8. + deposit (amt : float)+ withdraw (amt : float) BankAccount - balance Operation withdraw()Contract: Example Precondition: - amt > 0 - amt <= balancePostcondition: - New balance = Old balance - amt

  9. Step 2. Order of Implementation • Many classes with dependencies in the design: • Need an order of implementation. • Two basic strategies: • Top-Down: • Starts with high-level components. (e.g., Sys Manager class) • Then continue to implement the dependent components. • Bottom-Up: • Starts with the lower level classes, i.e., classes with least dependency. (Book, Dish, etc.) • Then proceed to code classes that make use of the implemented classes.

  10. Example A myB B • myB may be an attribute in class A of class B; • The navigability is one possible indicator of the dependency. methodA() methodB() { myB.methodB();} A B A depends on B, i.e., Amakes use of B

  11. Top Down Implementation • Starts with Class A, then Class B. • Advantages: • Class A represents ahigher level component as it makes use of other classes. • Starting with high level components enables earlyvalidation of the overall system. • Disadvantages: • Need temporary implementation (known as stub) for lower classes. • Example: • A temporary implementation of methodB()is needed for the implementation of methodA().

  12. Bottom Up Implementation • Starts with Class B, then Class A. • Advantages: • Low level classes can usually stand alone. • No need for stub. • Disadvantages: • Have to postpone the generation of a complete executable program.

  13. 2. Class Diagram Implementation

  14. Implementing Classes • Basic mapping: • A UML Class is implemented by a class in Java, C++, etc; • Attributes are implemented by fields; • Operations are implemented by methods. • There may be some language specific issues: • E.g., the implementation of abstract classes, interfaces, and generalization.

  15. # # + + + Example: The Booking Class public abstract class Booking { protected int covers; protected Date date; protected Booking(int c, Date d) { covers = c; date = d; } public void setCovers(int c) { covers = c; } public Date getDate() { return date; } public void setArrivalTime(Time t) { } } The getCovers(c:Integer) operation should be setCovers(c:Integer).

  16. Example: Generalization public class WalkIn extends Booking { public WalkIn(...) { ... } } public class Reservation extends Booking { Time arrivalTime ; public Reservation(...) { ... } public void setArrivalTime(Time t) { arrivalTime = t ; } } The setArrivalTime() operation should be setArrivalTime(Time t).

  17. Implementing Associations • Associations (Class Diagram) describe properties of links (Object Diagram). Account Guarantor :Account :Guarantor • A link gives one object access to another and enables message passing. • Java: References (C++: ObjectPointer) share these properties, so associations can be implemented with references. • References support only one direction of navigation. • Should restrict navigability to make implementation easier. • References should not be manipulated explicitly by other classes.

  18. Optional Unidirectional Association • Distinction between associations: • direction; • multiplicity. • Reference variables can hold: • a reference to another object; • or the null reference. • So the ‘default’ multiplicity of a reference is ‘0..1’.

  19. Implementation • The association is defined by a field in the Account Java class holding a reference to an instance of the DebitCard Java class: • public class Account { • private DebitCard theCard ; • ... • } Good match for simple object reference. 0..1 Account DebitCard

  20. Maintaining the Association • As only Accountis “aware” of this association, it should also maintainthe association: • Setup/Removal of the link; • Appropriate methods for accessing the linked object. e.g. public DebitCard getCard(){return theCard; } Return the linked object to outsider public void setCard(DebitCard card){ theCard = card; } Changing the linked object

  21. Mutability for Association • The last example assumes that the DebitCardassociation is mutable: • An Accountobject can be linked to a differentDebitCardobject during its lifetime. • Hence, it makes sense to have the following methods for setup/removal the link: public void setCard(DebitCard card){ theCard = card; } public void removeCard( ) { theCard = null; }

  22. {Immutable} Immutable Association • Some associations are immutable: • once assigned, a link must not be altered. • The designer can state this in the class diagram: • The programmer has to check the link’s existence explicitly: Explicit Check to maintain Immutable link If there is a card, you cannot change it public void setCard(DebitCard card) { if (theCard != null) { // throw ImmutableAssociationException } theCard = card ; }

  23. Compulsory Association • Multiplicity with lowerbound larger than 0 is compulsory, i.e., “At all times, the link(s) cannot be null”. • Example: • The above means “An Accountobject must have exactly one link to a Guarantorobject at all times”. • Programmers have to check explicitly to ensure this is true.

  24. Implementation • The earliest possible opportunity to setup the link is in the constructormethod: public Account(Guarantor g) { if (g == null) { // throw NullLinkError } theGuarantor = g ; } Make sure we have a guarantor • If the association is mutable, similar checks must be performed in methods that changes the link, e.g.: public setGuarantor(Guarantor g) { if (g == null) { // throw NullLinkError } theGuarantor = g ; } Make sure we have a guarantor

  25. CPSC-4360-01, CPSC-5360-01, Lecture 9

  26. 1-to-Many Unidirectional Association • Some associations require more than one link to be stored: • Data structures, such as arrays and ArrayLists, can be used to store the references. • For a specific upper bound, e.g., “0…8”, specific checks must be implemented: public class Manager { private ArrayList<Account> theAccounts ; public void addAccount(Account acc) { theAccounts.add(acc) ; } } Stores * Accounts references.

  27. Account DebitCard Account DebitCard theCard theAccount theCard: DebitCard theAccount: Account Bidirectional Association • Some associations need to be navigated in both directions: • because references are unidirectional, it will take two references to implement a bidirectional link; • the association can be implemented by including a suitable field in each of the associated classes. Bidirectional Association stated in Class Diagram Closest implementation of the Class Diagram in Java or C++

  28. Bidirectional Association Implementation • DebitCardis optional (“0..1” from Account). • Accountis compulsory (“1” from DebitCard). • Hence, the best way to satisfy the conditions is: • Create the Accountfirst, then the DebitCard: • { • Account acc1 = new Account() ; • DebitCard aCard = new DebitCard(acc1) ; • acc1.setCard(aCard) ;} Question: Why is that the order of associations creation to satisfy the conditions?

  29. theCard acc2: Account aCard: DebitCard acc1: Account theAccount Referential Integrity • The bidirectional association is implemented as two separate references, it is important to keep them consistent. • The links should be “inversed” one to each other. • Known as referential integrity. • Example of referential integrity violation: • Account acc1 = new Account() ; • Account acc2 = new Account() ; • DebitCard aCard = new DebitCard(acc1); • acc2.setCard(aCard) ; The two links do not correspond to a valid bidirectional association!

  30. Maintaining Referential Integrity • The problem with the example code on last slide: • DebitCardcreation and reference setup (setCard() method) are two separate operations. • Responsibility of programmer to make sure the two operations are performed in a consistent fashion. • To minimize the human error, delegate one of the classes to maintain the referential integrity instead. • Example: • public class Account { • private DebitCard theCard ; • public void addCard() { • theCard = new DebitCard(this); • } • // other methods as well • } Accountclass handles both the DebitCardcreation and reference setting.

  31. Joint Creation of Objects • Suppose an association is intended to be immutable and also needs to be traversed in both directions. • Constructors of both classes should take in an instance of the other to satisfy the constraint specified by the class diagram. • Java and C++ do not allow simultaneous object creation. • Must create one of the objects with the default constructor, i.e., to violate the constraint for a short time.

  32. Code Example • Attempts to satisfy the compulsory link: Account a = new Account(g) ; Guarantor g = new Guarantor(a) ; g is not initialized. Account a = new Account(new Guarantor(a)) ; Guarantor g = a.getGuarantor( ) ; a is not initialized. • Have to violate the constraint for a while: gis initialized by default constructor, no Accountreference. Guarantor g = new Guarantor( ) ; Account a = new Account(g) ;g.setAccount(a) ; Setup the reference after Accountais properly initialized.

  33. Domain Model Implementing Bidirectional Association myG Account Guarantor myG: Guarantor myA myA: Account Some likely methods getMyG( ): GuarantorsetMyG( Guarantor ) getMyA ( ): AccountsetMyA ( Account ) Class Diagram

  34. Maintaining Bidirectional Association Methods that change the reference should maintain referential integrity. Take setMyG() for example: Have to set the reversed link too. If Accounthasalready a Guarantor: Either do not allow the link change. OR, remove the link with previous Guarantor. a :Account oldG: Guarantor The Reverse link has to be removed too. newG: Guarantor a.setMyG(newG)

  35. Code Example //Class Account public void setMyG(Guarantor newG) { if (newG == null) //throw NullLinkError if (myG != null && myG != newG) { //previous Guarantor exists myG.removeMyA(this); } if (myG == newG) return; myG = newG; //set the reverse link myG.setMyA(this); } //Class Guarantorvoid removeMyA(Account a) { //only allows holder of //the reverse link call //this method if (a == myA) myA = null; }

  36. Code Example (Cont) //Class Guarantor public void setMyA(Account newA) { if (newA == null) //throw NullLinkError if (myA != null && myA != newA) { //previous Guarantor exists myA.RemoveMyG(this); } if (myA == newA) return; myA = newA; //set the reverse link myA.setMyG(this); } //Class Accountvoid RemoveMyG(Guarantor g) { //only allows holder of //the reverse link call //this method if (g == myG) myG = null; }

  37. Observations • Even with the complicated code, there are still some problems: • The old guarantor will be without an Accountobject. • Mutual recursive functions: • setMyA calls setMyG, which calls setMyA. • Very easy to get into infinite loop. • Should avoid compulsory bidirectional association if possible. • If bidirectional association must be used, immutability is recommended to curb the coding complexity.

  38. One-to-Many Association • Raise no new issues: • Customer holds a collection of references. • Account holds a non-null reference. • Customer is a better choice as the “maintainer” for the referential integrity: • It provides a method like addAccount() that creates a new account and setup the reference. • Similar to the addCard() method on slide 29.

  39. Many-to-Many Association • Previously discussed implementation techniques can be used. • Recommendation: • Allows only one of the classes to modify the links. • E.g., It makes sense to allow only the Customerto change links to Accountsand maintain the reversed link also. • Simplify the implementation as the coding logic can be considered from one direction only.

  40. Many-to-Many Association • Another implementation technique is to reify the association: • The new class (e.g., Signatoryin the example above) is in a good position to maintain referential integrity. :Account :Signatory :Customer

  41. Qualified Association • The purpose of a qualifier is often to provide efficient access to linked objects: • For example, to access accounts given only the account number; • Also to avoid a linear search through all accounts.

  42. Implementing Qualifier • The run-time structure involves some kind of index to accounts: Using accno as index.

  43. Code Example • Hash Table is a good choice to implement the index: public class Bank{ private HashTable theAccounts; public void addAccount (Account a) { theAccounts.put(new Integer(a.getNumber()), a); } public void removeAccount(int number) { theAccounts.remove(new Integer(number)); } public Account lookupAccount(int number) { return (Account) theAccounts.get(new Integer(number)); } } put (Object Key, Object Value) get(Object Key): Object

  44. Hash table - reminder • It means a data structure that associates keys with values. • The primary operation it supports efficiently is a lookup: given a key (e.g., a person's name), find the corresponding value (e.g., that person's telephone number). • It works by transforming the key using a hash function into a hash, a number that is used to index into an array to locate the desired location ("bucket") where the values should be.

  45. Hash table - reminder • Like arrays, hash tables provide constant-time O(1) lookup on average, regardless of the number of items in the table.

  46. Association Class • Common strategy: • Transform the association class into a simple class; replacing it by two associations.

  47. Module Student 1 * * Module Student :Module :Student :Module :Student :Registration Registration Registration :Registration :Registration :Registration Mark = 89 Mark = 76 Mark: Integer Mark = 89 Mark: Integer Mark = 76 :Student :Student Implementing Association Class Class Diagram Class Diagram Object Diagram Object Diagram

  48. Code Example public class Module { private Vector registrations; public void enrol(Student st) { registrations.addElement( new Registration(st) ); } ... } Maintain the link to Registration Pass the Student to Registration. class Registration { private Student student; private int mark; Registration(Student st) { student = st; mark = 0; } ... } Registration keeps track of the Student reference.

  49. Implementing Statecharts • If a statechart for a class exists: • it gives an overall specification of the class behaviour. • it can be used to structure the implementation of the operations in a systematic way. • Example: Account class • States: InCredit, OverDrawn, Suspended. • Operations: deposit, withdraw, suspend, unsuspend.

More Related