0% found this document useful (0 votes)
3 views

7-API Design and Framework Version 1.2 - 2016-12-01

Uploaded by

khuubaolong2k3
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

7-API Design and Framework Version 1.2 - 2016-12-01

Uploaded by

khuubaolong2k3
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 48

4/10/2017

Principles of Software Construction


(NGUYÊN LÝ XÂY DỰNG PHẦN MỀM)

Software Engineering Dept., CICT,


Cantho Unversity
Lecturer: Trương Minh Thái
email: [email protected]
Phần dành cho đơn vị

Contents

• API Design
• Framework

1
4/10/2017

Contents

• API Design
– Introduction to APIs: Application Programming
Interfaces
– The Process of API Design
– General Principles
– Class Design
– Method Design
– Exception Design
• Framework

What is an API?

• Short for Application Programming Interface


• A component specification in terms of its
operations, their inputs, and their outputs
– Defines a set of functionalities independent of
implementation
– Allows implementation to vary without compromising
clients
• Defines boundary between components in a
programmatic system
– Intermodular boundary
• A public API is one designed for use by others

2
4/10/2017

Libraries, frameworks both define


APIs

Why is API design important?

• APIs can be among your greatest assets


– Users invest heavily: acquiring, writing, learning
– Cost to stop using an API can be prohibitive
– Successful public APIs capture users
• Can also be among your greatest liabilities
– Bad API can cause unending stream of support
calls
– Can inhibit ability to move forward
• Public APIs are forever – one chance to get it
right

3
4/10/2017

Why is API design important to you?

• If you program, you are an API designer


– Good code is modular – each module has an API
• Useful modules tend to get reused
– Good reusable modules are an asset
– Once module has users, can’t change API at will
• Thinking in terms of APIs improves code
quality

Characteristics of a good API

• Easy to learn
• Easy to use, even without documentation
• Hard to misuse
• Easy to read and maintain code that uses it
• Sufficiently powerful to satisfy requirements
• Easy to evolve
• Appropriate to audience

4
4/10/2017

Contents

• API Design
– Introduction to APIs: Application Programming
Interfaces
– The Process of API Design
– General Principles
– Class Design
– Method Design
– Exception Design
• Framework

Gather requirements–skeptically

• Often you'll get proposed solutions instead


– Better solutions may exist
• Your job is to extract true requirements
– Should take the form of use-cases
• Can be easier & more rewarding to build more
general API
What they say: “We need new data structures and
RPCs with the Version 2 attributes”
What they mean: “We need a new data format that
accommodates evolution of attributes”

5
4/10/2017

Start with short spec – 1 page is ideal

• At this stage, agility trumps completeness


• Bounce spec off as many people as possible
– Listen to their input and take it seriously
• If you keep the spec short, it’s easy to modify
• Flesh it out as you gain confidence

Sample early API draft

// A collection of elements (root of the collection hierarchy)


public interface Collection<E> {
// Ensures that collection contains o
boolean add(E o);
// Removes an instance of o from collection, if present
boolean remove(Object o);
// Returns true iff collection contains o
boolean contains(Object o) ;
// Returns number of elements in collection
int size() ;
// Returns true if collection is empty
boolean isEmpty();
... // Remainder omitted
}

6
4/10/2017

Write to your API early and often

• Start before you've implemented the API


– Saves you doing implementation you'll throw away
• Start before you've even specified it properly
– Saves you from writing specs you'll throw away
• Continue writing to API as you flesh it out
– Prevents nasty surprises right before you ship
• Code lives on as examples, unit tests
– Among the most important code you’ll ever write
– Forms the basis of Design Fragments
[Fairbanks, Garlan, & Scherlis, OOPSLA ‘06, P. 75]

Write 3 implementations of each abstract


class or interface before release

• If you write 1, it probably won’t support another


• If you write 2, it will support more with difficulty
• If you write 3, it will work fine
• Will Tracz calls this “The Rule of Threes”
Confessions of a Used Program Salesman,
Addison-Wesley, 1995)

7
4/10/2017

Maintain realistic expectations

• Most API designs are over-constrained


– You won't be able to please everyone
– Aim to displease everyone equally
• Expect to make mistakes
– A few years of real-world use will flush them out
– Expect to evolve API

Contents

• API Design
– Introduction to APIs: Application Programming
Interfaces
– The Process of API Design
– General Principles
– Class Design
– Method Design
– Exception Design
• Framework

8
4/10/2017

API should do one thing and do it well

• Functionality should be easy to explain


– If it's hard to name, that's generally a bad sign
– Good names drive development
– Be amenable to splitting and merging modules
• Good: Font, Set, PrivateKey, Lock,
• ThreadFactory, TimeUnit, Future<T>
• Bad: DynAnyFactoryOperations,
_BindingIteratorImplBase,
ENCODING_CDR_ENCAPS, OMGVMCID

API should be as small as possible


but no smaller

• API should satisfy its requirements


• When in doubt leave it out
– Functionality, classes, methods, parameters, etc.
– You can always add, but you can never
remove
• Conceptual weight more important than bulk
• Look for a good power-to-weight ratio

9
4/10/2017

Implementation should not impact API

• Implementation details in APIs are harmful


– Confuse users
– Inhibit freedom to change implementation
• Be aware of what is an implementation detail
– Do not over specify the behavior of methods
• For example: do not specify hash functions
– All tuning parameters are suspect
• Don't let implementation details “leak” into API
– Serialized forms, exceptions thrown

Minimize accessibility of everything

• Make classes, members as private as possible


• Public classes should have no public fields
(with the exception of constants)
• Maximizes information hiding [Parnas]
• Minimizes coupling
– Allows modules to be, understood, used, built,
tested, debugged, and optimized independently

10
4/10/2017

Names matter – API is a little


language

• Names Should Be Largely Self-Explanatory


– Avoid cryptic abbreviations
• Be consistent
– Same word means same thing throughout API
– (and ideally, across APIs on the platform)
• Be regular – strive for symmetry
• If you get it right, code reads like prose
for (List<Integer> proposedSolution : Permutations.of(digits))
if (isSolution(proposedSolution))
solutions.add(proposedSolution);

Grammar is a part of naming

• Nouns for classes


– BigInteger, PriorityQueue
• Nouns or adjectives for interfaces
– Collection, Comparable
• Nouns, linking verbs or prepositions for non-
mutative methods
– size, isEmpty, plus
• Action verbs for mutative methods
– put, add, clear

11
4/10/2017

Documentation matters

Reuse is something that is far easier to say than


to do. Doing it requires both good design and
very good documentation. Even when we see
good design, which is still infrequently, we won't
see the components reused without good
documentation.
D. L. Parnas, Software Aging. Proceedings
of the 16th International Conference on
Software Engineering, 1994

Document religiously

• Document every class, interface, method,


constructor, parameter, and exception
– Class: what an instance represents
– Method: contract between method and its client
• Preconditions, postconditions, side-effects
– Parameter: indicate units, form, ownership
• Document thread safety
• If class is mutable, document state space

12
4/10/2017

Consider performance consequences

• Bad decisions can limit performance


– Making type mutable
– Providing constructor instead of static factory
– Using implementation type instead of interface
• Do not warp API to gain performance
– Underlying performance issue will get fixed, but
headaches will be with you forever
– Good design usually coincides with good
performance

Performance effects of a bad API


decisions can be real and permanent

• Component.getSize() returns Dimension


• Dimension is mutable
• Each getSize call must allocate Dimension
• Causes millions of needless object allocations
• Alternative added in 1.2; old client code still
slow
– getX(), getY()

13
4/10/2017

API must coexist peacefully with


platform

• Do what is customary
– Obey standard naming conventions
– Avoid obsolete parameter and return types
– Mimic patterns in core APIs and language
• Take advantage of API-friendly features
– Generics, varargs, enums, functional interfaces
• Know and avoid API traps and pitfalls
– Finalizers, public static final arrays, etc.
• Don’t transliterate APIs

Contents

• API Design
– Introduction to APIs: Application Programming
Interfaces
– The Process of API Design
– General Principles
– Class Design
– Method Design
– Exception Design
• Framework

14
4/10/2017

Minimize mutability

• Classes should be immutable unless there’s a


good reason to do otherwise
– Advantages: simple, thread-safe, reusable
– Disadvantage: separate object for each value
• If mutable, keep state-space small, well-defined
– Make clear when it's legal to call which method
• Bad: Date, Calendar
• Good: TimerTask

Subclass only where it makes sense

• Subclassing implies substitutability (Liskov)


– Don’t subclass unless an is-a relationship exists
– Otherwise, use composition
• Don’t subclass just to reuse implementation
• Bad: Properties extends Hashtable
Stack extends Vector
• Good: Set extends Collection

15
4/10/2017

Design & document for inheritance


or else prohibit it

• Inheritance violates encapsulation (Snyder, ‘86)


– Subclasses are sensitive to implementation details
of superclass
• If you allow subclassing, document self-use
– How do methods use one another?
• Conservative policy: all concrete classes final
• Bad: Many concrete classes in J2SE libraries
• Good: AbstractSet, AbstractMap

Contents

• API Design
– Introduction to APIs: Application Programming
Interfaces
– The Process of API Design
– General Principles
– Class Design
– Method Design
– Exception Design
• Framework

16
4/10/2017

Don't make the client do anything


the module could do
• Reduce need for boilerplate code
– Generally done via cut-and-paste
– Ugly, annoying, and error-prone
import org.w3c.dom.*;
import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
/** DOM code to write an XML document to a specified output stream. */
static final void writeDoc(Document doc, OutputStream out)throws IOException{
try {
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,
doc.getDoctype().getSystemId());
t.transform(new DOMSource(doc), new StreamResult(out)); // Does actual writing
} catch(TransformerException e) {
throw new AssertionError(e); // Can’t happen!
}
}

Don’t violate the principle of least


astonishment
• User of API should not be surprised by
behavior
– It's worth extra implementation effort
– It's even worth reduced performance

public class Thread implements Runnable {


// Tests whether current thread has been interrupted.
// Clears the interrupted status of current thread.
public static boolean interrupted();
}

17
4/10/2017

Here’s what happens if you violate both


of the last two rules at the same time
// Spec says: "Skips over n bytes of data from this input."
// But this is a lie. Ignore return value at your peril!
Pubic long skip(long n) throws IOException;
The only correct way to use InputStream.skip:
static void skipFully(InputStream in, long nBytes) throws IOException {
long remaining = nBytes;
while (remaining != 0) {
long skipped = in.skip(remaining);
if (skipped == 0) // EOF
throw new EOFException();
remaining -= skipped;
}
}

APIs should fail fast:


report errors as soon as possible

• Compile time is best – static typing, generics


– public int max(int... args);
– public int max(int first, int... rest);
• At runtime, first bad method invocation is best
– Method should be failure-atomic
/** A Properties instance maps strings to strings */
public class Properties extends Hashtable {
public Object put(Object key, Object value);
// Throws ClassCastException if this properties
// contains any keys or values that are not strings
public void save(OutputStream out, String comments);
}

18
4/10/2017

Provide programmatic access to all


data available in string form

• Otherwise, clients will parse strings


– Painful for clients
– Worse, turns string format into de facto API
public class Throwable {
public void printStackTrace(PrintStream s);
public StackTraceElement[] getStackTrace(); // Since 1.4
}
public final class StackTraceElement {
public String getFileName();
public int getLineNumber();
public String getClassName();
public String getMethodName();
public boolean isNativeMethod();
}

Overload with care

• Avoid ambiguous overloadings


– Multiple overloadings applicable to same actuals
• Just because you can doesn't mean you
should
– Often better to use a different name
• If you must provide ambiguous overloadings,
ensure same behavior for same arguments
public TreeSet(Collection<E> c); // Uses natural ordering
public TreeSet(SortedSet<E> s); // Uses ordering from s

19
4/10/2017

Use appropriate parameter & return


types

• Favor interface types over classes for input


– Provides flexibility, performance
• Use most specific possible input parameter type
– Moves error from runtime to compile time
• Don't use String if a better type exists
– Strings are cumbersome, error-prone, and slow
• Don't use floating point for monetary values
– Binary floating point causes inexact results!
• Use double (64 bits) rather than float (32 bits)
– Precision loss is real, performance loss negligible

Use consistent parameter ordering


across methods

• Especially important if parameter types


identical
#include <string.h>
char *strncpy(char *dst, char *src, size_t n);
void bcopy (void *src, void *dst, size_t n);

• java.util.Collections – first parameter always


collection to be modified or queried
• java.util.concurrent – time always specified as
long delay, TimeUnit unit

20
4/10/2017

Avoid long parameter lists

• Three or fewer parameters is ideal


– More and users will have to refer to docs
• Long lists of identically typed params harmful
– Programmers transpose parameters by mistake
– Programs still compile and run, but misbehave!
• Techniques for shortening parameter lists
– Break up method
– Create helper class to hold parameters
– Builder Pattern
// Eleven (!) parameters including > four consecutive ints
HWND CreateWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu,
HINSTANCE hInstance, LPVOID lpParam);

Avoid return values that demand


exceptional processing

• Return zero-length array or empty collection,


not null
package java.awt.image;
public interface BufferedImageOp {
// Returns the rendering hints for this operation,
// or null if no hints have been set.
public RenderingHints getRenderingHints();
}

21
4/10/2017

Contents

• API Design
– Introduction to APIs: Application Programming
Interfaces
– The Process of API Design
– General Principles
– Class Design
– Method Design
– Exception Design
• Framework

Throw exceptions to indicate


exceptional conditions
• Don’t force client to use exceptions for control flow
private byte[] a = new byte[CHUNK_SIZE];
void processBuffer (ByteBuffer buf) {
try {
while (true) {
buf.get(a);
processBytes(a, CHUNK_SIZE);
}
} catch (BufferUnderflowException e) {
int remaining = buf.remaining();
buf.get(a, 0, remaining);
processBytes(a, remaining);
}
}
• Conversely, don’t fail silently
ThreadGroup.enumerate(Thread[] list)

22
4/10/2017

Favor unchecked exceptions

• Checked – client must take recovery action


• Unchecked – generally a programming error
• Overuse of checked exceptions causes boilerplate
try {
Foo f = (Foo) super.clone();
....
} catch (CloneNotSupportedException e) {
// This can't happen, since we’re Cloneable
throw new AssertionError();
}

Include failure-capture information in


exceptions

• Allows diagnosis and repair or recovery


• For unchecked exceptions, message suffices
• For checked exceptions, provide accessors

23
4/10/2017

API Design Summary

• A good API is a blessing; a bad one a curse


• API Design is hard, but you can’t escape it
– Accept the fact that we all make mistakes
– Use your APIs as you design them
– Get feedback from others
• This talk covered some heuristics of the craft
– Don't adhere to them slavishly, but...
– Don't violate them without good reason

Contents

• API Design
• Framework
– Describe example well-known example frameworks
– Know key terminology related to frameworks
– White-box vs Black-Box frameworks
– Use vs Reuse: domain engineering
– Framework mechanics

24
4/10/2017

Reuse and variation:


Family of development tools

Reuse and variation:


Eclipse Rich Client Plaform

25
4/10/2017

Reuse and variation:


Web browser extensions

Reuse and variation:


Flavors of Linux

26
4/10/2017

Reuse and variation:


Product lines

Class-level reuse

• Language mechanisms supporting reuse


– Inheritance
– Subtype polymorphism (dynamic dispatch) for delegation
– Parametric polymorphism (generics)
• Design principles supporting reuse
– Small interfaces
– Information hiding
– Low coupling
– High cohesion
• Design patterns supporting reuse
– Template method, decorator, strategy, composite, adapter, …

27
4/10/2017

Contents

• API Design
• Framework
– Describe example well-known example frameworks
– Know key terminology related to frameworks
– White-box vs Black-Box frameworks
– Use vs Reuse: domain engineering
– Framework mechanics

Terminology: Libraries

• Library: A set of classes and methods that


provide reusable functionality

28
4/10/2017

Terminology: Frameworks

• Framework: Reusable skeleton code that can be


customized into an application
• Framework calls back into client code
– The Hollywood principle: “Don’t call us. We’ll call you.”

A calculator example (without a


framework)
public class Calc extends JFrame {
private JTextField textField;
public Calc() {
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
JButton button = new JButton();
button.setText("calculate");
contentPane.add(button, BorderLayout.EAST);
textField = new JTextField("");
textField.setText("10 / 2 + 6");
textField.setPreferredSize(new Dimension(200, 20));
contentPane.add(textfield, BorderLayout.WEST);
button.addActionListener(/* calculation code */);
this.setContentPane(contentPane);
this.pack();
this.setLocation(100, 100);
this.setTitle("My Great Calculator");
...
}
}

29
4/10/2017

• Consider a family of programs consisting of


buttons and text fields only:

• What source code might be shared?

A calculator example (without a


framework)
public class Calc extends JFrame {
private JTextField textField;
public Calc() {
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
JButton button = new JButton();
button.setText("calculate");
contentPane.add(button, BorderLayout.EAST);
textField = new JTextField("");
textField.setText("10 / 2 + 6");
textField.setPreferredSize(new Dimension(200, 20));
contentPane.add(textfield, BorderLayout.WEST);
button.addActionListener(/* calculation code */);
this.setContentPane(contentPane);
this.pack();
this.setLocation(100, 100);
this.setTitle("My Great Calculator");
...
}
}

30
4/10/2017

A simple example framework


public abstract class Application extends JFrame {
protected String getApplicationTitle() { return ""; }
protected String getButtonText() { return ""; }
protected String getInitialText() { return ""; }
protected void buttonClicked() { }
private JTextField textField;
public Application() {
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
JButton button = new JButton();
button.setText(getButtonText());
contentPane.add(button, BorderLayout.EAST);
textField = new JTextField("");
textField.setText(getInitialText());
textField.setPreferredSize(new Dimension(200, 20));
contentPane.add(textField, BorderLayout.WEST);
button.addActionListener((e) -> { buttonClicked(); });
this.setContentPane(contentPane);
this.pack();
this.setLocation(100, 100);
this.setTitle(getApplicationTitle());
...
}

Using the example framework


public abstract class Application extends JFrame {
protected String getApplicationTitle() { return ""; }
protected String getButtonText() { return ""; }
protected String getInitialText() { return ""; }
protected void buttonClicked() { }
private JTextField textField;
public Application() {
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
JButton button = new JButton();
button.setText(getButtonText());
contentPane.add(button, BorderLayout.EAST);
textField = new JTextField("");
textField.setText(getInitialText());
textField.setPreferredSize(new Dimension(200, 20));
contentPane.add(textField, BorderLayout.WEST);
button.addActionListener((e) -> { buttonClicked(); });
this.setContentPane(contentPane);
this.pack();
this.setLocation(100, 100);
this.setTitle(getApplicationTitle());
...
}

31
4/10/2017

Using the example framework


public abstract class Application extends JFrame {
protected String getApplicationTitle() { return ""; }
protected String getButtonText() { return ""; }
protected String getInitialText() { return ""; }
protected void buttonClicked() { }
private JTextField textField;
public Application() {
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
JButton button = new JButton();
button.setText(getButtonText());
contentPane.add(button, BorderLayout.EAST);
textField = new JTextField("");
textField.setText(getInitialText());
textField.setPreferredSize(new Dimension(200, 20));
contentPane.add(textField, BorderLayout.WEST);
button.addActionListener((e) -> { buttonClicked(); });
this.setContentPane(contentPane);
this.pack();
this.setLocation(100, 100);
this.setTitle(getApplicationTitle());
...
}

General distinction: Library vs. framework

32
4/10/2017

Libraries and frameworks in practice

• Defines key abstractions and their interfaces


• Defines object interactions & invariants
• Defines flow of control
• Provides architectural guidance
• Provides defaults

Framework or library?

• Java Collections
• Eclipse
• The Java Logging Framework
• Java Encryption Services
• Wordpress
• Ruby on Rails

33
4/10/2017

More terms

• API: Application Programming Interface, the


interface of a library or framework
• Client: The code that uses an API
• Plugin: Client code that customizes a
framework
• Extension point: A place where a framework
supports extension with a plugin

More terms

• Protocol: The expected sequence of


interactions between the API and the client
• Callback: A plugin method that the framework
will call to access customized functionality
• Lifecycle method: A callback method that gets
called in a sequence according to the protocol
and the state of the plugin

34
4/10/2017

Contents

• API Design
• Framework
– Describe example well-known example frameworks
– Know key terminology related to frameworks
– White-box vs Black-Box frameworks
– Use vs Reuse: domain engineering
– Framework mechanics

Whitebox frameworks

• Extension via subclassing and overriding


methods
• Common design pattern(s):
– Template Method
• Subclass has main method but gives control to
framework

35
4/10/2017

Blackbox frameworks

• Extension via implementing a plugin interface


• Common design pattern(s):
– Strategy
– Observer
• Plugin-loading mechanism loads plugins and
gives control to the framework

Is this a whitebox or blackbox


framework?
public abstract class Application extends JFrame {
protected String getApplicationTitle() { return ""; }
protected String getButtonText() { return ""; }
protected String getInitialText() { return ""; }
protected void buttonClicked() { }
private JTextField textField;
public Application() {
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setBorder(new BevelBorder(BevelBorder.LOWERED));
JButton button = new JButton();
button.setText(getButtonText());
contentPane.add(button, BorderLayout.EAST);
textField = new JTextField("");
textField.setText(getInitialText());
textField.setPreferredSize(new Dimension(200, 20));
contentPane.add(textField, BorderLayout.WEST);
button.addActionListener((e) -> { buttonClicked(); });
this.setContentPane(contentPane);
this.pack();
this.setLocation(100, 100);
this.setTitle(getApplicationTitle());
...
}

36
4/10/2017

An example blackbox framework

An example blackbox framework

37
4/10/2017

An aside: Plugins could be reusable


too…

Whitebox vs. blackbox framework


summary
• Whitebox frameworks use subclassing
– Allows extension of every nonprivate method
– Need to understand implementation of superclass
– Only one extension at a time
– Compiled together
– Often so-called developer frameworks
• • Blackbox frameworks use composition
– Allows extension of functionality exposed in interface
– Only need to understand the interface
– Multiple plugins
– Often provides more modularity
– Separate deployment possible (.jar, .dll, …)
– Often so-called end-user frameworks, plaforms

38
4/10/2017

Framework design considerations

• Once designed there is little opportunity for


change
• Key decision: Separating common parts from
variable parts
– What problems do you want to solve?
• Possible problems:
– Too few extension points: Limited to a narrow class
of users
– Too many extension points: Hard to learn, slow
– Too generic: Little reuse value

Contents

• API Design
• Framework
– Describe example well-known example frameworks
– Know key terminology related to frameworks
– White-box vs Black-Box frameworks
– Use vs Reuse: domain engineering
– Framework mechanics

39
4/10/2017

(one modularization: tangrams)

The use vs. reuse dilemma

• Large rich components are very useful, but


rarely fit a specific need
• Small or extremely generic components o3en
fit a specific need, but provide lible benefit

“maximizing reuse minimizes use”


C. Szyperski

40
4/10/2017

Domain engineering

• Understand users/customers in your domain


– What might they need? What extensions are likely?
• Collect example applications before designing a
framework
• Make a conscious decision what to support
– Called scoping
• e.g., the Eclipse policy:
– Interfaces are internal at first
• Unsupported, may change
– Public stable extension points created when there are at least
two distinct customers

Typical framework design and


implementation

• Define your domain


– Identify potential common parts and variable parts
• Design and write sample plugins/applications
• Factor out & implement common parts as framework
• Provide plugin interface & callback mechanisms for
variable parts
– Use well-known design principles and patterns where
appropriate…
• Get lots of feedback, and iterate

41
4/10/2017

Evolutionary design: Extract interfaces


from classes

• Extracting interfaces is a new step in


evolutionary design:
– Abstract classes are discovered from concrete
classes
– Interfaces are distilled from abstract classes
• Start once the architecture is stable
– Remove non-public methods from class
– Move default implementations into an abstract
class which implements the interface
(credit: Erich Gamma)

Contents

• API Design
• Framework
– Describe example well-known example frameworks
– Know key terminology related to frameworks
– White-box vs Black-Box frameworks
– Use vs Reuse: domain engineering
– Framework mechanics

42
4/10/2017

Running a framework

• Some frameworks are runnable by themselves


– e.g. Eclipse
• Other frameworks must be extended to be run
– Swing, JUnit, MapReduce, Servlets

Methods to load plugins

• Client writes main(), creates a plugin and


passes it to framework
• Framework writes main(), client passes name
of plugin as a command line argument or
environment variable
• Framework looks in a magic location
– Config files or .jar files are automatically loaded
and processed
• GUI for plugin management

43
4/10/2017

Supporting multiple plugins

• Observer design
public class Application {
pattern is commonly private List<Plugin> plugins;
used public Application(List<Plugin> plugins) {
this.plugins = plugins;
• Plugins can register for (Plugin p : plugins)
for events p.setApplication(this);
}
• Multiple plugins can public Message processMsg(Message msg) {
react to same events for (Plugin p : plugins)
• Different interfaces for msg = p.process(msg);
...
different events return msg;
possible }
}

Example: An Eclipse plugin

• A popular Java IDE


• More generally, a framework for
tools that
• facilitate “building, deploying
and managing software across
the lifecycle.”
• Plugin framework based on
OSGI standard
• Starting point: Manifest file
– Plugin name
– Activator class
– Meta-data

44
4/10/2017

Example: An Eclipse plugin

• plugin.xml
– Main configuration file
– XML format
– Lists extension points
• Editor extension
– extension point:
org.eclipse.ui.editors
– file extension
– icon used in corner of
editor
– class name
– unique id
• refer to this editor
• other plugins can extend
with new menu items,
etc.!

Example: An Eclipse plugin

• At last, code!
• XMLEditor.java
– Inherits TextEditor behavior
• open, close, save, display, select,
• cut/copy/paste, search/replace, …
• REALLY NICE not to have to
implement this
• But could have used ITextEditor
interface if we wanted to
– Extends with syntax highlighting
• XMLDocumentProvider partitions
into tags and comments
• XMLConfiguration shows how to
color partitions

45
4/10/2017

Example: A JUnit Plugin

Learning a framework

• Documentation
• Tutorials, wizards,
and examples
• Other client
applications and
plugins
• Communities, email
lists and forums

46
4/10/2017

Summary

• Reuse and variation essential


– Libraries and frameworks
• Whitebox frameworks vs. blackbox frameworks
• Design for reuse with domain analysis
– Find common and variable parts
– Write client applications to find common parts
• Revise, revise, revise…

References
• Course: Principles of Software Construction,
Carnegie Mellon University
• Craig Larman. Applying UML and Patterns: An
Introduction to Object‐Oriented Analysis and Design
and Iterative Development. 3rd Edition. Prentice Hall.
2004. ISBN 0‐13‐148906‐2
• Bloch, Joshua. Effective Java, Second Edition. Addison-
Wesley, ISBN 978-0321356680
• Alan Shalloway and James Trott. Design Patterns
Explained: A New Perspective on Object-Oriented
Design (2nd Ed.)
• Gamma et al. Design Patterns: Elements of Reusable
Object-Oriented Software. Addison Wesley. ISBN 0-
201-63361-2

47
4/10/2017

Thanks for your attention!

48

You might also like