TDDB84 Summary & wrap-up & some tips & some design

advertisement
TDDB84
Summary & wrap-up & some tips & some design
patterns & some other stuff
tisdag 20 oktober 15
Agenda
• Course goals, expectations
• Writing papers: FAQ
• Design Patterns revisited
• Course summary
• Life after the course
tisdag 20 oktober 15
Course goals
Identify and explain software design principles and design
patterns in existing object-oriented software.
Lab 1, 2
tisdag 20 oktober 15
Course goals
Apply software design principles and design patterns when
working with existing object-oriented software.
Lab 1, 3
tisdag 20 oktober 15
Course goals
Describe the purpose and consequences of design patterns
in object-oriented software.
Lab 2, 3, final paper
tisdag 20 oktober 15
Course goals
Critically evaluate software design principles and design
patterns in relationship to software qualities.
Lab 3, final paper
tisdag 20 oktober 15
Course goals
Analyze the relationship between software design
principles, design patterns, programming languages and
application frameworks.
Final paper
tisdag 20 oktober 15
Expectations
• Learn about design patterns
• Learn when to use design patterns
• Learn about design patterns in real
software
• Learn about the consequences of design
patterns
tisdag 20 oktober 15
Writing Papers, FAQ
tisdag 20 oktober 15
Writing Papers, tips
• Be
• specific
• precise
• formal
• direct
• unapologetic
tisdag 20 oktober 15
What is complexity? Design complexity, cyclomatic complexity?
This is not a popular science text. Refrain from wording that is ambiguous or less well defined
(”forgiving”, ”good”, ”bad”, ”easy”)
Do not say something is ”very hard”, use a reference and be precise about what exactly that
reference says
Do not say you ”will” do something, or ”intends”, be direct and state what you DO, or have
DONE.
You do not have to state ”someone made me write this”, or ”Due to time constraints”: you will
ALWAYS have external constraints on your work, as does everyone else. Write about what you
have done, do not make excuses for what you have not done.
Writing Papers, tips
• Use
• references
• the style of research papers as a guide
• the hourglass style
• your team
tisdag 20 oktober 15
Back up all claims with references
Check your wording & justifications against academic publications, not previous years’
reports.
Everything before the narrow part should lead to the waist, and everything after should relate
to the waist.
Don’t let your paper be overly focused on background material: you need to introduce only
that which is necessary for someone else of approximately your own backgrounds (before the
course) to understand the core of your paper: your evaluation of a specific design pattern.
Please do conduct a second round of reviews
Design Patterns
revisited
tisdag 20 oktober 15
Principles + Problem =
Pattern
tisdag 20 oktober 15
Principles = SOLID +
Some more tips
tisdag 20 oktober 15
Some more tips
• Encapsulate what varies
• Program to an interface not to an
implementation
• Favor Composition over Inheritance
• Don’t call us, we’ll call you
tisdag 20 oktober 15
Some more tips
• Depend upon abstractions. Do not depend
upon concrete classes.
• Strive for loosely coupled designs between
objects that interact
• Only talk to your friends
tisdag 20 oktober 15
Some Design Patterns
tisdag 20 oktober 15
You choose!
•
•
•
•
•
•
•
tisdag 20 oktober 15
Strategy
Factory Method
Decorator
Template Method
Composite
Abstract Factory (+
Dependency Injection)
Singleton (+ example in
Ruby)
•
•
•
•
•
•
•
Builder
Adapter
Bridge
Observer
Chain of Responsibility
Memento
Command
Strategy
tisdag 20 oktober 15
Context
Client
tisdag 20 oktober 15
Strategy
Strategy
Strategy: Consequences
Can choose
+implementation
of a
strategy at run time
Eliminate hardcoded
+conditionals
Avoids excessive
+subclassing
tisdag 20 oktober 15
must be aware
- Clients
of different strategies
- Communication
required between
context and strategies
many
- Potentially
strategy objects created
Factory Method
tisdag 20 oktober 15
Factory method
(before)
tisdag 20 oktober 15
Factory method
(before)
tisdag 20 oktober 15
Pizza pizza = null;
if (style.equals("NY")) {
if (type.equals("cheese")) {
pizza = new NYStyleCheesePizza();
} else if (type.equals("veggie")) {
pizza = new NYStyleVeggiePizza();
} else if (type.equals("clam")) {
pizza = new NYStyleClamPizza();
} else if (type.equals("pepperoni")) {
pizza = new NYStylePepperoniPizza();
}
} else if (style.equals("Chicago")) {
if (type.equals("cheese")) {
pizza = new ChicagoStyleCheesePizza();
} else if (type.equals("veggie")) {
pizza = new ChicagoStyleVeggiePizza();
} else if (type.equals("clam")) {
pizza = new ChicagoStyleClamPizza();
} else if (type.equals("pepperoni")) {
pizza = new ChicagoStylePepperoniPizza();
}
} else {
System.out.println("Error: invalid type of pizza");
return null;
}
Factory method
tisdag 20 oktober 15
Factory method
Decouples clients from
+specific
dependency
classes
Eliminates hardcoded
+conditionals
Connects parallel class
+hierarchies
(NY*Pizza,
Chicago*Pizza)
tisdag 20 oktober 15
keeping factory
- Requires
methods in sync with
domain classes
Decorator
tisdag 20 oktober 15
Component
Decorator
Beverage b = new Coffee();
b = new SweetenedBeverage(new SweetenedBeverage(b));
Decorator
return 5+beverage.cost();
tisdag 20 oktober 15
Decorator
Dynamically adds
+behavior
to specific
objects are
- Decorator
not of the same type as
Customizes an abstract
+class
without knowing the
result in many small
- May
objects
instances of a class
implementations
tisdag 20 oktober 15
the objects it comprises
Template Method
tisdag 20 oktober 15
class Beverage {
public:
void prepareRecipe();
void boilWater();
void pourInCup();
};
class Coffee{
public:
void prepareRecipe();
void boilWater();
void brewCoffeeGrinds();
void pourInCup();
void addSugarAndMilk();
};
tisdag 20 oktober 15
class Tea{
public:
void prepareRecipe();
brew
void boilWater();
void steepTeaBag();
void pourInCup();
addCondiments
void addLemon();
};
Template method:
Consequences
Can isolate the
+extensions
possible to an
algorithm
Isolates clients from
+algorithm
changes
tisdag 20 oktober 15
Template method
tisdag 20 oktober 15
Default
implementations
(hooks)
public abstract class CaffeineBeverageWithHook {
void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
boolean customerWantsCondiments() {
return true;
}
public class CoffeeWithHook extends CaffeineBeverageWithHook {
[ ... ]
public boolean customerWantsCondiments() {
return getUserInput().toLowerCase().startsWith("y");
}
}
tisdag 20 oktober 15
Duck[]
};
ducks = {
new Duck("Daffy", 8),
new Duck("Dewey", 2),
new Duck("Howard", 7),
new Duck("Louie", 2),
new Duck("Donald", 10),
new Duck("Huey", 2)
Arrays.sort(ducks, new Comparator<Duck>(){
@Override
public int compare(Duck arg0, Duck arg1) {
return new Integer(arg1.weight).compareTo(arg0.weight);
}
});
Template method?
No
public class Duck implements Comparable<Duck> {
String name;
int weight;
public Duck(String name, int weight) {
this.name = name;
this.weight = weight;
}
public String toString() {
return MessageFormat.format("{0} weighs {1}", name, weight);
}
public int compareTo(Duck object) {
return new Integer(this.weight).compareTo(object.weight);
}
}
tisdag 20 oktober 15
Yes
tisdag 20 oktober 15
// Java 8: With inline lambda
Arrays.sort(ducks, (arg0, arg1) -> new Integer(arg1.weight).compareTo(arg0.weight));
Composite
tisdag 20 oktober 15
Waiter
Diner
menu
Pizza
menu
Clam
Pizza
tisdag 20 oktober 15
print()
Breakfast
menu
printMenu()
print()
Cheese
Pizza
Coffee
menu
Ham &
eggs
Spam &
eggs
Dark
roast
Coffee
Tea
Espresso
print()
Eggs &
spam
Spam,
spam &
eggs
print()
Yes indeed we are intentionally violating
the SRP. Actually I m not violating it; I m
trading it for transparency
tisdag 20 oktober 15
• By allowing the Component Interface to
contain the child management operations
and leaf operations, a client can treat both
composite and leaf nodes uniformly
Client
Component
Composite
Leaf
tisdag 20 oktober 15
Composite:
consequences
Allow us to treat
+composite
objects and
composite
- Creates
classes that violate the
Allows arbitrarily
+complex
trees
composite cannot
- The
rely on components to
individual objects
uniformly
tisdag 20 oktober 15
principle of a single
responsibility
implement all methods
Abstract factory
tisdag 20 oktober 15
Ingredients
Pizza Store
Fresh Clam
Mozzarella Cheese
NY
Thin Crust Dough
Frozen Clam
Parmesan Cheese
Thick Crust Dough
tisdag 20 oktober 15
Clients
I Want a
Cheese
Pizza
Chicago
Abstract Factory Example
! Interface toolkit to support multiple look-and-feel standards
50
tisdag 20 oktober 15
The Abstract Factory Template
! Provide an interface for creating families of related or dependent
objects without specifying their concrete classes.
49
tisdag 20 oktober 15
tisdag 20 oktober 15
tisdag 20 oktober 15
tisdag 20 oktober 15
Concrete Factory
Abstract Factory
Abstract Products
tisdag 20 oktober 15
Clients
tisdag 20 oktober 15
Abstract factory:
consequences
Isolates clients from
+concrete
dependencies
Makes interchanging
+families
of products easier
tisdag 20 oktober 15
Strategy
•
When related classes only
differ in behavior
•
You need different variants
of an algorithm
•
An algorithm uses data the
clients don’t need to know
•
A class uses conditionals
for selecting behavior
Behavioral
tisdag 20 oktober 15
Abstract
Factory
•
A system should be
independent of how its
products are created
•
A system should be
configured with one of
multiple families of products
•
You want to provide a class
library of products, and only
expose their interfaces
Creational
Design principles
• Encapsulate what varies
• Program to an interface, not to an
implementation
• Favor composition over inheritance
• Classes should be open for extension but
closed for modification
• Don’t call us, we’ll call you
tisdag 20 oktober 15
Dependency Injection
tisdag 20 oktober 15
ICheesePizza
-cheese
StandardCheesePizza
<<ICheese>
>
MozzarellaCheese
ParmesanCheese
IClamPizza
-cheese
-clam
<<IClam>>
FancyClamPizza
FreshClam
FrozenClam
NYStyle
ChicagoStyle
Distinguished by namespaces in C#
tisdag 20 oktober 15
DI: How?
1. Declare dependencies as constructor
arguments of interface types
2. Register classes (components) in an
Inversion-of-Control Container
3. Resolve the top-level object from an
interface through the Container
tisdag 20 oktober 15
1. Dependencies
namespace DITest
{
!
public class FancyClamPizza: IClamPizza
!
{
!
!
private IClam clam;
!
!
private ICheese cheese;
tisdag 20 oktober 15
!
!
!
!
!
!
!
!
!
!
public FancyClamPizza (IClam clam, ICheese cheese)
{
!
this.clam = clam;
!
this.cheese = cheese;
}
!
!
!
!
!
!
public String ClamType() {
!
return String.Format("fancy {0}",clam);
}
!
!
!
!
}
!
!
!
}
public String Describe() {
!
return String.Format("fancy clam pizza with {0} and {1}",ClamType(), cheese);
}
2. Registration
namespace DITest
{
!
public class IoCInstaller: IWindsorInstaller
!
{
!
!
public void Install(IWindsorContainer container, IConfigurationStore store)
!
!
{
!
!
!
container.Register(Classes
!
!
!
.FromThisAssembly()
!
!
!
.InNamespace("DITest.NYStyle")
!
!
!
.WithServiceAllInterfaces());
!
!
!
container.Register (Classes
!
!
!
.FromThisAssembly()
!
!
!
.AllowMultipleMatches()
!
!
!
.InSameNamespaceAs<IoCInstaller>()
!
!
!
.WithServiceAllInterfaces());
!
!
}
!
}
}
Castle Windsor, http://www.castleproject.org
tisdag 20 oktober 15
3. Resolution
!
!
!
!
!
!
!
!
!
var container = new WindsorContainer();
// adds and configures all components using WindsorInstallers from executing assembly
container.Install(FromAssembly.This());
!
!
!
// instantiate and configure root component and all its dependencies and their dependencies and...
!
!
!
!
!
!
var p = container.Resolve<ICheesePizza>();
Console.WriteLine (p.Describe ());
tisdag 20 oktober 15
Singleton
tisdag 20 oktober 15
public class Singleton {
private static Singleton instance = new Singleton();
private String name;
public String getName() {
return name;
}
public static void someOtherMethod(){
System.out.println("Hi there!");
}
private Singleton() {
[ ... ]
}
What about
static methods?
}
private Singleton() {
try {
// Very expensive job indeed
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
name = Math.random() > 0.5 ? "Jonas" : "Anders";
}
Our app takes forever to load
tisdag 20 oktober 15
Thread t1 = new Thread(new StaticMethodInvocation());
Thread t2 = new Thread(new SingletonLookup());
t0 = System.nanoTime();
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
someOtherMethod invoked
Singleton name: Anders
Singleton lookup took 1 003 348 000 ns
Static method invocation took 1 002 463 000 ns
tisdag 20 oktober 15
How about now?
private static Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
someOtherMethod invoked
Static method invocation took 899 000 ns
Singleton name: Anders
Singleton lookup took 1 002 277 000 ns
tisdag 20 oktober 15
What about threads?
tisdag 20 oktober 15
private Singleton() {
try {
// Very expensive job indeed
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
name = Math.random() > 0.5 ? "Jonas" : "Anders";
}
private static final class SingletonLookup implements Runnable {
@Override
public void run() {
System.out.println(MessageFormat.format("Singleton name: {0}",
Singleton.getInstance().getName()));
}
}
public static void main(String[] args) {
Thread t1 = new Thread(new SingletonLookup());
Thread t2 = new Thread(new SingletonLookup());
t0 = System.nanoTime();
t1.start();
t2.start();
try {
t1.join();
Singleton name: Anders
t2.join();
Singleton name: Jonas
} catch (InterruptedException e) {
Singleton name after our threads have run: Anders
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Singleton name after our threads have run: "+Singleton.getInstance().getName());
}
tisdag 20 oktober 15
Oops!
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
Singleton
Singleton
Singleton
Singleton
Singleton
name: Anders
name: Anders
lookup took 1 003 340 000 ns
lookup took 1 003 286 000 ns
name after our threads have run: Anders
Woohoo!
tisdag 20 oktober 15
Singleton as Enum
public enum EnumSingleton {
INSTANCE;
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
tisdag 20 oktober 15
Singletons in Ruby
Object
A
MetaClass
class A; end
Singleton
Class for foo
foo
tisdag 20 oktober 15
foo = A.new
Class
Singleton
Class for A
class << foo; end
A
class A; end
class << A; end
class A
end
a = A.new
class << A
def new
raise "Illegal!"
end
end
irb(main):014:0> a
#<A:0x007f8d6b92bcb0>
irb(main):016:0> A.new
RuntimeError: Illegal!
from (irb):10:in `new'
from (irb):16
from /Users/olale/.rvm/rubies/ruby-2.0.0-p247/bin/irb:13:in `<main>'
Now we have one object, but we cannot produce another
of the same class
tisdag 20 oktober 15
Singleton:
consequences
Ensures single objects per
+class
tisdag 20 oktober 15
several design
- Violates
principles!
•
•
•
•
tisdag 20 oktober 15
Singleton considered
dangerous
Encapsulate what varies
Program to an interface, not to an implementation
Favor composition over inheritance
Classes should be open for extension but closed for
modification
•
•
Don’t call us, we’ll call you
•
•
Classes should only have one reason to change
Depend on abstractions, do not depend on concrete
classes
Strive for loosely-coupled design
Builder
tisdag 20 oktober 15
Builder – Non Software Exam
TDDB82 Design Patterns HT1 2009 LECTURE
05
tisdag 20 oktober 15
Client
Director
build()
Builder
buildA()
buildB()
buildC()
getProduct()
tisdag 20 oktober 15
The Builder
Separa
of a com
represe
same c
can cre
represe
The client creates t
configures it with t
Director notifies th
of the product shou
tisdag 20 oktober 15
Builder handles req
and adds parts to t
The client retrieves
builder.
Client
Director
Builder
tisdag 20 oktober 15
Abstract Factory
Client receives a Factory
Client requests a product from Factory
Client receives an abstract product
Builder
Client initializes Director with Builder
Client asks Director to build
Client requests product from Builder
tisdag 20 oktober 15
Client receives a builder-specific product
Builder: consequences
Can control the way
+objects
are created
Can produce different
+products
using the same
Director
tisdag 20 oktober 15
necessarily a
- Not
common interface for
products
must know how
- Clients
to initialize builders and
retrieve products
Adapter
tisdag 20 oktober 15
Class Adapter
Object Adapter
! An object adapter relies on object composition
11
Object Adapter
tisdag 20 oktober 15
12
Multiple back-end
objects
Client
Target
do()
Adapter
-adaptee1
-adaptee2
do()
tisdag 20 oktober 15
Adaptee1
+perform()
Adaptee2
+perform()
Multiple back-end
methods
Client
Target
do()
Adapter
-adaptee
do()
adaptee.foo()
adaptee.bar()
tisdag 20 oktober 15
Adaptee1
+foo()
+bar()
public interface Turkey {
public void gobble();
public void fly();
}
public interface Duck {
public void quack();
public void fly();
}
public class TurkeyAdapter implements Duck {
Turkey turkey;
public TurkeyAdapter(Turkey turkey) {
this.turkey = turkey;
}
public void quack() {
turkey.gobble();
}
}
public void fly() {
for(int i=0; i < 5; i++) {
turkey.fly();
}
}
tisdag 20 oktober 15
public class DuckAdapter implements
Turkey {
Duck duck;
Random rand;
public DuckAdapter(Duck duck) {
this.duck = duck;
rand = new Random();
}
public void gobble() {
duck.quack();
}
}
public void fly() {
if (rand.nextInt(5)
duck.fly();
}
}
== 0) {
Adapter: consequences
interface changes
+toIsolates
the adapter class
tisdag 20 oktober 15
adapters require
- Class
target interfaces or
multiple inheritance in
the language
Bridge
tisdag 20 oktober 15
The Bridge Pattern Structure
Abstraction == That which we (should) care about
20
tisdag 20 oktober 15
TV
Samsung
LG
Logitech
Harmony
On()
Off()
On()
Off()
One For All
On()
Off()
On()
Off()
Remote
tisdag 20 oktober 15
Message type
Transmission
type
tisdag 20 oktober 15
Password
recovery
Signup
E-mail
Send()
Send()
SMS
Send()
Send()
Intent
Collaborations
tisdag 20 oktober 15
Bridge
Strategy
Decouple two class
hierarchies
(abstraction/
implementation)
Allow for
exchangeable
algorithms
The Context and
The Bridge forwards
Strategy
requests to the
collaborate, passing
Implementor
data between them
Bridge
Intent
Applicability
tisdag 20 oktober 15
Adapter
Decouple two class
Convert an existing
hierarchies
class to fit a new
(abstraction/
interface
implementation)
In a new system
In an existing system
Design principles
tisdag 20 oktober 15
•
•
•
•
Encapsulate what varies
•
•
Don’t call us, we’ll call you
•
Classes should only have one reason to change
Program to an interface, not to an implementation
Favor composition over inheritance
Classes should be open for extension but closed for
modification
Depend on abstractions, do not depend on concrete
classes
Bridge: consequences
Lets two class hierarchies
+with
common
superclasses vary
independently
tisdag 20 oktober 15
some implementation
- Ifclasses
do not support
an abstract concept, the
abstraction breaks
Observer
tisdag 20 oktober 15
tisdag 20 oktober 15
Weather Station
Humidity Display
subscribe()
subscribe()
publish()
publish()
unsubscribe()
publish()
tisdag 20 oktober 15
Average Temp
Display
! The only things the subject knows ab
that it implements a certain interface
tisdag 20 oktober 15
! We can add new observers at any tim
! We never need to modify the subject t
observers
! We can reuse subjects or observers in
other
! Changes to either the subject or an ob
the other
Subject
tisdag 20 oktober 15
Concrete Observer
Mediator
vs
Observer
tisdag 20 oktober 15
Design principles
tisdag 20 oktober 15
•
•
•
•
Encapsulate what varies
•
•
Don’t call us, we’ll call you
•
•
Classes should only have one reason to change
Program to an interface, not to an implementation
Favor composition over inheritance
Classes should be open for extension but closed for
modification
Depend on abstractions, do not depend on concrete
classes
Strive for loosely-coupled design
Chain of Responsibility
tisdag 20 oktober 15
SPAM Filter
isSpam(Message)
accept
Size Filter
isTooLarge(Message)
accept
Sorting Filter
sort(Message)
process
reject
Message arrived
reject
Message
rejected
tisdag 20 oktober 15
Chain of Respon
tisdag 20 oktober 15
Avoid coupling the sender of a request to its rec
more than one object a chance to handle the re
receiving objects and pass the request along th
object handles it.
Examples
• Logging
• Input management in GUI:s
tisdag 20 oktober 15
CoR: consequences
provides the Observer
+with
more control over
invocation of targets
tisdag 20 oktober 15
handler does not
- Aknow
if it will receive a
message, depending on
the behavior of other
handlers in the chain
Memento
tisdag 20 oktober 15
The Memento – Non So
The Me
extern
interna
can be
later.
!
!
tisdag 20 oktober 15
!
This pattern is common among do-it-yourself mechanics repairin
their cars. The drums are removed from both sides, exposing bot
brakes .
Only one side is disassembled, and the other side serves as a Me
brake parts fit together
Only after the job has been completed on one side is the other si
When the second side is disassembled, the first side acts as the
TDDB84 Design Patterns
Slide 3
Iterative Optimizer
iteration
current target value
current solution
Optimize()
Abort()
GetState()
SetState()
SolverMemento
iteration
current target value
current solution
Client
- memento
- optimizer
Optimize()
Abort()
ResetOptimizer(SolverMemento)
tisdag 20 oktober 15
Memento
Originator o = new Originator();
o.state = "On";
// Store internal state
Caretaker c = new Caretaker();
c.memento = o.CreateMemento();
// Continue changing originator
o.State = "Off";
// Restore saved state
o.SetMemento( c.Memento );
TDDB84 Design Patterns
Slide 4
tisdag 20 oktober 15
Mementos in GUI:s Undo/Redo
User
1
gi
User
2
gi
jo
User
4
tisdag 20 oktober 15
gi
Name
Age
Ginnie
24
Name
Age
Ginnie
24
Johnny
37
Name
Age
Ginnie
24
3
Undo
Redo
Cut
Copy
Paste
Paste special...
Delete
Select All
Memento:
consequences
Can externalize object
+state
for later restoration
within the lifetime of the
object
Encapsulates access to the
+objects’
inner state
tisdag 20 oktober 15
on
- Depending
implementation, access
to private fields requires
memento classes as
inner/friend classes to
each domain class
Command
tisdag 20 oktober 15
Command
Client
Waiter
Order
Chef
Order
Place Order
Cook
tisdag 20 oktober 15
Remote control
The Ultimate Remote Control
Fan
High()
Low()
Off()
GetSpeed()
Joe’s Ultimate Remote Control
On
Off
On
Off
On
Off
On
Off
On
Off
On
Off
On
Off
Undo
Lamp
On()
Off()
Dim()
TV
TurnOn()
TurnOff()
SetChannel()
tisdag 20 oktober 15
TDDB84 Design Patterns
Slide 30
Client
Invoker
-command
perform()
Receiver
+perform()
tisdag 20 oktober 15
Command
+execute()
Concrete
Command
-receiver
Client
Concrete
Commands
Invoker
Receiver
Command
tisdag 20 oktober 15
Command:
consequences
Allows extensions of
+commands
design if not
- Bad
needed!
Decouples the execution
+from
the specification of
be confusing if it
- May
removes the receiver
the command
tisdag 20 oktober 15
from responsibilities
Course summary
• Practical work:
• Intro seminar + three labs
• Reflection and analysis:
• Reading a research paper, and studying
design patterns in a real context
tisdag 20 oktober 15
Life after the course
• Writing your papers :)
• Masters theses: Info @ 12:15!
• Research project in Software Engineering
• Exam? No.
tisdag 20 oktober 15
Thanks for your
participation, and good
luck with your papers!
tisdag 20 oktober 15
Download