Download as pdf or txt
Download as pdf or txt
You are on page 1of 42

Systeemontwikkelingsmethoden -

Summary
Utrecht University, Informatiekunde
2020-2021, blok 1
Lecturer: Arjan Eggens
Summary: Ayco Geul

Table of Contents
1 Programming tools: functions, modules and classes. 3
1.1 Functions 3
1.2 Module 3
1.3 Class 3
1.4 Class inheritance 4
1.5 Type hints 5

2 Waterfall & (R)UP 6


2.1 Waterfall model (1970) (outdated and naive) 6
2.2 (R)UP (1999) 6
2.2.1 Core idea of UP 6
2.2.2 Four phases of UP 7
2.2.3 Different activities of UP 8

3 Agile development processes 9


3.1 Principles of Agile 9
3.2 Differences UP and Agile 9
3.3 The Scrum Process 10
3.3.1 User stories: brief description of a feature 10
3.3.2 Sprints 10
3.3.3 Scrum Artifacts 11
3.3.4 Scrum Roles 11

4 Requirements Engineering (Development process) 12


4.1 Elicitation 13
4.1.1 Elicitation techniques 13
4.2 Specification: Scenario’s and use cases 13
4.2.1 Scenario 13
4.2.2 Use Case 14
4.2.3 UML use case diagrams 14
4.3 Validation and verification 14
Requirements validation 14
Requirements verification 15
4.4 Negotiation 15

5 Object Oriented Design (OO) 16

1
5.1 From Requirements to Design 16
5.2 Cohesion and coupling 17
5.3 Responsibility 17
5.4 GRASP Principles 18

6 UML 19
6.1 Analysis 19
6.2 UML diagrams 19
6.2.1: Activity diagrams 19
6.2.2: UML: Class Diagram 20
Associations 22
6.2.3 UML: Sequence diagrams 22

7 Design Patterns 23
Upfront Design 23
Principles for a good design 24
7.1 The Facade Pattern 26
7.2 The Adapter Pattern 27
7.3 The Strategy Pattern 28
7.4 The Bridge Pattern 29
7.5 The Abstract Factory 30
7.6 The Decorator Pattern 30

8 Design By Contract 32
Hoare Logic 32
Design by Contracts 33

9 System Design Methods 34


9.1 Refactoring 34
9.2 Testing 38

10 OO Principles 40

11 CVA - Analysis Matrix 40

12 The Model-View-Controller Pattern & Observer Pattern 41


Model-View-Controller Pattern 42
The Observer Pattern 43
The Singleton Pattern 43
The Object Pool Pattern 44
The Template Method Pattern 44

2
1 Programming tools: functions, modules and
classes.

1.1 Functions
Translates into a complex expression.
Example:

A function:
- Groups related code
- Provides generic interface via parameters
- returns values

1.2 Module

A module:
- Groups functions and constants (that are useful in other parts of an application)

1.3 Class
A class:
- Groups functions
- contains data

3
1.4 Class inheritance
Allows you to indicate that certain types are related and should behave the same
For example: a class rectangle and circle are both shapes where you can compute the area
from.

The Shape class should act purely as an interface/contract how shaped are implemented.
Shape itself is an abstract class and should not be used to generate shapes.

To indicate an abstract class in Python, you call the shape (ABC):

1.5 Type hints


Type hints help make clear what the expected structure of data is. Always use type hints to
clarify what data and code is expected to do.

4
2 Waterfall & (R)UP
What is a way to create a good fundament for complex software?
One of the first widely used development processes is the Waterfall model

2.1 Waterfall model (1970) (outdated and naive)

1. Requirements: What does the customer want?


2. Design: Software designed according to those requirements
3. Code and debugging: Actual code is written
4. Testing and verification: tested by the engineers. Customer indicates if this meets his
requirements
5. Maintenance: The software is being maintained after it has been shipped.

The waterfall model doesn’t deal well with change.Its a one way path. New models
emerged.
● (Rational) Unified Process / RUP
● Extreme Programming
● Scrum
● Kanban
● Do whatever

2.2 (R)UP (1999)


● Was very popular for many years
● Introduced standard components for software development processes.
● Uses visually model software (UML)

2.2.1 Core idea of UP


● Develop software iteratively & involve users early

5
○ Develop software in time-box mini-projects called iterations
○ Iterations are stand alone projects with its own milestones etc.
● Embrace change
○ Stakeholders change their mind/requirements all the time.
○ Iterations make those changes possible.

2.2.2 Four phases of UP


1. Inception - define the scope (a rough sketch, not an in depth plan)
a. Goal:
i. Determines what problem it is going to solve
ii. Scope
iii. Vision
iv. Analysis how it fits in the business (go/no go decision)
b. Lasts few weeks max.
c. Artifacts
i. Vision document - General vision of the project + key features and
constraints
ii. List of use-cases - how will the end-users interact with the system?
iii. Project glossary - domain specific lingo
iv. Business case - How to earn money
v. Risk assessment - What might go wrong
vi. Project plan (phases and iterations) - How will we move forward?
vii. One or several prototype experiments
2. Elaboration - plan and specify the project
a. Establish a foundation of the architecture the software is going to use.
b. Create a prototype
c. Artifacts
i. Use-case model - how users will interact with the system
ii. Add (non-functional) requirements.
iii. Software architecture document: should explain why a system is
designed in a particular way and what the trade-offs are that lead to
this design.
1. Definition according to Larman p.448
a. Overview of the mayor elements of the software system
b. How these elements are related
c. What the elements do
d. What they are responsible for
d. Results of elaboration
i. A stable vision of what the software is supposed to be and its
architecture.
ii. Minimized the risks by building prototypes
iii. Better grasp on the duration and the costs of the project
3. Construction - program/build
a. Main goal: develop and test a baseline product.
4. Transition - enabling users to use the system.
a. deliver the first version of the software to its users.

6
2.2.3 Different activities of UP
During those 4 phases of UP, multiple activities are done. There are engineering activities
and supporting activities.

Engineering activities in UP
1. Business modelling
a. Establish a common understanding between stakeholders about how the
organization works.
2. Requirements engineering
a. Describes what the system should do
3. Analysis and Design
a. How the system should be implemented.
4. Implementation
5. Test
6. Deployment

Supporting activities in UP
1. Project management work
2. Configuration and change Management
3. Environment: development kit, tools for building and process control

7
3 Agile development processes
Mainly talk about Scrum today
Agile is a collection of processes (not just a process)

3.1 Principles of Agile


● The team organizes itself
○ To improve communication inside the team
○ To have better interactions inside the team
● Regularly deliver working software
○ Once every few weeks/months
○ Working software is the most important measure of progress.
● Integrate the customer in the progress
○ Give the customer the possibility to to provide continuous feedback during
development.
● Be flexible and respond to scope changes ASAP.

3.2 Differences UP and Agile


● Up is an iterative top down approach - prescriptive
○ Carefully think about requirements and design beforehand to minimize
change)
● Agile is a iterative top down, buttom up approach - adaptive
○ Keep things simple, minimize work for developers
■ Release prototypes quickly
■ Involve users in each iteration

8
3.3 The Scrum Process

User stories: brief description of a feature


● Contains: <type of user>, <some goal> and <some reason>
● EPIC is a user story on a higher level with larger amounts of functionality.
○ Split an EPIC up in single user stories usable for the sprint.
● INVEST Checklist for a user story.
○ Independent,
○ Negotiable,
○ Valuable,
○ Estimable,
○ Small,
○ Testable.

Sprints
● Each iteration of SCRUM is called a Sprint.
● Length is about 2-4 weeks.
● This scope can’t be changed during the Sprint.
● Parts of a sprint
1. Sprint planning (Result: Sprint backlog)
a. What items will be worked on during the sprint
b. Tasks needed to deliver these items
2. Daily Scrum / Daily stand up (Short meeting +- 15 minutes
a. Discuss practical issues to make sure there are no bottlenecks.
3. Sprint review - Results are discussed with stakeholders
a. Provides feedback
b. Show the output of the sprint
c. Consider the effect on the planning on the next sprint

9
4. Sprint retrospective - Deals with the process (Did we follow the process
correctly?)
a. Goal: Always improve and finetune the process.

Scrum Artifacts
1. Product Backlog
Ordered list of all the possible changes that could be made to the product.

2. Sprint Backlog
a. Collection of items from the product backlog that's created at the beginning of
each sprint.
b. Contains specific tasks which needs to be done to deliver those items.

3. Definition of Done
Explains the criteria that a Product Backlog Item must fulfill to be considered done.

4. Increment
Collection of items that passed the Definition of Done at the end of the sprint.

Scrum Roles
Product Owner
- Manage the Product Backlog.
- Uses the Product Backlog to give the development team direction to where the
software product is headed.

Scrum Master
- Ensures that the development process stays Agile.
- Coaching role

Development Team
- Perform tasks in the Sprint Backlogs
- Decides how to divide the tasks

10
4 Requirements Engineering (Development
process)

Goal of requirements engineering


Determine what the system is supposed to do. Developers and customers can then agree on
that description.

Why is it useful?
By knowing what the requirements are, communication and planning can be done correctly.
● Software errors can be very costly (NASA project costed $60 billion dollars/yr)
● 3 out of 4 software projects are unsuccessful
○ Due to poor planning and communication.

Requirements should identify (1) stakeholders and (2) concerns.


1. Stakeholder: Someone with an interest in the product / involved in the project.
a. End user, manager, board member company, etc.
2. Concerns: A requirement, objective, intention or aspiration a stakeholder has for the
system.

Definitions
Requirements:
- a feature that the system must have, or
- a constraint it must satisfy
Requirements are required and not just a wish list. Make sure you can promise to deliver.

Requirements engineering:
- The process of identifying and defining all the requirements of a software system.
- It is a cycling process of 4 steps:
1. Elicitation
2. Specification (e.g. use cases/scenarios)
3. Validation and verification
4. Negotiation

11
Examples of requirements
1. Functional: actual features of a system
2. Usability (online help)
3. Reliability (uptime, recoverability)
4. Performance (how long it takes to respond)
5. Supportability (easily updatable)
Other sub-factors:
6. Implementation (which languages, tools, hardware)
7. Legal (licensing)
8. Interface (e.g. assignment submission system must be paired with Osiris)

4.1 Elicitation
Elicitation can be harder than you expect.
● Talk to clients and end-users
● Gather existing documentation
● Observe how future users work now
Make sure your interpretation is correct and complete!
Think about the other possibilities besides the Happy Flow.

Elicitation techniques
1. Asking (Interview/brainstorm/questionnaire)
2. Task analysis (what actions a user needs to do and how are they organized?)
3. Scenario-based analysis (What happens if …?)
4. Ethnography (actively observe what users are doing)
5. Analyse existing documents and systems (What are the problems with the current
system and/or methods?)
6. Prototyping (Check if this is what the customer wants)
7. Domain analysis (How do existing systems solve problems?)

A good set of requirements are:


● Correct
● Consistent
● Complete
● Clear
● Realistic
● Verifiable
Make sure to be realistic rather than perfect.

4.2 Specification: Scenarios and use cases


To establish detailed requirements, write scenarios with associated use cases. (Like User
Stories in Scrum)
● System’s behavior from a users POV to clarify how the system helps the user.

12
Scenario - Narrative story that details what people do and how they experience as they
make use of the system and application

Use Case - more general; describes the interaction between users and the system that
produces some kind of result/value.

Different levels of detail in Use Cases


● Brief: One paragraph summary of the main success scenario
● Casual: Covers various scenarios including several non-successful ones
● Fully dressed: detailed account of all the possible steps and variations, including:
○ Unique name
○ Participating actors
○ Entry conditions
○ Flow of events
○ All the other possible flow of events
○ Exit conditions
■ The possible outcomes of the system
○ Special (non-functional) requirements

UML use case diagrams


You can use diagrams supporting your use case using “UML Use Case Diagrams”

- Actors
- Anyone involved in the system (even other systems)
- Systems
- Use Cases
- Arrows
- Show the relationship between use cases.

4.3 Validation and verification

Requirements validation
checks the requirements document on:
- Consistency
- Completeness
- Accuracy

Need to talk to customers and users and check if you covered everything

Requirements verification
is an (automatic) mathematical analysis to determine if the requirements are consistent.

13
4.4 Negotiation
Establish a sensible set of requirements that you can guarantee to deliver
Resolve conflicts between stakeholders

14
5 Object Oriented Design (OO-design)
OO design thinks in terms of objects and responsibilities first.
● We should think of object abstractly as managing responsibilities
● We can use the GRASP principles to assign responsibilities to the conceptual
classes in our domain model

The step from analysis to actually designing the software


● How to use the domain model to write class diagrams?
● Can I make quality requirements more explicit?
● What are the principles behind this process?

5.1 From Requirements to Design

Suppose you have fulfilled the requirements phase:


● You have talked to all the stakeholders (elicitation)
● Written various use cases (specification)
● Agreed upon a set of requirements (negotiation)

Now how do we make a great design?


1. A requirement document
a. Written in English
b. Understood by the customer
c. Aims to establish the system requirements
2. A design
a. Written in UML (class) diagrams
b. Understood by the developers
c. Aims to communicate how to implement the system

Before making the design (or drawing class diagrams), create a domain model.
- Help you understand the world of the customer
- First step towards defining the system and in structure and data
- There are various ways to design these concepts in a computer program.

15
- A software system design aims to decompose a big problem into smaller
manageable pieces.
- If a design is tightly coupled or weakly cohesive, a minor change can
affect a lot of other parts of the system!

How to write a domain model?


● Talk to experts in the domain
● Identify existing solutions/components
● Identify design patterns (later in the course)
● Textual analysis
○ Use text from use cases and requirements to identify parts of the domain:
■ Nouns are good candidates for conceptual classes
■ Verbs are good candidates for associations

Common pitfalls creating a domain model


- Keep attribute types simple
Natural language is imprecise

Functional Design
The idea behind functional design is to give each modular part of software a single
responsibility and make each part as independent as possible from the other parts.
- Each module should be strongly cohesive and loosely coupled.

5.2 Cohesion and coupling


Cohesion refers to how closely the operations in a unit are related.
- Strongly cohesive methods to do one thing, and one thing only.
- are easier to maintain, understand and to reuse.
- Weak cohesion methods do several unrelated things.

Coupling refers to how closely different methods are related.


- Loosely coupled methods operate independently from others
- Tightly coupled methods, changing one probably makes you change the other one
too.

Pure functions are functions without any side-effects.


- are easy to test, reason about and reuse.
- because they are (often) loosely coupled.

Types of coupling:
● Data coupling - One method relies on the data produced somewhere else.
● Control coupling - One method tells the other what to do
● Global data coupling - Different methods access the same global variables
● Pathological coupling (worst) - One method relies on the exact implementation of
another method.

16
Loose coupling is important

5.3 Responsibility
Another way to decompose a problem into smaller parts is to look at responsibility.
- By designing classes, responsibilities are assigned to the classes.

Three different perspectives


Martin Fowler identifies 3 separate perspectives on the software development process
1. Conceptual perspective
a. Purely thinking about the domain model. You don't think about how to
implement this in the software.
2. Specification perspective
a. From this perspective, you think about the interface and how parts
communicate with each other.
3. Implementation perspective
a. Thinking about how to implement the software.
b. This is the most used perspective, but often not the best perspective.

Shalloway and Trott argue that these 3 levels are useful to understand objects.
1. Conceptual: view an object as a set of responsibilities
2. Specification: view an object as a set of methods
3. Implementation: view an object as a set of code and data.
OO-design thinks in terms of objects and responsibilities first.

Key question to ask during design: “Which class is responsible for what?”

5.4 GRASP Principles


GRASP Principles: Larman’s principles for a good design.
General Responsibility Assignment Software Principles

These principles help assign responsibility to the classes in the domain model
1. Information Expert (who has the info?)
2. Creator (who is responsible to create instances)
3. Loose coupling
4. Strong cohesion
5. Controller (Which subsystem handles events and activities?)
Every design decision has pros and cons. A good design is about balancing the pros and
cons.

17
6 UML
Analysis and how to use UML
Create diagrams that visualizes the domain and the resulting software design.

Previously: How to translate requirements and use cases into a software design.
- What kind of notation can you use?

6.1 Analysis
Perform an analysis to come up with an abstract model of the problem’s domain.
- You have a bunch of requirements and use cases
- You want to translate those to a technical specification that is used by
developers.
- A good model simplifies reality, but represents all relevant data.

Why do we need to model software?


● Software is too complex to oversee all the details at once
○ We need abstractions
● Code is written to a machine to execute, not for a human to understand

How can we model software?


● UML is a language with 14 different ‘dialects’.
○ Class diagrams
○ Activity diagrams
○ Use case diagrams
○ Sequence diagrams
○ …
● This is the standard used in the industry.

6.2 UML diagrams

6.2.1: Activity diagrams


Used to describe existing business processes.
- Help to validate how the business works.

18
Different symbols of a activity diagram

You use activity diagrams in the Business Modeling Phase. There, you establish how
the current business processes work.

6.2.2: UML: Class Diagram


Most common UML diagram.
Class diagrams contain:
● Boxes: represent classes (which has attributes and methods)
○ If a class is abstract, write the abstract class name in italic.
● Various arrows to describe the relationship between classes

Modifiers
You can use modifiers to indicate the visibility of the methods and attributes of a class.
● + means Public
● - means Private
● # means protected

Different levels of detail


Class diagrams are drawn at varying levels of detail,
depending on the situation.
- On early sketches: just use class name
- Full design: complete overview of attributes and methods

19
Relations between classes
1. Inheritance
- B is a subclass of A
- B is derived from A
- A is the superclass of B

2. Dependency
Vague relation (Often used: relation but no aggregation)
Dependency means:
- B depends on A, or
- B uses A in some way

3. Aggregation (and association)


Aggregation means:
- A has a B, or
- B is a part of A
Association means:
- A has a B (but B is not a part of A)
- An order has a customer, but a customer is
not a part of an order

4. Composition
A special form of aggregation.
Composition means:
- A has a B, but B cannot exist without A

20
Associations
Directed Associations
Associations can be directed.

● A knows B
● B knows A
● A and B know each other

Cardinalities
You can also write a number or range with any association.

● Every A has 0 or 1 B’s


● Every B has 3 A’s
○ e.g. a car has 4 wheels

Labeled associations
You can add labels to associations to clarify the nature of the associations

● A works for B

Undirected arrows
(Avoid if possible)
This can mean:
● The exact relation is undecided
● Both objects know about each other

6.2.3 UML: Sequence diagrams


Captures the dynamic control flow of the program.
- What happens when you run the code

21
7 Design Patterns
Design patterns are standard solutions to problems, which generally makes your software
easier to modify and maintain.

Design patterns are based on the principles of OO design:


1. Program to an interface, not to an implementation.
2. Favor aggregation over inheritance.
3. Find what varies and encapsulate it.

Why are design patterns useful?


- They are usable solutions to common problems
- Learn from other ones failures too
- They help establish a common vocabulary
- They force you to design the overall system instead of getting lost in irrelevant
details.

Structure of design patterns


1. Name
2. Intent (purpose)
3. Problem
4. Solution
5. Participants
6. Consequences
7. Implementation
8. Generic structure (UML diagram)

Upfront Design
What should you design upfront?
- If, according to the Agile Manifesto, you shouldnt focus too much on upfront design,
why are design patterns relevant?
- By learning Design Patterns, you will learn the qualities of good code and a
good design.

There are two ways to design a program


1. Quick and dirty
2. Overdesigning
But there is a third way:
3. Somewhere in between
a. Upfront, think about where changes are most likely to happen
b. If requirements change, upfront thinking makes changing things a lot easier.

Principles for a good design


1. Program an interface, not an implementation

22
2. Favor aggregation over inheritance
3. Encapsulate the concept that varies
Design Patterns and Agile have a few key elements in common:
4. No redundancy (DRY)
a. Don’t repeat yourself: if you reuse code, encapsulate change-sensitive code
in a well defined interface.
5. Readability
b. Name objects and methods to their purpose.
c. Aim for short, cohesive methods
6. Testability
d. Loosely coupled and strongly cohesive methods are easier to test.

Types of encapsulation
1. Data encapsulation: Use private attributes to hide data
2. Use private methods to hide computation
3. Hide one object behind another (hiding hisStar behind Star)
4. Type encapsulation: The implementation of specific shapes behind an abstract class
Shape.
Focus on encapsulating the variables that can vary (e.g. the color, special border of a shape)

CVA, Commonality and Variability Analysis: Focus on what classes have in common and
what varies.

CVA is a valuable tool for designers:


- Implement an Abstract Class capturing the Common interface
- Use aggregation for nontrivial properties
- Allow subclasses to implement the properties that vary.

When defining an Abstract class, ask yourself:


- What interface is needed to handle the responsibilities of this class?
When defining a Derived class, ask yourself:
- How can I implement this particular variation of the superclass?

23
Facade Adapter Strategy Bridge Factory

Intent Provides a Convert one Use different Separate Separate the


unified interface into strategies abstraction creation and
interface another depending from the usage of
on the implementati
objects.
context on

Problem Big systems Classes are Computation Subclasses Classes


can be unable to depends on of an which create
complicated work the client abstract a strategy,
together making a class must also use
request use them.
implementati
ons

Solution Hide Create a Seperate the Define an Create an


complexity wrapper selection interface for abstract
by creating a which wraps and the all factory class
simple API the class implementati implementati to create a
which on of a ons to use strategy
doesn’t work strategy and have the
together with derivation of
the system the abstract
class use
that.

Participants The facade The wrapper Abstract Abstract An abstract


class, and the strategy abstraction factory with
class which class, his class with subclasses
the set of needs to be subclasses, subclasses, of concrete
interfaces in wrapped and a Abstract factories. A
a context class implementati class which
subsystem, on class with uses these
subclasses. concrete
the classes strategies.
which used
the facade
interface

Consequences The number Allow the Minimal use Objects don’t There is less
of interfaces use of of have to deal copy/pasting
you have to pre-existing conditionals, with , and
deal with are objects to fit all implementati stronger
being into new algorithms on issues. cohesion of
reduced class are being Extensibility classes.
structures called in the increases.
without same way,
being limited new
by their strategies
interface are easy to
implement

24
Implementation Create a Contain the Create an Create two Create an
facade class existing abstract strategies, abstract
which uses class into a class, and and relate factory class
the new class derive them with an with
interfaces of and make specific aggregation. concrete
subsystems that match strategy factory
to create a the wanted methods as subclasses.
simple interface subclasses Another
interface of that class. class which
uses there
concrete
strategies.

Structure

7.1 The Facade Pattern

The Facade pattern


provides a unified interface to a set of interfaces in a subsystem.
- It defines a higher level interface that makes the subsystems easier to use.

The idea of the facade


A big system can be complicated. The facade hides the complexity by creating a simple
Application Programming Interface with the specific things you need.
(It is basically a TL;DR of a big software system)

Facade variations
The facade can also reduce the number of subsystems you have to deal with, by creating
one facade where all the subsystems come together.

25
7.2 The Adapter Pattern

The Adapter Pattern allows you to program to one unified interface.


Commonly seen in libraries which integrated other libraries.

● Intent:
○ Convert one interface into another
■ This lets classes work together which otherwise couldn't (since their
interfaces weren’t compatible.
● Problem:
○ Classes are unable to work together.
● Solution
○ Create an “wrapper” around an existing class. Thos wrapper satisfies the right
syntax and is still able to use the original code from the class it wrapped
around.
● Consequences
○ Allows pre-existing objects to fit into new class structures without being
limited by their interface.
● Implementation
○ Contain the existing class in another class. Make the containing class match
the wanted interface.

26
7.3 The Strategy Pattern
Pattern which encapsulates variation according to the GRASP principles.

The strategy pattern defines all the different strategies/variations to do something (like
calculating tax) in subclasses of an abstract class CalcTax. The abstract class defines the
interface of the different strategies.
Strategy pattern separates the use of a calculation and the defining of a calculation.

● Intent
○ Use different rules/algorithms depending on the context
● Problem
○ Some computation depends on the client making the request
● Solution
○ Separate this selection of the algorithm from the implementation of the
algorithm.
● Participants
○ Abstract Strategy class
○ His subclasses with all one possible implementation
○ Context uses a specific variation of the implementation
● Consequences
○ Defines a family of algorithms
○ Minimal use of switches and if/else-conditionals
○ All algorithms are being called in the same way

Ways to deal with variations (Favor aggregation over inheritance)


1. Copy-paste the code
a. Don’t do that!
2. Switches/if-statements
a. Leads to a lack of cohesion
i. If you want to add a new variation, a lot of code needs to be changed.
3. Inheritance
a. Looks good, but there are some issues too.
4. Aggregation (Strategy Pattern)
a. Strong cohesion
b. Easy to shift responsibility

27
7.4 The Bridge Pattern
The Bridge Pattern is a connection between 2 strategy patterns, so that the 2 strategies can
use each other without knowing the actual variations that are being used.

● Intent:
○ Decouple an abstraction from its implementation so they can vary
independently (Make two parts of a software system work together)
● Problem
○ The different subclasses of an abstract class must use multiple
implementations, without having to explode in a number of classes.
● Solution
○ Define an interface for all implementations to use and have the derivation of
the abstract class use that.
● Consequences
○ By decoupling implementation and abstraction, extensibility increases.
Objects are not aware of implementation issues.

Couple 2 things which vary through abstract classes, so that the coupling is looser.

28
7.5 The Abstract Factory
To separate the creation and the usage of objects.
- Loosening the coupling from

The Context class uses the factory to create the strategy it needs.

Who is responsible for creating objects?

7.6 The Decorator Pattern


Addresses the problem of recursion
Recursion = using a method in the method itself.
Voorbeeld Fibonacci-sequence: getal is afhankelijk van de 2 getallen daarvoor.

Decorator is de subclass van Component, maar heeft zelf ook een Component.

29
8 Design By Contract
How do you design “correct” software?
- Software meets its specifications

Structured programming = Using if-statements and for-loops instead of go-to


programming.

Hoare Logic
A logic language to proof statements about programs.

{P} C {Q}
Consists of 3 parts:
1. {P} = Precondition - state before the execution of the program
2. C = Program - the program
3. {Q} = Postcondition - state after the execution of of the program

Rules in Hoare Logic:


● Skip
○ Does nothing
■ {P} skip {P}
● Assignment
○ Determine the precondition by the postcondition
■ C: x := x+1
■ {Q}: x<N
■ Then:
■ {P}: x+1 < N
● Composition
○ If p → q and q → r, then p→ r (Transitivity)
■ {P} c1 {Q} and
■ {Q} c2 {R}
■ Then:
■ {P} c1; c2 {R}
● Conditional rule
○ Combine two logic statements with the same postcondition into a single one
with an if-statement (only if the preconditions have a specific structure.
■ {B^P}S{Q}, {¬B^P}T{Q}
■ Then:
■ {P}if B then S else T endif {Q}
● Consequence rule
○ Strengthen the precondition
■ P1 → P2, {P2}S{Q2}. Q2 → Q1
■ Then:
■ {P1} S {Q1}

30
Design by Contracts
A contract is:
Establish agreement between two parties.
- Expect certain benefits
- Willing to incur obligations to obtain those benefits

You can make these contracts (pre- and postconditions) explicit in Python:
● Assert statement - Check pre- and postconditions in code
○ The caller of the method is responsible for that the preconditions hold.
○ The method itself is responsible for that the postconditions hold.

● Invariant - something which is always true.


○ Example:

■ Invariants:
● X is in the range {0..10}
● X <= 10
● X is an integer
● ...

31
9 System Design Methods

9.1 Refactoring
Changing existing code with the aim to improve it.
In practice, you more often than not will work in existing software, rather than creating some
from scratch.

Martin Fowler - “Refactoring: a change made to the internal structure of software to make it
easier to understand and cheaper to modify without changing its observable behavior.”

Applying design patterns can still be done to existing software:


- To improve internal structure
- To facilitate testing
- To pave the way for new features

In short, Refactoring...
● Keeps your code clean
● Aims for self-documenting code:
○ choose meaningful names
○ Lift complex computations into separate methods
○ Keep control flow simple
○ …
● When refactoring, take small steps and test all the time.

Different types of refactoring


● Extracting code into separate methods
● Removing code which is no longer needed
● Introduce a design pattern

Refactoring safely
It is easy to create bugs while refactoring codes.
Best way to refactor:
● Don’t start refactoring complex code, unless you have a way to test it.
● Refactor in small steps. Test and verify these small steps individually.
● Make sure that there is a revision history
● Test your program after each refactoring step to catch bugs as early as possible.

Reasons to refactor:
● Improve software design (eliminating duplicate code)
● Easier to understand
● Easier to adapt
● Easier to test
● Helps spotting bugs
● Supports faster programming

When to refactor? (No golden rule for refactoring)

32
● Rule of three
○ 1st time you write something
○ 2nd time you notice you have to write duplicate code
○ 3rd time, you refactor
● When you add a new feature
● Fix a bug
● Do a code review

Bad code smells - Symptoms in the source code which may indicate bad design (not bugs)
● Keep a list of bad code smells in the back of your mind.
● Examples of bad code smells:
○ Duplication
■ Problem: Duplication
■ Fix: introduce a method
○ Long method (with a vague name)
■ Problem: Method is doing too much (weak cohesion)
■ Fix: Split to methods into smaller cohesive methods
○ Large class (with vague name)
■ Problem: Class is doing too much
■ Fix: Split the class into smaller, more cohesive, loosely coupled
classes.
○ Too many parameters
■ Problem: method is doing too much (weak cohesion)
■ Fix: Split the method into smaller cohesive methods
○ Shotgun surgery
■ Problem: introducing a new feature you need to update the existing
code in many different places.
■ Fix: Introduce strategy pattern
○ ,,,
■ Problem: Responsibility for the computation is in the wrong place
■ Fix: Put the computation in a separate method or use a Strategy
○ Comments
■ Problem: If a lot of comments are needed to explain what something is
doing, it is probably badly designed.
■ Fix: ?
○ Bad naming
■ Problem: names should explain what it’s for. Too long or too short
names don’t do that.
■ Fix: name classes, methods and variables to what they do or what
they are.

Fowler's refactoring catalogue - Every refactoring is described in a uniform format:


● The refactoring’s name
● A summary of what the refactoring does
● The motivation explaining when to apply the refactoring (and when not to)
● The mechanics giving a recipe of how to apply refactoring
● Examples illustrating a refactoring

33
A few refactorings
● Introduce parameter object
○ If a method has many parameters, it is difficult to call.
○ Instead, group parameters into an object.

34
● Moving methods, fields or attributes
○ If something is too weakly cohesive
○ Extract class refactoring to extract attributes and store it in a new class.
● Pull-up refactoring
○ If all subclasses have the same method, it can be called in the superclass.
● Pull-down refactoring
○ If not all subclasses have a method, remove it from the superclass.
● Splitting classes
● Hiding delegates

35
9.2 Testing
Testing is about:
● Testing software
● What types of tests there are
● How to use tests to improve software design

Why test software?


● Bug fixing
● Check if installed correctly
● Check if code changes introduce new bugs
● Test non-functional requirements

Different types of tests


● Unit testing - tests individual types of code
● Regression tests - (automatically) regularly ran tests to check for new bugs
● Integration testing - verifying if software components work together well
● System testing - tests the system as a whole. Looks if the requirements are being
met.
● Acceptance testing - aims to find out if the product is acceptable to the client.

Unit testing
● Test 1 unit at a time
● Write testing code for parts that might break (simple getters and setters don't need
testing)
● Testing code is code too
● Same design principles apply to testing code.

● Test that tricky functions compute the right thing


● Test that exceptional cases get triggered
● Tests are typically written using assertions
○ Assertion passes a Boolean:
■ If true, the test passes
■ If false, reports error and bugging information

Python has a unittest library


● assertAlmostEqual - tests whether the outcome is close to the expected result
○ Allows to test code with imprecisions

36

Unit testing best practices


1. Make sure your tests test only 1 thing
2. Write unit tests as you go, preferably before you write the code you are testing
against
3. Do not unit test the GUI (dedicated tests for GUI which work better)
4. Minimize dependencies of your tests
5. Mock behavior with mocks

Coverage
● amount of code which is tested
● Organizations often have a coverage goal of 80% to ensure a level of stability etc.
● https://coverage.readthedocs.io/ is a python library for computing coverage reports.

TDD - Test-driven development


1. Start the iteration by writing tests
2. Add code the makes the tests pass
3. Refactor your solution
This approach is sometimes summarized as ‘red-green-refactor’

Benefits of TDD
1. Forces developers to think about specifications first
2. Encourages better design (loosely coupled and strongly cohesive code is easier to
test)
3. Avoid the skimp of writing tests
4. Code will require less refactoring later

37
10 OO-Principles
When designing software:
1. Start with the big picture - a conceptual understanding of the whole
a. First think about which rooms a house should have, instead of which bricks to
use.
2. Identify patterns at this level
3. Start filling in details, identify patterns at this level, creating context
4. Work inward: repeatedly apply patterns, identify new patterns and repeat.
5. The final implementation is guided by the sequence of design patterns you chose to
apply.

SOLID-principles of OO-Design
(instead of the GRASP-principles)
● Single Responsibility - (Strong cohesion)
● Open/closed - Software is open for extension, closed for modification
○ Changing already existing strategies is more work/closed
● Liskov substitution - Don’t change the behavior of a superclass in a subclass.
● Interface segregation - to an interface, not an implementation
● Dependency inversion - Start with abstractions instead of implementations
○ High-level modules should not depend on low-level modules.
○ Abstractions shouldn't depend on details
○ Implementations are more likely to change than the abstract concepts.

11 CVA - Analysis Matrix


Analysis techniques:
1. Noun/verb analysis
a. Uses the elicitation interview text data.
2. CVA (commonality and variability analysis)

a. Uses the concepts from the domain model.


b. Tries to identify the commonalities and variations.
c. Helps to decide where to use design patterns.

38
3. Analysis Matrix

a. Uses the use cases instead of the domain model

12 The Model-View-Controller Pattern &


Observer Pattern
Introduction of software architecture
High-level structure of a software system
Decisions about the fundamentals of a software system:
- Concepts
- Behavior
- Relations

Fowler: Software architecture are the decisions which are hard to change.
So: Software architectural decisions are on a higher level than software design decisions.
- Establish how users will use the application
- Where the data is stored
- How to be deployed
- How to be maintained

Next to design patterns, there are also architectural patterns.


● Component-based
● Data-centric
● Event-driven
● Layered
● Peer-to-peer
● Pipes and filters
● Plug-ins

One architectural pattern is the Model-View-Controller.

39
Model-View-Controller Pattern
Used in applications to combine a GUI, database and business logic.

The patterns consists of 3 components:


1. Model - responsible for storing data (e.g. a HTML page)
2. View - responsible for visualizing the data (e.g. the CSS file)
3. Controller - responsible for handling user interactions (e.g. your web browser)

Why is MVC useful?


● Strong cohesion -
● It separates responsibilities - Easier to change/extend the application
○ Allows multiple views of the same data
○ Allows completely different controllers
○ Allows to change the way a view responds to the controller

How do the different parts of MVC communicate?


- They are good candidates for using the Observer pattern.

40
The Observer Pattern
Also Listener Pattern / Publish-Subscribe-model
Intent: Allows you to notify other objects when objects change.

The Singleton Pattern


Makes sure there is only 1 instance of a certain class

- Alternatives: create a module of the classes where you only want 1 instance from.

41
The Object Pool Pattern
Manages the amount of instances you want to have.

The Template Method Pattern


A Strategy with various steps of a process (instead of 1 method)
- When process is the same
- But the steps of the process can vary

The Factory Method


A Template Method, which also has a class which creates the instance

42

You might also like