l04 software design 2

Post on 01-Nov-2014

94 Views

Category:

Technology

5 Downloads

Preview:

Click to see full reader

DESCRIPTION

Framhald af umfjöllun um hlutbundna forritun og hönnun. Nú förum við yfir Generic Programming sem sem leið til að búa til sveigjanlega og endurnýtanlegar einingar. Skoðum líka reflection. Þá verður farið fyrir hvernig má hann laustengdar einingar og notum við frægan andarleik sem dæmi. Þá mun Code Horror Dude kíkja í heimsókn

TRANSCRIPT

Lecture 04Software Design 2

Agenda Programming with Objects– Classes– Interfaces– Generic programming– Reflection

Software Design– Ducks…

Reading Barbin Introduction, 1 Core Principles– Separation of concerns (SoC)– Coupling– Cohesion– Information Hiding

Don’t Repeat Yourself Polymorphism Optional:– http://docs.oracle.com/javase/tutorial/

Generic Programming

Generic Programming Programming in an data type independent

way– Same code is used regardless of the data type

Example– Sort can be applied to any data type– Generic collection

• Java Collection Framework

Design Principle– Always use the most generic data type

possible

Generic Programming All classes extend Object– Allows generic algorithms and data structures

static int find (Object[] a, Object key){ int i; for (i=0;i<a.length;i++) if (a[i].equals(key)) return i; return -1;}

Employee[] staff = new Employee[10];Employee e1 = new Employee("Dilbert");

staff[x] = e1;int n = find(staff, e1);

Generic Programming Generic collections– ArrayList is an example class that uses

Object ArrayList al = new ArrayList(); al.add (new Employee ("Dilbert")); al.add (new Employee ("Wally")); al.add (new Employee ("Alice"));

Iterator i = al.iterator(); Employee e; while (i.hasNext()) { e = (Employee)i.next(); System.out.println(e.getName()); }

DilbertWallyAlice

Generic Programming Generic collections– The Collections class is another exampleList<Employee> list = new ArrayList<Employee>();

list.add (new Employee ("Dilbert"));list.add (new Employee ("Wally"));list.add (new Employee ("Alice"));

Collections.sort(list);for (Employee e: list){ System.out.println(e);}

AliceDilbertWally

Reflection

Reflection Reflection allows examination and manipulation

of objects at runtime– Get information about a class

• Fields, methods, constructors, and super classes• Constants and method declarations belong to an interface

– Create an instance of a class whose name is not known until runtime

– Get and set the value of an object's field, even if the field name is unknown to your program until runtime

– Invoke a method on an object, even if the method is not known until runtime

Reflectionstatic void showMethods(Object o){ Class c = o.getClass(); Method[] theMethods = c.getMethods(); for (int i = 0; i < theMethods.length; i++) { String methodString = theMethods[i].getName(); System.out.println("Name: " + methodString); String returnString = theMethods[i].getReturnType().getName(); System.out.println(" Return Type: " + returnString); Class[] parameterTypes = theMethods[i].getParameterTypes(); System.out.print(" Parameter Types:"); for (int k = 0; k < parameterTypes.length; k ++) { String parameterString = parameterTypes[k].getName(); System.out.print(" " + parameterString); } System.out.println(); } } }

Reflection

Bla

public class ReflectMethods{ public static void main(String[] args) { Polygon p = new Polygon(); showMethods(p); } Name: getBoundingBox

Return Type: java.awt.Rectangle Parameter Types:Name: contains Return Type: boolean Parameter Types: java.awt.geom.Point2D...Name: toString Return Type: java.lang.String Parameter Types:

Reflection Reflection is very useful in frameworks– Infrastructure code– “plumbing” – The “Noise”

Examples– Create Java objects from XML descriptions– Load classes at runtime and invoke methods– Tools and utilities for development

Dynamically Loading Classes Classes can be dynamically loaded at

runtime– Offers the flexibility to decide which class to

run dynamically– Class names can be specified in configuration

files Class class

Class instanceClass = Class.forName("RssFeedReader"); reader = (FeedReader)instanceClass.newInstance();

A) BDB) DBC) BDCD) Compilation fails

QUIZclass Top { public Top(String s) { System.out.print("B"); } }public class Bottom2 extends Top { public Bottom2(String s) { System.out.print("D"); } public static void main(String [] args) { new Bottom2("C"); System.out.println(" "); } }

A) BDB) DBC) BDCD) Compilation fails

QUIZ

class Top { public Top(String s) { System.out.print("B"); } }public class Bottom2 extends Top { public Bottom2(String s) { System.out.print("D"); } public static void main(String [] args) { new Bottom2("C"); System.out.println(" "); } }

Software Design

Object Oriented Design Design and implementation of software

needs to be of quality– Badly designed, well implemented = problem!– Well designed, badly implemented = problem!

CODEHORROR!!

CODE HORROR DUDE

Object Oriented Design Good design

Is based on OO principles

Abstracts complex APIs such as J2EE

Is flexible and can be changed

Contains loosely coupled components

Example from Head First Design Patterns

Getting Started SimUDuck is highly successful duck pond

simulation game Original design

Change Request But now we need the ducks to FLY

Problem! But not all duck fly – We forgot Rubber

Duck!

How can we fix this? Just override fly and quack to do nothing

We even think ahead We fix all non-flyable and non-quackable

ducks as wellCode smell!

Which of the following are disadvantages of using inheritance to provide Duck behavior?

A) Code is duplicated across subclassesB) Runtime behavior changes are difficultC) We can’t make ducks danceD) Hard to gain knowledge of all duck behaviorsE) Ducks can’t fly and quack at the same timeF) Changes can unitentionally affect other ducks

QUIZ

✔✔

The Problem The problem is this– Derived classes (RubberDuck) are forced to

inherit behaviour they don’t have– Derived classes (RubberDuck) needs to be

exposed to the inner workings of the superclass (Duck)

– Users of the base class (Duck) should expect same functionality

– Violation of the Liskov Substitution Principle

The Liskov Substitution Principle

Subtypes must be substitutable for their base types. Code that uses references to base class must be able to use objects of derived classes without knowing it.

BarbaraLiskov

The Liskov Substitution Principle All code operating with reference to the

base class should be completely transparent to the type of the inherited object

It should be possible to substitute an object of one type with another within the same class hierarchy

Inheriting classes should not perform any actions that will invalidate the assumptions made by the base class

LSP Examplepublic class Rectangle {

protected int _width; protected int _height; public int getWidth() { return _width; } public int getHeight() { return _height; } public void setWidth(int width) { _width = width; } public void setHeight(int height) { _height = height; }}

LSP Examplepublic class Square extends Rectangle {

public void setWidth(int width) { _width = width; _height = width; }

public void setHeight(int height) { _height = height; _width = _height; } }

Implementation convenience

LSP Exampleimport junit.framework.Assert;import org.junit.Test;

public class RectangleTests {

@Test public void areaOfRectangle() {

Rectangle r = new Square(); r.setWidth(5); r.setHeight(2); // Will Fail - r is a square and sets // width and height equal to each other. Assert.assertEquals(r.getWidth() * r.getHeight(),10); }}

Trying to fix the Problem Let’s try using interfaces– Flyable and Quackable Code duplication!

What is the Problem? We tried this– Inheritance changes all subcasses– Interfaces cause code duplication

The problem is we are mixing different types of code in one type of classes

Fix– Separate Variation Design Principle– Take what varies and encapsulate it so it

wont affect the rest of the code

Separate Variations

Identify the aspects of your application that vary and separate them from what stays the same

Separation of Concerns Separate what changes from what stays

the same– Move duck behavior to a separte classes

FlyWithWings flyBehavior = new FlyWithWings();DATA TYPE IS TOO SPECIFIC

Separation of Concerns But the Duck classes cannot use the

concrete behavior classes! – We need an interface or supertype

FlyBehavior flyBehavior = new FlyWithWings();

INTERFACE - POLYMORPHISIM

The Interface Design Principle

Program to an interface, not an implementation

Loose Coupling with Interfaces Advantages– The ability to change the implementing class of

any application object without affecting calling code

– Total freedom in implementing interfaces– The ability to provide simple test

implementations and stub implementations of application interfaces as necessary

Program to an interfacesProgram to an implementation

Program to interface/subtype

Program to unknown creation

Dog d = new Dog();d.bark();

Animal animal = new Dog();animal.makeSound();

Animal animal = getAnimal();animal.makeSound();

Program to an interfacesDependency Injection– Make the caller responsible for setting the

dependencyprivate Animal animal;

public setAnimal(Animal animal){ this.animal = animal;}...

animal.makeSound();

Injection happens here, in the set-method

LOOSE COUPLING = BEAUTIFUL!

Implementing Behavior We can add new behaviors without

touching the Duck classes

Integrating the Behavior The Duck classes will now delegate its

flying and quacking behavior

Behavior interfaces

Perform the Bahavior

Integrating the Behavior Using the behavior

public class Duck { QuackBehavior quackBehavior; ...

public void performQuack() { quackBehavior.performQuack() }

}

We don’t care what kind of object this is, all we care is that it knows how to

quack!

Integrating the Behavior Setting the behavior

public class MallardDuck extends Duck { public MallardDuck() { quackBehavior = new Quack(); flyBehavior = new FlyWithWings(); }

}

This is not programming to an interface!

Setting Behavior Dynamically Add two new methods to the Duck class Dependency Injection

public void setFlyBehavior(FlyBehavior flyBehavior){ this.flyBehavior = flyBehavior}

public void setQuackBehavior(QuackBehavior quackBehavior){ this.quackBehavior = quackBehavior}

DuckFactory{ public Duck getMallardDuck() { Duck duck = new MallardDuck() duck.setFlyBehavior(new FlyWithWings()); duck.setQuackBehavior(new Quack()); return duck; }}

Setting Behavior Dynamically The idea– Don´t think: Mallard is-a flying duck, think: it

has-a flying behavior– Putting two classes together where one is a

member in the other is a composition Creating systems using composition give

flexibilty– You can change the behavior at runtime

Composition Design Principle

Favor composition over inheritance

Object Composition Problems with concrete inheritance– Class hierarchy can get rigid– Difficult to change the implementation

Object Composition is more flexible – Allows the behaviour of an object to be altered

at run time, through delegating part of its behaviour to an interface and allowing callers to set the implementation of that interface

Summary OO Programming is powerful– If used correctly– Remember Encapsulation, Interfaces,

Polymorphism Generic programming– Using classes, abstract classes and interfaces

can lead to powerful and flexible programs Reflection– Powerful for building infrastructure

Job interview question

You are given the assignment of creating a component that needs to know sales statistics of Lottery tickets. You know that there is a another component in the system, Sale Server, that handles the sale. You need real-time information. What would you suggest?

EXERCISE

Design Patterns Design pattern is a general solution to a common

problem in software design– Systematic approach for problems that reoccur in

software development– Not complete solution but starting point for design – Not code ready to use– Patterns have names and definitions– Built on common practices

Patterns should not be language dependant– However patterns apply for types of programming

languages

Next Design Patterns

top related