Wolfram Language Paclet Repository

Community-contributed installable additions to the Wolfram Language

Primary Navigation

    • Cloud & Deployment
    • Core Language & Structure
    • Data Manipulation & Analysis
    • Engineering Data & Computation
    • External Interfaces & Connections
    • Financial Data & Computation
    • Geographic Data & Computation
    • Geometry
    • Graphs & Networks
    • Higher Mathematical Computation
    • Images
    • Knowledge Representation & Natural Language
    • Machine Learning
    • Notebook Documents & Presentation
    • Scientific and Medical Data & Computation
    • Social, Cultural & Linguistic Data
    • Strings & Text
    • Symbolic & Numeric Computation
    • System Operation & Setup
    • Time-Related Computation
    • User Interface Construction
    • Visualization & Graphics
    • Random Paclet
    • Alphabetical List
  • Using Paclets
    • Get Started
    • Download Definition Notebook
  • Learn More about Wolfram Language

SoftwareDesignMethodsWithWLBook

Guides

  • BookChapters

Tech Notes

  • Implementation of Object-Oriented Patterns Design Patterns in WL
  • Monad code generation and extension
  • Parsing and interpretation of integration commands
  • Typical software development workflows
Implementation of Object-Oriented Patterns Design Patterns in WL
Introduction
Composite
UML diagrams
Decorator
Preliminary concepts
Observer
Class inheritance
Interpreter
Static class inheritance
Future plans
Template Method
References
Strategy
​
Introduction
This document presents a particular style of programming in Mathematica that allows the application of the Object-Oriented Programming (OOP) paradigm (to a point). The approach does not require the use of preliminary implementations, packages, or extra code. Using the OOP paradigm is achieved by following a specific programming style and conventions with native, fundamental programming constructs in Mathematica’s programming language.
We can say that the Object-oriented paradigm came to maturity with OOP Design Patterns, which were introduced in [5]. The book [5] describes Design Patterns as software architectural solutions obtained from analysis of successful software products. Design Patterns help overcome limitations of programming languages, give higher level abstractions for program design, and provide design transformation guidance. Because of extensive documentation and examples, Design Patterns help knowledge transfer and communication between developers. Because of these observations it is much better to emulate OOP in Mathematica through Design Patterns than through emulation of OOP objects.
It is beyond the scope of this document to give an OOP introduction to Design Patterns. For detailed description of the patterns implemented and discussed we are going to refer to [5]. (All of the design patterns considered in this document have entries in Wikipedia.)
The following Venn-like diagram shows the large context of patterns. This document is for the patterns in the dark red area (“Design Patterns by GoF”).

Design patterns history

In 1975 the architect Christopher Alexander et al., [2], introduced a pattern language for architectural solutions. Alexander’s book “The Timeless Way of Building”, [3], is the more fundamental one -- some sort of philosophical prequel of [1] and [2].
The computer scientists Kent Beck and Ward Cunningham started applying these ideas in software architecture in 1987 and presented results in the conference Object-Oriented Programming, Systems, Languages, and Applications (OOPSLA) -- see [4].
In 1995 the book by Gamma et al. “Design Patterns: Elements of Reusable Object-Oriented Software” provided a catalog of well researched and documented design patterns and that brought design patterns and pattern languages great popularity and acceptance. In 2005 ACM SIGPLAN awarded that year’s Programming Language Achievements Award to the authors. The authors are of often references ad the “Gang of Four” (GoF).
.

Design Patterns structure

The OOP Design Patterns in [5] are classified in three groups: creational, structural, and behavioral. The application of the structural and behavioral patterns in a design brings the need for the application creational patterns. In this document we are mostly interested in the structural and behavioral patterns, since in Mathematica creation of objects is much more immediate than in languages like C++ and Java.
The OOP Design Patterns are presented in a certain standard form. The form has four essential elements, [5], pattern name, problems for which the pattern is applicable, solution description, consequences of applying the pattern. The book [5] presents each pattern in the following form:
1
.
Pattern name and classification
2
.
Intent
3
.
Also known as
4
.
Motivation
5
.
Applicability
6
.
Structure
7
.
Participants
8
.
Collaborations
9
.
Consequences
10
.
Implementation
11
.
Sample code
12
.
Known uses
13
.
Related patterns
All enumerated parts are considered important.
(Because [5] is also structured as a manual it can be very difficult to read at first if the reader has little exposure to OOP. )
We are not going to follow the template given above. For each considered design pattern we are going to cite the intent from [5], provide code in Mathematica, and discuss applications inside Mathematica or with Mathematica.

Narration

It is accepted in technical and scientific writings to use plural voice or make neutral objective-like statements. Since Design Patterns were (and are) discovered in successful software that narrative style seems applicable. Understanding and applying Design Patterns, though, rely on extensive experience of software systems programming, maintaining, and utilization. Trying to apply them within a functional and rule based programming language like Mathematica inevitably requires a more personal perspective of programming and software goals.
Because of these observations I am going to use first person narration where objectivity cannot be fully guarantied, where there are multiple choices for the design solution, or where the design justification is based on past experience.
It seems appropriate at this point to discuss my past programming experiences.

Personal experiences with Design Patterns

This section is mostly to provide some background of why want to discuss the implementation of Design Patterns in Mathematica and why I think they are useful to apply in large development projects.

Large scale air-pollution modeling

In 2001 I obtained my Ph.D. in applied mathematics for writing an OOP framework for the numerical simulation of large scale air pollution (and writing related articles and thesis). Air pollution simulations over continents like Europe are grand challenge problems that encompass several scientific sub-cultures: computational fluid dynamics, computational chemistry, computational geometry, and parallel programming. I did not want to just a produce an OOP framework for addressing this problem -- I wanted to produce the best OOP framework for the set of adopted methods to solve these kind of problems.
One way to design such a framework is to use Design Patterns and did so using C++. Because I wanted to bring sound arguments during my Ph.D. defense that I derived on of the best possible designs, I had to use some formal method for judging the designs made with Design Patterns. I introduced the relational algebra of the Database theory into the OOP Design Patterns, and I was able to come up with some sort of proof why the framework written is designed well. More practically this was proven by developing, running, and obtaining results with different numerical methods for the air-pollution problems.
In my Ph.D. thesis I showed how to prove that Design Patterns provide robust code construction through the theory Relational Databases, [13].
(One of the key concepts and goals in OOP is reuse. In OOP when developing software we do not want changes in one functional part to bring domino effect changes in other parts. Design Patterns help with that. Relational Databases were developed with similar goals in mind -- we want the data changes to be confined to only one relevant place. We can view OOP code as a database, the signatures of the functions being the identifiers and the function bodies being the data. If we bring that code-database into a third normal form we are going to achieve the stability in respect to changes desired in OOP. We can interpret the individual Design Patterns as bringing the code into such third normal forms for the satisfaction of different types of anticipated code changes.)
While working at Wolfram Research Inc. I re-implemented that framework in order to demonstrate the capabilities of
grid
Mathematica
. (And that demo became quite popular and presented in different conferences in 2006 and 2007.) The re-implementation in top-level Mathematica code was done using Design Patterns, [6].

Numerical integration

After joining Wolfram Research, Inc. I designed, developed, and documented the (large) numerical integration framework of
NIntegrate
. The implementation was done using both C and Mathematica and I used Design Patterns with both languages.

Other applications

In the last 9 years I have worked in the field of machine learning and data mining. I have used Design Patterns to implement digital media search engines, recommendation engines, and a broadcast scheduler. I use Design Patterns when I program larger projects in Mathematica or R and I always use Design Patterns when I program in Java and C++.

Small example of Design Patterns in Mathematica

After I answered the question “
Import and Plot Git Commit History
” in Mathematica StackExchange, I realized that the problem and desired functionalities presented there are both complex enough and simple enough to make a good example of object-oriented implementation in Mathematica using Design Patterns. The package
GitHubPlots.m
, [7], provides are “standard” implementation, and the package
GitHubDataObjects.m
, [8], provides an implementation with Design Patterns.
A separate document explaining that implementation is ....
UML diagrams
The
Unified Modeling Language
(UML) diagrams used in this document are more basic than the ones used in [5], but provide (I hope) a sufficient visual aid. They are generated over the Mathematica implementation code of the Design Patterns. See the package
UMLDiagramGeneration.m
, [10].
In UML abstract classes and operations (methods) are given in slanted font (italic). Inheritance is depicted with a line with unfilled triangle pointing to the parent class.
Here is an example:
Here are simplified versions of chart above:
The package
UMLDiagramGeneration.m
can be loaded with the command:
Import["https://raw.githubusercontent.com/antononcube/MathematicaForPrediction/master/Misc/UMLDiagramGeneration.m"]
Preliminary concepts
Here is a list of notions I assume the readers of this document to be familiar with:
◼
  • S-expressions
  • ◼
  • Closures
  • ◼
  • Dynamic and lexical scoping
  • ◼
  • Inheritance & Delegation
  • ◼
  • DownValues, SubValues
  • Class inheritance
    Inheritance is the fundamental implementation to understand. This section shows delegation to a more abstract class. The section “Template Method” shows how to make the ancestor delegation even more useful.
    Consider the following example. We have three classes C0, C1, and C2. The class C1 inherits C0, C2 inherits C1. We write this as C0←C1←C2.

    UML diagram

    Implementation

    The basic idea is to use symbols` sub-values.

    Experiments

    Here we define a C2 object:
    This invokes C1' s definition
    This invokes C2's definition:
    Finally, this invokes C0’s definition:
    Let us look into more detail of what is happening. We have made an object of the class C2, meaning we have an expression with head C2 and some data inside the expression:
    There are sub-value rules for C2:
    Here is one more example:
    It is instructive to look at the evaluation trace of C2 and C1 expressions called over “f1”. For example:
    Static class inheritance
    The inheritance implementation in the previous section was achieved through dynamic resolution of the symbols sub-value rules in order to invoke the corresponding implementation for a given signature. We can implement static inheritance by using direct manipulation of sub-values.
    The idea of the static inheritance is simple: (i) we take the sub-values of the parent and assign them to the child, and (ii) we change one or several of child sub-values to correspond to the desired changes of behavior.
    Note that the classes have the same definitions of the “delegated” function members. Using static inheritance we have saved copying and assigning code.

    UML diagram

    Implementation

    Static inheritance C0  C1:
    Static inheritance C1 C2:
    pos is for the positions of the overridden methods.

    Experiments

    Here we define a C2 object:
    Functions borrowed from C0:
    Functions borrowed from C1:
    And finally genuine the C2 function:
    It is instructional to see the definitions of the symbols defined above.
    Global`C0
    Template Method
    Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.

    Motivational example

    Mathematica has the function Inner that perfectly demonstrates the usefulness of Template-Method-like functionality code breakdown.
    Here is an algorithm “skeleton” made with Inner:
    We can easily derive different algorithms by replacing the symbols op1 and op2 with concrete functions:
    Alternatively, we can consider varying the data arguments of Inner:
    These concrete implementations of op1 and op2 provide different functionalities depending on the data types:
    Note that for _Mat objects the code above returns the result in MatrixForm.

    UML diagram

    Implementation

    For the implementation of Template Method we basically combine sub-values with Block's dynamic scoping.

    Experiments

    It is instructive to see the trace of the invocations.
    This call uses a method defined in the abstract class:
    This trace shows the call for the abstract algorithm (template method) for a concrete class object that invokes the primitive operation defined in that concrete class.

    Other concrete examples

    Template Method version of the motivational example

    Using the motivational example let us implement a class hierarchy adhering to the Template Method that provides an invariant algorithm and different specializations of its concrete operations.
    Note that there is the question of the right selection of a Template Method descendant for a given pair of argument objects. There are creational Design Patterns that address these type of problems (Abstract Factory, Factory Method); see [5]. In Mathematica we can easily address that problem with pattern matching.

    GitHubData

    The functionality of the main GitHub data class in [5] GitHubData is modified with the descendant object GitHubDataMessageHyperlinks​
    so the ticks of the plots have hyperlinks to the github.com pages corresponding to the commits. The template method algorithm is the method “Plot”, the primitive operations are “ParseData”, “TickLabels”, and “DatePoints”. The class GitHubDataMessageHyperlinks provides its own implementation of “TickLabels” (making the ticks click-able).
    Strategy
    Here is intent of the design pattern Strategy from [5]:
    Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
    Generally Strategy’s structure is not needed in Mathematica because of the functional programming paradigm support and pattern matching of function signatures. Conceptually Strategy is applied all the time, e.g. second order functions or writing functions with arguments being other functions.
    Nevertheless, we are going to give an implementation of Strategy that might be useful when prototyping in Mathematica and considering moving to production languages like C++ or Java. The implementation is essentially similar to the one given in the section “Inheritance”. Here we are going to endow it with additional code to facilitate the use of the class hierarchy within several Design Patterns.

    UML diagram

    Implementation

    Experiments

    Here we create an object of StrategyContext using a concrete strategy object:
    Here we simply replace one concrete strategy with another concrete strategy:

    Uses in Mathematica

    As it was mentioned above all second order functions (Map, Fold, Nest, FixedPoint, etc.) provide good examples of the functionality achieved by Strategy. Further, very often the algorithms specified by the Method option in different functions can be seen -- at least conceptually -- as playing within the Strategy design pattern.

    Other concrete examples

    The plotting functionality of the main GitHub data class in [5] GitHubData given by the method “Plot” is changed through the Strategy design pattern. The data member “PlotFunction” can be set to one of the functions GHDDateListPlot, GHDBarPlot, or GHDGraphics3D. In this way different plots are derived for the representation of the ingested GitHub data.
    Composite
    Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
    A typical example is moving one or several desktop icons by mouse selection and dragging.

    UML diagram

    Implementation

    Experiments

    First we create concrete non-composite Component objects (leafs).
    Next we create a composite object and add the leaf objects to it.
    Here is code creating and operating a second composite object that uses the first composite object:

    Other concrete examples

    The GitHubData object utilizes Composite to visualize the commit histories of a collection of GitHub repositories.
    Decorator
    Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub-classing for extending functionality.
    A typical example is adding scroll-bars to screen outputs.

    Motivational example

    Here is a core algorithm that takes randomly a specified number of words from a text:
    CoreAlg might give a very large output, so we want to confine its output in a small window and use scroll-bars to examine the content:
    Further, we might want to show in red certain special words:

    UML diagram

    Implementation

    Experiments

    First we create concrete components.
    Next we create concrete decorators that wrap around the component objects.

    Other concrete examples

    In [6] Decorator was used to implement a Single Instruction Multiple Data (SIMD) parallel algorithm for handling the simulations.
    GitHubData objects use Decorator for changing of the font styles and the colors of graphs and charts. See [8].
    Observer
    The design pattern Observer is also known as Model-View-Controller (MVC).

    The MVC functionality within Mathematica

    Here is a slightly modified version an example from the function page for Dynamic:
    The example above allows to change the value in the input field by moving the arrow, and change arrow's direction by changing the input value. (This MVC behavior is similar in spirit to the one in the motivational example for Observer in [5].)

    UML diagram

    For Observer it is beneficial to see not just an structural UML diagram but also an UML interaction sequence diagram, see[5]. Here is shown just a structural one.

    Implementation

    Experiments

    First let us we create a concrete subject to be observed.
    The signature of the creating function is such that it has the head of the concrete subject class ConcreteSubject and it takes two arguments, an identifier symbol and a list of observers (that can be empty). The creator function returns a ConcreteSubject object.
    Next we are going to set a state for the concrete subject.
    Let us create two concrete Observer objects, one for printing the state of the subject, the other for plotting the state of the subject.
    What the creator functions of the observers do parallels what the creator for concrete subject objects does. The signature of each creating function is such that it has the head of the concrete observer class and it takes two arguments, an identifier symbol and a list of subjects (that can be empty). The creator functions return the corresponding concrete observer objects.
    Next we attach the observers to the subject.
    This command retrieves the current state of the subject:
    The following command notifies the observers attached to the subject about its state. The result is a list of the observers views on the subject’s state.
    Let us change the state of the subject to something else.
    And let us notify the attached observers to react to the state change.
    Interpreter
    Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
    Interpreter is a powerful design pattern that allows to approach the solution of re-occurring problems using Domain Specific Languages (DSL’s).

    UML diagram

    Backus-Naur Form (BNF)

    Here is the BNF of a DSL for handling Boolean expressions of a certain type:
    BooleanExp::=VariableExp|Constant|OrExp|AndExp|NotExp|'(' BooleanExp')'
    AndExp::=BooleanExp'and' BooleanExp
    OrExp::=BooleanExp'or' BooleanExp
    NotExp::='not' BooleanExp
    Constant::='true'|'false'
    VariableExp::='A'|'B'|...|'X'|'Y'|'Z'

    Implementation

    The implementation follows the BNF in the previous section.
    Dummy client class for the UML diagram.

    Experiments

    (true and x) or (y and (not x))

    Other concrete examples

    I designed and implemented NIntegrate’s Method option using the Interpreter design pattern. (That design was also applied to NSum.) See [9] for brief details.

    Extension

    For example here is the Extended BNF (EBNF) of a simple grammar for expressing food desires:
    This command generates the grammar parsers:
    These commands show the parsing of different sentences of the grammar defined above:
    At this point it is easy enough to develop interpreters for the parsed sentences.
    Future plans
    1. Implement the generation of UML object interaction sequence diagrams using Design Patterns implementations (in Mathematica).
    2. Implement code generation based on specified Design Patterns. It is especially interesting the code generation to be specified by natural language sentences describing the system architecture.
    3. Investigate discovering design patterns within existing code.
    References
    [1] Christopher Alexander et al., The Oregon Experiment, Oxford University Press, 1975.
    [2] Christopher Alexander et al., A Pattern Language - Towns, Buildings, Construction, Oxford University Press, 1977.
    [3] Christopher Alexander, The Timeless Way of Building, Oxford University Press, 1979.
    [4] Kent Beck, Ward Cunningham, “Using Pattern Languages for Object-Oriented Programs”, OOPSLA-87, (1987).
    [5] Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, 1994.
    [13] Anton Antonov, Object-oriented framework for large scale air pollution models, 2001. Ph.D. thesis, Informatics and Mathematical Modelling, Technical University of Denmark, DTU.

    © 2025 Wolfram. All rights reserved.

    • Legal & Privacy Policy
    • Contact Us
    • WolframAlpha.com
    • WolframCloud.com