In theory, developing software applications that use concurrent and networked services can improve system performance, reliability, scalability, and cost-effectiveness. In practice, however, developing efficient, robust, extensible, and affordable concurrent and networked applications is hard, due to key differences between stand-alone and networked application architectures.

In stand-alone application architectures, user interface, application service processing, and persistent data resources reside within one computer, with the peripherals attached directly to it. In contrast, in networked application architectures, interactive presentation, application service processing, and data resources may reside in multiple loosely-coupled host computers and service tiers connected together by local area or wide area networks.

A network of X-terminals and `thin client NetPCs' is an example of a networked system architecture. In this environment, user interface presentation is handled by a display service on end-user hosts. The processing capabilities are provided by host computer(s) on which all or part of application services run. Access to persistent resources is mediated by one or more network file servers. Other services, such as naming and directory services, time services, HTTP servers, and caches and network management services, can run in the network and provide additional capabilities to applications.

There are three common reasons to adopt a networked architecture:

Although networked applications offer many potential benefits, they are harder to design, implement, debug, optimize, and manage than stand-alone applications. For example, developers must address topics that are either not relevant or are less problematic for stand-alone applications in order to handle the requirements of networked applications. These topics include:

These topics are generally independent of specific application requirements, so learning to master them helps to address a wide range of software development problems. Moreover, in the context of these topics many design and programming challenges arise due to several inherent and accidental complexities associated with concurrent and networked systems:

By studying and applying patterns and pattern languages, developers can often resolve hard problems in their domain effectively and escape traps and pitfalls, such as accidental complexities, that have been avoided traditionally only via long and costly apprenticeship [PLoPD1].

Until recently [Lea99a] patterns for developing concurrent and networked software existed only in programming folklore, the heads of expert researchers and developers, or were buried deep in complex source code. These locations are not ideal, for three reasons:

As a result many concurrent and networked software systems are developed from scratch. In today's competitive, time-to-market-driven environments, however, this often yields non-optimal ad hoc solutions. These solutions are hard to customize and tune, because so much effort is spent just trying to make the software operational. Moreover, as requirements change over time, evolving ad hoc software solutions becomes prohibitively expensive. Yet, end-users expect--or at least desire--software to be affordable, robust, efficient, and agile, which is hard to achieve without solid architectural underpinnings.

To help rectify these problems, this book documents key architectural and design patterns for concurrent and networked software. These patterns can and have been applied to solve many common problems that arise when developing object-oriented middleware frameworks and applications. When used as a documentation aid, these patterns preserve vital design information that helps developers evolve existing software more robustly. When used as a design aid, the patterns help guide developers to create new software more effectively.

Of course, patterns, objects, components, and frameworks are no panacea. They cannot, for example, absolve developers from responsibility for solving all complex concurrent and networked software analysis, design, implementation, validation, and optimization problems. Ultimately there is no substitute for human creativity, experience, discipline, diligence, and judgement.

When used properly, however, the patterns described in this book help alleviate many of the complexities enumerated earlier. In particular, the patterns