Enabling White-Box Reuse in a Pure Composition Language
-
Upload
elliando-dias -
Category
Technology
-
view
800 -
download
1
Transcript of Enabling White-Box Reuse in a Pure Composition Language
Enabling White-Box Reuse in aPure Composition Language
Andreas Schlapbach
January, 2003.
Overview
• Introduction
– Component-based software development.
– Roles of inheritance.
– Subclassing as a form of white-box reuse.
– Subclassing considered harmful.
• Goal
– To combine the power of inheritance with theease of scripting.
• Solution
– Piccola, our composition language.
– Introduce a language extension to JPiccola thatenables inheritance.
– Implementation and examples.
– Applications.
• Lessons Learned
• Questions & Comments
2
Component-based Software Development
• Modern applications must be flexible and
extendible to adapt to changing require-
ments.
• These requirements can be addressed best
by a component-oriented software devel-
opment approach.
• Component-oriented software development
shifts away from programming towards soft-
ware composition.
3
Scripting Real-World Components
• Applications = Components + Script
+ a Drop of Glue.
• We build applications by scripting compo-
nents.
• These components must adhere to a com-
positional style.
• In reality, such components often do not
exist.
� We have to adapt existing components, us-
ing a drop of glue.
4
Adaptation: Black-box versus White-box
White-box Reuse. Adapts a mismatched com-
ponent by either changing or overriding its
internal specification.
E.g.: Copy & Paste, Inheritance
Black-box Reuse. Adapts the interface of a
component only.
E.g.: Wrapping techniques, Reflective ap-
proach, Standardization
5
Roles of Inheritance
Inheritance is a key concept of object-oriented
languages and plays different roles:
Subclassing. At the implementation level, it
is a means for code reuse.
Subtyping. At the design level, it defines a
substitutability relationship.
Is-a Relationship. At the conceptual level, it
represents a conceptual specialization rela-
tionship.
These roles of inheritance can conflict.
6
Subclassing Considered Harmful
• Subclassing can break encapsulation by ac-
cessing internal implementation details of
an object.
• Subclassing introduces subtle dependencies
between base and extending classes.
• Subclassing is a white-box form of reuse.
� Let’s minimize the use of inheritance.
7
Goal: Migrate from Class Inheritance to
Object Composition
• There are many powerful object-oriented
frameworks we would like to reuse as black-
box components.
• We need inheritance to access their func-
tionality.
• Our approach is to gain access to the com-
ponents of a framework using inheritance,
wrap them and script those wrapped com-
ponents.
� We would like to have the power of inheri-
tance combined with the ease of scripting.
8
Piccola
• Piccola is a small, pure and general pur-
pose scripting language.
• Piccola is based on forms, agents and chan-
nels: Agents communicate by sending forms
along channels.
• Forms are extensible records unified with
services. Everything is a form.
• JPiccola is the Java-based implementation
of Piccola.
9
A Language Extension for JPiccola
We want to use Java frameworks in Piccola
using inheritance.
Key idea: Create Java objects implementing
a given type that delegate all calls to its meth-
ods to Piccola services.
up(args)
func(arg1, arg2,...,argn)
func(args):
...
result
Piccola
Java
down(result)
� We have to generate classes of a given type
at runtime.
10
Implementation I
The class generation process consists of three
steps:
1. Gather information on the structure of the
class.
2. Generate the class, using the BCEL byte
code engineering library.
3. Load the class into the Java Virtual Ma-
chine, using a custom class loader.
11
Structure of a Generated Class I
Let’s suppose we have class A with a methodplus(int i, int j) . We define a service plus
in Piccola to handle calls to this method.
plus(args):
’i = args.at(1)
’j = args.at(2)
i + j
We generate a subclass of A and redirect theJava call to a Piccola service:
public int plus(int j, int j) {Arguments args = new Arguments();
args.add(this);
args.add(new Integer(i));
args.add(new Integer(j));
return ((Integer) getService("plus")
.callback(args)).intValue();
}12
Structure of a Generated Class II
Actually, we generate byte code.
Method int plus(int, int)0 new #22 <Class ch.unibe.piccola.bridge.Arguments>3 dup4 invokespecial #23
<Method ch.unibe.piccola.bridge.Arguments()>7 astore 49 aload 4
11 aload_012 invokevirtual #27 <Method void add(java.lang.Object)>15 aload 417 new #56 <Class java.lang.Integer>20 dup21 iload_122 invokespecial #65 <Method java.lang.Integer(int)>25 invokevirtual #27 <Method void add(java.lang.Object)>28 aload 430 new #56 <Class java.lang.Integer>33 dup34 iload_235 invokespecial #65 <Method java.lang.Integer(int)>38 invokevirtual #27 <Method void add(java.lang.Object)>41 aload_042 ldc #75 <String "plus">44 invokevirtual #33
<Method ch.unibe.piccola.IFormgetService(java.lang.String)>
47 aload 449 invokeinterface (args 2) #39
<InterfaceMethod java.lang.Objectcallback(ch.unibe.piccola.bridge.Arguments)>
54 checkcast #56 <Class java.lang.Integer>57 invokevirtual #60 <Method int intValue()>60 ireturn
13
Example I
generateSubclassOfA():
newClass
name = "B"
superClassName = "A"
interfaceNames = [ ]
methods =
plus =
argumentTypeList =
[ Type.int, Type.int ]
returnType = Type.int
body(args): args.at(1) + args.at(2)
14
Implementation II
Often, we do not need to generate an arbitrary
class but implement an interface or generate a
direct subclass of an abstract class.
� We can use reflection to gather the infor-
mation needed to generate a class.
15
Example II
generateKeyListener():
newInterface
className = "java.awt.event.KeyListener"
methods =
keyPressed(args): println "Key Pressed"
keyReleased(args): println "Key Released"
keyTyped(args): println "Key Typed"
16
Applications
• Print Service
• Scripting an Event Based Parser
• Scripting Web Browser Frameworks
• GUI Event Composition Style
• . . .
� We use the language extension whenever we
need inheritance.
17
Role of Java Interfaces in Frameworks
• We seldom generate arbitrary classes, mostoften we just implement Java interfaces.Why is this?
• A framework consists of ready-to-use andhalf finished building blocks.
• While most parts are stable, it permits itsuser to adapt parts of it according to theirneeds. These are the hot spots of a frame-work.
• Superior to (abstract) classes, interfacesdo not impose a specific inheritance hier-archy.
� Java interfaces provide a good way to con-trol the type of adaptations compatible with aframework.
18
Closing Remarks
• The language extension integrates nicely
into JPiccola.
• Good components are hard to find.
• A framework is more than a bundle of classes.
19
ClassFile
ClassFile {u4 magic;u2 minor_version;u2 major_version;u2 constant_pool_count;cp_info constant_pool[constant_pool_count-1];u2 access_flags;u2 this_class;u2 super_class;u2 interfaces_count;u2 interfaces[interfaces_count];u2 fields_count;field_info fields[fields_count];u2 methods_count;method_info methods[methods_count];u2 attributes_count;attribute_info attributes[attributes_count];
}
21