Design Patterns in PHP
The article is an overview of design patterns in PHP, their importance, types, history, and criticism. Here are some quick bits from the article.
- A design pattern is a generic solution to recurring design problems.
- A good design’s top features are scalability, maintainability, and efficiency.
- A software system may perform the intended functionality correctly regardless of the design.
- Good design promotes scalability, flexibility, and maintainability.
- Three types of design patterns are Creational, Structural, and Behavioral.
- The Gang of Four (GoF) introduced design patterns in their book.
These are some quick facts, but we recommend you read the full article to understand thoroughly.
Table of Contents
- What is a design pattern
- What makes good software design
- Using design patterns in PHP
- Why use design patterns
- Types of design patterns
- criticisms of design patterns
- History of design patterns
- books on design patterns
What is a Design Pattern?
Computer programming is more than just learning syntax.
A considerable focus of computer programming is on problem-solving. Languages, frameworks, libraries, and other tools are there to help solve problems.
Though the problem statements can vary, there is usually a recurring pattern in many problems that seem apparently distinct. For instance – all the nested data structures may have recursive patterns. If you are efficient in applying recursion, you may be able to tackle virtually any problem involving such data structures.
That’s one effective way of problem-solving – identifying recurring patterns. That’s what the idea of design patterns is all about.
“A design pattern is a generic solution to recurring design problems.”
Design patterns are not algorithms.
Patterns are neither algorithms nor computer programs. They are not hard and fast programming rules either. You may not apply a design pattern, and your program will still run. Running a computer program is one thing and designing an efficient and scalable solution is another.
Design patterns are derived by experienced individuals who have been through design problems frequently occurring when designing an object-oriented software program. So, these patterns are a sort of observation and experience, general templates, and design decisions you can reuse in the right scenarios to develop better software systems.
But what is a good design in software development?
A well-designed software has some prime characteristics that set it apart from the bad ones. A good design’s top features are scalability, maintainability, and efficiency. Though there are other essential features that software must accomplish but from a design POV, these are the top three players.
Design patterns are a means to an end, meaning that they help us design scalable, efficient, and maintainable systems. Some fundamental ideas of modularity, decoupling, and interface programming are vital to good design. Thus, the patterns rely on these fundamentals and help us identify the right scenarios to engineer better solutions.
Good Design vs. Bad Design
Enough theory. Let’s look at a program that relies on a third-party Email service to send Emails. The visual below compare two software designs. Both of these accomplish the Email functionality. So, what’s the catch, then? Can you figure it out?
Well, the components are rightly connected. A client program calls an Email service and delegates email-sending functionality to it. That’s correct, isn’t it? But think for a while about what happens if.
- You need to switch to a new email service.
- You need to use more than one service and switch dynamically.
These are some changes that are highly likely to happen. A new Email service could be drastically different than the one you are using. Now, if your client program is tightly bound to the Email service implementation, you must make many changes in the client code.
It is not unusual to break things and introduce bugs while trying to make changes. This issue is escalated if someone else has developed it, and now you’re stuck with all the problems and bugs. The problem can be huge if many other components rely on the Email service. This design is undoubtedly a maintenance nightmare.
Besides, this design violates the Open-closed principle, which is one of the fundamental design principles and states that
‘A software should be open for extension but closed for modification.’
So, how to improve this design and build more scalable software?
So what’s up with the ‘<interface> SendEmail’? What difference does it make? Think of it as an abstraction. The client or any other code that needs Email functionality would call the interface function without worrying about the underlying Email services.
What’s the benefit of this abstraction? Other modules are not tightly coupled with the underlying Email service. The software is flexible, extendable, and maintainable. Need to change the Email service? Implement this interface in the new service, and the rest of the code will work fine. You don’t need to make any changes to the existing code.
Need to add more than one Email service? Implement this interface in other services, and you can dynamically switch them during runtime. Long short story, your modules see the interface only, and it doesn’t care about what Email services are and how they have been working.
Contrary to this design, the bad design had tightly coupled modules. The client code was highly dependent on the Email service. Therefore, any change to the Email service had a chain reaction on the rest of the program.
Design Patterns to the Rescue
We have seen a good design and a bad design. A fun fact is that regardless of the design, both programs could accomplish the user functionality of sending emails. The flaws are more apparent in the long run when change requests kick in, and maintenance activities are scheduled. Bad design can be a pain point at that moment.
Developers are often tempted to devise a solution without considering factors that can negatively impact the design and architecture. In software development, change is the only constant. Therefore, if your software is inflexible and resistant to change, it will cost you alot of time, effort, and money.
So, next time ask yourself these questions even if your software passes the functionality check.
Using Design Patterns in PHP
Design patterns are general templates and observations. They are not bound to a programming language. You can, however, apply them in any programming language of your choice. We will learn how to use design patterns in PHP in future articles. More scenario-oriented design patterns articles will follow this introductory article in PHP.
Why use Design Patterns
Though much has been clear about the usefulness of design patterns, the following are some essential summary points.
- Improves the software architecture using the tested design paradigms.
- Accelerates the development process by using patterns for recurring problems.
- Improves code readability and standardization.
- Implicitly employs best practices and design principles.
- Helps in knowledge sharing and process documentation.
- It makes the software system more scalable and maintainable.
Types of Design Patterns
Design Patterns are broadly categorized as follows.
- Creational Design Patterns
- Structural Design Patterns
- Behavioral Design Patterns.
Each of them has numerous design patterns. Let’s have a brief overview.
Creational Design Patterns
As the name suggests, Creational design patterns are concerned with class instantiation. We are familiar with the new keyword for creating objects of a class. While this may be an obvious way to instantiate an instance of a class, it is not always the most flexible.
The creational pattern uses object-oriented paradigms to delegate the instantiation.
- Abstract Factory
Uses abstraction to create instances of families of sub-classes.
Calls a method to construct a complex object step-by-step.
- Factory Method
Uses abstraction to create instances of sub-classes.
- Object Pool
Reuses objects from an existing pool.
Clones an existing object.
Creates a single global object.
Structural Design Patterns
Structural design patterns help in composing and building complex relationships between objects and classes to obtain new functionalities.
Adapt one interface to a different kind.
Uses abstraction to separate abstract and concrete classes.
Creates a tree structure to define hierarchies.
Uses decorator classes to add functionalities on the fly.
Uses shared states to use memory efficiently.
Provides a convenience class for complex sub-systems.
Uses an object to represent another.
- Private Class Data
Creates a class to limit data exposure.
Behavioral Design Patterns
Behavioral design patterns are concerned with communication between objects.
Encapsulates commands as objects.
- Chain of responsibility
Regulates the flow of data in a system.
Defines a class for iterating different traversable data structures.
Provides an interpreter class to deal with expressions in the program.
Memorizes a former state of an object for restoration purposes.
Uses a mediating class for simplified object communications.
Uses a change notification mechanism.
Encapsulates algorithms in a concrete class.
Alters an object’s behavior with changing state.
- Template Method
Defines a template of algorithms and functions for sub-classes to implement.
Defines new operations without modifying the existing classes.
History of Design Patterns
Patterns are a common phenomenon in many other fields of life. An architect, Christopher Alexander, first articulated the concept of using patterns in architecting buildings and infrastructure.
This idea became popular in software development because designing or engineering software is similar to designing a physical structure. Many attempts have been made to define various design principles and patterns.
The Gang of Four (GoF)
Erich Gamma, John Vlissides, Ralph Johnson, and Richard Helm are four authors commonly known as the Gang of Four (GoF). In 1994, they published Design Patterns: Elements of Reusable Object-Oriented Software, in which they introduced the design patterns idea in object-oriented software design.
They included around 23 patterns in their book and became popular in the dev circles. The same book by the GoF inspires the patterns we have included in this article.
Criticism of Design Patterns
Blaming the Programming Languages
Some developers think that design patterns are applicable in languages with low abstraction, for instance – C or C++. High-level and modern languages may not need any pattern because it comes with abstractions out of the box. So, most experts believe that it is an inherent problem with programming languages.
Overuse of Patterns
Some developers criticize the design patterns for unnecessarily increasing code complexity. At the same time, this is debatable because patterns are not supposed to be overused. They are best practices and not some hard-and-fast rules. Developers tend to use patterns unnecessarily, which compromises readability and efficiency most of the time.
No Formal Ground
Like any other engineering branch, software development is highly rational and algorithmic. It relies on standardization and a fixed set of rules. So, many people blame the GoF had no formal ground for publishing their work, and they were up for more general guidelines, which were not backed by any research.
Books on Design Patterns
Want to learn more about Design Patterns? There are many great resources online. We recommend the following books for your collection as they both can teach you the theoretical and the application of using design patterns in your day-to-day programming. Feel free to use the following Amazon affiliate links if you’d like to purchase them and a way to support our efforts.
This is the book that started it all. I believe that every programmer should have a referenced copy to this book at some point in their career. There have been many updates and excellent newer content through the years, but this is a classic. It still stands the test of time and is just as relevant for today as it was in the original printing in the 90s.
This is an excellent book to go beyond the theory and apply it to writing good PHP code. Learning PHP Design Patterns is published by the popular O’Reilly media company. O’Reilly consistently publishes some of the most useful reference material related to software development. They are known to provide materials that thoroughly cover a topic in a way that is simple to understand. I recommend this book to every PHP developer.
What are Design Patterns in PHP?
Design patterns in PHP are simply a collection of repetitions that have been discovered in well-written code that has been applied to this language. You shouldn’t feel obligated to map to these patterns. Instead, they are good guides and references as you write code to solve business and technical challenges.
PHP Object-Oriented Programming Learning Path
This article is part of our series on learning Object-oriented programming with PHP. It introduces some concepts, best practices and strategies to help you level up your skills. This is a great intro to growing into a successful programmer.
Design Patterns in PHP Learning Series.
This article is part of our series of design patterns in PHP. We are going through all of the patterns and showing how they can help you build better applications. Browse through our full list of patterns below.
- What are Design Patterns in PHP?
- Builder Design Pattern
- Strategy Design Pattern
- Factory Design Pattern
- Prototype Design Pattern
- Singleton Design Pattern
- Adapter Design Pattern
- Bridge Design Pattern
- Iterator Design Pattern
- Composite Design Pattern
- Decorator Design Pattern
- Facade Design Pattern
- Flyweight Design Pattern