Detailed Table of Contents
Introduction
[W10.3a] Design → Design Patterns → Introduction → What
[W10.3b] Design → Design Patterns → Introduction → Format
Singleton pattern
[W10.3c] Design → Design Patterns → Singleton → What
[W10.3d] Design → Design Patterns → Singleton → Implementation
[W10.3e] Design → Design Patterns → Singleton → Evaluation
Facade pattern
Guidance for the item(s) below:
Good news: this will the the last installment of UML notations.
Bad news: we are going to cover an entire new diagram type in one go (reason: to give you more time to use them in project documentation).
Can draw basic sequence diagrams
UML Sequence Diagrams → Introduction UML/SequenceDiagrams
UML Sequence Diagrams → Basic Notation UML/SD/Basic
UML Sequence Diagrams → Loops UML/SD/Loops UML Sequence Diagrams → Object Creation UML/SD/Creation
UML Sequence Diagrams → Minimal Notation UML/SD/Minimal
Exercises
Explain Sequence Diagram about Machine
Explain in your own words the interactions illustrated by this Sequence Diagram:
Draw a Sequence Diagram for the code (PersonList
, Person
, Tag
)
Consider the code below:
class Person {
Tag tag;
String name;
Person(String personName, String tagName) {
name = personName;
tag = new Tag(tagName);
}
}
class Tag {
Tag(String value) {
// ...
}
}
class PersonList {
void addPerson(Person p) {
// ...
}
}
Draw a sequence diagram to illustrate the object interactions that happen in the code snippet below:
PersonList personList = new PersonList();
while (hasRoom) {
Person p = new Person("Adam", "friend");
personList.addPerson(p);
}
Find notation errors in Sequence Diagram
Find notation mistakes in the sequence diagram below:
Can draw intermediate-level sequence diagrams
UML Sequence Diagrams → Object Deletion UML/SD/Deletion UML Sequence Diagrams → Self-Invocation UML/SD/Self-Invocation UML Sequence Diagrams → Alternative Paths UML/SD/Alternative UML Sequence Diagrams → Optional Paths UML/SD/Optional
UML Sequence Diagrams → Calls to Static Methods
UML/SD/StaticMethods
Method calls to static
(i.e., class-level) methods are received by the class itself, not an instance of that class. You can use <<class>>
to show that a participant is the class itself.
In this example, m
calls the static method Person.getMaxAge()
and also the setAge()
method of a Person
object p
.
Here is the Person
class, for reference:
Exercises
What’s going on here?
What’s going on here?
Logic
object is executing a parallel thread.Logic
object is executing a loop.Logic
object is creating another Logic
instance.Logic
object’s methods is calling another of its methods.Minefield
object is calling a method of Logic
.(d)
Explain Sequence Diagram (ParserFactory
)
Explain the interactions depicted in this sequence diagram.
First, the createParser()
method of an existing ParserFactory
object is called. Then, ...
Draw Sequence Diagram for printing a quote
Draw a sequence diagram to represent this code snippet.
if (isFirstPage) {
new Quote().print();
}
The Quote
class:
class Quote {
String q;
Quote() {
q = generate();
}
String generate() {
// ...
}
void print() {
System.out.println(q);
}
}
new Quote().print();
as two method calls.print()
method is called.
Can interpret sequence diagrams with parallel paths
UML uses par
frames to indicate parallel paths.
Notation:
Logic
is calling methods CloudServer#poll()
and LocalServer#poll()
in parallel.
If you show parallel paths in a sequence diagram, the corresponding Java implementation is likely to be multi-threaded because a normal Java program cannot do multiple things at the same time.
Can interpret sequence diagrams with reference frames
UML uses ref frame to allow a segment of the interaction to be omitted and shown as a separate sequence diagram. Reference frames help you to break complicated sequence diagrams into multiple parts or simply to omit details you are not interested in showing.
Notation:
The details of the get minefield appearance
interactions have been omitted from the diagram.
Those details are shown in a separate sequence diagram given below.
Follow up notes for the item(s) above:
After you have learned how to interpret sequence diagrams, you can watch this:
Guidance for the item(s) below:
Previously, you learned:
This week, we cover design patterns, a concept that builds upon the above. Again, we limit to only two of them, for similar reasons.
Guidance for the item(s) below:
First, let's learn what design patterns are, in general.
Can explain design patterns
Design pattern: An elegant reusable solution to a commonly recurring problem within a given context in software design.
In software development, there are certain problems that recur in a certain context.
Some examples of recurring design problems:
Design Context | Recurring Problem |
---|---|
Assembling a system that makes use of other existing systems implemented using different technologies | What is the best architecture? |
UI needs to be updated when the data in the application backend changes | How to initiate an update to the UI when data changes without coupling the backend to the UI? |
After repeated attempts at solving such problems, better solutions are discovered and refined over time. These solutions are known as design patterns, a term popularized by the seminal book Design Patterns: Elements of Reusable Object-Oriented Software by the so-called "Gang of Four" (GoF) written by Eric Gamma, Richard Helm, Ralph Johnson, and John Vlissides.
Exercises
Definition of design patterns
Which one of these describes the ‘software design patterns’ concept best?
(b)
Can explain design patterns format
The common format to describe a pattern consists of the following components:
Exercises
Anti-patterns required?
When we describe a pattern, we must also specify anti-patterns.
False.
Explanation: Anti-patterns are related to patterns, but they are not a ‘must have’ component of a pattern description.
Guidance for the item(s) below:
Now that you know what design pattern is, let's learn a few example design patterns.
Can explain the Singleton design pattern
Context
Certain classes should have no more than just one instance (e.g. the main controller class of the system). These single instances are commonly known as singletons.
Problem
A normal class can be instantiated multiple times by invoking the constructor.
Solution
Make the constructor of the singleton class private
, because a public
constructor will allow others to instantiate the class at will. Provide a public
class-level method to access the single instance.
Example:
Exercises
Statements about the Singleton pattern
You use the Singleton pattern when
(c)
Can apply the Singleton design pattern
Here is the typical implementation of how the Singleton pattern is applied to a class:
class Logic {
private static Logic theOne = null;
private Logic() {
...
}
public static Logic getInstance() {
if (theOne == null) {
theOne = new Logic();
}
return theOne;
}
}
Notes:
private
, which prevents instantiation from outside the class.private
class-level variable.public
class-level operation getInstance()
which instantiates a single copy of the singleton class when it is executed for the first time. Subsequent calls to this operation return the single instance of the class.If Logic
was not a Singleton class, an object is created like this:
Logic m = new Logic();
But now, the Logic
object needs to be accessed like this:
Logic m = Logic.getInstance();
Can decide when to apply Singleton design pattern
Pros:
Cons:
Given that there are some significant cons, it is recommended that you apply the Singleton pattern when, in addition to requiring only one instance of a class, there is a risk of creating multiple objects by mistake, and creating such multiple objects has real negative consequences.
Can explain the Facade design pattern
Context
Components need to access functionality deep inside other components.
The UI
component of a Library
system might want to access functionality of the Book
class contained inside the Logic
component.
Problem
Access to the component should be allowed without exposing its internal details. e.g. the UI
component should access the functionality of the Logic
component without knowing that it contains a Book
class within it.
Solution
Include a a French word that means 'front of a building'Façade class that sits between the component internals and users of the component such that all access to the component happens through the Facade class.
The following class diagram applies the Facade pattern to the Library System
example. The LibraryLogic
class is the Facade class.
Exercises
Is this Facade?
Is the design below likely to use the Facade pattern?
True.
Facade is clearly visible (Storage is the <<Facade>>
class).
Follow up notes for the item(s) above:
To learn more design patterns, you can refer to https://se-education.org/se-book/designPatterns/
Guidance for the item(s) below:
Previously, you learned how to write JUnit tests. How do you know which parts of the code is being tested by your tests? That's where test coverage comes in.
Can explain test coverage
Test coverage is a metric used to measure the extent to which testing exercises the code i.e., how much of the code is 'covered' by the tests.
Here are some examples of different coverage criteria:
if
statement evaluated to both true
and false
with separate test cases during testing is considered 'covered'. if(x > 2 && x < 44)
is considered one decision point but two conditions.
For 100% branch or decision coverage, two test cases are required:
(x > 2 && x < 44) == true
: [e.g. x == 4
](x > 2 && x < 44) == false
: [e.g. x == 100
]For 100% condition coverage, three test cases are required:
(x > 2) == true
, (x < 44) == true
: [e.g. x == 4
](x < 44) == false
: [e.g. x == 100
](x > 2) == false
: [e.g. x == 0
]Exercises
Highest intensity coverage
Which of these gives us the highest intensity of testing?
(b)
Explanation: 100% path coverage implies all possible execution paths through the SUT have been tested. This is essentially ‘exhaustive testing’. While this is very hard to achieve for a non-trivial SUT, it technically gives us the highest intensity of testing. If all tests pass at 100% path coverage, the SUT code can be considered ‘bug free’. However, note that path coverage does not include paths that are missing from the code altogether because the programmer left them out by mistake.
Guidance for the item(s) below:
Learn how to measure test coverage in your tP. You will be asked to demo that in the coming tutorial.
Can explain how test coverage works
Measuring coverage is often done using coverage analysis tools. Most IDEs have inbuilt support for measuring test coverage, or at least have plugins that can measure test coverage.
Coverage analysis can be useful in improving the quality of testing e.g., if a set of test cases does not achieve 100% branch coverage, more test cases can be added to cover missed branches.
Measuring code coverage in Intellij IDEA