Choosing a PHP Design Pattern: Part I—Selection Criteria

PickDP Which Design Pattern?

One of the most persistent questions that I get is, How do you select a Design Pattern?, and usually, my response is, Decide what varies and see which pattern handles that variation. Of course, you will find that lots of things vary, and deciding which one to build a design pattern around can be tricky. Furthermore, GoF have lots more to say about how to go about choosing a design pattern than just encapsulating variation. This series will cover the different criteria so that we can get a complete picture of the selection process.

Gamma, Helm, Johnson and Vlissides (aka Gang of Four) provide six criteria for making a selection (pp.28-30). They include:

  • Consider how design patterns solve design problems
  • Scan Intent sections
  • Study how patterns interrelate
  • Study patterns of like purpose
  • Examine a cause of redesign
  • Consider what should be variable in your design

Many of the selection solutions that GoF offer are simply references to a part of their book that discusses what design patterns do (which you may not have yet read), and so I’m going to try and summarize each of these criteria. That may result in an oversimplification, and you’re welcome to point out any such misstep I make and set me straight if you believe that a summarized explanation is too terse. (Better yet, go over pp. 11-31 and read all of the detail yourself.)

Consider how design patterns solve design problems

Section 1.6 (pp. 11-28) of Design Patterns is laden with major concepts and information about design pattern use as a strategy for solving design problems in programming. The foundation in finding an appropriate object is the idea that,

objects package both data and procedures that operate on data, and the only way that an object performs an operation is when it receives a request from a client.

Implied in that idea is that an objects’s internal states are encapsulated. You know what that is, and so we can move on to the central OOP issue of decomposing a system into objects. How do you do that? It’s not easy because you have so many factors to consider (some of which may be conflicting) in the decomposition process.

Figure 1: Breaking down complexity into simple parts

Figure 1: Breaking down complexity into simple parts

So what is the decomposition process? Basically, it’s breaking down a complex problem down into smaller, more manageable units—in the case of PHP design patterns, classes, (objects). At the root of all English literature is the alphabet. (See Figure 1) The degree to which you decompose a task refers to its granularity. Breaking down the works of Shakespeare can have different levels of granularity. For example all of Shakespeare’s works can be broken down into plays, plays into acts, acts into scenes, scenes into paragraphs, paragraphs into sentences, sentences into words, and finally words into letters of the alphabet. The degree of granularity depends on what you need. Understanding the alphabet will not help you understand much about Shakespeare, but if you don’t know the alphabet, you cannot read his plays, sonnets and poems. (See Object Granularity below).

Beginning with the problem (e.g., How to make a sniffer, how to create a UI for an online store, how securely store and retrieve data), you have to decide the way in which you want to break it down. (It’s not going to break itself down!) The only thing that has ever worked for me is knowing exactly what I want to do. In other words, you need some serious understanding of the problem itself. So even before you begin to work through the decomposition process, you need to study the project you want to complete. The OOP process for decomposition has different approaches:

  • Write a problem statement and create classes and operations from nouns and verbs in the statement.
  • Focus on the collaborations and responsibilities in the system (problem you’re trying to solve).
  • Model the real world and translate the objects found during analysis into design.

At one time or another, I’ve used all of these approaches, and they all work. Usually, I find myself going between them, combining them—shaking the box with the problem inside to see how things settle at the bottom. However, it’s difficult to provide a generic case, and so I’ll provide two cases that I actually worked through.

Mobile Device Sniffer: When it became clear that mobile devices are going to be a big part of how people get information on the Internet, I made a sniffer. I was concerned with the following realities:

  1. multiple viewing devices
  2. rapid change that would have to be incorporated as new mobile devices were introduced
  3. different groupings of devices (e.g., desktop, tablet, mobile phone)
  4. ease of update and change

The decomposed sniffer is a series of actions; so I want to make encapsulated objects of each. The client requests that the player performs the different operations.

Help Desk: I wanted something more than an FAQ; so I decided to build an automated Help Desk. The decomposition process led to the following breakdown based on the question,

What does a Help Desk do?

  1. Explain a process
  2. Show where to find an operation
  3. Clarify a procedure
  4. Provide an example

However, each of these processes have to address one of several topic areas, and so I decided that each topic area would be divided into the four tasks. The Help Desk needed to be organized by topic area, and then each topic area would provide all “help” features. (I was tempted to include “Putting the person requesting help on hold” but resisted.)

Object Granularity

By object granularity, GoF are referring to the size and number of objects. The larger and fewer the classes, the less granularity. There’s not a whole lot of advice here from GoF other than that granularity depends on the nature of the general task (creation, structure, behavior). Most helpful is the fact that the design patterns themselves determine granularity. The Facade pattern has huge objects representing entire subsystems while the Flyweight is a pattern that supports a large number of finely granulated objects.

The the heart of granularity is the decomposition process. In a word,

…decomposition determines granularity.

Because the design patterns describe the decomposition process, they determine granularity. As far as deciding which design pattern to use, there’s a bit of a Catch 22 here—the granularity may help to see the most appropriate pattern, but since the pattern determines granularity, you may not know what the granularity will be until you’ve selected a pattern. (I don’t know about you, but statements like that make my brain bounce around the room like a balloon you blow up and let go without tying off.) Moving on….

Specifying Object Interfaces

Understanding interfaces is key to understanding design patterns in PHP (See pp. 23-29 in Learning PHP Design Patterns.) In PHP, you will find the keyword interface used to declare a new interface. That kind of interface is used in class diagrams and play key roles in design patterns. That’s not what I want to consider now.

As we noted in Learning PHP Design Patterns (p. 23), the term interface has many meanings, and GoF use it in all different ways. However, in considering how design patterns are determined,

interfaces are the set of all signatures defined by an object’s operations. The interface represents the full set of requests that can be sent to the object, and if a request matches an object’s signature in the interface, it can be sent to the object.

So what? What does this have to do with selecting a design pattern? It’s the foundation on which polymorphism rests and allows a request to be accepted by any object with the correct interface. In looking at the decomposed collection of objects, you must first think about them in terms of their relationship to one another, and to do that you must consider their interfaces.

At this stage, the decision-making process still rests on understanding the structures underlying OOP. Included in the mix is a clear understanding of objects, interfaces, classes, and inheritance. Along with these understandings you need to see how objects relate to one another.

Also, you may want to dig up the Design Pattern Variation and Intents Table for an overview of what design patterns you can choose from and key features of each pattern. In the next segment of this series, we’ll look at more of the design pattern selection criteria.


Copyright © 2013 William Sanders. All Rights Reserved.

0 Responses to “Choosing a PHP Design Pattern: Part I—Selection Criteria”

  • No Comments

Leave a Reply