Real world problem Requirements Engineering Design Requirements Specification
Real world problem Requirements Engineering Design Requirements Specification Maintenance Design Specification Testing Working code with quality assurances Implementation Working code 3
Classes • Class (package, if abstract, …) • State properties (attributes) • Dynamic behavior (methods) • Annotate: – Class if abstract – For methods && attributes: + for public, - for private, # for protected – Method if constructor, abstract, … – Method signature – Attribute type 13
Classes package bookstorecounterexample; public class Item { public Item(){title=""; price=-1. 0; } public Item(String a. Title, double a. Price){ title = a. Title; price=a. Price; } public void show. Details() { System. out. println(title + "tt Price: " + price); } public double get. Original. Price() {return price; } public double get. Final. Price() { return price; } protected String title; protected double price; } 14
Comment Notes are used (with restraint) to comment on key points of the SW structure With dashed lines, if they pertain to a specific construct, e. g. , a class 15
Σχέση εξάρτησης (dependency) • Class DC (Dependent. Class) depends upon class DUC (Depended. Upon. Class) if even one of the following holds: – There exists a method DC. f that takes as parameter an object of DCU DC. f(DUC x): … – There exists a method DC. f that returns an object of DUC DC. f(…): DUC – There exists a method DC. f that uses an object of DUC as an internally declared variable 18
Παράδειγμα public class Simple. Bookstore. Application { public static void main(String args[]){ Item. Manager amazon = new Item. Manager(); Book book. Ref; book. Ref = new Book("Discours de la methode", "Rene Descartes", 1637, 50. 00, 0); amazon. add. Item(book. Ref); book. Ref = new Book("The Meditations", "Marcus Aurelius", 180, 30. 00, 1); amazon. add. Item(book. Ref); book. Ref = new Book("The Bacchae", "Euripides", -405, 30. 00, 1); amazon. add. Item(book. Ref); CD cd. Ref; cd. Ref = new CD("Piece of Mind", 10. 0, "Iron Maiden", 4. 0); amazon. add. Item(cd. Ref); cd. Ref = new CD("Matter of Life and Death", 12. 0, "Iron Maiden", 2. 0); amazon. add. Item(cd. Ref); amazon. report. All. Items(); } } 19
Εναλλακτικοί συμβολισμοί https: //en. wikipedia. org/wiki/Class_diagram 23
public class Shopping. Cart { private Array. List<Item> items; } /* Attribute => association * Observe the concrete association * (not dependency), the role name * and the multiplicity => Array. List */ public class Simple. Bookstore. Application { … public static void main(String args[]){ Item. Manager item. Manager = new Item. Manager(); … Shopping. Cart cart = new Shopping. Cart(); … cart. show. Details(); } Παρατηρείστε το διακεκομμένο βελάκι από τον Simple. Bookstore. Application προς τον Item. Manager, που υποδηλώνει την εξάρτηση, η οποία προκύπτει από αυτό το new. Οποιαδήποτε από τις μπλε εντολές αρκεί για να δημιουργήσει την εξάρτηση από τον Simple. Bookstore. Application προς τον 25 Shopping Cart
package simple. Bookstore. Demo; public class Item {. . . } public class Book extends Item {. . . } public class CD extends Item {. . . } public class Item. Manager { private Array. List<Item> all. Items; . . . } Προσοχή! Εδώ οι CD & Book κληρονομούν από την κλάση Item. Θα δούμε αργότερα ότι η σωστή σχεδίαση επιτάσσει η μαμά-κλάση να είναι αφηρημένη! 29
package bookstore. Acceptable; public abstract class Item { protected String title; protected double price; protected int id; Abstract class public Item(){title=""; price=-1. 0; id=-1; } public Item(String a. Title, double a. Price, int id){ title = a. Title; price=a. Price; this. id =id; } public abstract String show. Details(); public abstract String get. Details(); public abstract double get. Final. Price(); public double get. Original. Price(){return price; } public String get. Title(){return title; } public int get. Id(){return id; } } 35
One implementation package bookstore. Acceptable; public class Book extends Item { private String author; … @Override public double get. Final. Price() { return price; } } 36
Another implementation public class CD extends Item { private String artist; … @Override public double get. Final. Price() { return (price - discount); } @Override public String show. Details() { String result = "***Item id: " + id + "*** n" + title + "tt Price: " + price + "n" + "by " + artist + "n" + "final price: " + get. Final. Price()+ "nn"; return result; } } 37
Abstract coupling public class Item. Manager { private Array. List<Item> all. Items; … } The “client” class Item. Manager uses ONLY the abstract class and is completely agnostic to any subclasses the abstract class has. => Zero maintenance cost when new subclasses appear 38
Interfaces definition by Arlow & Neustadt • An interface specifies a named set of public features (practically speaking: operations) • The key idea behind interfaces is to separate the specification of functionality (the interface) from its implementation by a classifier such as a class or subsystem. • An interface can’t be instantiated - it simply declares a contract that may be realized by zero or more classifiers. • Anything that realizes an interface accepts and agrees to abide by the contract that the interface defines. 48
Παράδειγμα An interface is an abstraction of a contract, which specifies guaranteed methods to be offered by materializations of the interface public interface IBreaks { public abstract double get. Speed. Reduction(Double excerted. Force); public abstract boolean report. If. Broken(double threshold); } public class Break. Factory { public IBreaks construct. Break(String concrete. Class. Name){ if (concrete. Class. Name. equals("Nice. Breaks")) return new Nice. Breaks(); else if (concrete. Class. Name. equals("Duper. Breaks")) return new Duper. Breaks(); System. out. println("If you got up to here, you passed a wrong argument to Break. Factory"); return null; } } 50
Παράδειγμα public class Nice. Breaks implements IBreaks { @Override public double get. Speed. Reduction(Double excerted. Force){ return 45*excerted. Force; } @Override public boolean report. If. Broken (double threshold) { if ((threshold > 1. 0) || (threshold > 1. 0)){ System. out. println(“Threshold for breaks' health should be between 0 & 1"); System. exit(-1); } Random random. Dice = new Random(); if (random. Dice. next. Double() > threshold) return false; else return true; } } 51
Παράδειγμα public class Duper. Breaks implements IBreaks { @Override public double get. Speed. Reduction(Double excerted. Force){ return 45*excerted. Force; } @Override public boolean report. If. Broken (double threshold) { //Intentional issue, food for thought: parameter unused! return false; } } 52
Παράδειγμα import bicycle. Breaks. IBreaks; import bicycle. Breaks. Break. Factory; … public class Bicycle. Manager { … public double set. Breaking(double force){ velocity -= breaks. get. Speed. Reduction(force); return velocity; } public boolean report. If. Damage. Exists(){ boolean broken. Status = false; if (breaks. report. If. Broken(0. 7) == true){ broken. Status = true; System. out. println("breaks are broken"); } … return broken. Status; } private double velocity; private IBreaks breaks; private Break. Factory break. Factory; … } A client class: - has an attribute typed by the interface (here: IBreaks) - uses a factory to generate concrete objects of the concrete classes - uses the abstract methods of the contract to complete its task (here: get. Speed. Reduction and report. If. Broken) => The client code is completely independent of the concrete classes (just knows exactly two elements, the interface and the factory) … … thus allowing the addition of new classes or maintaining the existing ones, without any impact to the client! //see how the constructor uses the factory public Bicycle. Manager( …, String breaks. Name){ break. Factory = new Break. Factory(); … breaks = break. Factory. construct. Break(breaks. Name); … velocity = 0. 0; } 53
Interfaces: why & how • Client code specifies the service it wants to use • Service-provision code implements the specified functionality Specification Implementation • The interface is a contract between the service provider and the service consumer • As service provision evolves (new versions, new alternatives, bug fixes, …) the client is immune to change if and only if the contract is respected 54
Interface as a contract Example Client class Client of the client Service providers Observe the notation between the interface and its concrete materializations: dotted line stemming from an 55 empty triangle �
Interface as a contract Example Specification Implementation Client class Client of the client Service providers Observe the notation between the interface and its concrete materializations: dotted line stemming from an 56 empty triangle �
Συμβολισμός Τυπικός συμβολισμός: Εδώ ο Bicycle (client ) έχει ως πεδίο το IBreaks. Δείτε πώς συμβολίζεται η υλοποίηση του interface από Nice. Breaks, Duper. Breaks Provider interface Required (by the client) interface Εναλλακτικά: με provider interface as lollipop & required interface 57 as hook
Interfaces: a checklist • Avoid: – Attributes and implementation details • just stick to the fundamental set of methods needed – Any kind of associations to other classes – The temptation of reusing code (!!) 58
Abstract classes vs. interfaces • Abstract classes have a predefined behavior for some of their functionality; interfaces don’t • Interfaces are used for: – Stable contract-as-API between subsystems – Dissimilar objects that have common functionalities – Small bits of functionality 60
Sequence Diagrams public class AClass { public int aa 1; public float aa 2; public AClass(int a 1, float a 2){ aa 1 = a 1; aa 2 = a 2; } public void ma 1(BClass bo, int flag){ bo. mb 1(flag); } public void ma 2(){ System. out. println(aa 1+aa 2); } } 69
Sequence Diagrams public class BClass { public String ab 1; public String ab 2; public BClass(String a 1, String a 2){ ab 1 = a 1; ab 2 = a 2; } public void mb 1(int flag){ System. out. println(ab 1 + flag); } public void mb 2(AClass ao){ System. out. println(ab 2); ao. ma 2(); } } 70
Sequence Diagrams public class Main { public static void main(String[] args) { Input. Stream. Reader in = new Input. Stream. Reader(System. in); Buffered. Reader br = new Buffered. Reader(in); String in. Data 1, in. Data 2; try { in. Data 1 = br. read. Line(); in. Data 2= br. read. Line(); AClass ao = new AClass(Integer. parse. Int(in. Data 1), Integer. parse. Int(in. Data 2)); in. Data 1 = br. read. Line(); in. Data 2= br. read. Line(); BClass bo = new BClass(in. Data 1, in. Data 2); } } in. Data 1 = br. read. Line(); ao. ma 1(bo, Integer. parse. Int(in. Data 1)); bo. mb 2(ao); } catch (IOException ex) { System. out. println(ex. get. Message()); } 71
Sequence Diagrams public class AClass { public int aa 1; public float aa 2; public AClass(int a 1, float a 2){ aa 1 = a 1; aa 2 = a 2; } public void ma 1(BClass bo, int flag){ if(flag >= 0) bo. mb 1(flag); εναλλακτικές αλληλεπιδράσεις else bo. mb 2(this); } public void ma 2(){ System. out. println(aa 1+aa 2); } } 75
Sequence Diagrams public class BClass { public String ab 1; public String ab 2; public BClass(String a 1, String a 2){ ab 1 = a 1; ab 2 = a 2; } public void mb 1(int flag){ System. out. println(ab 1 + flag); } public void mb 2(AClass ao){ System. out. println(ab 2); ao. ma 2(); } } 76
Sequence Diagrams public class Main { public static void main(String[] args) { Input. Stream. Reader in = new Input. Stream. Reader(System. in); Buffered. Reader br = new Buffered. Reader(in); String in. Data 1, in. Data 2; try { in. Data 1 = br. read. Line(); in. Data 2= br. read. Line(); AClass ao = new AClass(Integer. parse. Int(in. Data 1), Integer. parse. Int(in. Data 2)); in. Data 1 = br. read. Line(); in. Data 2= br. read. Line(); BClass bo = new BClass(in. Data 1, in. Data 2); } } in. Data 1 = br. read. Line(); ao. ma 1(bo, Integer. parse. Int(in. Data 1)); } catch (IOException ex) { System. out. println(ex. get. Message()); } 77
Sequence Diagrams public class AClass { public int aa 1; public float aa 2; public AClass(int a 1, float a 2){ aa 1 = a 1; aa 2 = a 2; } public void ma 1(BClass bo, int flag){ while(flag >= 0){ bo. mb 1(flag); flag--; } } public void ma 2(){ System. out. println(aa 1+aa 2); } επαναλαμβανόμενες αλληλεπιδράσεις } 79
Sequence Diagrams public class BClass { public String ab 1; public String ab 2; public BClass(String a 1, String a 2){ ab 1 = a 1; ab 2 = a 2; } public void mb 1(int flag){ System. out. println(ab 1 + flag); } public void mb 2(AClass ao){ System. out. println(ab 2); ao. ma 2(); } } 80
Sequence Diagrams public class Main { public static void main(String[] args) { Input. Stream. Reader in = new Input. Stream. Reader(System. in); Buffered. Reader br = new Buffered. Reader(in); String in. Data 1, in. Data 2; try { in. Data 1 = br. read. Line(); in. Data 2= br. read. Line(); AClass ao = new AClass(Integer. parse. Int(in. Data 1), Integer. parse. Int(in. Data 2)); in. Data 1 = br. read. Line(); in. Data 2= br. read. Line(); BClass bo = new BClass(in. Data 1, in. Data 2); } } in. Data 1 = br. read. Line(); ao. ma 1(bo, Integer. parse. Int(in. Data 1)); } catch (IOException ex) { System. out. println(ex. get. Message()); } 81
Real world problem Requirements Engineering Design Requirements Specification Maintenance Design Specification Testing Working code with quality assurances Implementation Working code 86
- Slides: 86