Policy-based design
Encyclopedia
Policy-based design, also known as policy-based class design or policy-based programming, is a computer programming paradigm
based on an idiom for C++
known as policies. It has been described as a compile-time variant of the strategy pattern
, and has connections with C++ template metaprogramming
. It was first popularized by Andrei Alexandrescu
with his 2001 book Modern C++ Design
and his column Generic in the C/C++ Users Journal
.
Although the technique could theoretically be applied to other languages, it is currently closely associated with C++, and depends on the particular feature set of that language. Furthermore, even in C++ it requires a compiler
with highly robust support for template
s, which wasn't common before about 2003.
template (called the host class), taking several type
parameter
s as input, which are instantiated with types selected by the user (called policy classes), each implementing
a particular implicit interface
(called a policy), and encapsulating
some orthogonal (or mostly orthogonal) aspect of the behavior of the instantiated host class. By supplying a host class combined with a set of different, canned implementations for each policy, a library or module can support an exponential
number of different behavior combinations, resolved at compile time, and selected by mixing and matching the different supplied policy classes in the instantiation of the host class template. Additionally, by writing a custom implementation of a given policy, a policy-based library can be used in situations requiring behaviors unforeseen by the library implementor. Even in cases where no more than one implementation of each policy will ever be used, decomposing a class into policies can aid the design process, by increasing modularity and highlighting exactly where orthogonal design decisions have been made.
While assembling software components out of interchangeable modules, communicating with each other through generic interfaces, is far from a new concept, policy-based design represents an innovation in the way it applies that concept at the (relatively low) level of defining the behavior of an individual class.
Policy classes have some similarity to callback
s, but differ in that, rather than consisting of a single function
, a policy class will typically contain several related functions (method
s), often combined with state
variables
and/or other facilities such as nested types.
A policy-based host class can be thought of as a type of metafunction
, taking a set of behaviors represented by types as input, and returning as output a type representing the result of combining those behaviors into a functioning whole. (Unlike MPL metafunctions, however, the output is usually represented by the instantiated host class itself, rather than a nested output type.)
A key feature of the policy idiom is that, usually (though it is not strictly necessary), the host class will derive
from (make itself a child class of) each of its policy classes using (public) multiple inheritance
. (Alternatives are for the host class to merely contain a member variable of each policy class type, or else to inherit the policy classes privately; however inheriting the policy classes publicly has the major advantage that a policy class can add new methods, inherited by the instantiated host class and accessible to its users, which the host class itself need not even know about.) A notable feature of this aspect of the policy idiom is that, relative to object-oriented programming
, policies invert the relationship between base class and derived class - whereas in OOP interfaces are traditionally represented by (abstract) base classes and implementations of interfaces by derived classes, in policy-based design the derived (host) class represents the interfaces and the base (policy) classes implement them. It should also be noted that in the case of policies, the public inheritance does not represent an is-a relationship between the host and the policy classes. While this would traditionally be considered evidence of a design defect in OOP contexts, this doesn't apply in the context of the policy idiom.
A disadvantage of policies in their current incarnation is that the policy interface doesn't have a direct, explicit representation in code
, but rather is defined implicitly, via duck typing
, and must be documented separately and manually, in comment
s.
The main idea is to use commonality
-variability analysis to divide the type into the fixed implementation and interface, the policy-based class, and the different policies. The trick is to know what goes into the main class, and what policies should one create. Andrei's excellent article, mentioned above, gives us the clue: wherever we would need to make a possible limiting design decision, we should postpone that decision, we should delegate it to an appropriately named policy.
Policy classes can contain implementation, type definitions and so forth. Basically, the designer of the main template class will define what the policy classes should provide, what customization points they need to implement.
As we go by the analysis in policy-based design, it is a delicate task to create a good set of policies, just the right number. As little as necessary, but not less. The different customization points, which belong together, should go into one policy argument, such as storage policy, validation policy and so forth. A good rule of thumb during design is that you should be able to give a name to your policy, which represents a concept, and not one which represent an operation or some really tiny implementation detail. Persistence policy seems to be a good choice, while how to save policy does not.
As you do your policy-based design you will see how many other techniques will be useful, even if changed a bit, during your work. One example is that the template method pattern
can be reinterpreted for compile time; so that your main class has a skeleton algorithm, which — at customization points — calls the appropriate functions of some of the policies. You will also find yourself in using your policy classes as traits are used, asking type information, delegating type related tasks to it, a storage policy is one example where it can happen.
, where the text to be printed and the method of printing it are decomposed using policies.
You could easily write another OutputPolicy by adding a new class with the member function Print and take that as the new output_policy.
Programming paradigm
A programming paradigm is a fundamental style of computer programming. Paradigms differ in the concepts and abstractions used to represent the elements of a program and the steps that compose a computation A programming paradigm is a fundamental style of computer programming. (Compare with a...
based on an idiom for C++
C++
C++ is a statically typed, free-form, multi-paradigm, compiled, general-purpose programming language. It is regarded as an intermediate-level language, as it comprises a combination of both high-level and low-level language features. It was developed by Bjarne Stroustrup starting in 1979 at Bell...
known as policies. It has been described as a compile-time variant of the strategy pattern
Strategy pattern
In computer programming, the strategy pattern is a particular software design pattern, whereby algorithms can be selected at runtime. Formally speaking, the strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable...
, and has connections with C++ template metaprogramming
Template metaprogramming
Template metaprogramming is a metaprogramming technique in which templates are used by a compiler to generate temporary source code, which is merged by the compiler with the rest of the source code and then compiled. The output of these templates include compile-time constants, data structures, and...
. It was first popularized by Andrei Alexandrescu
Andrei Alexandrescu
Andrei Alexandrescu is a Romanian C++ programmer and author. He is particularly known for his pioneering work on policy-based design implemented via template metaprogramming. These ideas are articulated in his book Modern C++ Design and were first implemented in his programming library, Loki. He...
with his 2001 book Modern C++ Design
Modern C++ Design
Modern C++ Design: Generic Programming and Design Patterns Applied is a book written by Andrei Alexandrescu, published in 2001 by Addison-Wesley. It has been regarded as "one of the most important C++ books" by Scott Meyers ....
and his column Generic
C/C++ Users Journal
C/C++ Users Journal was a computer magazine published by CMP Media LLC in the United States. The magazine concentrated on the C++ programming language and was one of the last printed magazines to cover the topic....
.
Although the technique could theoretically be applied to other languages, it is currently closely associated with C++, and depends on the particular feature set of that language. Furthermore, even in C++ it requires a compiler
Compiler
A compiler is a computer program that transforms source code written in a programming language into another computer language...
with highly robust support for template
Template (programming)
Templates are a feature of the C++ programming language that allow functions and classes to operate with generic types. This allows a function or class to work on many different data types without being rewritten for each one....
s, which wasn't common before about 2003.
Overview
The central idiom in policy-based design is a classClass (computer science)
In object-oriented programming, a class is a construct that is used as a blueprint to create instances of itself – referred to as class instances, class objects, instance objects or simply objects. A class defines constituent members which enable these class instances to have state and behavior...
template (called the host class), taking several type
Data type
In computer programming, a data type is a classification identifying one of various types of data, such as floating-point, integer, or Boolean, that determines the possible values for that type; the operations that can be done on values of that type; the meaning of the data; and the way values of...
parameter
Parameter (computer science)
In computer programming, a parameter is a special kind of variable, used in a subroutine to refer to one of the pieces of data provided as input to the subroutine. These pieces of data are called arguments...
s as input, which are instantiated with types selected by the user (called policy classes), each implementing
Implementation
Implementation is the realization of an application, or execution of a plan, idea, model, design, specification, standard, algorithm, or policy.-Computer Science:...
a particular implicit interface
Interface (computer science)
In the field of computer science, an interface is a tool and concept that refers to a point of interaction between components, and is applicable at the level of both hardware and software...
(called a policy), and encapsulating
Separation of concerns
In computer science, separation of concerns is the process of separating a computer program into distinct features that overlap in functionality as little as possible. A concern is any piece of interest or focus in a program. Typically, concerns are synonymous with features or behaviors...
some orthogonal (or mostly orthogonal) aspect of the behavior of the instantiated host class. By supplying a host class combined with a set of different, canned implementations for each policy, a library or module can support an exponential
Exponential growth
Exponential growth occurs when the growth rate of a mathematical function is proportional to the function's current value...
number of different behavior combinations, resolved at compile time, and selected by mixing and matching the different supplied policy classes in the instantiation of the host class template. Additionally, by writing a custom implementation of a given policy, a policy-based library can be used in situations requiring behaviors unforeseen by the library implementor. Even in cases where no more than one implementation of each policy will ever be used, decomposing a class into policies can aid the design process, by increasing modularity and highlighting exactly where orthogonal design decisions have been made.
While assembling software components out of interchangeable modules, communicating with each other through generic interfaces, is far from a new concept, policy-based design represents an innovation in the way it applies that concept at the (relatively low) level of defining the behavior of an individual class.
Policy classes have some similarity to callback
Callback (computer science)
In computer programming, a callback is a reference to executable code, or a piece of executable code, that is passed as an argument to other code. This allows a lower-level software layer to call a subroutine defined in a higher-level layer....
s, but differ in that, rather than consisting of a single function
Subroutine
In computer science, a subroutine is a portion of code within a larger program that performs a specific task and is relatively independent of the remaining code....
, a policy class will typically contain several related functions (method
Method (computer science)
In object-oriented programming, a method is a subroutine associated with a class. Methods define the behavior to be exhibited by instances of the associated class at program run time...
s), often combined with state
State (computer science)
In computer science and automata theory, a state is a unique configuration of information in a program or machine. It is a concept that occasionally extends into some forms of systems programming such as lexers and parsers....
variables
Variable (programming)
In computer programming, a variable is a symbolic name given to some known or unknown quantity or information, for the purpose of allowing the name to be used independently of the information it represents...
and/or other facilities such as nested types.
A policy-based host class can be thought of as a type of metafunction
Template metaprogramming
Template metaprogramming is a metaprogramming technique in which templates are used by a compiler to generate temporary source code, which is merged by the compiler with the rest of the source code and then compiled. The output of these templates include compile-time constants, data structures, and...
, taking a set of behaviors represented by types as input, and returning as output a type representing the result of combining those behaviors into a functioning whole. (Unlike MPL metafunctions, however, the output is usually represented by the instantiated host class itself, rather than a nested output type.)
A key feature of the policy idiom is that, usually (though it is not strictly necessary), the host class will derive
Inheritance (computer science)
In object-oriented programming , inheritance is a way to reuse code of existing objects, establish a subtype from an existing object, or both, depending upon programming language support...
from (make itself a child class of) each of its policy classes using (public) multiple inheritance
Multiple inheritance
Multiple inheritance is a feature of some object-oriented computer programming languages in which a class can inherit behaviors and features from more than one superclass....
. (Alternatives are for the host class to merely contain a member variable of each policy class type, or else to inherit the policy classes privately; however inheriting the policy classes publicly has the major advantage that a policy class can add new methods, inherited by the instantiated host class and accessible to its users, which the host class itself need not even know about.) A notable feature of this aspect of the policy idiom is that, relative to object-oriented programming
Object-oriented programming
Object-oriented programming is a programming paradigm using "objects" – data structures consisting of data fields and methods together with their interactions – to design applications and computer programs. Programming techniques may include features such as data abstraction,...
, policies invert the relationship between base class and derived class - whereas in OOP interfaces are traditionally represented by (abstract) base classes and implementations of interfaces by derived classes, in policy-based design the derived (host) class represents the interfaces and the base (policy) classes implement them. It should also be noted that in the case of policies, the public inheritance does not represent an is-a relationship between the host and the policy classes. While this would traditionally be considered evidence of a design defect in OOP contexts, this doesn't apply in the context of the policy idiom.
A disadvantage of policies in their current incarnation is that the policy interface doesn't have a direct, explicit representation in code
Source code
In computer science, source code is text written using the format and syntax of the programming language that it is being written in. Such a language is specially designed to facilitate the work of computer programmers, who specify the actions to be performed by a computer mostly by writing source...
, but rather is defined implicitly, via duck typing
Duck typing
In computer programming with object-oriented programming languages, duck typing is a style of dynamic typing in which an object's current set of methods and properties determines the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface...
, and must be documented separately and manually, in comment
Comment (computer programming)
In computer programming, a comment is a programming language construct used to embed programmer-readable annotations in the source code of a computer program. Those annotations are potentially significant to programmers but typically ignorable to compilers and interpreters. Comments are usually...
s.
The main idea is to use commonality
Commonality
Aviation commonality describes the economic and logistic benefits of operating a standardized fleet of aircraft that share common parts, training requirements, or other characteristics. Commonality lowers the cost of operating a fleet of aircraft by reducing the quantity and variety of spare parts...
-variability analysis to divide the type into the fixed implementation and interface, the policy-based class, and the different policies. The trick is to know what goes into the main class, and what policies should one create. Andrei's excellent article, mentioned above, gives us the clue: wherever we would need to make a possible limiting design decision, we should postpone that decision, we should delegate it to an appropriately named policy.
Policy classes can contain implementation, type definitions and so forth. Basically, the designer of the main template class will define what the policy classes should provide, what customization points they need to implement.
As we go by the analysis in policy-based design, it is a delicate task to create a good set of policies, just the right number. As little as necessary, but not less. The different customization points, which belong together, should go into one policy argument, such as storage policy, validation policy and so forth. A good rule of thumb during design is that you should be able to give a name to your policy, which represents a concept, and not one which represent an operation or some really tiny implementation detail. Persistence policy seems to be a good choice, while how to save policy does not.
As you do your policy-based design you will see how many other techniques will be useful, even if changed a bit, during your work. One example is that the template method pattern
Template method pattern
In software engineering, the template method pattern is a design pattern.It is a behavioral pattern, and is unrelated to C++ templates.-Introduction:A template method defines the program skeleton of an algorithm...
can be reinterpreted for compile time; so that your main class has a skeleton algorithm, which — at customization points — calls the appropriate functions of some of the policies. You will also find yourself in using your policy classes as traits are used, asking type information, delegating type related tasks to it, a storage policy is one example where it can happen.
Simple example
Presented below is a simple (contrived) example of a C++ hello world programHello world program
A "Hello world" program is a computer program that outputs "Hello world" on a display device. Because it is typically one of the simplest programs possible in most programming languages, it is by tradition often used to illustrate to beginners the most basic syntax of a programming language, or to...
, where the text to be printed and the method of printing it are decomposed using policies.
You could easily write another OutputPolicy by adding a new class with the member function Print and take that as the new output_policy.