
NewsLook for Outlook
Patterns and OO
|
The Web Site you seek
Cannot be located, so
Waste your time here
|
Contents History
The origin of design patterns lies in work done by an architect named
Christopher Alexander during the late 1970s. He began by writing two books, A
Pattern Language and A Timeless Way of Building which, in addition to giving
examples, described his rationale for documenting patterns.
The software
pattern movement started slowly, and did not really impinge on the majority of
software developers until in 1995 Erich Gamma, Richard Helm, Ralph Johnson, and
John Vlissides published
Design Patterns: Elements of Reusable Object-Oriented Software, which
has been followed by many articles in trade journals, and in many additional
books.
Patterns Defined
A pattern is a proven solution to a problem in a
context Or Each pattern is a three-part rule, which expresses a relation
between a certain context, a problem, and a solution (Alexander)
Patterns are devices that allow programs to share knowledge about their design. In our daily
programming, we encounter many problems that have occurred, and will occur
again. The question we must ask ourselves is how we are going to solve it this
time. Documenting patterns is one way that you can reuse and possibly share the
information that you have learned about how it is best to solve a specific
program design problem.
The general form for documenting patterns is to define
items such as:
- The motivation or context that this pattern applies to.
- Prerequisites that should be satisfied before deciding to use a pattern.
- A description of the program structure that the pattern will define.
- A list of the participants needed to complete a pattern.
- Consequences of using the pattern...both positive and negative.
- Examples!
Example Pattern Definition (from GoF)
Intent | What the pattern does (short) |
Also known as | Any other names |
Motivation | The problem the pattern is intended to solve (long) |
Applicability | The context in which the pattern can solve the problem |
Structure | A generalised UML Static Class diagram of the classes in the pattern |
Participants | A short description of each of the classes used in the pattern |
Collaborations | A short description of interactions between participants |
Consequences | The advantages and disadvantages of using the pattern |
Implementation | Will generally contain an equivalent of the phrase "Consider the following issues when implementing this pattern:" followed by fairly detailed examples. |
Sample code | Annotated code of an example of this pattern |
Known Uses | Examples of places where the pattern has been used � to good or bad effect. |
Related Patterns | Patterns which may be used by this one, or which use this one. |
What a pattern is not
Is this a pattern? This extract is the first two paragraphs of one section of an
article. The remaining paragraphs do not mention anything pattern-related.
Object Identifier Pattern
In order to synchronize identity and relationships
between the middle tier objects and the database rows, we will use the Object
Identifier (OID) pattern. This pattern calls for each object to be assigned a
unique value. These OID values must correlate to primary key values in the
database. Each new object created in the system must be assigned a unique OID.
This OID value can be alphanumeric, but should probably be a long integer. At a
minimum, the OID must be unique over a class type and probably any subclasses.
This strategy has an immediate effect on the database structure. To fully take
advantage of the OID strategy, the database should use surrogate keys for
identification rather than one or more fields with business meaning. Surrogate
keys are typically an autonumber field in SQL Server or generated by a Sequence
in Oracle. These keys are created by the database itself and have no meaning
other than as an identifier.
I would say that this is not a pattern, it's a
buzz-word. There is nothing wrong with anything in the article � it just
doesn't use patterns save as buzz-words. Also the solution presented is
too trivial to be a pattern: use AutoNumber or a Sequence. Well duh.
I have in
fact seen something which could be called an 'Object Identifier Pattern', at
Scott Ambler's excellent site,
as part of a large, complex article - one in a series - about OO-RDBMS mapping.
He doesn't actually give a representative implementation of it, but he does
discuss how to assign OID's in a distributed environment. However, his
description is merely part of a much longer article and although it has the
capability to become a pattern, it isn't yet. I'd still use it and name the
objects as though they were a formal pattern, though. (By the way, the Scott
Ambler paper above is well worth a read, if only as an example of a very clear
way to write about a complex problem. If you're interested in actually writing
a Persistence Layer, it's pure gold.)
Types of Pattern
The GoF book splits its
patterns into three types:
- Creational
- Structural
- Behavioural
These are not the only possible classifications. There are for instance several patterns
relating to translating between OO systems and RDMBS's. These are rather larger
than most patterns (I personally am not sure that they should be called
Patterns at all) and cannot be classified in this way at all. (See particularly
http://www.objectarchitects.de/ObjectArchitects/orpatterns/index.htm and
http://www.ksc.com/articles.htm for examples.)
Creational Patterns These deal,
obviously enough, with ways to create objects. When using polymorphism
(inheritance or interface based) picking the right type to actually instantiate
may not be totally straightforward. These patterns move this decision-making
process away from the place the eventual object is used and so free the user of
what, to it, is extraneous clutter.
Structural PatternsThese involve ways to
structure the design of a system. Their effect, amongst other things, is very
often to reduce coupling (dependencies) between classes that really have no
need to know about each other, and increase their individual cohesion.
Behavioural PatternsThese describe ways in which classes or objects can
interact and distribute responsibility sensibly.
Example pattern implementation: A Factory pattern
Factory method is a Creational pattern. It is used when there are several different sub-types of a particular class and
the decision which one to use is either non-obvious or should not be made by the user of the class.
This is a very basic version of Factory Method. The problem is that this system can use
one of any number of RDBMS', and each RDBMS requires a different bit of code to
actually access the database. Rather than put potentially lots of decision
logic about which RDBMS is being used in the main-line code of the client,
abstract this logic to a Factory class which returns one of a number of
compatible database manipulation classes.
Client Code:
GatewayDB db = GatewayDBFactory.DB();
string sql = "select count(*) from orders where rec-status <> 0";
DataSet ds = db.Select(sql);
GatewayDBFactory class:
public class GatewayDBFactory {
private GatewayDBFactory() { }
public static GatewayDB DB() {
string dbType = ConfigurationSettings.ApplicationSetting["DBType"];
string cs =
ConfigurationSettings.ApplicationSetting["GatewayConnectionString"];
switch (dbType) {
case "SQLServer":
return new GatewaySqlDB(cs);
case "Progress":
return new GatewayProgressDB(cs);
case ""ProgressV9":
return new GatewayProgressV9DB(cs);
case "Oracle":
return new gatewayOracleDB(cs);
default:
return null;
}
}
}
Abstract GatewayDB class:
public abstract class GatewayDB {
internal GatewayDB (string connectionString) {
this.connectionString = connectionString;
}
protected string connectionString;
public virtual DataSet Select(string sql);
public virtual void Execute(string sql);
}
Concrete DB ClassesThe concrete classes - GatewayProgressDB, GatewaySqlDB, etc - inherit from GatewayDB. They have internal constructors, so can only be created by the Factory class, or another class in
their namespace. Note that the same effect would have been achieved if instead
of using inheritance, an Interface had been used. In that case, the two
concrete classes would implement the interface rather than inherit and the
Factory Method would return the concrete class constructed as IGatewayDB.
Random Notes
Patterns apply to micro-architectures, not macro. The example
above is quite small; most implementations will take up more code, but each one
will not be a significant part of the size of a system. Occasionally in
comp.software.patterns someone posts something like "I am writing an Accounting
system. Does anyone have a good pattern for this?" The only possible answer to
this is "Ha ha ha!".
Apart from actually solving some problems in the design of
a program, Patterns provide a vocabulary to talk about the structure of a
system. If someone says something like "The appropriate database wrapper is
given by a Factory" then I know to expect code very similar to the example
above; if I see a class called CustomerFactory then I know to expect there to
be several different types of Customer classes in the system and that choosing
the correct one is not trivial; and so on. This aspect of the value of patterns - as a method os communication about the design - is sometimes not stressed enough.
The language you write in affects not only the
implementation of individual patterns, but also sometimes whether a pattern is
visible at all. VB6 Forms, for example, uses the Observer pattern extremely
heavily but any mention of it is redundant as, well, that's how VB Forms work.
Similarly, C# and Java implementations of Observer will be different as one
might use Delegates and the other might use anonymous inner classes.
It is perfectly possible to write excellent software without using any Patterns at all, but you
cut yourself off from distilled experience and some easy communication if you
do. If you come up with some neat structure to solve a given problem, good for
you! But it's not a pattern�yet. A pattern must have been used in at least two
systems for it to be a real pattern � after all, it might just have been a
super-cool solution applicable only to the one instance of the problem. The
essence is repeatability.
References
http://hillside.net/patterns/ Lots of links, and some useful information
The Portland Pattern repository
The original Wiki site, which started off talking mostly about Patterns, but started to
rapidly digress about 4 years ago.
Brad Appleton's web site. Lots of good � or at least provocative � information about
software development, including
this and
this about patterns
Robert C Martin, at ObjectMentor, has a number of very good things,
not least being this
which goes through a design, applies patterns to it, and sees what comes out at
the end.
Books There are many, many, books about Patterns and I have read very
few of them. My recommendations below are not exclusively about
Design Patterns but are in the same sort of area which I found very
useful. I would avoid books which slavishly translate the GoF book to your
favourite language; the ones I've looked at miss out enough to make the Gof book necessary anyway,
and once you've understood it you won't need it translated anyway. Google has enough examples available.
The GoF book goes without saying.
Martin Fowler's books include UML Distilled, the best introduction to UML which helps talk about OO designs, Analysis Patterns about - yes! - patterns in analysis, and Patterns of Enterprise Application Architecture.
Not required reading, but quite interesting. Applying UML and Patterns by Craig Larman. I think it's an excellent book. He uses "Patterns"
with a slightly different meaning, and you won't really learn much about UML,
but well worth a read in any case.
Return to top
|
|