Design Patterns use Abstraction Effectively
Outline
Introduction to abstraction
Visualize Abstraction
Importance of abstraction in software design
Introduction to Design Patterns
How Design Patterns uses abstraction
Takeaway
Abstraction
It is an act of representing the essentials and hiding unnecessary details from the client. Every day we use different applications on our phones, but we do not care about the internal details of how an application transfers bits over communication media.
You have probably used open-source packages or modules or libraries while working on your project. You don't care about the internal details of the package until you have a specific special case. Abstraction is everywhere, using inbuilt modules and functions in the operating system or any software framework or library, client and server communication, and building scalable infrastructure.
In general, we do not focus on adding the right level of abstraction when programming. Consequently, We will write tightly coupled and less cohesive code. In simpler terms, it costs a lot of money to cope with changes in the future.
Imagine your project manager asking you for an estimate for adding a payment gateway to your backend services for the first time. After a week, he comes up with the brilliant idea of adding another payment gateway and this time he expects a lower estimate than the first time, believing that every developer has an innate talent for good software design. It takes longer than earlier if you don't have the right level of abstraction in implementation.
Visualize Abstraction
We can achieve abstraction by adding extra layers between two entities. We do this because we want to make both entities replaceable without them knowing each other.
Imagine you are in your favorite restaurant and you order your favorite dish. The waiter takes your order and asks the chef to prepare the food. Let us imagine for a moment that the waiter is an abstraction between you and the chef. You care about how the food is prepared. Also, the chef is not interested in knowing who the customer is and to whom the order belongs. In this case, because of the abstraction between them, both the customer and the Chef are replaceable without knowing each other.
In software development, we achieve this by using an interface or abstract class between two classes or objects. The following diagram illustrates how we achieve this.
Abstraction in software design
In software design, we break down applications into several smaller components to reduce complexity. Efficient design simplifies maintenance and increases extensibility. The cost of managing change is higher than developing features from scratch in poorly designed software. Adding a High level of abstraction also makes it difficult to understand. A balanced level of abstraction between components can save a lot of money.
Introduction to Design Patterns
Design patterns are the solution to a common problem often encountered in the development of modern software applications. The solution explains relationships, interactions and responsibilities of objects and classes. It is a template that does not prescribe strict rules that must be applied. The main goal is to manage change in the future with less effort.
In a nutshell, Design patterns also explain solutions by providing the right amount of abstraction in between the interaction, relationship and responsibilities of objects and classes.
Types of Design Patterns
It's easy to confuse the differences between the various design patterns. They're distinguished by Purpose and Scope. Purpose reflects what a pattern does, and scope can be at the class or object level. The categorization of design patterns on this basis can be seen in the following diagram.
Let's define some vocabulary before getting into further detail.
Client: Any method or function uses to fulfill any task
Interface: Interface is an abstraction between a client and a concrete class or object. Java developer maps it to the interface and Python developer can consider it as an Abstract class.
Concrete: Any class or object
Creational
In your application, several similar objects will work together to complete a function. If we create instances of the concrete class directly where we need them, changes to the concrete class will affect wherever it was used. When we have a common place to instantiate objects, we can more easily reuse and extend them.
Creational design patterns provide several effective solutions for creating instances. An interface creates an abstraction between the client and the complex instance creation logic. Creational design patterns are divided into the following subtypes depending on their purpose and scope.
Class Scope
Class creational pattern deals with class instantiation.
- Factory Method
Object Scope
Object creational pattern deals with object creation
Abstract Factory
Builder
Prototype
Singelton
Structural
In object-oriented design, we can establish relationships between different classes through inheritance and composition. Composition is preferred over inheritance to avoid the complexity introduced by multi-level inheritance or the diamond problems associated with multiple inheritances. Structural design patterns introduce various ways in which the relationship between objects can be realized. It is also divided into the following.
Class Scope
- Adapter (Class)
Object Scope
Adapter (Object)
Bridge
Composite
Decorator
Facade
Flyweight
Proxy
Behavioral
In object-oriented design, we can use methods or functions to interact between objects. Behavioral patterns introduce different ways of interaction/communication between objects. It is also divided into the following categories.
Class Scope
Interpreter
Template Method
Object Scope
Chain of Responsibility
Command
Iterator
Mediator
Momento
Observer
State
Strategy
Visitor
How Design Patterns uses abstraction
Design patterns also use the right level of abstraction between relationship and interaction/communication to present a solution. Therefore, solutions presented by design patterns are extensible and reusable.
Takeaway
As developers, we should focus on adding abstraction early on. The right amount of abstraction can save future effort. Design patterns use abstraction effectively to solve common problems.
PS. Design patterns are explained briefly to shorten the article. Commonly used design patterns will be covered in the next articles.
References
Design Patterns: Elements of Reusable Object-Oriented Software
Subscribe to my newsletter
Read articles from Rajesh Khadka directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Rajesh Khadka
Rajesh Khadka
I am a developer from Nepal and currently living in Paris. I have spent more than 8 years in software development (backend + mobile). Currently, I am focusing on developing large applications using Python. I have experience working with popular web frameworks: Flask, FastAPI, Django to develop backend services. I have mainly worked with start-up companies. I have been involved in building and mentoring a backend team in a startup. I helped turn an initial idea into a revenue-generating product.