Лучшая техника инкапсуляции

У меня есть этот класс:

class Mail
{
private $content;
private $from;
private $to;
private $subject;

public function __construct($content, $from, $to, $subject)
{
$this->content = $content;
$this->from = $from;
$this->to = $to;
$this->subject = $subject;
}
}

В какой-то момент я хотел бы отправить объект почты. Контент может быть оформлен с помощью html + css, возможны другие модификации перед отправкой. Есть разные почтовые провайдеры, которые я могу использовать. Какой вариант будет лучше:

class Mail
{
// ...

public function mail(MailProvider $provider)
{
$provider->send($content, $subject, $to, $from);
}
}

а потом:

$mail = new Mail(/* Parameters */);
$mail->send(new Mailjet());

Или просто добавьте геттеры в класс Mail и затем выполните:

$mail = new Mail(/* Parameters */);
$mailProvider = new Mailjet();
$mailProvider->send($mail->getContent(), $mail->getFrom /* etc */);

0

Решение

А как насчет других сообщений? Что если вы хотите отправить контент и тему в виде текста?

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

Эти принципы помогают продвигать мысль о том, «как может измениться приложение, и когда оно изменится, какой код нужно будет изменить», с целью изменения как можно меньше и с минимальной когнитивной нагрузкой, насколько это возможно. , необходимо выполнить изменение.

Вообще первый вариант кажется ненужной связью. Почтовый объект должен понимать, как использовать поставщика? Это строго необходимо? Чтобы добавить поставщика, нам, возможно, придется изменить Mail объекты mail метод. (т.е. если поставщик send нужны дополнительные параметры.

В то время как второй вариант устраняет 1 степень связи и требует только, чтобы поставщик мог работать с сообщением. Добавление поля сообщения или наличие метода отправки провайдером с меньшей вероятностью потребует изменения почты.

Какой вариант делает его максимально простым для клиента (клиент может быть самим собой :)) Субъективно я думаю, что второй вариант делает то, что позволяет «почтовой» команде работать независимо от команды интеграции, и требует только того, чтобы команда mailjet знает, что получит «почтовый» интерфейс, если это вообще имеет смысл …

1

Другие решения

Спросите себя: какова ответственность каждого объекта? Тогда ответ становится несколько самоочевидным.

  • Mail: представляет собой почтовое сообщение (акцент на представляет собой)
  • Mailjet: содержит код, специфичный для связи с внешним сервисом

Из этого описания ни один класс не должен содержать код Отправить почта. То, что вы, вероятно, хотите, это третий класс:

  • MailSender: принимает Mail и отправляет его, используя определенный сервис

Примерно набросал:

interface Mail {
public function getContent();
...
}

interface MailServiceAdapter {
public function send($content, $from, ...);
}

interface MailSender {
public function send(Mail $mail);
}

class MailSenderImplementation implements MailSender {
public function __construct(MailServiceAdapter $adapter) { ... }
...
}
1

По вопросам рекламы [email protected]