
Note: These notes are a mixture of lecture material, textbook material and private research. All credit to the University of Melbourne.
Software Modelling and Design
Modelling and Design
Aim is to learn about Software Modelling and Software Design
Software Design
Purposefully choosing the structure and behaviour of the software system. Behaviour is about how the system responds to inputs and events, and choosing how parts of the system collaborate to achieve goals.
Software Modelling
Creation of tangible, but abstract, representations of a system so that design ideas can be communicated and critiqued, and alternatives explored.
Analysis and Design
Analysis
Analysis - investigation of the problem and requirements
Object-Oriented Analysis - finding and describing objects and concepts in the problem domain
Design
Design - conceptual solution to a problem that meets the requirements
Object-Oriented Design - defining software objects and their collaboration
Implementation
Implementation - a concrete solution to a problem that meets the requirements
Object-Oriented Implementation - implementation in object-oriented languages and technologies
Object-orientation emphasises the representation of objects.
We want to understand the domain → represent it → define solution → implement it
(all in terms of objects)
Should be able to:
- apply principles and patterns to create better designs
- assign responsibilities to SW objects with emphasis on the 9 GRASP principles
- iteratively follow a set of common analysis and design activities (based on Agile/Unified Process)
- create frequently used models in UML
Domain Model
Used to visualise real-world concepts. Includes domain objects, attributes, responsibilities and multiplicities.
Design Class Diagram
Used to visualise software elements. Includes classes, attributes, methods and multiplicities.
Structure:
- System
- Build
- Subsystem
- Package
- Cluster
If packages are highly dependent on each other, they are highly coupled. High coupling is usually bad and hard to understand.
Developers tend to add complexity unnecessarily if unconstrained. Important to ensure developers think through implications of a structure/design change to maintain good design (particularly important in large projects).
This subject focusses on the object-oriented design method, with object-oriented modelling and modelling heuristics.
Sidenote: Heuristic - any approach to problem solving that employs a practical method not guaranteed to be optimal but sufficient for immediate goals. Used when classic methods are too slow, or for finding an approximate solution when classic methods fail to find any exact solution.
UML - Unified Modelling Language
Domain Models
Should be able to:
- Identify conceptual classes related to the current iteration
- Create an initial domain model
- Model appropriate attributes and associations
Domain models look at the role that use cases play in relation to modelling. The purpose is understanding the problem space (not talking about software yet). The domain objects will be familiar to experts in the problem space.
This diagram shows the relationship between artefacts.
Associations - model the relationships between the objects
Attributes - give information about the domain objects beyond the relationships
A domain model should not include:
- software artefacts/classes (such as a database)
- methods
Conceptual Class
An idea, thing, or object in the real world
A Conceptual class C is a combination of:
- Symbol - words or images representing C
- Intension - the definition of C
- Extension - a set of instances represented by C
Representation Gap
Ideal to keep the “representation gap” between domain and design model as small as possible. This helps stakeholders to understand the software. The domain model should inspire objects and names in the design model.
Steps to creating a domain model:
- Find the conceptual classes
- Reuse or modify existing models
- Use a category list
- Identify noun phrases
- Draw them as classes in a UML class diagram
Make a list of candidate conceptual classes in domain based on commonly
occurring categories e.g:
- Business transactions - Sale, Payment
- Physical objects - Item, Register, Board, Piece
- Containers of things - Store, Bin, Aeroplane
- Recording transactions - Register, Ledger
- Add associations and attributes
Modelling is highly iterative, need to keep adding, removing and adjusting.
Attributes vs Classes
If something is not considered a number or text in the real world, it’s probably a conceptual class, not an attribute.
Description Classes
A description class contains information that describes something else. Should be used when:
- groups of items share the same description
- items need to be described even when there are currently no examples
- it reduces redundant or duplicated information
- deleting instances results in losing required info
We should clearly distinguish between items and their descriptions to avoid duplication.
Associations
An association represents some meaningful and significant relationship between classes. Guidelines:
- significant in domain (don’t have to model all associations)
- knowledge of the relationship needs to be preserved
- derived from common associations list
Association category list:
- A is a member of B - Cashier-Store, Player-MonopolyGame, Pilot-Airline
- A is a role related to a transaction B - Customer-Payment, Passenger-Ticket
- A is physically or logically contained in/on B - Register-Store, Item-Shelf, Square-Board
- A is known/logged/recorded/reported/captured in B - Sale-Register, Piece-Square
Association name - User verbs
Multiplicity - 0..1
→ “optionally-one”. Multiplicities will be
dependent on the context and what rules we want to enforce.
Use Cases
Use Cases - Textual representations of how particular users or actors interact with the system to achieve a goal
Use Case Diagrams - Give an overview of the use cases and the relationships between them
SuD - system under discussion (what we’re aiming to develop)
Actor - something with behaviour, such as a person, computer system or organisation (e.g. a cashier). Interacts with the SuD (can be people or other systems). Can trigger behaviour in the system and react to output.
Scenario (use case instance) - a specific sequence of actions and interactions between actors and the SuD
Use Case - a collection of related success and failure scenarios that describe an actor using the SuD to support a goal. Non-conditional (a specific sequence). Use Cases are text, not diagrams, and are not object-oriented constructs.
A use case can be brief, casual or fully dressed.
With use cases don’t say anything about how the user interacts with the system, just what information is going in or out.
Define the main success scenario and any alternate scenarios.
Types of Actors:
- Primary - uses services of the SuD
- Supporting - provides a service to the SuD (often a computer system, but not necessarily)
- Offstage - has an interest in behaviour of the use case, but is not primary or supporting
Tests for “Useful” Use Cases:
- Boss Test - would your boss be happy if you told them the use case you’ve been working on all day?
- Elementary Business Process Test - should be a task performed by one person in one place at one time, in response to a business event, which adds measurable business value and leaves the data in a consistent state
- Size Test - very seldom a single action/step; often 3-10 pages of text for a fully dressed use case
Object-Oriented Layers
An example of layers can be:
- User Interface
- Application Logic - our primary focus → explore how to design objects (other layers can be technology/platform dependent)
- Other layers/components
System Sequence Diagrams
A form of dynamic modelling. They capture the dynamic context of the system.
Treats the system as a black box.
Derived from use cases.
Objectives:
- identify system events
- create system sequence diagrams for use case scenarios
System Sequence Diagrams (SSDs) try to work out what events the system needs to handle by going through the use case diagrams and extracting the sequence of events.
A SSD analyses the “external” behaviour of the system.
Sometimes show what’s going inside the system “black box” if it’s necessary to understand what is going on.
Multiple Actors
Mobile user
is the primary user. Can have secondary actors like
ProductInventory
and MappingService
.
Both indicate a return, just different notation (explicit vs implicit):
closestToMe(storeLocations): storeLocation
:store
Choose abstract naming e.g. enterItem(...)
is better than scan(...)
Interaction Diagrams
Sequence Diagrams (SD)
Different to SSD
- External source generates the method call
doOne
- A now has control of execution of the system
- A asks B to
doTwo
and passes control to B - Control returned to A
- A asks B to
doThree
and passes control to B - Control returned to A
Communication Diagram
Not constrained by layout like a sequence diagram → more like a class diagram
public class A {
private B myB = new B();
public void doOne() {
myB.doTwo();
myB.doThree();
}
}
- Instance of Class A
- A has access to B through a private variable called myB
- When
doOne()
is invoked in A - Ask B to
doTwo()
- Ask B to
doThree()
{:class=”image fit-small”}
Accessing a static variable through a static method:
public class Bicycle {
private static int numberOfBicycles = 0;
public static int getNumberOfBicycles() {
return numberOfBicycles;
}
}
A frame is a mechanism for more complex computational constructs.
Note: Polymorphism is often a better choice than an alt
frame.
Polymorphism
Subclasses of a class can define their own unique behaviours and yet share some of the functionality of the parent class.
In Java, the JVM calls the appropriate method for the object that is referred to in each variable. It does not call the method that is defined by the variables type. This behaviour is referred to as virtual method invocation.
Payment
→ abstract superclass
CreditPayment
and DebitPayment
→ concrete subclasses
Both subclasses have to implement the authorize()
abstract method.
Asynchronous Calls & Active Objects
Synchronous → wait for executed statement to finish before executing next statement
Asynchronous → can move onto another task before the previous one has finished
SD
Strengths:
- Time Ordering
- Shows detail between objects
Weaknesses:
- Linear Layout can obscure relationships
- Consumes horizontal space
CD
Strengths:
- More layout options
- Shows relationships b/w objects
- Combines scenarios to provide complete picture
Weaknesses:
- More difficult to see message sequencing
- Fewer notation options to express patterns
GRASP Responsibilities
GRASP - General Responsibility Assignment Software Patterns/Principles
Responsibility: A contract or obligation of a classifier
A classifier is a class/interface or other component of the software system.
We want to make components responsible for some part of the system.
Doing responsibilities:
- Direct - create object, perform calculation
- Initiate action in other objects
- Control and coordinates activities in other objects
Knowing responsibilities (informational knowledge):
- Private, encapsulated data (made available through methods)
- Related objects
- Derivable or calculable items
Responsibilities and Methods are related but not the same:
- Responsibility → abstract concept
- Methods → concrete ways of meeting responsibilities
Responsibility driven design sees an OO design as a community of collaborating, responsible objects.
Involves assigning responsibilities to classes based on proven principles.
9 GRASP principles are:
- Creator
- Information Expert
- Low Coupling
- Controller
- High Cohesion
- Polymorphism
- Indirection
- Pure Fabrication
- Protected Variations
1. Creator
Deals with problem of which class is responsible for creating a new instance of a class. The action of creating another class is an assignment of responsibility.
We want to ensure low coupling, increased clarity, encapsulation and reusability.
B should be responsible for creating A if:
-
B contains or compositely aggregates A (most important)
-
B records A
-
B has the initialising data for A (B is an expert)
When board is created, the board is assigned the responsibility of creating squares.
Contraindications
May decide against the creator pattern in the case of:
- Creation of significant complexity e.g.
- When recycling instances for performance (taking objects from a pool before creating new ones)
- Only retrieving specific instances based on property
In these cases we can delegate to a helper class in the form of a Concrete Factory or Abstract Factory.
2. Information expert
A general principle to assign responsibilities to objects to achieve outcomes that are easier to understand, maintain, extend and reuse.
Assign responsibility to the class that has the information necessary to fulfil the responsibility.
Contraindications
Don’t use expert if the suggested solution results in poor coupling or cohesion.
3. Low Coupling
Coupling is a measure of how strongly one element is connected to, has knowledge of, or relies on others.
It relates to the connections between components in a software system. More connections → harder to maintain.
Low coupling suggests assigning responsibility so that the design supports low dependency, low change impact and increased reuse. The lower the dependency the less changes propagate through the system.
Contraindications
- High coupling to stable elements like Standard Java Libraries is not an issue
- Coupling is actually essential, so we are just choosing to keep it low where we can without compromising other design aspects.
4. Controller
Relates to which object receives the first message from an external system and coordinates/controls a system operation (major input event, appears on SSD).
Assign responsibility to a class representing one of:
- the overall system, a “root” object, a device the system is
running in, or a major subsystem
- a facade controller → representation of system as a whole with routing point where all messages go through
- a use case scenario or session controller that deals with the event in complex systems
The controller lives just under the UI layer in the domain layer. The UI layer needs to know where to route the message to.
Contraindications
Can sometimes get a bloated controller with too many responsibilities and low cohesion. The controller becomes too complicated with too much logic and duplicated information. Solutions:
- May need to add more controllers based on use case.
- Delegate to responsibility
5. High cohesion
Keeping objects focussed, understandable and manageable. A measure of how strongly (functionally) related and focussed the responsibilities of an element are.
Contraindications
- Lower cohesion sometimes required to meet non-functional requirements such as performance.
- Coupling and cohesion are fundamental design properties that are interdependent and must be considered together.
6. Polymorphism
If we purely use if-else’s, we get a proliferation of them. Need a better way of handling alternatives based on type.
Allows us to handle alternatives based on type by giving a single interface to entities of different types. When related alternatives differ by type (class):
- Use operations with the same interface to assign responsibilities for the behaviour to the types for which the behaviour varies
Polymorphism helps us to create pluggable software components.
Polymorphic → “giving a single interface to entities of different types”
Adapters → objects responsible for handling varying interfaces.
If the superclass doesn’t have any default behaviour, declare it {abstract}
.
7. Pure Fabrication
Which object should have responsibility when solutions offered (say, by Expert) violate High Cohesion and Low Coupling?
Can fabricate an object not in the domain to give a better design. Required when a low representation gap/ solution offered by expert causes high coupling/low cohesion.
Only to be used when other techniques don’t work.
Example: Creating a PersistentStore
for saving DB related transactions like a
Sale
.
Contraindications
- Sometimes driven by behavioural decomposition into functions, resulting in functions being group into objects. Don’t just create an object when looking for a place to put a quick set of functions.
8. Indirection
Where to assign responsibility to avoid direct coupling between two or more software elements?
De-coupling components so that low coupling is supported and reuse potential remains high by assigning the responsibility to an intermediate object. The intermediary creates an indirection between the other components.
Coupling isn’t about the number of links but the nature of those links.
9. Protected Variations
A way of designing objects/systems so that variations/instability in these elements do not have an undesirable impact on other elements.
Identify known or predicted variation/instability and assign responsibilities to create a stable interface around them. An interface refers to a means of access, it’s not just a programming language interface.
Points of change include:
- variation points: variations in existing system - e.g. multiple tax calculators
- evolution points: speculative variations that may arise in the future
Open-Closed Principle (OCP) - strongly related to protected variation
Modules should be both open (for extension; adaptable) and closed (to modification that affects clients) e.g. define a class and only use access methods → can change field definitions without impacting clients
Contraindications
Cost of speculative “future-proofing” at evolution points can outweigh the benefits. Can be cheaper/easier to rework a simple “brittle” design.
GRASP Examples
Here makePayment()
is delegated to Sale
, and Sale
creates Payment.
Visibility
Object Oriented Analysis and Design (OOAD) applies encapsulation (through objects and classes).
- High cohesion → encourages grouping highly related responsibilities
- Low coupling → encourages minimising dependency on other elements
- Design → requires assigning responsibilities and objects cooperating to achieve required outcomes
- Objects → require visibility of each other to cooperate
How does Register
gain visibility of ProductCatalog
?
Accessing objects can be done in a few ways:
- Create new object
- Access existing object
- Global object
- Made available at some point
- Passed in as a constructor
- By calling one of our own methods
- Is an attribute of class
The different ways in which we access objects has an impact on the coupling of the design.
What is visibility?
The ability of an object to see or refer to another object.
For A to send a message to B, B must be visible to A.
Being in scope or visible:
- B is an attribute of A
- B is a parameter of a method of A
- B is a local object in a method of A
- B has in some way global visibility
1. Attribute Visibility
Attribute visibility is considered a tight form of coupling.
Here we can make ProductCatalog
an attribute of Register
:
class Register {
...
private ProductCatalog catalog;
...
public void enterItem(int itemID, int qty) {
...
desc = catalog.getProductDesc(itemID)
...
}
}
2. Parameter Visibility
Looser form of coupling than attribute visibility.
Register
already needs to know about ProductCatalog
, so it gets it and
passes to Sale
as a parameter of makeLineItem(...)
A worse option with higher coupling would be passing the item id
into makeLineItem(...)
and making ProductCatalog
visible to Sale
in some way.
Parameter to attribute visibility → pass a parameter in to a constructor and save it as an attribute. This gives higher coupling.
e.g.
SalesLineItem(ProductDescription desc, int qty) {
...
ProductDescription description = desc;
...
}
3. Local Visibility
Where we provide access through scope of declaration (temporary visibility).
enterItem(int id, int qty) {
...
ProductDescription desc = catalog.getProductDesc(id);
...
}
desc
has limited context → not available outside of enterItem
This is weak, localised coupling.
Note: even if catalog
wasn’t stored as an attribute, if we were to somehow
access the catalog e.g. other.getCatalog().getProductDesc(id)
that is still a
dependency (still coupling) as there is implicitly a catalog object there.
4. Global Visibility
Strong form of coupling → needs to be used in a controlled way.
Java doesn’t strictly have global visibility, but it is achievable through static attributes (but use Singleton). e.g.
public class Global {
public static int v = 1;
}
public static void main(String[] args) {
Global g = new Global();
int n1 = g.v; // can access through object
int n2 = Global.v; // can access through class
}
v
will be the same regardless of it’s access (through object or class) as it
is a static variable.
UML Visibility Marks
+
→ public-
→ private#
→ protected/
→ derived
Mapping Designs to Code
Objective is to map design artefacts to code in an object oriented language.
OO implementation requires:
- Class and Interface definitions
- Method definitions
As SalesLineItem
only has 1 ProductDescription
, can make it an attribute.
public class SalesLineItem {
private int quantity;
private ProductDescription description;
public SalesLineItem(ProductDescription description, int qty) {...}
public Money getSubTotal() {...}
}
Need to consider who will be making the SalesLineItem and hence where the constructor lives. Also need to consider which attributes are to be included in the constructor (there may be default values). Need to look at the dynamic models.
public class Register {
private ProductCatalog catalog;
private Sale currentSale;
public Register(ProductCatalog catalog) {...}
public void endSale() {...}
public void enterItem(ItemID id, int qty) {...}
public void makeNewSale() {...}
public void makePayment(Money cashTendered) {...}
}
public void enterItem(ItemID id, int qty) {
ProductDescription desc = catalog.getProductDescription(id);
currentSale.makeLineItem(desc, qty);
}
Multiplicity: Adding a Collection
public class Sale {
...
private List lineItems = new ArrayList();
...
}
Collections class is necessary to maintain visibility to all of the
SalesLineItems
.
Choice of the collections class depends on the operations we want to perform on the items:
- Key-based lookup →
Map
- Growing ordered list →
List
If implementing an interface, declare in terms of the interface:
Map<String, Integer> map = new HashMap<String, Integer>();
Map
is the interface, HashMap
is the concrete instance (can change
initialisation without having to change variable type)
public void makeLineItem(ProductDescription desc, int qty) {
lineItems.add(new SalesLineItem(desc, qty));
}
When implementing, move from least-coupled to most-coupled.
State Machine Diagrams
Note: State machines relate to compiler theory.
A state machine describes the behaviour of an object in terms of:
- events that affect the object
- the state of the object between the events
- Event - a significant or noteworthy occurrence
- State - condition of the object at a moment in time
- Transition - directed relationship between two states such that an event can cause the object to change from the prior to the subsequent state
State-dependent object → reacts differently to events depending on their state (interested in these for state machines)
Applying State Machines
Consider them when:
- Object is state-dependent and has complex behaviour
- Developing a communications or control application (very common, more so than business information systems)
Examples
- Complex Reactive Objects
- Physical device controllers - e.g. state of a lift
- Transactions and related business objects - e.g. e-commerce transaction
- Role mutators (objects that change roles) - e.g. employee from contractor to permanent
- Protocols and Legal Sequences
- Communications protocols
- UI Page/Window Flow, Navigation
- Use Case Operation Sequencing
State Machine Notation
When** the object is in State A
, if trigger event occurs, and guard is true, perform behaviour action and transition the object to State B
Choice Pseudostate
- Can have more than two choice states
- Can use
[else]
guard - States don’t have to be mutually exclusive (nondeterministic state machine)
Nested States
- Transition into
Active
viaoff hook
, which transitions intoPlayingDialTone
(orActive.PlayingDialTone
) - All substates of
Active
inherit theon hook
transition
Decision must be made as to what behaviour we want to model and at what level of abstraction.
Domain Model Refinement
Refine with:
- generalisations
- specialisations
- association classes
- time intervals
- composition
- packages
Generalisation-Specialisation Class Hierarchy
Being {abstract} indicates that the subclasses are disjoint and
complete. Every Payment
can only be one of Cash Payment
,
Credit Payment
, or Check Payment
.
Each subclass conforms to all of the properties of the superclass.
Abstract v Concrete
Generalisation:
- Identify commonality among concepts
- Define superclass (general concept)
- Define relationships with subclasses (specialised concepts)
Enables:
- Economy of expression
- Reduction in repeated information → less chance of errors
- Improved cohesion → domain model that matches intuition
These are all separate but related concepts.
- The top associations are power types
- The bottom inheritance sets are specialisation hierarchies
Here we have two specialisation hierarchies for coverage type
and
insurance plan
.
Guideline for creating subclasses:
- Subclass has additional attributes of interest
- Subclass has additional associations of interest
- Subclass is operated on, handled, reacted to, or manipulated differently to other classes in noteworthy ways
Modelling guidelines:
- Declare superclasses abstract
- Append the superclass name to the subclass