Introduction to Design Patterns

A design pattern is a description of a generalized solution to a recurring problem within a well-defined context. Design patterns are often created from best practices and contain the essential elements of the problems they tackle and their corresponding solutions. They offer a template on how to solve a specific problem that may apply to different situations. They may also describe different solution alternatives to a specific problem.

The concept of design patterns originates in civil architecture and engineering. Design patterns captured the detailed designs of towns and neighborhoods, houses, gardens and rooms with the goal of designing functional and aesthetically beautiful living spaces and structures. They identify and catalog solutions to recurrent problems encountered during the process of building and planning. Each pattern describes a problem that occurs repeatedly in our environment and the core of the solution to that problem in such a way that it may be used a million times over, without ever doing it the same way twice [B6].

In general, a design pattern identifies the key aspects of a solution and creates an abstract description that makes it useful in the creation of a reusable design element. Patterns don’t describe a concrete design or an implementation - they are intended to be templates that may be applied by a designer in various contexts and modified to suit the problem at hand. Patterns are also free from constraints of detail associated with the level of system abstraction at which the solution is implemented. Patterns also describe the design decisions that must be made when applying a certain solution. This enables a designer to reason about the impact of the design decisions on a system’s flexibility or scalability as well as consider implementation issues. Design patterns must address a specific problem at hand, and yet must be general enough to remain relevant to future requirements of systems.

Software Design Patterns

In the domain of software design, patterns were introduced in an effort to create reusable solutions in the design of software and bring discipline to the art of programming. The intent of software design patterns isn’t to provide a finished design that may be transformed directly into code; rather, design patterns are used to enhance the software development process by providing proven development paradigms. With the use of design patterns, there is sufficient flexibility for software developers to adapt their implementation to accommodate any constraints, or issues that may be unique to specific programming paradigms, or the target platform for the software. Related to design patterns, the concept of algorithmic skeletons was introduced [B7] and further refined [B8].

In the context of object-oriented programming, design patterns provide a catalog of methods for defining class interfaces and inheritance hierarchies, and establish key relationships among the classes [B9]. In many object-oriented systems, reusable patterns of class relationships and communications between objects are used to create flexible, elegant, and ultimately reusable software design. There are three categories of object-oriented patterns: (i) creational patterns for ways to do instantiation of objects, (ii) structural patterns concerned with class and object composition, and (iii) behavioral patterns for communication between objects. Patterns have also been defined in the design of software architectures [B10] to capture repeatedly used methodologies in software engineering practice. Pattern systems have also been developed for cataloging concurrent and networked object-oriented environments [B11], resource management [B12], and distributed software systems [B13].

In the pursuit of quality and scalable parallel software, patterns for programming paradigms were developed [B14] as well as a pattern language, called Our Pattern Language (OPL) [B15]. These parallel patterns are used as means to systematically describe parallel computation and communication when architecting parallel software. In an effort to enable a more structured approach to designing and implementing parallel applications, particularly for many-core processors, a catalog of parallel patterns enables programmers to compose parallel algorithms, which may be easily implemented using various programming interfaces such as OpenMP, OpenCL, Cilk Plus, ArBB, Thread Building Blocks [B16]. For the design of parallel algorithms, deterministic patterns support the development of systems that automatically avoid unsafe race conditions and deadlock [B17].

Design patterns have been identified in a variety of other domains for codifying the best-known solutions to common problems, including natural language processing [B18], user interface design [B19], Web design [B20], visualization [B21], software security [B22] and high-performance computing resilience [B23, B24]. Patterns have also been defined for enterprise applications that involve data processing in support or automation of business processes [B25] in order to bring structure to the construction of enterprise application architectures. In each of these domains of design, patterns capture the essence of effective solutions in a succinct form that may be easily applied in similar form to other contexts and problems.

Execution patterns, not design patterns, for workflows in general describe the functionality of a workflow [B26], such as execution graphs, decision points and synchronization points. Common motifs in scientific workflows [B27] start making the connection between the functionality of a workflow and certain common execution patterns, such as data movement and data analysis steps. Similar workflows execution patterns, not design patterns, have been recently proposed for instrument science [B28]. The Integrated Research Infrastructure Architecture Blueprint Activity [B4] has recently defined Workflow Patterns for scientific computational workflows, such as Time-Sensitive, Data Integration-Intensive and Long-Term Campaign.