Software Product Lines - Carnegie Mellon School of ... Philips Siemens ... Software Product Lines...

74
Software Product Lines Christian Kästner ISR · CMU 1

Transcript of Software Product Lines - Carnegie Mellon School of ... Philips Siemens ... Software Product Lines...

Software Product Lines

Christian Kästner

ISR · CMU

1

Feature-Oriented

Product Lines

Configuration in Software

• Systems cover all possible functionality– e.g., Windows, Open Office, Oracle, SAP myERP,

Photoshop

• Specialized software and software for embedded systems increasingly important– Mobile divices, sensor networks, automotive systems,

consumer electronics, smart cards, ubiquitious computing

– 98% of all CPUs in embedded devices [2000]

– Resource constraints, heterogeneous hardware

4

Database Systems

• Increasing data volumes

• Resource constraints inembedded environments

5

DatabaseEngine

Printer Firmware

LinuxKernel

Linux kernel

~6 000 000 Lines of C code Highly configurable

> 10.000 configuration options! (x86, 64bit, …)

Most source code is “optional”

10

Software Product Linesin Industry

BoeingBosch GroupCummins, Inc.EricssonGeneral DynamicsGeneral MotorsHewlett PackardLockheed MartinLucentNASANokiaPhilipsSiemens…

CHALLENGES

12

a unique configuration for every

person on this planet

33 featuresoptional, independent

320 features

more configurations than estimated

atoms in the universe

optional, independent

2000 Features 10000Features

199 Configuration parameters

for the optimizer

(1600 total)

Correctness?Correctness?

Understanding?Understanding?

Variability Models

19

Reusing Implementations

Wo Fehler korrigieren?

Software Product Lines

• Coordinated development of a family of software systems

• Sharing code, reusealbe parts(instead of developing from scratch)

• Tailoring to specific needs

IMPLEMENTATION

22

Runtime Parameters

Parameters, variables, constants

Parameter

24

Parameter –i in grep

25

Global configuration optionsclass Config { public static boolean isLogging = false; public static boolean isWindows = false; public static boolean isLinux = true;}class Main { public void foo() { if (isLogging) log( running foo()“);„ if (isWindows) callWindowsMethod(); else if (isLinux) callLinuxMethod(); else throw RuntimeException();} 26

Propagating Parameters

27

durch viele Aufrufepropagiert statt globaler Variable

Selecting configurations

28

• Command line parameters

• Config file

• User dialog

• Source code

• …

Graph Library

class Edge { Node a, b; Color color = new Color(); Weight weight; Edge(Node _a, Node _b) { a = _a; b = _b; } void print() { if (Conf. COLORED) Color.setDisplayColor(color); a.print(); b.print(); if (!Conf.WEIGHTED) weight.print(); }}

class Graph { Vector nv = new Vector(); Vector ev = new Vector(); Edge add(Node n, Node m) { Edge e = new Edge(n, m); nv.add(n); nv.add(m); ev.add(e); if (Conf.WEIGHTED) e.weight = new Weight(); return e; } Edge add(Node n, Node m, Weight w) if (!Conf.WEIGHTED) throw RuntimeException(); Edge e = new Edge(n, m); nv.add(n); nv.add(m); ev.add(e); e.weight = w; return e; } void print() { for(int i = 0; i < ev.size(); i++) { ((Edge)ev.get(i)).print(); } }}

class Node { int id = 0; Color color = new Color(); void print() { if (Conf.COLORED) Color.setDisplayColor(color); System.out.print(id); }}

class Color { static void setDisplayColor(Color c) { ... } } class Weight { void print() { ... } }

class Conf { public static boolean COLORED = true; public static boolean WEIGHTED = false;}

199 Configuration parameters

for the optimizer

(1600 total)

Limitations

31

• Variable code scattered in entire program

– Hard to test in isolation

• Global variables or long parameter lists

• All code always included

– Binary size, memory consumption

– Performance

– Unused functionality as attack vector

• Changes at runtime or load-time?

Limitations

32

• Variable code scattered in entire program

– Hard to test in isolation

• Global variables or long parameter lists

• All code always included

– Binary size, memory consumption

– Performance

– Unused functionality as attack vector

• Changes at runtime or load-time?

compile-time if

designpattern

Preprocessors

conditional compilation

#ifdef

Berkeley DB

#include "db_int.h"

static int __rep_queue_filedone(dbenv, rep, rfp)DB_ENV *dbenv;REP *rep;__rep_fileinfo_args *rfp; {

#ifndef HAVE_QUEUECOMPQUIET(rep, NULL);COMPQUIET(rfp, NULL);return (__db_no_queue_am(dbenv));

#elsedb_pgno_t first, last;u_int32_t flags;int empty, ret, t_ret;

#ifdef DIAGNOSTICDB_MSGBUF mb;

#endif// over 100 lines of additional code

}#endif

35

Preprocessor in Java?• No native preprocessor• Some compilers support conditional compilation

at statement level

• External tools

class Example {public static final boolean DEBUG = false;

void main() {System.out.println(“immer”);if (DEBUG) {

System.out.println(“debug info”); printDetails(); }

} void printDetails() { ... }}

36

Munge• Simple external preprocessor for Java• Originally developed for Swing 1.2

class Example {void main() {

System.out.println(“immer”);/*if[DEBUG]*/System.out.println(“debug info”);/*end[DEBUG]*/

}}

java Munge –DDEBUG –DFEATURE2 file1.java file2.java

http://weblogs.java.net/blog/tball/archive/2006/09/munge_swings_se.html37

Configurable Graph Libraryclass Edge { Node a, b; /*if[COLOR]*/ Color color = new Color(); /*end[COLOR]*/ /*if[WEIGHT]*/ Weight weight; /*end[WEIGHT]*/ Edge(Node _a, Node _b) { a = _a; b = _b; } void print() { /*if[COLOR]*/ Color.setDisplayColor(color); /*end[COLOR]*/ a.print(); b.print(); /*if[WEIGHT]*/ weight.print(); /*end[WEIGHT]*/ }}

class Graph { Vector nv = new Vector(); Vector ev = new Vector(); Edge add(Node n, Node m) { Edge e = new Edge(n, m); nv.add(n); nv.add(m); ev.add(e); /*if[WEIGHT]*/ e.weight = new Weight(); /*end[WEIGHT]*/ return e; } /*if[WEIGHT]*/ Edge add(Node n, Node m, Weight w) Edge e = new Edge(n, m); nv.add(n); nv.add(m); ev.add(e); e.weight = w; return e; } /*end[WEIGHT]*/ void print() { for(int i = 0; i < ev.size(); i++) { ((Edge)ev.get(i)).print(); } }}

class Node { int id = 0; /*if[COLOR]*/ Color color = new Color(); /*end[COLOR]*/ void print() { /*if[COLOR]*/ Color.setDisplayColor(color); /*end[COLOR]*/ System.out.print(id); }}

/*if[COLOR]*/class Color { static void setDisplayColor(Color c) { ... } }/*end[COLOR]*/

/*if[WEIGHT]*/class Weight { void print() { ... } } /*end[WEIGHT]*/

2000 Features 10000Features

Discussion• Compile-time configuration• Can remove arbitrary code before

compilation• Simple programming model

• Bad reputation– Scattered code

– Error prone

– Hard to understand

– Invites neglecting design

– Hinder tool support40

class Stack {void push(Object o

#ifdef SYNC, Transaction txn

#endif) {

if (o==null#ifdef SYNC

|| txn==null#endif

) return;#ifdef SYNC

Lock l=txn.lock(o);#endif

elementData[size++] = o;#ifdef SYNC

l.unlock();#endif

fireStackChanged();}

}

class Stack {void push(Object o

#ifdef SYNC, Transaction txn

#endif) {

if (o==null#ifdef SYNC

|| txn==null#endif

) return;#ifdef SYNC

Lock l=txn.lock(o);#endif

elementData[size++] = o;#ifdef SYNC

l.unlock();#endif

fireStackChanged();}

}

Femto OS

42

Error Prone

static int _rep_queue_filedone(...)DB_ENV *dbenv;REP *rep;__rep_fileinfo_args *rfp; {

#ifndef HAVE_QUEUECOMPQUIET(rep, NULL);COMPQUIET(rfp, NULL);return (__db_no_queue_am(dbenv));

#elsedb_pgno_t first, last;u_int32_t flags;int empty, ret, t_ret;

#ifdef DIAGNOSTICDB_MSGBUF mb;

#endif//over 100 lines of additional code

}#endif

#ifdef TABLESclass Table { void insert(Object data,

Txn txn) { storage.set(data,

txn.getLock()); }}#endifclass Storage {#ifdef WRITE boolean set(…) { ... }#endif}

Error Prone

static int _rep_queue_filedone(...)DB_ENV *dbenv;REP *rep;__rep_fileinfo_args *rfp; {

#ifndef HAVE_QUEUECOMPQUIET(rep, NULL);COMPQUIET(rfp, NULL);return (__db_no_queue_am(dbenv));

#elsedb_pgno_t first, last;u_int32_t flags;int empty, ret, t_ret;

#ifdef DIAGNOSTICDB_MSGBUF mb;

#endif//over 100 lines of additional code

}#endif

#ifdef TABLESclass Table { void insert(Object data,

Txn txn) { storage.set(data,

txn.getLock()); }}#endifclass Storage {#ifdef WRITE boolean set(…) { ... }#endif}

A matter of scale

E x a m p l e : S e s s i o n e x p i r a t i o n i n t h e A p a c h e T o m c a t S e r v e r

47

Design Pattern and Frameworks

best practice

separation

Design Patterns

• Solutions to reoccuring design problems

• Design for extensibility, variation, and reuse are reoccuring problems

• Separate variable part from stable part

• Strategy pattern• Template method pattern• Decorator pattern• Observer pattern

49

Strategy Pattern

50

Template Method Pattern

51

Inheritance for Variability

52

S t a c k

S e c u r e S t a c k S y n c h r o n i z e d S t a c kU n d o S t a c k

modular, but inflexible

Inflexible Extension Mechanism

S t a c k

S e c u r e S t a c k

S y n c h r o n i z e d S t a c k

U n d o S t a c k

S t a c k

S e c u r e S t a c k S y n c h r o n i z e d S t a c kU n d o S t a c k

Extensions

not combinable

Middle extension

not optional

cf. White-Box Framework

Work arounds?

• Combining inheritance hierarchies– Combinatorical explosion– Massive code replication

• Multiple inheritance– Diamond problem

S t a c k

S e c u r e S t a c k

S y n c h r o n i z e d U n d o S e c u r e S t a c k

U n d o S t a c k

U n d o S e c u r e S t a c kS y n c h r o n i z e d U n d o S t a c k

S y n c h r o n i z e d S t a c k

+ p u s h ( )+ p o p ( )+ s i z e ( )

- v a l u e s

S t a c k

+ p u s h ( )+ p o p ( )+ s i z e ( )+ l o c k ( )+ u n l o c k ( )

L o c k e d S t a c k

+ p u s h ( )+ p o p ( )+ u n d o ( )

- l o g

U n d o S t a c k

L o c k e d U n d o S t a c k

Decorator Pattern

+ p u s h ( )+ p o p ( )+ s i z e ( )

« i n t e r f a c e »I S t a c k

+ p u s h ( )+ p o p ( )+ s i z e ( )

- v a l u e s

S t a c k

+ p u s h ( )+ p o p ( )+ s i z e ( )

- d e l e g a t e

S t a c k D e c o r a t o r

+ p u s h ( )+ p o p ( )+ s i z e ( )+ l o c k ( )+ u n l o c k ( )

L o c k e d S t a c k

+ p u s h ( )+ p o p ( )+ u n d o ( )

- l o g

U n d o S t a c k

+ p u s h ( )+ p o p ( )+ e n c r y p t( )+ d e c r y p t( )

- k e y p h r a s e

S e c u r e S t a c k

1

1

Decorators in java.io

56

Delegation vs. Inheritance

• Allows dynamic (re-)configurations• Requires independent extensions• Can override but not add methods• Late binding hard to implement• Many indirection (runtime overhead)• No compile-time optimization

• Advanced language constructs: mixins, traits, ...

Frameworks

• Set of abstract and concrete classes• Reusable solutions of a set of problems• Planned hot spots, extended by plug-ins

• Extension mechanisms often based on design patterns

– Strategy

– Template method

– Observer

58

Discussion

• Separated, modular extensions

– Compile and test plug-ins separately• Compile-time/load-time configuration• Well understood in practice• Hard to design, hard to evolve• Small runtime overhead• Suited for coarse-grained extensions

59

ANALYSIS

60

320 features

more configurations than estimated

atoms in the universe

optional, independent

From HP to Linux

2000 FeaturesInhouse configuration100 Printers (Product Map)30 New Printers per Year

10000 FeaturesEnd user configures

210000 Configurations

∀ p PL . ...∈

true

Dead-Code Detection

line 1#ifdef Aline 2 #ifndef A line 3 #endifline 4#elif defined(X)line 5#elseline 6#endif

A

A ^ not A

A

not A ^ X

not A ^ not X

Dead code

Analysis:SAT(pc(block i))

Variability Models

65

Dead-Code Detection

class Example {public static final boolean DEBUG = false;

void main() {System.out.println(“immer”);if (DEBUG) {

System.out.println(“debug info”); printDetails(); }

} void printDetails() { ... }}

66

4/13/2011

Closed-World Analysis

Specified Variability Implementation Variability

P

WORLD

BYE

WORLD v BYE

¬ (WORLD ˄ BYE)

(WORLD v BYE) ˄¬ (WORLD ˄ BYE)

Check Consistency

∀ p PL .∈ p is well-typed

Cohen et al. Interaction testing of highly-configurable systems in the presence of constraints. ISSTA 2007

F1 F2 F3

on on on

on on off

on off on

on off off

off on on

off on off

off off on

off off off

Pairwise Testing

Cohen et al. Interaction testing of highly-configurable systems in the presence of constraints. ISSTA 2007

F1 F2 F3

on on on

on on off

on off on

on off off

off on on

off on off

off off on

off off off

Pairwise Testing

Other Topics

• Product planning, product-line scoping

• Team organization

• Development and design process (domain engineering)

• More implementation techniques (components, version control systems, feature/aspect-oriented development)

• Product-line analysis

Summary

• Software product lines: Systematic reuse by planning variations

• From runtime parameters and conditional compilation to design patterns and frameworks

• Analysis for product lines

73

Further Reading

K. Czarnecki and U. Eisenecker. Generative Programming: Methods, Tools, and Applications. Addison-Wesley, 2000.

Christian Kästner, and Sven Apel. Feature-Oriented Software Development: A Short Tutorial on Feature-Oriented Programming, Virtual Separation of Concerns, and Variability-Aware Analysis. In GTTSE Summer School: Generative & Transformational Techniques in Software Engineering, Springer-Verlag, 2011.

P. Clements, L. Northrop. Software Product Lines: Practices and Patterns. Addison-Wesley, 2002

74