design pattern for switching email providers in the code












0















We need to send emails in our php app (who doesn't). Initially when our app was in infancy, we used simply linux sendmail.
A bit moving forward we switched to our own SMTP server. That means code change in every file that has email related function.
A year later we shifted to AWS and had to change the code again to start using AWS email service.
Now we moved to Google cloud and again email code is changed to use some third party provider.



Configuration of email, is spread all over the places and changing one provider means hundreds of files need to be updated and if you miss one, clients may not be able to receive email for one part but can get emails for other.



I just took a step back and realized that we are changing code that makes no sense to change only because our email provider is changed.



But for the life of me I am unable to figure out what would be a way out of this mess.



All I need to do is to remove emailing from my code and refactor it in such a way that my app code can function independent of the mail service provider.



Her is my take on this



class EmailGateway()
{
private $emailer;
public function __construct($someEmailProvider)
{
$this->emailer = $someEmailProvider;
}

public function send($from, $to, $subject, $bodyText, $bodyHtml="")
{

this->emailer->send($from, $to, $subject, $bodyText, $bodyHtml="");
}
}


And then in my code all I need is to call it like



# Gmail?
$mailGateway = new EmailGateway(new GmailEmailer("username", "password"));

# local?
$mailGateway = new EmailGateway(new SendMailer());

# SMTP?
$mailGateway = new EmailGateway(new MyMailServerMailer("192.168.0.3", "no_user", "secret_password"));


In my app code, I can even go one step further and calla a factory to get the current default email provider



class EmailService()
{
public static function currentProvider(): EmailProviderInterface
{

return new MyMailServerMailer("192.168.0.3", "no_user", "secret_password");

}
}


That will make my above caller code even simpler one liner



# SMTP?/GMAIL?/Local?/Whatever
$mailGateway = new EmailGateway(EmailService::currentProvider());


So whenever I need to change the provider, all I will do is change the guts of currentProvider() and I am good to go.



Am I doing it the right way?
Is it a proper strategy pattern at all?
Should I even care about what pattern it is as long as it can solve my problem?



Is there a better way to pull myself out of this ever increasing mess?










share|improve this question





























    0















    We need to send emails in our php app (who doesn't). Initially when our app was in infancy, we used simply linux sendmail.
    A bit moving forward we switched to our own SMTP server. That means code change in every file that has email related function.
    A year later we shifted to AWS and had to change the code again to start using AWS email service.
    Now we moved to Google cloud and again email code is changed to use some third party provider.



    Configuration of email, is spread all over the places and changing one provider means hundreds of files need to be updated and if you miss one, clients may not be able to receive email for one part but can get emails for other.



    I just took a step back and realized that we are changing code that makes no sense to change only because our email provider is changed.



    But for the life of me I am unable to figure out what would be a way out of this mess.



    All I need to do is to remove emailing from my code and refactor it in such a way that my app code can function independent of the mail service provider.



    Her is my take on this



    class EmailGateway()
    {
    private $emailer;
    public function __construct($someEmailProvider)
    {
    $this->emailer = $someEmailProvider;
    }

    public function send($from, $to, $subject, $bodyText, $bodyHtml="")
    {

    this->emailer->send($from, $to, $subject, $bodyText, $bodyHtml="");
    }
    }


    And then in my code all I need is to call it like



    # Gmail?
    $mailGateway = new EmailGateway(new GmailEmailer("username", "password"));

    # local?
    $mailGateway = new EmailGateway(new SendMailer());

    # SMTP?
    $mailGateway = new EmailGateway(new MyMailServerMailer("192.168.0.3", "no_user", "secret_password"));


    In my app code, I can even go one step further and calla a factory to get the current default email provider



    class EmailService()
    {
    public static function currentProvider(): EmailProviderInterface
    {

    return new MyMailServerMailer("192.168.0.3", "no_user", "secret_password");

    }
    }


    That will make my above caller code even simpler one liner



    # SMTP?/GMAIL?/Local?/Whatever
    $mailGateway = new EmailGateway(EmailService::currentProvider());


    So whenever I need to change the provider, all I will do is change the guts of currentProvider() and I am good to go.



    Am I doing it the right way?
    Is it a proper strategy pattern at all?
    Should I even care about what pattern it is as long as it can solve my problem?



    Is there a better way to pull myself out of this ever increasing mess?










    share|improve this question



























      0












      0








      0








      We need to send emails in our php app (who doesn't). Initially when our app was in infancy, we used simply linux sendmail.
      A bit moving forward we switched to our own SMTP server. That means code change in every file that has email related function.
      A year later we shifted to AWS and had to change the code again to start using AWS email service.
      Now we moved to Google cloud and again email code is changed to use some third party provider.



      Configuration of email, is spread all over the places and changing one provider means hundreds of files need to be updated and if you miss one, clients may not be able to receive email for one part but can get emails for other.



      I just took a step back and realized that we are changing code that makes no sense to change only because our email provider is changed.



      But for the life of me I am unable to figure out what would be a way out of this mess.



      All I need to do is to remove emailing from my code and refactor it in such a way that my app code can function independent of the mail service provider.



      Her is my take on this



      class EmailGateway()
      {
      private $emailer;
      public function __construct($someEmailProvider)
      {
      $this->emailer = $someEmailProvider;
      }

      public function send($from, $to, $subject, $bodyText, $bodyHtml="")
      {

      this->emailer->send($from, $to, $subject, $bodyText, $bodyHtml="");
      }
      }


      And then in my code all I need is to call it like



      # Gmail?
      $mailGateway = new EmailGateway(new GmailEmailer("username", "password"));

      # local?
      $mailGateway = new EmailGateway(new SendMailer());

      # SMTP?
      $mailGateway = new EmailGateway(new MyMailServerMailer("192.168.0.3", "no_user", "secret_password"));


      In my app code, I can even go one step further and calla a factory to get the current default email provider



      class EmailService()
      {
      public static function currentProvider(): EmailProviderInterface
      {

      return new MyMailServerMailer("192.168.0.3", "no_user", "secret_password");

      }
      }


      That will make my above caller code even simpler one liner



      # SMTP?/GMAIL?/Local?/Whatever
      $mailGateway = new EmailGateway(EmailService::currentProvider());


      So whenever I need to change the provider, all I will do is change the guts of currentProvider() and I am good to go.



      Am I doing it the right way?
      Is it a proper strategy pattern at all?
      Should I even care about what pattern it is as long as it can solve my problem?



      Is there a better way to pull myself out of this ever increasing mess?










      share|improve this question
















      We need to send emails in our php app (who doesn't). Initially when our app was in infancy, we used simply linux sendmail.
      A bit moving forward we switched to our own SMTP server. That means code change in every file that has email related function.
      A year later we shifted to AWS and had to change the code again to start using AWS email service.
      Now we moved to Google cloud and again email code is changed to use some third party provider.



      Configuration of email, is spread all over the places and changing one provider means hundreds of files need to be updated and if you miss one, clients may not be able to receive email for one part but can get emails for other.



      I just took a step back and realized that we are changing code that makes no sense to change only because our email provider is changed.



      But for the life of me I am unable to figure out what would be a way out of this mess.



      All I need to do is to remove emailing from my code and refactor it in such a way that my app code can function independent of the mail service provider.



      Her is my take on this



      class EmailGateway()
      {
      private $emailer;
      public function __construct($someEmailProvider)
      {
      $this->emailer = $someEmailProvider;
      }

      public function send($from, $to, $subject, $bodyText, $bodyHtml="")
      {

      this->emailer->send($from, $to, $subject, $bodyText, $bodyHtml="");
      }
      }


      And then in my code all I need is to call it like



      # Gmail?
      $mailGateway = new EmailGateway(new GmailEmailer("username", "password"));

      # local?
      $mailGateway = new EmailGateway(new SendMailer());

      # SMTP?
      $mailGateway = new EmailGateway(new MyMailServerMailer("192.168.0.3", "no_user", "secret_password"));


      In my app code, I can even go one step further and calla a factory to get the current default email provider



      class EmailService()
      {
      public static function currentProvider(): EmailProviderInterface
      {

      return new MyMailServerMailer("192.168.0.3", "no_user", "secret_password");

      }
      }


      That will make my above caller code even simpler one liner



      # SMTP?/GMAIL?/Local?/Whatever
      $mailGateway = new EmailGateway(EmailService::currentProvider());


      So whenever I need to change the provider, all I will do is change the guts of currentProvider() and I am good to go.



      Am I doing it the right way?
      Is it a proper strategy pattern at all?
      Should I even care about what pattern it is as long as it can solve my problem?



      Is there a better way to pull myself out of this ever increasing mess?







      php design-patterns refactoring strategy-pattern






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 20 '18 at 2:34







      Waku-2

















      asked Nov 20 '18 at 2:12









      Waku-2Waku-2

      309213




      309213
























          1 Answer
          1






          active

          oldest

          votes


















          1














          Yes, basically you are doing right -- given your objective of easily modifying code when you need to change the mail provider.



          However, you can make your design simpler and better.



          Look into the EmailGateway class: it does not do any significant thing. It has the same interface with the EmailProvider and merely delegates the send task to the EmailProvider.



          So you could just have an interface named EmailProvider -- I'm using Java but it should be easy to translate to PHP:



          interface EmailProvider {
          void send(String from, String to, String subject, String bodyText, String bodyHtml);
          }


          And then several implementations:



          class GoogleEmailProvider implements EmailProvider {
          public GoogleEmailProvider (String username, String password) {
          ...
          }
          public void send(String from, String to, String subject, String bodyText, String bodyHtml) {
          ...
          }
          }
          // and so on ...


          At the CompositionRoot of your application (like the main method), you simple create one instance of the EmailProvider that you need:



          EmailProvider emailProvider = new GoogleEmailProvider("username", "password");


          Then you can pass that instance to anywhere that needs to send emails:



          Foo foo = new Foo(emailProvider);


          This design offers some benefits. First, it is easier to unit test the classes like Foo. You can always write a MockEmailProvider and pass it to Foo. Second, users of classes like Foo should be easily aware that Foo can send emails just by looking on its signature. Sending email, doing IO/Database/Network ... are significant things and should always be well-aware.



          Hope this helps.






          share|improve this answer


























          • Thanks for a very detailed answer. Just needed the confirmation that I am on a right path. Removing Gateway did help to further simplify the design. thanks

            – Waku-2
            Nov 20 '18 at 11:21











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53385248%2fdesign-pattern-for-switching-email-providers-in-the-code%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          Yes, basically you are doing right -- given your objective of easily modifying code when you need to change the mail provider.



          However, you can make your design simpler and better.



          Look into the EmailGateway class: it does not do any significant thing. It has the same interface with the EmailProvider and merely delegates the send task to the EmailProvider.



          So you could just have an interface named EmailProvider -- I'm using Java but it should be easy to translate to PHP:



          interface EmailProvider {
          void send(String from, String to, String subject, String bodyText, String bodyHtml);
          }


          And then several implementations:



          class GoogleEmailProvider implements EmailProvider {
          public GoogleEmailProvider (String username, String password) {
          ...
          }
          public void send(String from, String to, String subject, String bodyText, String bodyHtml) {
          ...
          }
          }
          // and so on ...


          At the CompositionRoot of your application (like the main method), you simple create one instance of the EmailProvider that you need:



          EmailProvider emailProvider = new GoogleEmailProvider("username", "password");


          Then you can pass that instance to anywhere that needs to send emails:



          Foo foo = new Foo(emailProvider);


          This design offers some benefits. First, it is easier to unit test the classes like Foo. You can always write a MockEmailProvider and pass it to Foo. Second, users of classes like Foo should be easily aware that Foo can send emails just by looking on its signature. Sending email, doing IO/Database/Network ... are significant things and should always be well-aware.



          Hope this helps.






          share|improve this answer


























          • Thanks for a very detailed answer. Just needed the confirmation that I am on a right path. Removing Gateway did help to further simplify the design. thanks

            – Waku-2
            Nov 20 '18 at 11:21
















          1














          Yes, basically you are doing right -- given your objective of easily modifying code when you need to change the mail provider.



          However, you can make your design simpler and better.



          Look into the EmailGateway class: it does not do any significant thing. It has the same interface with the EmailProvider and merely delegates the send task to the EmailProvider.



          So you could just have an interface named EmailProvider -- I'm using Java but it should be easy to translate to PHP:



          interface EmailProvider {
          void send(String from, String to, String subject, String bodyText, String bodyHtml);
          }


          And then several implementations:



          class GoogleEmailProvider implements EmailProvider {
          public GoogleEmailProvider (String username, String password) {
          ...
          }
          public void send(String from, String to, String subject, String bodyText, String bodyHtml) {
          ...
          }
          }
          // and so on ...


          At the CompositionRoot of your application (like the main method), you simple create one instance of the EmailProvider that you need:



          EmailProvider emailProvider = new GoogleEmailProvider("username", "password");


          Then you can pass that instance to anywhere that needs to send emails:



          Foo foo = new Foo(emailProvider);


          This design offers some benefits. First, it is easier to unit test the classes like Foo. You can always write a MockEmailProvider and pass it to Foo. Second, users of classes like Foo should be easily aware that Foo can send emails just by looking on its signature. Sending email, doing IO/Database/Network ... are significant things and should always be well-aware.



          Hope this helps.






          share|improve this answer


























          • Thanks for a very detailed answer. Just needed the confirmation that I am on a right path. Removing Gateway did help to further simplify the design. thanks

            – Waku-2
            Nov 20 '18 at 11:21














          1












          1








          1







          Yes, basically you are doing right -- given your objective of easily modifying code when you need to change the mail provider.



          However, you can make your design simpler and better.



          Look into the EmailGateway class: it does not do any significant thing. It has the same interface with the EmailProvider and merely delegates the send task to the EmailProvider.



          So you could just have an interface named EmailProvider -- I'm using Java but it should be easy to translate to PHP:



          interface EmailProvider {
          void send(String from, String to, String subject, String bodyText, String bodyHtml);
          }


          And then several implementations:



          class GoogleEmailProvider implements EmailProvider {
          public GoogleEmailProvider (String username, String password) {
          ...
          }
          public void send(String from, String to, String subject, String bodyText, String bodyHtml) {
          ...
          }
          }
          // and so on ...


          At the CompositionRoot of your application (like the main method), you simple create one instance of the EmailProvider that you need:



          EmailProvider emailProvider = new GoogleEmailProvider("username", "password");


          Then you can pass that instance to anywhere that needs to send emails:



          Foo foo = new Foo(emailProvider);


          This design offers some benefits. First, it is easier to unit test the classes like Foo. You can always write a MockEmailProvider and pass it to Foo. Second, users of classes like Foo should be easily aware that Foo can send emails just by looking on its signature. Sending email, doing IO/Database/Network ... are significant things and should always be well-aware.



          Hope this helps.






          share|improve this answer















          Yes, basically you are doing right -- given your objective of easily modifying code when you need to change the mail provider.



          However, you can make your design simpler and better.



          Look into the EmailGateway class: it does not do any significant thing. It has the same interface with the EmailProvider and merely delegates the send task to the EmailProvider.



          So you could just have an interface named EmailProvider -- I'm using Java but it should be easy to translate to PHP:



          interface EmailProvider {
          void send(String from, String to, String subject, String bodyText, String bodyHtml);
          }


          And then several implementations:



          class GoogleEmailProvider implements EmailProvider {
          public GoogleEmailProvider (String username, String password) {
          ...
          }
          public void send(String from, String to, String subject, String bodyText, String bodyHtml) {
          ...
          }
          }
          // and so on ...


          At the CompositionRoot of your application (like the main method), you simple create one instance of the EmailProvider that you need:



          EmailProvider emailProvider = new GoogleEmailProvider("username", "password");


          Then you can pass that instance to anywhere that needs to send emails:



          Foo foo = new Foo(emailProvider);


          This design offers some benefits. First, it is easier to unit test the classes like Foo. You can always write a MockEmailProvider and pass it to Foo. Second, users of classes like Foo should be easily aware that Foo can send emails just by looking on its signature. Sending email, doing IO/Database/Network ... are significant things and should always be well-aware.



          Hope this helps.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 20 '18 at 5:03

























          answered Nov 20 '18 at 4:05









          Nghia BuiNghia Bui

          1,453813




          1,453813













          • Thanks for a very detailed answer. Just needed the confirmation that I am on a right path. Removing Gateway did help to further simplify the design. thanks

            – Waku-2
            Nov 20 '18 at 11:21



















          • Thanks for a very detailed answer. Just needed the confirmation that I am on a right path. Removing Gateway did help to further simplify the design. thanks

            – Waku-2
            Nov 20 '18 at 11:21

















          Thanks for a very detailed answer. Just needed the confirmation that I am on a right path. Removing Gateway did help to further simplify the design. thanks

          – Waku-2
          Nov 20 '18 at 11:21





          Thanks for a very detailed answer. Just needed the confirmation that I am on a right path. Removing Gateway did help to further simplify the design. thanks

          – Waku-2
          Nov 20 '18 at 11:21


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53385248%2fdesign-pattern-for-switching-email-providers-in-the-code%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

          Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

          A Topological Invariant for $pi_3(U(n))$