Symmetry and Symmetry Breaking in Software Patterns James O. Coplien Bell Laboratories, ILIE00 2Z307, 263 Shuman Blvd, Naperville, IL 60566 USA, +1–630–713– 5384,
[email protected]
Liping Zhao Department of Computation, UMIST, P. O. Box 88, Sackville Street, Manchester M60 1QD, UK, +44-161-200-3340,
[email protected]
Abstract. Software patterns draw on the work of the architect Christopher Alexander, which in turn builds on foundations that may be more suitable to software than the architectural metaphors themselves. Patterns have a longstanding identity in the scientific community as results of a phenomenon called symmetry breaking. Symmetry breaking can be defined formally in terms of group theory. We establish formal group-theoretic foundations for several object-oriented programming models and show, by formal constructs and by analogy to other fields, that software patterns reduce to symmetry breaking. Such formalisms may be useful as a foundation for pattern taxonomies, and to differentiate patterns as a design discipline from heuristics, rules, and arbitrary microarchitectures.
1 Introduction Most contemporary attempts to formalize patterns (e.g., [13], [14]) ignore both the prior art and the most relevant foundations for potential formalization. This paper points a path to formalization that draws on the foundations that inspired Alexander's early work. Patterns are about geometry; we will show that geometry is symmetry, and that the foundations of symmetry theory might serve software as well as they served Alexander's theories of architecture. We will also show, as a biproduct, that the foundations are not based only in an architectural metaphor—which is a frequent source of criticism of software patterns—but in fact broaden to many disciplines in the sciences. Briefly, the focus of this research is on the geometry of programs. Alexander’s original theory of patterns (in building architecture) is preoccupied with geometry, and the role of geometry in effective system composition. Leading software pattern practitioners recognize that the best software patterns are also geometric; this is important for practical reasons of composability, and is in concert with Alexander's newly developed theories of geometric centers. Centers are geometric regions that combine with each other into larger structures that are effective “wholes”. The “goodness” of a whole corresponds to properties of the combination of the centers: deep interlock and ambiguity, echoes, good shape, proportions of scale, and so forth.
An early realization of our research is that most of these structural properties relate to symmetry. Group theory offers constructs that formally characterize different kinds of symmetry through symmetry groups that describe structure-preserving transformations on centers. It is apparent from Alexander's writings that group theoretic constructs such as symmetry and structure-preserving transformations have been a central aspect of his thinking over the years, as we will explore below. The research described here defines a group basis for programming language constructs. For example, both class hierarchies and type hierarchies form symmetry groups. Symmetry breaking occurs when the forces that preserve symmetry no longer can be sustained, and the degree of symmetry is transformed. The phenomenon is grounded in a law of physics called Curie's Principle that states: • If certain causes produce certain effects, then the symmetries of the cause reappear in the effects produced. • If certain effects reveal a certain asymmetry, then this asymmetry will be reflected in the causes that give rise to them. ([27], p. 8) Modern treatment of symmetry theory in physics notes that Curie's principle applies to what is mathematically possible; in practice the single cause can lead to any one of a number of results with different symmetries. Instabilities cause nature to choose only one effect at a time; any one may lose some of the symmetries of the cause. It's possible that if you observe the system over time, you will eventually see more of the original symmetries appear. For example, one solution to the differential equations will allow you to stand a pin on end, but instabilities make it very unlikely to happen. One might conjecture that this is related to Alexander's insight that a pattern can be implemented a million times without ever being the same twice ([1], p. x). As an example of symmetry breaking, consider a sphere in rotation (like a ball of molten matter during the formation of the solar system) with infinite degrees of symmetry. If it spins so fast that it starts to break apart, the symmetry is reduced from three dimensions to two. The instability results from exceeding the threshold in the angular momentum of the system. Symmetry-breaking leads to spatial configurations called, curiously enough, patterns. We will show here that the use of the term “pattern” by Alexander’s is consistent with the use of the term in the formal sense of symmetry-breaking, and what remains is to complete the exercise to extend these theories to software. For example, class extension is a symmetry; Bridge is a pattern that reflects symmetry-breaking under the stress of certain design desiderata. By using group theory as the formal model for the symmetry and symmetry breaking that underlie key programming constructs, we establish a formal basis for the characterization of software patterns that is consistent with the pattern foundations of the architectural literature that are commonly cited as the inspiration for software patterns. This paper will show how group theory forms a formal basis for Alexander's pattern theory, in ways that are hinted at in his work but rarely made explicit. It will show how the same formalisms fit existing language and design formalisms in object orientation in particular and in other language paradigms as well. This formal link establishes a novel basis for the application of Alexander's pattern theory to the design of software.
It is not, and cannot be, the goal of this paper to show that a formal basis exists for everything in the software pattern literature today. Indeed, this paper was motivated in part by the problem of the term having fallen into informal abuse, and by the everpresent need for criteria that separate patterns from structures better suited to other formalisms. Two important rules of thumb have served in the absence of such a formal basis: that a pattern be structural in nature, and that a pattern emanate from a pattern language. This paper will focus on a more formal presentation of the first aspect and establish a direction for similar considerations of the second aspect. The next section sets the tone for the paper by reviewing pattern theory. Section 3 presents group theory as a formal basis for symmetry. Section 4 shows the relevance of symmetry to design, particularly to Alexander's theories, and introduces symmetry breaking as a foundation for patterns. Section 5 develops a similar basis for software. Then Section 6 goes into detail with software examples of symmetry that build on the preceding sections, and Section 7 builds on these symmetries to introduce symmetry breaking and patterns in software. Section 8 broadens the relevance of symmetry breaking as a basis for patterns broader than those covered in the preceding sections. Finally, Section 9 recaps with a proposed base formalism for software patterns.
2 Alexander’s Theories Software pattern concepts took their inspiration from Christopher Alexander's research and application in the fields of architecture and urban design. We summarize that work here. 2.1 Patterns Alexander's publications on architecture in the late 1970s focused on design elements called patterns. Patterns were a reaction to modernistic trends in architecture that suffered from overuse of pre-manufactured parts and processes that were antithetical to piecemeal growth. The goal of pattern languages was to contribute to “the quality without a name,” a deep feeling of architectural excellence suitable to a given culture. If people could re-discover the patterns of their culture, they could regain control of their own living environments by participating in the construction of their homes, schools, and towns. A pattern is a description of an architectural relationship that integrates parts of an architecture into a larger whole. A pattern is itself something that can be built—not as a simple wart here or there, but as an architectural transformation. Adding window sills or window seats to the design of a house adds to the wholeness of the window areas of the house, and therefore to the wholeness of the house as a whole. Alexander's theory allows that a builder can build a house by applying one pattern at a time, in sequence.
2.2 Geometric Theory of Centers Alexander found that pattern languages alone were inadequate to achieve the beauty he sought. There were two problems: the economic processes of building didn't support piecemeal growth, and the people using the pattern language had the skills necessary only for gross scales of beauty, not the very fine artisanship necessary for wholeness at all scales. Alexander developed a new theory consistent with, but fundamentally different than, the theory of patterns. This theory is based on centers, is rooted in pure geometry and uses a piecemeal growth process. The theory is intended to be used with patterns as an adjunct. A center is something that draws the eye, a geometric region that we notice. Centers combine to form geometrically attractive configurations. Beauty roughly correlates to the density of centers in a built object, subject to the structural properties described below and the process used to intensify them. Patterns usually are stereotypical centers that carry a (likely culturally attuned) aesthetic in addition to any visceral beauty they may have. Centers drive more at the visceral beauty that owes to pure geometric configuration. 2.2.1 Structure Preserving Transformations The process for building with centers is a simple process of structure-preserving transformations. One finds the weakest center in a whole and strengthens it by adding new centers that make it more whole. If the overall result is more whole, then the process iterates to the next center. Each of these transformations increases wholeness while preserving the structure of the whole, though there are adjustments in the details. A given transformation can clean out a center that has become too messy, but the overall structure is preserved. Symmetry is fundamental to the process itself. In Alexander's Fundamental Process as presented in Nature of Order, step 4 has been given broad press: 4. As we work to enhance this new living center, we do it in such a way as also to create or intensify (by the same action) the life of some larger center. That, in itself, speaks to symmetry. However, note step 5 that follows, which adds at least two additional subsymmetries: 5. Simultaneously we also make at least one center of the same size (next to the one we are concentrating on), and one or more smaller centers—increasing their life, too. ([2], The Process of Creating Life, p. 227) 2.2.2 Structural Properties Each transformation strives to strengthen a center by reinforcing one or more of the following (non-orthogonal) properties in the whole: 1. 2.
Levels of Scale: within or around a given center, other centers should be within a factor of 4 to a factor of 10 of the same size Strong Centers: centers shouldn’t overlap too much; they should have their own
3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
15.
identity Alternating Repetition, in the intuitive sense Boundaries: each center gives rise to fuzzy centers that enclose the center itself, forming rather wide boundaries Positive Space: the space waiting to become a center; a latent center Good Shape: there are simple shapes that are pleasing to the eye (triangles, circles, stars, etc.) Local Symmetries (as opposed to overall system-level symmetry) Deep Interlock and Ambiguity: like city-country fingers in [1] Contrast, in the common sense of the term Graded Variation: step-by-step gradients pointing toward the center and strengthening it Roughness: particularly from centers that bump into each other as the system unfolds Echoes: repeated structural similarities The Void: periodic cleaning out or self-organizing that preserves overall structure by cleaning out overly intense centers Simplicity and Inner Calm: “It is essential that the great beauty and intricacy of ornament go only just far enough to bring this calm into being, and not so far that it destroys it.” Not-Separateness: eliminate exaggerated difference; unification [2]
We note that most of the structural properties are based in symmetry. Alexander emphasizes this:
Even
There is a profound connection between the idea of a center, and the idea of symmetry. … 1. Most centers are symmetrical. This means that they have at least one bilateral symmetry. 2.
Even when centers are asymmetrical, they are always composed of smaller elements or centers which are symmetrical ([4], p. 42-43).
3 Group Theory and Symmetry While symmetry is an intuitive concept to almost everyone, we can use symmetry group formalisms to ground its semantics. On one hand such formalism may be good for its own sake. But on the other hand, group theory has a longstanding legacy of practical service in the fields of crystallography, astrophysics, and subatomic particle physics.
3.1 A Geometric Basis If Alexander viewed geometry to be the essence of what he was doing, it pays to understand geometry: … in Klein’s words, ‘geometrical properties are characterised by their invariance under a group of transformations.’ Each type of geometry has its own group … Group theory provides the common ground that links different geometries ([27], p. 44). So by Klein's formulation, a geometry is defined by the symmetries it expresses, and how it expresses them; it is thus that mathematicians deal (abstractly) with geometry. So symmetry is the essence of individual geometries, and that seems to fit the hints Alexander gives us in his own text about the importance of symmetry in geometric centers (above). Alexander's Theory of Centers lays foundations for patterns, and one can argue that these same foundations should be relevant to a dutiful application of the pattern concept in software. And those symmetries can be formalized in group theoretic constructs. 3.2 The Group Definition The formalism of symmetry is couched in group theory. This section gives a mathematical definition of groups ([25], pp 9-10). A group is a nonempty set G together with a law of composition G × G → G satisfying the following four axioms:
(a, b)
ab :
1. Closure. For all a, b ∈ G, the set G is closed under composition: ab, ba ∈ G. 2. Associativity. For all a, b, c ∈ G, the composition is associative: (ab)c = a(bc). 3. Existence of An Identity Element. For all a ∈ G, there exists an element e ∈ G such that ae = a = ea . 4. Existence of Inverses. For each a ∈ G, there exists an aa-1 = e = a-1a.
a-1∈ G such that
3.3 Symmetry and Symmetry Groups Symmetry is a simple and familiar concept in everyday life. In mathematics, symmetry has a precise, operational definition. A symmetry of an object is a transformation that leaves the object apparently unchanged ([27], p.28). Symmetry transformations are also called symmetry operations. For example, an operation that defines bilateral symmetry is reflection. The human body is invariant under reflection
such that the distances from any origin point to its mirror image is preserved with respect to the reflection centre. More formally, Symmetry is immunity to a possible change ([25], p.2). … symmetry is represented by the existence of transformations that leave equivalence subspaces invariant, i.e., transformations that map every state to an image state equivalent to the object state. Such a transformation is called a symmetry transformation for the equivalence relation. Thus the defining property of a symmetry transformation S is s u →v ≡ u
or
S( u) = v ≡ u
for all states u ([25], p.80). In the above definition, v ≡ u denotes the equivalence relation between the states v and u. A subspace comprises a subset of states of a state space. An equivalence subspace is a subspace within which all the states are equivalent to each other. The set of all invertible symmetry transformations of a state space of a system for an equivalence relation forms a group, a subgroup of the transformation group, called the symmetry group of the system for the equivalence relation ([25], p. 80). An invertible transformation means that the mapping from one state to another can be inverted, which is called an isomorphism or isometry. The concept of isometry, which is based in a distance-preserving mapping in metric space, is the analog to Klein's transformation invariant. In geometric algebras, it means that the distances between points on solid objects don't change: the objects don't stretch or deform as they are translated or rotated. We can extend the concept to non-geometric isometries, as Galois used algebraic relations between solutions of equations as the foundation of his theory of permutation groups. Many symmetries in physics, called gauge symmetries, obey symmetry group properties but are not strictly geometric. With the concept of isometry, we can give an alternative definition of symmetry groups: Let X = L (line), P (plane), or S (3-D space), and let A ⊂ X. A symmetry of A is an isometry T:X→X which leaves A invariant. The set Symm(A) = {T | T:X → X is an isometry, and T(A) = A} is called the symmetry group of A. If the group contains only the identity transformation I, A said to have no symmetry. ([18], p. 409) Note that this definition is equivalent to that of Rosen’s: a symmetry group is a set of all the invertible transformations of a state space of a system for an equivalent relation.
Since a symmetry group is also a group, it satisfies the four axioms described in Section 3.2. However, a symmetry group doesn't comprise objects (buildings, objects) of a system, but rather a set of structure-preserving transformations on these objects. The above definitions—certainly the geometric one—fit our intuition of what symmetry means in the ordinary natural language sense. If we look at Alexander's structural properties we see that many of them exhibit symmetries. For example, Deep Interlock and Ambiguity and Alternating Repetition exhibit bilateral symmetry, and Echoes exhibit translational symmetry. Many of these structural properties show through in Alexander's patterns as City-Country Fingers [1] is an example of Deep Interlock and Ambiguity. The symmetries we investigate in this paper are those that appear in programming language constructs. The symmetry groups will be the collections of program transformations that are possible to apply to a program using programming language features with respect to a certain set of invariants, and all the compositions of those transformations.
4 Patterns and Symmetry Breaking When a system encounters stress it loses symmetry. Consider the common example of a proto-planet rotating in space, a sphere of symmetry group O(3). If it spins too fast it may become pear-shaped, losing one degree of symmetry so as to fall into O(2). If the spinning continues it may break into a planet/moon system which still has overall symmetry O(2), though it has lost the spherical symmetry of the original system. This is called symmetry breaking—really a misnomer because symmetry doesn't really break, but it's just reduced or redistributed. When a symmetry group is broken, it results in a new group that is a subgroup of the original. Note in this moonformation example, each of the parts still has O(3) symmetry, even though the system has been reduced to O(2). The phenomenon of symmetry-breaking is the foundation for natural phenomena called patterns. It's important to understand that the term—as Alexander appropriated it—is not simply a term of vernacular English, but reflects a formal characterization of a phenomenon: This paradox, that symmetry can get lost between cause and effect, is called symmetry-breaking. In recent years scientists and mathematicians have begun to realise that it plays a major role in the formation of patterns. … From the smallest scales to the largest, many of nature's patterns are a result of broken symmetry; and our aim is to open your eyes to their mathematical unity. ([27], p. xviii) More formally,
Definition. Given an image algebra I we shall understand by a pattern any Sinvariant subset P of I, and by a pattern family { Pγ } a partition of I into patterns. ([16], p. 93) where S is a similarity group. This notion of pattern carries through to Alexander's architecture work. Varied Ceiling Heights [1] is a symmetry-breaking pattern. Light on Two Sides of Every Room [1] is another symmetry-breaking pattern; a perfectly symmetric room would have either no windows or would have windows on four sides. A room with windows on four sides would be perfectly symmetric and would lack the quality Alexander seeks in his work; too much symmetry is a bad thing: Living things, though often symmetrical, rarely have perfect symmetry. Indeed perfect symmetry is often a mark of death in things, rather than life. I believe the lack of clarity in the subject has arisen because of a failure to distinguish overall symmetry from local symmetries. [2], The Phenomenon of Life, 44. and: In general, a large symmetry of the simplified neoclassicist type rarely contributes to the life of a thing, because in any complex whole in the world, there are nearly always complex, asymmetrical forces at work—matters of location, and context, and function—which require that symmetry be broken. [2], The Phenomenon of Life, 45. Symmetry breaking extends beyond patterns into some of the deep structural properties. Roughness, Gradients, Echoes, and Levels of Scale all exhibit symmetry, but lack perfect symmetry characteristic of the next largest symmetry groups (perfect smoothness, bilateral symmetry, and equal size). For example, beautiful buildings have windows whose sizes follow a gradient with the largest windows at the bottom and the smallest on top; perfect symmetry would have them all be the same size.
5 A Geometry for Software Symmetries abound in programs and can be found beneath almost all programming structures. Loops are spiral time symmetries. Simple conditionals can be viewed as symmetry breaking or bifurcation symmetries, while case statements can also be viewed as symmetries that hold the entry and exit points invariant. Rather than focusing on these programming-in-the-small symmetries, in this paper we focus on the design structures that are of greater interest to the field of object orientation. Gabriel posited in 1996 that Alexander's preoccupation with geometry translates, for us in computer science, to the structure of the code: But what of geometry? Alexander always goes back to this. And one of his key questions is this: What is it that dictates geometry possessing the quality without a name—what is that thing that is falsely called “simplicity”?
What corresponds to geometry for us? I think it is the code itself… ([7], p. 34) Later work by Coplien informally explored the role of symmetry in software structure, particularly in its modular [8] and temporal [9] structure. Subsequent work by Coplien [12] attempted to establish a geometric basis for C++ idioms for types whose operations have inverses. That effort was an attempt to bring some of the popular Design Patterns [15], which draw in part on those idioms, better in line with Alexander's geometric theories. The work of this paper attempts to explore symmetry in software from the perspectives of the deeper common roots of group theory. And, indeed, if one goes back before patterns to the very basics of polymorphism, one finds applicability of group theoretic foundations for object orientation to be strikingly strong despite the fact that no popular link ever joined the two fields. Consider this quote from a plant physiologist in a math journal circa 1986: …new theories of symmetry treat as equal also such objects (such equalities) which were considered as essentially different in previous theories (respectively, as inequalities). The unique reason why these equalities have been adopted is always the same thing, i.e. the existence of real or/and mental operations making the objects O, compared in features F, indistinguishable. ([29], p. 396) As we will extemporize below, this is almost a textbook definition of (objectoriented) polymorphism.
6 Symmetry in Object-Oriented Software Recall that a symmetry is a transformation that leaves some states of a system invariant. A symmetry transformation is an isometry which preserves the structure of space. A symmetry group comprises a set of all the symmetry transformations that operate on the same state space. What are the structure-preserving transformations on objects? To answer that question, we must first define what is meant by “structure.” Return for a moment to Klein's definition: …geometrical properties are characterised by their invariance under a group of transformations. We can look at several language features that support these properties as a basis for a symmetry group model of programs. There are precedents for the approach we will take here; for example, Cook and Palsberg [5] define inheritance as an operation on generators that transform a base class into a (distinct) derived class. Consider some examples of symmetry groups in object-oriented programming languages.
6.1 Classification as Symmetry To start with, a class in an object-oriented program is a symmetry. A class defines the common data structure and functionality for its objects. The class invariants hold for all its objects. A class is an analogy which is a valid statement for all its instances, and such analogies form symmetries ([25], p. 164). Many language features—inheritance, subtyping, overloading, and others—are ways of expressing classification. By the above reference, all such features are symmetries. The following sections look at inheritance, class methods, and subtyping in more detail.
6.2 Inheritance as Symmetry In the case of inheritance, all the classes in the same class hierarchy are considered equivalent to each other, i.e., they are invariant with respect to the base class representational structure and its invariants under class derivation. The law of composition of a class hierarchy is the derivation operation and its inverse, where the inverse can be implemented as slicing (see below), or through conversion operators or constructors (e.g. in Smalltalk, many algebraic types respond to messages such as asInteger). The symmetry group consists of the identity derivation (null class derivation) and all the derivations that produce any single path through the class hierarchy. We can define symmetry groups in a class hierarchy using the notation presented in Section 3.3. Let P be a program space; let A ⊂ X be a path through a class hierarchy. A symmetry of A is an isometry under the derivations D:P→P which leave A invariant. The set: Derive(A) = {D| D:P →P is an isometry, and D(A) = A} is called the symmetry group of A. By D(A) = A, we mean that the truth of the class invariants is maintained. We can evaluate the symmetry group of a path through a class hierarchy according to the four axioms of group theory ([25], ff. 7; [29], p. 380): 1. 2. 3. 4.
Closure. Inheritance is closed under composition; one can inherit from the class that results when deriving class B from class A. Associativity. Associativity holds for any group of transformations in general ([25], Chapter 4). An identity tranformation. Deriving the null class from any class yields that class, and vice versa. Existence of inverses. The (now vestigial) class slicing feature of C++, for example, is a way to restore the original state of the system when an instance of some class is supplied in a context where a less derived class is expected. This means that not only inheritance, operations, but the corresponding slicing
inverses, are also part of the symmetry group. The inverse could similarly be affected as a conversion operator or constructor in C++ or as a conversion method in Smalltalk.
6.3 Class Methods as Symmetry A programming language type can be defined as offering a signature, for which each behavior has preconditions and postconditions characterizing its suitable use, such that the implementations of the behaviors honor a set of invariants that hold for each instance of the type. Note the direct parallel between this definition of a type and Klein's definition of a geometry. We can more formally define a type as a symmetry group that is the collection of its member functions. In this paper, we will consider only algebraic types. The symmetry transformations of an object type are the member functions of the object type. The symmetry group is the object's type, or more properly, its signature, Type(A). The members of the group are the member functions that change the object in a way that preserves the class invariants. This appeals to the original, mathematical definition of “type” as being a structured set. Let P be a program space; let A ⊂ P be an object type. A symmetry of A is an isometry under the member functions Ψ:P→P which leave A invariant. The set: Type(A) = {Ψ | Ψ:P → P is an isometry, and Ψ(A) = A} is called the symmetry group of A, where Ψ(A) = A implies the maintenance of the truth of the class invariants for A. We also evaluate types according to the four axioms of group theory: 1. 2. 3.
4.
Closure holds for arithmetic operators. Associativity of operations on the type, which clearly holds for well-behaved objects. If the type is abelian, then the class will be implemented to have an identity. For example, the identity for a class Complex under addition will be addition of zero, and under multiplication will be multiplication by 1. Existence of an inverse. Our research has not been able to formalize this property for classes in general (though it should be possible; Section 6.1), but it holds in the universe of algebraic types.
For example, the operations + and – on a Complex number are members of the symmetry group for the type Complex. Considering the geometric metaphor, these functions correspond to translations (addition and subtraction), reflections (multiplication by –1), and rotations (addition to the angle component) in the complex plane. We consider all of these operations to preserve the isometry of the objects (complex numbers) because they honor the class invariants. We see this holds, within the limits of a finite value representation, in software for instances of some class Complex. Analogous properties hold for any algebraic type. There exist pattern
languages designed for symmetry breaking in the class and type structure of algebraic types in particular, e.g., [12]. 6.4 The Liskov Substitution Principle as Symmetry Symmetry is preserved in well-formed subtyping; we know this because the invariants of the derived class must be at least as strong as those of the base class. Derived types have more invariants than base types: in addition to the invariants of a complex number, a real has the invariant that the imaginary part of the number is zero; in addition to the invariants of a rectangle type, a square has the invariant that all sides are equal in length; relative to an ellipse, a circle has the invariant that the values of its foci be equal. Since symmetry is defined by the preservation of invariants under a certain set of transformations, we can say that subtyping is a symmetry under class invariants. We can derive a different subtyping symmetry in another state space, that of the program in which the type is embedded. Remember that a symmetry is the holding of some invariants under a transformation. The Liskov substitution principle can be read exactly this way: What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2, them S is a subtype of T. [19] That is, there are invariants (in this case, behavioral invariants) that hold for a program under a transformation that substitutes objects of type S for those of type T. Behavior is symmetric with respect to subtyping—only here, the constancy of behavior is itself the litmus test by which subtyping is judged, not vice versa. More formally, Symm(B) = { D | D: P → P is an isometry, and D(B) = B } holds directly where D is the subtyping relation, and B is the behavior of any program
P. By “isometry” in B we mean behavior in time. We could derive the formal succession of equivalent subgroups of the program state space, SP, over time, if we wanted to be literally compliant with the formal definition from [18]. Temporal structure is a common theme in symmetry breaking in the natural sciences; in fact, the idea that time is reversible is called the T symmetry in the classic CPT symmetry model of physics; symmetry breaking in all of these symmetries is the very reason that anything exists ([17], pp. 79-81). More generally, we can define symmetry in terms of any invariant or notion of equality ([29], pp. 395-396). So, by definition, subtyping is a symmetry.
7 Patterns and Symmetry Breaking in Software Many programming language constructs express symmetry. When those constructs fail, programmers often resort to patterns to express the design in the programming language. In fact, the source of most patterns seems to be a result of symmetry breaking. Why does symmetry break? In physical models there is some input from outside the system that causes the symmetry to break: thermal energy, instabilities, etc. The system settles into a new pattern of broken symmetry in response to the input. It isn't that the nature of the system is intrinsically asymmetric; it's just that the asymmetric configuration satisfies those forces that now include the new input. For example, there is nothing fundamental about the system in which Half-Object plus Protocol (HOPP) [22] is embedded that suggests that symmetry break in a way that results in two objects; it could just as well break into three objects, as it does in the pattern Three-Part Call Processing [9]. Either pattern adequately addresses the forces that originally give rise to HOPP (standards, efficiency, etc.), but Three-Part Call Processing may respond to additional forces as well. Symmetry breaking leads to subgroups, where the original group has all the symmetries of the subgroup. In this section we present some examples from objectoriented software. 7.1 Breaking Type Symmetry Let's say we have an existing class, List, that exists in some library. We wish to transform it in a way that preserves most of its properties because we want to create a new type, Set. From the perspective of class invariants this should be O.K.: sets have an invariant that stipulates element uniqueness, but that doesn't weaken any of the class invariants of lists. However, one of the symmetries held by objects of List is the ability to be sorted. Consider that Symm(List) = U ψ ∈ Signature(List) Each member function is a transformation of the object that preserves structure; it must be, if the class invariants are to hold. For example: sort ∈ Symm(List) If we wanted to derive Set from List, then it must be true that Symm(Set) ⊇ Symm(List) However, sort ∉ Symm(Set) which means the symmetry is broken. The common approach to such software configurations is to use encapsulation instead of delegation or inheritance. In
particular, one might use the Adapter pattern (to adapt the interface) or Bridge pattern (to separate the concerns of interface and implementation). Variants of this reasoning apply to modes of inheritance other than subtyping, such as for the inheritance mechanisms described in Chapter 24 of [24]. Let’s step back and consider this from the perspective of symmetry breaking. What exactly is a pattern? It is a way of redistributing the forces in a symmetric system in light of some instability. Symmetry is reduced, but not lost; it is redistributed in the pattern. The exact way in which it is redistributed is difficult to predict. Though global symmetries are broken down, local symmetries are preserved. Recall Alexander: I believe the lack of clarity in the subject has arisen because of a failure to distinguish overall symmetry from local symmetries. And consider that “local symmetry” is hardly an original Alexandrian formulation, but is a term of the trade in the symmetry group communities of crystallography ([20], p. 29; [26], p. 567) and quantum physics ([21], p. 173), as well as in other disciplines based in group theory. If one considers what happens in the case of Adapter or Bridge, we start with a List and want to transform it into a Set. The symmetry between the two is strong and, since inheritance is a language feature that expresses symmetry, we try to use it to express the relationship. The problem is that the symmetry breaks in a small way. Where does it go?
m1(arg) m2(arg) m3(arg)
m1’(arg) m2’(arg) m3’(arg) Figure 1. Inheritance Symmetry
The original relationship was an inheritance relationship, which has strong global symmetry (Figure 1). The new relationship, lacking the same global symmetry, reflects only local symmetries. The number of local symmetries hasn't increased dramatically; it is an example of what Alexander would call minimal symmetry breaking. But now, the insert and has method selectors appear on all three classes. We have not only the additional symmetries caused by the addition of new signatures on new objects (remember, each method is itself a symmetry), but we have more local symmetries between the classes as well (Figure 2).Most of the structural patterns (Adapter, Bridge, Composite, Decorator, and Proxy) of the Design Patterns
[15] book deal with the tension between language constructs that express symmetries, and the small perturbations that make those constructs unsuitable for use. Some of the behavioral patterns (Iterator, Memento, Observer, State, Strategy, Template Method, and Visitor (see below)) can also be easily described in terms of temporal symmetry breaking. Other GOF patterns take more imagination to describe in symmetry-breaking terms, which raises the question of whether they are patterns in the Alexandrian vein.
7.2 Breaking Method Symmetry
7.2.1 Multiple Dispatch A method, as described above, is a symmetry of an object or class. There are further symmetries in the methods of a type graph in polymorphic languages: derived type methods have preconditions no stronger than those in the base class, and postconditions no weaker than those in the base class. That is, they have a level of equivalent semantics defined by the bounds of these pre- and postconditions, semantics that programmers usually associate (however informally) with the method selector. In a classful language these symmetries follow derivation symmetries, and methods' symmetries depend on their respective classes. A method is chosen according to the type of its instance, at run time; that is, the object is a structure-preserving (semantics-preserving) transformation of the method selector at run time that changes the behavior (run-time structure) of the program. Symmetry theory deals frequently with symmetry in time, particularly in the domain of physics, but also in simple domains such as the symmetry of the hoof sequencing of a trotting or galloping animal. But the behavior (run-time structure) at some level is the same, as given in the Liskov Substitution Principle (LSP) above. The symmetry breaks if the method depends on the types of more than one object; the LSP no longer holds verbatim, and the formal model of a method as a symmetry no longer holds. This is a form of symmetry breaking for which the longstanding linguistic solution is multiple dispatch. The pattern literature calls this the Visitor pattern [15]. Visitor's semantics attempt to preserve much of the articulation of method symmetry developed earlier in this paper. The solution was documented as an idiom in the early literature [6]. Languages such as CLOS that support multiple dispatch start with a fundamentally different model of symmetry; the metaphor suggests that it is formally a different algebra or geometry, in which multiple dispatch does not break symmetry. 7.2.2 Promote and Add Independent of whether multiple dispatch is part of the language, there is still symmetry and symmetry breaking in methods. Let's look at some binary methods for simplicity, and in fact look at one of the simplest, binary addition. It brings out symmetric structure in most algebraic types.
Object orientation usually implies encapsulation, and most object-oriented languages are built around constructs that encourage and support encapsulation. Most methods operate on a single type as their primary operand, taking other types as parameters. Addition is interesting because of highly symmetric signature: TxT→T If we picture + operations between pairs of objects, where each object participates in a class hierarchy, we get a nicely symmetric picture as in Figure 3. Complex
+
Complex
Co mplex Real
+
Real
+
Integer
Rea l Integer
Integer
Figure 3. Bilateral Symmetry
But reality is messier because of the need for heterogeneous addition. For example, it makes sense to ask for 1 + 4.5, as in Figure 4. This configuration breaks the simple symmetry of the original, homogeneous addition case. Note that the problem arises independent of whether there is multiple dispatch—in which event the combinatorics are handled within the compiler—or single dispatch, in which case the combinatorics are handled within individual classes. And the pattern applies whether the programming language is run-time polymorphic or simply uses overloading; FORTRAN compilers must deal with similar conceptual structures. Complex
Real
Complex
+
Real Complex?
Integer
Integer
Figure 4. Symmetry Breaking in +
The solution is a geometric transformation, a pattern, called “Promote and Add,” originally written up as a C++ idiom [12]. It adds subsymmetries by promoting (a
symmetry) heir types to their parent types as a prelude to addition, thereby reducing the problem to that of the first picture. It is a structure-preserving transformation that adds centers (the transformations from derived types to base types) to the first picture. This is one of the most broadly used configurations in software patterns. The resulting Smalltalk bears out the pattern explicitly, as one can find in a perusal of these Smalltalk 80 methods: Double>>+ aNumber ^aNumber sumFromDouble: self Double>>sumFromInteger: anInteger ^anInteger asDouble + self Integer>>asDouble | factor sum | sum := 0.0 asDouble. factor := self sign asDouble. 1 to: self digitLength do: [:i | sum := factor * (self digitAt: i) + sum. factor := factor * 256.0]. ^sum ArithmeticValue>>+ aNumber ^self subclassResponsibility ArithmeticValue>>sumFromDouble: aDouble ^aDouble retry: #+ coercing: self ArithmeticValue>>sumFromInteger: anInteger ^anInteger retry: #+ coercing: self ArithmeticValue>>retry: aSymbol coercing: aNumber self generality < aNumber generality ifTrue: [^(aNumber coerce: self) perform: aSymbol with: aNumber]. self generality >aNumber generality ifTrue: [^self perform: aSymbol with: (self coerce: aNumber)]. self error 'coercion attempt failed'
This pattern represents the same symmetries and symmetry breaking as the pattern Add a Switch [9]. 7.3 Breaking Class Symmetry
We usually think of types as abstract specifications with classes as their less abstract counterparts. The class structure often follows the type structure. But sometimes, even though the type structure reflects a structure-preserving transformation consistent with the LSP, the class structure does not preserve structure for reasons that owe to language implementation peculiarities. This means that the symmetry of the class structure is broken, and a pattern usually results.
Again consider class Complex, whose implementation is two reals. Abstractly we can talk of the symmetry group of type Complex as comprising transformations that preserve class invariants. These invariants hold, with respect to member function behavior (type symmetry) for heir classes such as Real and Integer, as one would expect. Even though the member function symmetries are preserved in the transformations from Complex to derived types, the structure of the Complex class may not be preserved in Real and Integer. In particular, Complex has two reals and Real would have only one. Eiffel would call this restriction inheritance ([24], p. 826). In the representation of the class, there is at best a weakened symmetry between Complex and Real (one could argue that they are symmetric with respect to the preservation of the real component) but all structure is lost by the time we get to Integer. Symmetry slowly breaks as we descend the hierarchy. We find the same case for Ellipse and Circle: Meyer ([24], p. 467) shows that an Ellipse with two foci can be established as a base class, with a derived class Circle that adds an invariant that both foci (or major and minor axes) are the same. If one preserves both foci and adds an invariant that the foci have identical value, then it is a structure-preserving transformation. But a good designer is likely to reduce the data structure from two focal points to a single center, and perhaps to add a diameter—a feature that might not have been explicit in Ellipse (if it were, it might have been the sum of the distance from a point on the Ellipse to each of the foci). In either of the cases, we lose symmetry when the inheritance transformation is not structure preserving, so we have symmetry breaking. What results is usually a pattern; in this case, something like Bridge might be in order. We get the same breaking into local symmetries as before.
8 Other Examples We can look beyond object-oriented programming language features to find myriad examples of symmetries and symmetry breaking in software design. 8.1
Linguistic
More generally, we can think about any language feature—not just inheritance and subtyping—as a symmetry. Inheritance and subtyping are symmetries on objects (particularly when considering delegation) and classes. Overloading is a symmetry where names are invariant. Argument defaulting is a form of overloading where the symmetries explicitly extend to some argument types. Patterns exist for symmetry breaking in all of these cases. We showed above, in Section 7.2.2, what happened when the symmetry of overloaded operator + broke. This is hardly an object-oriented phenomenon, either. The work of [10] introduced the notion that functional and applicative languages may succumb to these analyses
more readily than object-oriented languages do, owing to the largely geometric nature of the source and translated program structures. The symmetries of language features might be used as a basis for objectively comparing their relative expressive power. For example, the number of generators in a symmetry group might be used as such an objective indicator. We suggest further empirical research to ground this hypothesis.
8.2
Extralinguistic
Patterns such as Half Object plus Protocol (HOPP) [22] are an obvious example of symmetry breaking reminiscent of bifurcation symmetry. Symmetries arise in many other application domains. In a Driver Duty program, we observed that both the driver duty object and its builder were cascades. A driver duty can be seen as a result of a translational symmetry of its builder (the Prototype pattern) or as a rotated bilateral symmetry [31]. Symmetries also abound in telecommunication software as documented in [9]; HOPP itself is one example common to this domain. The original Model-View-Controller pattern grew out of the Smalltalk direct manipulation metaphor, a direct symmetry between a Model object and a User object. What breaks the symmetry is the need for the User object to maintain multiple views of the Model. That gives rise to the View object itself, and to the Controller as a dispatcher from the User to the Model and View. The MVC architecture lacks the system-level symmetry of the direct manipulation metaphor, but is richer in subsymmetries than the original. In the current popularization of MVC, the importance of the original User object has been lost [Trygve Reenskaug, Personal conversation, June 1999]. Fresh Work before Stale [23] is a classic example of temporal symmetry breaking. The flow of work arrival and work processing, which is symmetric under normal conditions, breaks down under the stress of queue resource exhaustion. The result is a broken symmetry in the flow of work that gives priority to new work over pending work, and throughput increases as a result. Factory Method and Abstract Factory [15] break the symmetry of the structures of the object produced by instantiation processes. Template Method breaks the symmetry of individual algorithms. Domain analysis techniques are commonly rooted in axioms of commonality and variation. Group theory may provide a set of constructs for formalizing this structure as well: symmetry is about commonality invariance; symmetry breaking is about variations.
9 So, What is a Pattern?
9.1 The Pattern Community Value System The question of “What is a pattern?” is the closest thing to a religious debate in computer science since the debate raged about “What is object orientation?” There are many qualities often used to distinguish, or sometimes distance, patterns from mainstream academic computer science. Among these are beauty, maturity of ideas, and attunement to human comfort. It pays to spend a little time putting these elements in perspective.
9.2 Pattern Languages Alexander says that a pattern doesn't exist apart from a pattern language ([3], p. 312). We can imagine practical reasons for this, relating to gestalt theory and to the importance of taking an architectural view. But might symmetry theory also provide clues? Remember that a pattern is a transformation, a transformation that breaks symmetry. This implies that the pattern breaks some symmetry present in the original system, adding asymmetry. The original system defines context; without that context, there may in fact be no symmetry to be broken. What might otherwise pass as a pattern, out of context, may simply be a symmetry. But, in general, symmetry doesn't exist without asymmetry. ([25], p. 161) One can criticize the GOF patterns [15] as not meeting the Alexandrian criterion of necessarily emanating from a whole, from a pattern language. However, some of the GOF structures constitute patterns from any reasonably defined “geometry” of programming or framework of design symmetries, subject to the criterion that symmetry breaking and patterns are related. This leaves hope that the GOF structures can be legitimized as patterns in a fashion tantamount to, or at least analogous to, the closely related idioms work [12]. One key suggestion for future work is to show that a pattern language forms a contextual framework for the formalization of symmetry breaking (the very definition of individual patterns), and that such a framework forms not only a language, but also an algebra. The outcome seems likely; after all, a geometry is essentially an algebra of symmetries. 9.3 Towards a Formalism Based on these foundations, we posit the following formal definition of a pattern: Definition: A pattern is a structure that results from breaking a non-local symmetry, where the symmetry is defined by an invariant. Non-limiting
examples of invariants include class structure (in the vulgar sense) and behavior (as in the LSP or as in a data or control flow model of a suitable granularity). A pattern is a subsymmetry of some configuration of symmetry in a system with isomorphic invariants. This system formally forms a geometry or algebra. A pattern must always be interpreted with respect to this algebra; for example, without the algebraic context, what might otherwise be a pattern may be only a symmetry. This algebra or geometry is known in the vernacular as a pattern language. Patterns precipitate from symmetries in response to both internal and external forces that are the analogy of instability. The formal aspect of the definition is necessary but not sufficient. The articulation of a pattern is also subject to a value system, and in particular to aesthetic and quality considerations beyond the scope of the formal aspect of the definition. Among these considerations are human comfort, utility, beauty, durability, and maintainability. This definition is simply a distillation of the findings of this paper, cast in a way that ties the group theoretic foundations with the vernacular definitions. We propose it as a foundation for further work in the formalization of software patterns. One might use this definition to conclude that because the GOF structures reflect different geometric contexts, they could never all be unified in a single pattern language. For example, the context for Observer and Memento is temporal symmetry while the context for most other patterns is more spatial. This contextual modeling might provide a framework for a pattern taxonomy that would be more useful than the current taxonomy (creational, structural, etc.) for the stated purpose of a pattern language: to create whole systems through a piecemeal growth process.
10 Conclusion Other attempts to formalize patterns have striven for implementation automation. That is not our goal here, as automation of pattern assembly is an oxymoron from first principles. What it does do is to provide a formal basis for the characterization of patterns in specific contexts. For example, the symmetry theory foundation for patterns explains formally why multiple dispatch is a pattern in Smalltalk, and is not a pattern in CLOS. It explains why inheritance is a symmetry, lacking the symmetrybreaking properties that are characteristic of patterns, even though Inheritance wrongly appears as a pattern in some collections [28]. This model may provide a foundation for legitimizing other patterns on the basis of temporal symmetry breaking models, even though such patterns break with the longstanding software pattern rule of thumb that suggests that the best patterns are spatial. This paper deals with patterns commonly associated with design. There may be other useful patterns of programming, such as indentation style and other modular constructs, that also exhibit symmetry and symmetry breaking and which are equally important to the success of software development.
Acknowledgments Michael Benedikt, Ellie D'Hondt, Maja D'Hondt, Ed Remmel, and Curtis Tuckey were very helpful sounding boards for some of the ideas in this article. A very special thanks to Gottfried Chen for his expert advice late in the evolution of the manuscript. Ralph Johnson provided valuable insights from his experience with symmetry theory and objects alike, and corrected a number of errors in the original draft. A very special thanks to Edith Adan-Bante for her patient and expert help with group theory. Peter Mataga not only offered insight into group theory, but also gave helpful examples from engineering mechanics and physics that helped us search for the appropriate software parallels. Rachel Suddeth and Kevlin Henney helped correct mistakes in the articulation of the group invariants. Other helpful review comments came from Neil Harrison and Rich Delzenero.
References [1] Alexander, C., et al. A Pattern Language. New York: Oxford University Press, ©1977. [2] Alexander, C. The Nature of Order. Pending publication by Oxford University Press, New York, New York. Citations quoted with permission. [3] Alexander, C. The Timeless Way of Building. New York: Oxford University Press, ©1979. [4] Alexander, C. A Foreshadowing of 21st Century Art: The Color and Geometry of Very Early Turkish Carpets. New York: Oxford University Press, ©1993. [5] Cook, W., and J. Palsberg. A Denotational Semantics of Inheritance and its Correctness. IN OOPSLA '89 Conference Proceedings, SIGPLAN Notices 24(10), 1989. New York: ACM SIGPLAN, p. 436. [6] Coplien, J. Advanced C++ Programming Styles and Idioms. Reading, MA: Addison-Wesley, ©1992. [7] Coplien, J. Software Patterns. New York: SIGS Publications, ©1996. [8] Coplien, J. Space: The Final Frontier. C++ Report 10(3). New York: SIGS Publications, March 1998, 11-17. [9] Coplien, J. Worth a Thousand Words. C++ Report 10(5). New York: SIGS Publications, May/June 1998, ff. 54. [10] Coplien, J. To Iterate is Human, to Recurse, Divine. C++ Report 10(7). New York: SIGS Publications, July/August 1998, 43-48; 51. [11] Coplien, J. Take Me Out to the Ball Game. C++ Report 11(5). New York: SIGS Publications, May 1999, 52-8. [12] Coplien, J. C++ Idioms Patterns. In Pattern Languages of Program Design 4. Reading, MA: Addison-Wesley, ©2000.
[13] Eden, A. H., J. Gil, A. Yehudai. A Formal Language for Design Patterns. 3rd Annual Conference on the Pattern Languages of Programs (Washington University Technical Report WUCS-97-07). [14] Eden. A. H., J. Gil, A. Yehudai. Precise Specification and Automatic Application of Design Patterns. The Twelfth IEEE International Automated Software Engineering Conference (ASE 1997). [15] Gamma, E., et al. Design Patterns: Elements of Reusable Object-Oriented Software. Reading, MA: Addison-Wesley, ©1996. [16] Grenander, U. Elements of Pattern Theory. Hopkins University Press, ©1996.
Baltimore, Maryland: Johns
[17] Hawking, S. A Brief History of Time. New York: Bantam, ©1996. [18] Kappraff, J. Connections: The Geometric Bridge Between Art and Science. McGraw-Hill, 1990. [19] Liskov, B. Data Abstraction and Hierarchy. SIGPLAN Notices 23,5, May 1988, p. 25. [20] Mackay, A. L. Generalized Crystallography. Computers & Mathematics With Applications, 12B(1/2). Exeter, UK: Pergamon Press, 1986. [21] Mannheim, P. D. Symmetry and Spontaneously Broken Symmetry in the Physics of Elementary Particles. In Computers and Mathematics with Applications, 12B(1/2). Exeter, UK: Pergamon Press, 1986, 169-183. [22] Meszaros, G. Pattern: Half-Object plus Protocol (HOPP). In J. O. Coplien and D. Schmidt, eds., Pattern Languages of Program Design, Reading, MA: AddisonWesley, ©1996, Chapter 8, 129-132. [23] Meszaros, G. A Pattern Language for Improving the Capacity of Reactive Systems. In Pattern Languages of Program Design - 2. Reading, MA: AddisonWesley, ©1998, p. 586, "Fresh Work Before Stale." [24] Meyer, B. Object-Oriented Software Construction. Prentice-Hall, ©1997.
Upper Saddle River, NJ:
[25] Rosen, J. Symmetry in Science: An Introduction to the General Theory. New York: Springer-Verlag, 1995. [26] Senechal, M. Geometry and Crystal Symmetry. In Computers and Mathematics with Applications 12B(1/2). Exeter, UK: Pergamon Press, 1986. [27] Stewart, I., and M. Golubitsky. Fearful Symmetry: Is God a Geometer? London: Penguin, ©1992, 1993. [28] Tichy,
Walter.
Essential
Software
Design
Patterns,
http://wwwipd.ira.uka.de/~tichy/patterns/overview.html, n.d.
[29] Urmantsev, Y. Symmetry of System and System of Symmetry. Computers and Mathematics with Applications, 12B(1/2). Exeter, UK: Pergamon Press, 1986, 379-405. [30] Weyl, H. Symmetry. Princeton University Press, 1952.
[31] Zhao, L, and T. Foster. Driver Duty Constructor: A Pattern for Public Transport Systems. In The Journal of Object-Oriented Programming 12(2), May 1999, 4551;77.