SOLID : Open/Closed Principle (OCP)
Objectif : Une classe peut-être ouverte pour l'ajout ou l'extension mais fermée pour la modification
On peut y ajouter des fonctionnalités mais doit éviter la surcharge et la modification de code existant.
Remarque : En Ruby, la possibilité de sucharge se fait aussi bien via l'héritage que par le mixin ou l'inclusion, donc il s'agit d'une vigilence spécifique
Anti-pattern
class PushManager
def initialize(medium: "email")
end
def send(content: )
if medium == "email"
# send by email
elsif medium == "sms"
# send by sms
else
raise "Medium unavailable"
end
end
end
🔴 Problème : Chaque fois qu'on veut ajouter un nouveau medium il faut modifier la Classe PushManager
🔴 Autre problème : l'usage d'une structure de controle dans ce cas n'est pas souhaitable, une map/hashage serait plus adaptée
Rubyway : l'usage deString
et non deSymbol
pour identifier le medium n'est pas optimum, uneString
n'est pas unique, unSymbol
si.
Pattern
class Pusher
def initialize(content:)
@content = content
end
def send
raise NotImplementedError, "Must be implemented in a subclass"
end
class EmailPusher < Pusher
def send
# send by mail
end
end
class SMSPusher < Pusher
def send
# send by SMS
end
end
class PushManager
def self.send(content:, medium: EmailPusher)
medium::new(content: content).send
end
end
# usage
data = "......"
PushManager.send content: data, medium: SMSPusher
Maintenant on peut instancier un nouveau type dePusher
sans modifier lePushManager
Remarque : on ne juge pas de la qualité d'un code à sa concision
Remarque : la méthode::send
dePushManager
est une méthode de classe