While working on a project, it is crucial to remember that you do not want to reinvent the wheel. If a solution for a problem is proved to be effective, reusing it will save you tons of time and a few headaches. In case of system architecture dilemmas, we have developed some patterns to ease a design process.
What is a design pattern?
A design pattern is a conceptual model that helps you solve design problems in various contexts. It is like a reusable template you can apply to a structuring code. The thing is, design patterns are well-documented, well-proven and commonly known. In other words, use a proper design pattern and be sure that other design pattern insiders (aka your coworkers) will get the hang of your ideas smoothly.
Eager to learn? Here comes the Strategy Design Pattern.
The strategy design pattern:
– defines a family of algorithms,
– implements each of the algorithms as a separate entity,
– allows each of the algorithms to be used interchangeably in a given context.
Real life example? Authentication
In one of our apps we have implemented a few strategies for authenticating requests. We allow authentication with cookies, JWT tokens and API keys. Sounds like a family of algorithms to me.
Let’s have a look at a sample implementation.
We have our family of authentication algorithms divided into three separate classes. Each class defines the concrete behavior; it is where all the implementation details go:
module AuthenticationStrategies class CookiesAuthentication def self.authenticate_request(request) puts "I implement a cookie authentication algorithm" end end
class JWTAuthentication def self.authenticate_request(request) puts "I implement a jwt authentication algorithm" end end
class ApiKeyAuthentication def self.authenticate_request(request) puts "I implement an api key authentication algorithm" end end end
Then, we have a context/client class:
class Authentication def self.authenticate(authentication_strategy, request) authentication_strategy.authenticate_request(request) end end
request = "I pretend to be a request"
Authentication.authenticate(AuthenticationStrategies::CookiesAuthentication, request) Authentication.authenticate(AuthenticationStrategies::JWTAuthentication, request) Authentication.authenticate(AuthenticationStrategies::ApiKeyAuthentication, request)
The above script outputs:
I implement a cookie authentication algorithm
I implement a jwt authentication algorithm
I implement an api key authentication algorithm
Summing it up
– design patterns are useful tools for solving architectural problems,
– knowledge of design patterns improves communication on system architecture with other developers,
– the Strategy Design Pattern suits your needs if you have a bunch of algorithms that can be used interchangeably in a given context.