Complex Components Create New Challenges
Doug Lea
State University of New York at Oswego
Oswego, NY 13126
Tel: (315) 341-2688
Fax: (315) 341-5424
Email: dl@cs.oswego.edu
Abstract
Attempted reuse across concurrent, distributed, persistent,
and/or secure components and systems all seem to hit similar snags surrounding
larger policy spaces, greater complexity, limitations of black-boxes, context
dependence, compositionality failures, and reflective design.
Keywords: Reuse, concurrency, distribution, persistence, security
Workshop Goals: Learning; networking;
Working Groups: Designs for or with reuse
Java (and arguably other languages and platforms) ``solve''
some of the easy reuse problems:
- Packaging
- Objects, classes, components, packages
- Portability
- Bytecodes, unicode, transports
- Extensibility
- Subclassing, interfaces, class loaders
- Safety
- Virtual machine, GC, verifiers
But this seems not to make reuse in most projects much easier. One reason
for this is that just about every Java project involves one or more aspects
[Kiczales97] of software design that become widespread when developers no longer
have to wrestle so hard with the easy stuff:
- Concurrency
- Use of threads, locks, and monitors
to support multiprocessing, and/or to improve availability in
reactive systems.
- Distribution
- Use of RMI, CORBA, etc., to
support fault tolerance, resource sharing, mobility, and
communication in open systems.
- Persistence
- Use of serialization, JDBC, etc.,
to support versioning, recovery, and transactionality
in systems in which object lifetimes exceed program lifetimes.
- Security
- Use of security managers, protection domains, and
encryption to support privacy and commerce in ubiquitous computing
systems.
Reuse of concurrent, distributed, persistent, and/or secure components
faces challenges not seen for example in most UI toolkits, data
structure libaries or spell-checker plug-ins. Reasons include:
- Extended senses of correctness
- The need for safety, liveness,
fault-tolerance, auditability, recovery, and so on make components
more difficult to specify, test, and reason about.
- Large policy spaces
- Each of these aspects introduces
specification and design choices in places where no such choice
exists in simpler systems: Optimistic or pessimistic?, Local or
remote? Synchronous or asynchronous? Persistent or transient? Clear
or encrypted? Support infractructures that accommodate all of the
associated mechanisms create an unwieldy policy jungle. Those that
do not become unusable.
- Architectural constraints
- TO avoid policly clashes, components
cannot be build in isolation, but must observe compatibility
constraints that are often phrased as architectural rules; for
example those concerning locking or flow. These rules are often
sub-optimal, even arbitrary, but must be fervently believed in
anyway by developers.
- Infiltration
- The imposition of architectural constraints generates a slew of programmer
obligations when building or adapting even the simplest parts. Policies and
constraints inevitably alter nearly every line of code, and resist factoring
and layering[Lea98]. Nearly every successful concurrent, distributed, persistent,
and/or secure system was designed that way from the outset.
- Compositionality failures
- Many components are safe, live,
recoverable, secure, mobile, and so on, only within particular sets
of contexts, and thus may be composed only within those contexts.
These problems are compounded when more than one of these aspects is
involved. For example, when serializing objects that may engage in
multiple threads.
- Need for abstraction without transparency
- Interfaces and the
like must be abstracted out enough to manage complexity. Yet
implementations cannot afford to be treated as pure black boxes.
Eventually, someone else will need to get behind an abstraction,
often as a result of a policy change or customization. Open source
helps.
- Verticality
- Systems increasingly entail reflective, multilevel design in
which objects at each level manipulate, manage, and coordinate
lower-level ground objects as resources. Thread-objects
interpret passive objects. Distributed server-objects pass around
informational resources. Database-objects manage states of ground objects.
Builder-objects create functional objects for later deployment.
Kiczales et al[Kiczales97] have introduced Aspect-Oriented Programming
as a way to help separate out concerns such as those discussed here. They have
created ``aspect languages'' and associated tools that allow developers to isolate
those parts of programs that deal with, for example, concurrency control, and
then weave them back together via pre-processing to generate full programs.
This approach has some chance of improving the management of complexity during
development, but does not yet deal with broader issues of reuse.
[Lea98] Lea, D. "Design for Open System in Java", Coordination 98,
D. Garlan and D. Le Metayer", editors, Springer-Verlag, 1998.
[Kiscales97] Kiczales, G., J. Lamping, A. Mendhekar, C. Maeda, C. Lopes, J.
Loingtier and J. Irwin, "Aspect-Oriented Programming", ECOOP 97, Springer-Verlag,
1997
Biography
Doug Lea is a professor of Computer Science at the State University
of New York at Oswego. He is author of the book ``Concurrent Programming in
Java'', and co-author of the text ``Object-Oriented System Development''. He
is the author of several widely used software packages, as well as articles
and reports on object oriented software development including those on specification,
design and implementation techniques, distributed object systems, and software
reusability.