Бортовой журнал Ктулху

Пример паттерна "фасад"

Любой уважающий себя программист просто обязан рассказать как он легко оперирует паттернами, а я как-то совершенно упускаю эту тему и совершенно ничем не оперирую. Хотя, если окунуться в омут кода, то парочку примеров таки можно найти - к гадалке не ходи.

В условиях постоянно модифицирующегося ПО с регулярными перестройками в угоду рыночным тенденциям, которое дорабатывается в момент появления необходимости нет почти никакой возможности заранее что-то архитектурно спрогнозировать.

Сегодня, к примеру, нужно просто отправлять клиентам емейлы при совешении каких-то действий, завтра емейлы уже неактуальны и все сидят в телеге, послезавтра нужно будет транслировать мысли прямо в мозг.

Когда сначала был простой магазин и в скрипте оформления вызывался метод email все было просто. Когда добавилась CRM и появились подписки на проверку наличия товара, отправка почты стала происходить в разных местах.

2022 12 01 13.37.17

Получилась система неудобная в поддержке. Теперь при добавлении какой-то фичи надо править в трех местах.

Если расширить функционал и отправлять еще и СМС, придется править в шести местах. Ну это если прогеру Уасе не надавать по ушам. Если надавать, то править придется всего в двух местах. А если повысить ему зарплату, то Уася станет мидлом, нахватается экспириенса и получит левел-ап и задействует какой-нибудь паттерн программирования, который все упростит в будущем.

Например, когда я писал систему отправки сообщений через разные каналы, то реализовал паттерн «Фасад». Но к этому пришел не сразу.
Сначала был простой класс отправки почты, который отправляет письмо покупателю. Со временем появились пользователи, которым нужно отправить эти данные через смс. Также, возможно что скоро появятся клиенты, которым нужно отправлять сообщения на вайбер, телеграм и пушап.
Прикручивать switch\case и четыре класса? Это же детский сад.

Пришло время сделать простой интерфейс для всего этого зоопарка, принимающий стандартный запрос типа «сообщение\получатель». А что там за пределами интерфейса не должно волновать пользователя этого интерфейса.
Таким образом, уже получается так:

2 2022 11 28 10.11.39

Если хотим, что бы емейл отправлялся даже если апокалипсис накроет какого-либо провайдера, то к классу емейлов можно добавить субклассы с отдельными провайдерами почты, например Гугл, MailChimp и какой-нибудь свой собственный SMTP сервер, который стоит под столом бухгалтерши Мариночки.

То же самое и с СМС, будем использовать несколько провайдеров.

А потом еще и с мессенджерами такая же петрушка.

Хорошо, что я сделал специальный фасад, работающий с 2-3 передаваемыми параметрами. А если бы делал вызовы напрямую, то пришлось бы в каждом скрипте добавлять туеву кучу классов со свитчами и при любом изменении в логике отправке пришлось бы переписывать кучу кода.

3 2022 11 28 10.30.45

Разработчик CRM проклянет разработчика отправщика уведомлений в таком случае.

Первый, в таком случае, отправит на указанный интерфейс %Покупатель% + %товар% и больше его ничего не волнует, а второй разраб примет запрос и отправит в необходимую ветку логики и все довольны.

И небольшой пример псевдокода, где есть класс-обертка для нескольких классов с различной бизнес-логикой

class email
{
public function sendEmail() {}
private function connectToGmail() {}
}

class sms
{
 public function sendSMS() {}
private function connectVodafone() {}
}
class telegram
{
 public function sendMessage() {}
private function connetToTelegaApi() {}
}
class anySend
{
 public function __costruct($recipient, $message ) {
switch ($recipient){
 // obtain contact type
 }
 }
 
 public function send()
 {
 // select channel, recipient
 }
}