3. Software components and interfaces 3.1 The component vision: rationalizing software development 3.2 The component concept 3.3 Components as software units 3.4 Interfaces 3.5 Specifying interfaces 3.6 Customizing components 1
3.1 The component vision: rationalizing software production Developing software products from existing components products become more realiable easier to construct products easier to train people component competition reduces prices More or less standard practice in other engineering areas 2
Exercise: Write down 5 characteristic properties of a good software component 3
Composing applications from components Composing new applications from existing components Visual component integration tools 4
Example: BeanBox 5
3.2 The component concept Component = independent unit of software providing services through a well-defined interface Szyperski: A software component is a unit of composition with contractually specified interfaces and explicit context dependencies only. A software component can be deployed independently and is subject to composition by third parties. 6
Issues related to components Degree of independence Deployment Size Standardization Technology-specific properties 7
3.3 Components as software units Units of architecture Units of functionality who is responsible of functionalites? Units of reuse what remains common? Units of product configuration what is included in a product? Units of deployment what can be upgraded in isolation? Units of variance what can be changed, how? Units of third-party software what can be obtained from outside? Units of work division what can be separated as tasks? 8
History: 3.4 Interfaces A M interface X B C subroutine A B data Y data data Z Subroutine library C A A Abstract service signature Service implementation module Module library B C class B C Class library 9
Interfaces as first-class entities Interface1 ComponentA Interface2 Interface3 ComponentB Interface4 10
Provided and required interfaces in UML 2.0 PowerSource provided interface Car Engine PowerSource required interface Car PowerSource Engine 11
Possible implementation in Java: interface PowerSource { void start(); int temperature(); void stop(); class Engine implements PowerSource... {... public void start() {... public int temperature() {... public void stop() {... class Car... {... private PowerSource eng;... public void seteng(powersource e) { eng = e; public void run() {... eng.start();... eng.stop();... 12
Ports in UML 2.0 Point of interaction between an object (component) and its environment PowerSource PowerSource Port Engine host Engine Warnings Warnings 13
3.5 Specifying interfaces: contracts precondition: must hold, when the service is called service interface design-by-contract (Eiffel) Client Service provider defines the abstract semantics of the service allows exchange of participants, as long as the interface and its preand postconditions hold defines the responsibilities of checking (no multiple checking, clear separation of concerns) postcondition: must hold, when the service has been delivered, assuming that the precondition held when the service was called 14
Class/component invariants Person age: int toberetired: int op1(...) op2(...) op3(...) invariant age > 0 & age < toberetired 15
Inheritance & contracts pre' post' pre post A public oper(...) pre post pre' pre post' post B public oper(...) pre' post' pre pre' post' post C pre post' Which is correct (A,B,C,D)? pre' post D 16
Design by contract: example (1) class Stack { private Object [] storage; private int top; public Stack(int size) { storage = new Object[size]; top = -1; public int size() {return top+1 public boolean full() {return top == storage.length; public void push(object x) { if (top < storage.length-1) { storage[++top] = x; else { System.out.println("Overflow"); 17
Design by contract: example (2) public Object pop() { if (top >= 0) { return storage[top--]; else { System.out.println("Underflow"); return null; client:... if s.size() > 0 then {s.pop(); else {... error handling...... Problems? 18
Design by contract: example (3) Idealistic solution: interface Stack { Object pop() // pre size() > 0; // post size = old size 1; class ArrayStack implements Stack { public Object pop() { return storage[top--]; Prove that the pre- and postconditions hold (?) Produce run-time checks that the pre- and postconditions hold (?) 19
Pragmatic approach: exceptions exception = contractor is unable to fulfill its part of the contract method either fulfills the contract or throws an exception implies that the service provider is able to detect the unableness exceptions become part of the interface pre- and postconditions can be given informally public Object pop() throws Underflow { // pre: stack non-empty // post: stack size reduced by one // Underflow: stack is empty upon entry if (top >= 0) { return storage[top--]; else { throw new Underflow(this); 20
3.6 Customizing components Changing the initial state of a component Implementing required interfaces Subclassing 21
Changing the initial state of a component Client :Comp ServicesI setproperty(...) Comp create setproperty(...) use 22
In Java: class Button extends Component... {... String label; public Button() {... public Button(String arg) { label = arg;... public setlabel(string arg) { label = arg;... 23
Implementing required interfaces ActionListener Button AppLogic 24
Subclassing Button CompanyButton 25
In Java: class CompanyButton extends Button { public CompanyButton(String arg) { super(arg); label = arg.touppercase(); public void setlabel(string arg) { label = arg.touppercase(); 26
Fragile base class problem Library component Comp "Innocent" modification of the original component can make the customized component invalid Customized component Custom 27
Example (1) <<interface>> Container addelement(object) addcontainer(container) List addcontainer: {...addelement(...);... <<interface>> CountedContainer getcount() CountedList addelement: { super.addelement(...); counter++; 28
<<interface>> Container addelement(object) addcontainer(container) Example (2) List addelement no more called! addcontainer: {... <<interface>> CountedContainer getcount() CountedList addelement: { super.addelement(...); counter++; 29