# Programming 2.2 exercise solutions ## UML diagrams ```mermaid stateDiagram SequenceDiagram --> InteractionDiagrams CommunicationDiagram --> InteractionDiagrams InteractionDiagrams --> Behavioural ClassDiagram --> Structural PackageDiagram --> Structural ``` *** ## M1 Iterative, evolutionary and agile ### Agile manifesto - Individuals and interactions over processes and tools - Working software over comprehensive documentation - Customer collaboration over contract negotiation - Responding to change over following a plan ### EX2 Process consultant To Gaston, because a team with agile approach has a better chance to finish everything. Also to Rita, because agile produces business value quicker than waterfall. However, because of the iterative process, unexpected costs can arise. *** ## M2 Inception ### EX2 Drill glossary > Make a glossary for the Grill mini case. Separate in a domain and technical section and order each alphabetically. > Include concepts, their definition and aliases. #### Domain |Concept|Definition|Synonims|Remarks|Values |-|-|-|-|-| |Administrator|A contributor with increased platform privileges||E.g. teachers, developers |Answer|user input for a Question| |Badge|Grants access to contribution priviliges||Acquired by collecting reputation|Mentor, Reviewer |Course|Courses in participaint institution's programmes|class, subject| |Exam|Trial questionnaires in the system|test|Can be based on any real-life assessment from the participating universities |Hint|Additional help to answer a question|||Level 1, 2, 3 |Point|Reward for a correct answer to a question that counts to the exam score |Programme|Programmes of a participating institution |User|Student with or without badges|Student |Question|Atomic assessment in exam||Multiple choice or open answer| |Reputation|Reward for succeeded exam scores, distributed per course|karma|Visible on user profile| |Reward|Advantages users can earn by collecting reputation||e.g. vouchers, film tickets |Score|Final mark received on a test|exam result|calculated by points and used up hints|| |Subscription|Describes a student's enrollment in a course|| |Vote|Positive or negative feedback on a hint submitted by a mentor||numerical #### Technical |Concept|Definition|Synonims|Remarks |-|-|-|-| |External Administrative System|The participating universities inner administrative system|EAS|Accessed by APIs |System|The Drill platform as a whole||E.g. *students quit if the system is unresponsive* > Are there any words in the domain that have another meaning for KdG outside the scope of the project? Plenty. *** ## M3 Requirements Definition of Ready (DoR): INVEST **I**ndependent: dependencies are available **N**egotiable: stakeholders understand and agree on the content **V**aluable: a priority has been assigned **E**stimable: sufficient details available to estimate effort **S**mall: can be implemented in 1 sprint **T**estable: acceptance criteria has been defined, test data available Definition of Done (DoD): - features implemented - acceptance criteria fulfilled - code has been peer reviewed - code has 85% test coverage - all tests succeed - accepted by stakeholders *** ## M4 Domain Model ```mermaid classDiagram A --|> B: Inheritance C --* D: Aggregation E ..> F: Dependency G "0..1" -- "*" H: Relation I --> J: Association ``` ### Exercise 1 > The Belgian National Registration Number is a Value Object (UML datatype). Write a Java class for it that respects the Value Object conventions. ```java public final class RegistryNumber { private final String value; public RegistryNumber(String value) { this.value = value; } public String getValue() { return value; } } ``` ### Exercise 2 1. Entity 2. - code: primitive - destination: value object - hotel: entity - maxParticipants: primitive - hosts: collection ### Exercise 3 > Extend the Money class with an add method, adding an amount (in the same currency) to the Money object. Respect the immutability of the class. ```java @EqualsAndHashCode public final class Money { private final double amount; private final Currency currency; public Money(double amount, Currency currency) { this.amount = amount; this.currency = currency; } public double getAmount() { return amount; } public Currency getCurrency() { return currency; } public Money add(double amount) { this = new Money(this.amount + amount, this.currency); return this; } } ``` ### Exercise 4 > A country is divided into provinces. A province is divided into cities. A country has neighbouring countries, a province has neighbouring provinces and a city has neighbouring cities. Countries, provinces and cities have all names and sizes (in square km). > 1. Make a domain model to handle this information. ```mermaid classDiagram class Area { <<abstract>> name: String size: double } class Country class Province class City Country --|> Area Province --|> Area City --|> Area Area "*" -- "*" Area: neighbours Country "1" -- "*" Province Province "1" -- "*" City ``` Disadvantages: circular reference. > 2. What would be the most generic domain model you can make? What are advantages/disadvantage of a more generic model? ```mermaid classDiagram class AreaType { <<enum>> COUNTRY, PROVINCE, CITY } class Area { name: String size: double type: AreaType } Area "1" -- "*" Area: contains Area "*" -- "*" Area: neighbours ``` *** ## M5 - From analysis to design ### Exercise 1 **1.** **User Story** As a traveler, I want to see the fee breakdown before I pay So that I know how much the base price and the zone price cost **Given** the traveler selected a ticket and pressed on pay **When** the ticket is valid through 3 zones **Then** the dispenser displays £2 + £1.5 **2** As a ticket dispenser, I want to be returned to the main menu if the latest transaction is idle for 1 minute So that the next buyer don't have to press on cancel if the previous left before finalizing **Given** the traveler selected a ticket, but didn't press on finalize **Given** the traveler selected a ticket, pressed on finalize but didn't pay **When** the system is in this state for 1 minute **Then** the purchase is automatically cancelled and the dispenser displays the main menu again **Sequence diagram** ```mermaid sequenceDiagram autonumber actor T as Traveler participant TD as :TicketDispenser participant PS as :PaymentService T->>+TD: enters zone count Note over T,TD: 3 TD--)-T: displays price Note over TD,T: £2 + 3 * £0.5 T->>+TD: presses on pay TD--)-T: prompts for card T->>+TD: presents card TD->>+PS: sends card data PS--)-TD: verifies payment TD--)-T: prints ticket Note over TD,T: Valid for zones A, B, C<br>£3.5 ``` **Operation contracts** | **No** | **Operation** | **Cross reference** | **Pre-conditions** | **Post-conditions** | | -------| ------------------| ------------- | -----| -----------------------| | 1 | Enters zone count | Zone selection| None | `TicketSale ts` (instance creation)| |2|Displays price||Existing `TicketSale` with number of zones|Calculated price displayed| |3|Presses on pay|| ## M6 Interaction diagrams ### Exercise 1: XFrame interaction diagram > We have a class XFrame with attributes nameField of type JTextField and helloLabel of type JLabel with a method nameAction ```java class XFrame { JTextField nameField = new JTextField(); JLabel helloLabel = new JLabel(); void nameAction() { String name= nameField.getText(); String hello = "Hello " + name; helloLabel.setText(hello); } } ``` > Make an interaction diagram for a call to nameAction on an XFrame. Is the value of variable hello specified in the sequence diagram? ```mermaid sequenceDiagram actor A as Actor participant XF as :XFrame participant JTF as :JTextField participant JL as :JLabel A ->>+ XF: nameAction() XF ->>+ JTF: getText() JTF ->>- XF: text XF ->>+ JL: setText(text) ``` > How does the interaction diagram change if we write the method nameAction like this? ```java public void nameAction() { helloLabel.setText("Hello " + nameField.getText()); } ``` It doesn't. >How does the interaction diagram change if we write the method nameAction like this (happy is en attribute of XFrame )? ```java void nameAction() { String name = nameField.getText(); String hello; if(happy) hello = "Nice to meet you " + name; else hello = "Hello " + name; helloLabel.setText(hello); } ``` ```mermaid sequenceDiagram actor A as Actor participant XF as :XFrame participant JTF as :JTextField participant JL as :JLabel A ->>+ XF: nameAction() XF ->>+ JTF: getText() JTF ->>- XF: text alt happy XF ->>+ JL: setText("Nice to meet you" + text) else XF ->>+ JL: setText("Hello" + text) end ``` ### Exercise 2: Printer > Make an interaction diagram for a computer receiving a request from a user to print a file. The computer contacts a print server which sends it to the printer. If the printer is busy the print job should be queued by the print server. ```mermaid sequenceDiagram Actor U as User participant C as Computer participant PS as PrintServer participant P as Printer U ->>+ C: print C ->>+ PS: print(:File) alt printerBusy loop printerBusy PS ->>+ PS: queue(:File) end else PS ->>+ P: print(:File) end P ->>- PS: done PS ->>- C: done C ->>- U: done ``` ### Exercise 3: flights interaction diagram > Class Airline manages multiple instances of class Flight (with attributes: flightNumber, price and destination). Each Flight instance has a unique number. Draw a domain model and an interaction diagram for these actions: > 1. Raise the price for a flight with a given flightNumber. > 2. Raise the price of all flights. > 3. Raise the price of all flights with a given destination. > 4. Remove a flight with a given flightNumber ```mermaid classDiagram class Airline { name: String } class Flight { flightNr: long price: double destination: String } Airline "1" -- "*" Flight ``` #### 1. ```mermaid sequenceDiagram actor M as Manager participant A as :Airline participant Fs as :Flight[*] participant F as :Flight M ->>+ A: raiseByFlightNr(flightNr:long, percent:double) A ->>+ Fs: getByFlightNr(:long) Fs ->>- A: :Flight A ->>+ F: raisePrice(:double) ``` #### 2. ```mermaid sequenceDiagram actor M as Manager participant A as :Airline participant Fs as :Flight[*] participant F as :Flight M ->>+ A: raiseAll(percent:double) loop i < Flight.size A ->>+ Fs: get(i) Fs ->>- A: :Flight A ->>+ F: raisePrice(percent:double) end ``` #### 3. ```mermaid sequenceDiagram actor M as Manager participant A as :Airline participant Fs as :Flight[*] participant F as :Flight M ->>+ A: raiseByDestination(destination: String, percent:double) loop i < Flight.size A ->>+ Fs: get(i) Fs ->>- A: f:Flight opt f.destination == destination A ->>+ F: raisePrice(percent:double) end end ``` #### 4. ```mermaid sequenceDiagram actor M as Manager participant A as :Airline participant Fs as :Flight[*] M ->>+ A: removeByFlightNr(flightNr:long) A ->>+ Fs: getByFlightNr(:long) Fs ->>- A: f:Flight A ->>+ Fs: remove(f:Flight) ``` ### Exercise 4: `Team::getPlayerNames():String[]` ## M7 Design Class Diagrams Also called Evolved Domain Model. ### Exercise 1: bidirectional navigation > For the class diagram below, add a method to link a person to another dog. Make sure that the bidirectional navigation remains consistent. Also, add a method to link a Dog to another person. Show how the methods work in an interaction diagram. ```mermaid classDiagram class Person { name:String birthday:Date setDog(:Dog) } class Dog { name:String breed:String setPerson(:Person) } Person "0 .. 1" <--> "0..1" Dog : has ``` `setDog():` ```mermaid sequenceDiagram actor U as User participant P as :Person participant OD as old:Dog participant ND as new:Dog U ->>+ P: setDog(new:Dog) opt this.dog != new opt old != null P ->>+ OD: setDog(null) Note over P,OD: old = this.dog end opt new != null P ->>- ND: setDog(this) end end ``` `setPerson():` Same, but reversed. ```mermaid sequenceDiagram actor U as User participant D as :Dog participant OP as old:Person participant NP as new:Person U ->>+ D: setPerson(new:Person) opt this.person != new opt old != null D ->>+ OP: setPerson(null) Note over D,OP: old = this.person end opt new != null D ->>- NP: setPerson(this) end end ``` > How would your solution change if a Person can have multiple dogs? Provide an interaction diagram. ### Exercise 2: movie roles > Write the classes using roles as concepts in a package a. Initialise your system with the objects in the above example. Is the model a good solution for this business context? ```java package a; import java.util.List; import java.util.ArrayList; import java.time.LocalTime; abstract class User { String name; User(String name) { this.name = name; } } class Planner extends User { List<Show> managedShows = new ArrayList(); Planner(String name) { super(name); } } class ContentManager extends User { List<Movie> managedMovies = new ArrayList(); ContentManager(String name) { super(name); } } class Show { Movie movie; LocalTime start; Show(Movie movie, LocalTime start) { this.movie = movie; this.start = start; } } class Movie { String title; Movie(String title) { this.title = title; } } class Main { public static void main(String[] args) { /* This roles as concept model is not a good solution for this context, * because it introduces double effort if we want to update Josh. */ Planner planner = new Planner("Josh"); ContentManager manager = new ContentManager("Josh"); Movie dune = new Movie("Dune"); Movie spiderman = new Movie("Spiderman"); Movie brokenCircle = new Movie("The Broken Circle Breakdown"); Show s1 = new Show(dune, LocalTime.of(16, 0)); Show s2 = new Show(brokenCircle, LocalTime.of(20, 0)); manager.managedMovies.add(spiderman); planner.managedShows.add(s1); planner.managedShows.add(s2); } } ``` > Copy your code to a package b. Write the classes using roles as associations. Initialise your system with the objects in the above example. Is the model a good solution for this business context? ```java package b; import java.util.List; import java.util.ArrayList; import java.time.LocalTime; class User { String name; List<Show> plannedShows = new ArrayList(); List<Movie> plannedMovies = new ArrayList(); User(String name) { this.name = name; } } class Show { Movie movie; LocalTime start; Show(Movie movie, LocalTime start) { this.movie = movie; this.start = start } } class Movie { String title; Movie(String title) { this.title = title; } } class Main { static void main(Strin[] args) { /* This model is a better solution, because we don't have to * double manage Josh */ User u = new User("Josh"); Movie dune = new Movie("Dune"); Movie spiderman = new Movie("Spiderman"); Movie brokenCircle = new Movie("The Broken Circle Breakdown"); Show s1 = new Show(dune, LocalTime.of(16, 0)); Show s2 = new Show(brokenCircle, LocalTime.of(20, 0)); } } ``` ### Exercise 3: student inheritance > Our developers have indicated a problem with this design: when a student becomes a MasterStudent, the object needs to be removed and recreated. Change the design to solve this. Do you need to add business rules to guarantee that your new design keeps the same semantics as the original design? In this design, there are is no extra business logic. `StudentStatus` could also be an enumeration that each `Student` has an attribute of, and then extra rules are needed to enforce the fact bachelor students don't have a thesis. ```mermaid classDiagram class Student { number: long name: String } class StudentStatus { <<abstract>> start: LocalDate } class Institute { location: String } class BachelorStatus class MasterStatus class Thesis { title: String } Student "*" -- "1" Institute Student "1" -- "1" StudentStatus MasterStatus "1" -- "1" Thesis BachelorStatus --|> StudentStatus MasterStatus --|> StudentStatus ``` ## M8 GRASP Part of Responsibility-Driven Design. Generalized Responsibility Assignment Software Patterns Important patterns: - low coupling - high cohesion - controller - creator - information expert ### Exercise 1: communication diagram to class diagram, coupling > Given the above communication diagram: > 1. Make an (evolved) domain model ```mermaid classDiagram class B { bCode getE() } class C { m1() } class E { doQ(:D) } C --> "*" B B --> "1" E ``` > 2. Change the communication diagram to lower coupling, if possible. ```mermaid flowchart LR Start -- "m1(bCode, d)" --> :C :C -- "1: b = getCode(bCode)" --> :B[":B[*]"] :C -- "2: doQ(d)" --> b:B b:B -- "3: e = getE()" --> b:B b:B -- "4: doQ(d)" --> e:E ``` ### Exercise 2: Contacts GRASP patterns: ```mermaid classDiagram class Contacts class Person { name: String } class Phone { type countryCode: int number: int } Contacts "1" -- "*" Person Person "1" -- "*" Phone ``` > Study the above domain model. > 1. Make an interaction diagram for a user story where a new user with one phone is added. ```mermaid flowchart Start -- "addNew(name, type, countryCode, number)" --> :Contacts :Contacts -- "<< create >>(name, type, countryCode, number)" --> :Person :Person --"<< create >> (type, countryCode, number)" --> :Phone ``` **Low coupling**, because `Contacts` needn't create `Phone`. > 2. Make an interaction diagram for a user story to retrieve all phones with a given countryCode. ### Exercise 3: Enrollment 1. ```mermaid classDiagram class Enrollment class Course { durationInDays: int } class CourseEnrollment { start: Date end: Date } class EnrollmentController { getGraduationDate(:Enrollment) } class EnrollmentService { getGraduationDate(:Enrollment) } Course "1" -- "*" CourseEnrollment CourseEnrollment --* Enrollment EnrollmentController --> EnrollmentService ``` 3. ```mermaid sequenceDiagram actor U as UI participant EC as :EnrollmentController participant ES as :EnrollmentService participant E as e:Enrollment participant CE as :CourseEnrollment U ->>+ EC: getGraduationDate(e:Enrollment) Note over U, EC: e could be the result of automatic parameter<br>parsing, as in e.g. Java Sprint EC ->>+ ES: getGraduationDate(e:Enrollment) ES ->>+ E: getGraduationDate() loop courseEnrollments:CourseEnrollment[*] ES ->>+ CE: d=getEnd() Note over ES, CE: finding latest endDate not elaborated end ES ->>- EC: d:Date EC ->>- U: d:Date ``` GRASP patterns: **Controller**, because `EnrollmentController` is the only point of interaction from the UI. **Information expert**, because `EnrollmentService` has the information to obtain the graduation date. **High cohesion**, because all objects do one thing, and they do that well, in order to fulfill the query. # **Low couplnig**, because not all objects have knowledge about each other. ## M14 Logical architecture ### EX2 Convert addressbook application to layered architecture > Adapt the interaction diagrams to fit a 3 layer architecture. Addressbook controller should be stateless. ```mermaid flowchart TD ABC[:AddressBookController] ABS[:AddressBookService] ABR[:AddressBookRepository] PS[:PersonService] PR[:PersonRepository] AS[:AddressService] AR[:AddressRepository] AB[AddressBook] P[Person] A[Address] Start -- "1. addPerson(nm, str, hNr, zip, city)" --> ABC ABC -- "2. addPerson(nm, str, hNr, zip, city)" --> ABS ABS -- "3. p=addPerson(nm)" --> PS PS --"3.1 p=create(nm)" --> PR PR --"3.2 p=<< create >> (nm) " --> P ABS -- "4. a=addAddress(str, hNr, zip, city)" --> AS AS --"3.1 a=create(str, hNr, zip, city)" --> AR AR --"3.2 a=<< create >>(str, hNr, zip, city)" --> A ABS -- "5. create(p, a)" --> ABR ABR -- "5.1 << create >>(p, a)" --> AB ``` > 2. Adapt the design class diagram based on the modified interaction diagrams > 3. Add a package diagram based on the above diagrams nah DDD, RDD, GoF, GRASP, INVEST