to which EmailListsendemail delegates in line 3 yet our controller method is

To which emaillistsendemail delegates in line 3 yet

This preview shows page 434 - 436 out of 517 pages.

(to which EmailList#send_email delegates in line 3), yet our controller method is already set up to call send_email on the mailer object. The Adapter pattern can help us here: it’s designed to convert an existing API into one that’s compatible with an existing caller. In this case, we can define a new class AmikoAdapter that converts the more complex Amiko API into the simpler one that our controller expects, by providing the same send_email method that MailerMonkey provides: 1 class AmikoAdapter 2 def initialize ; @amiko = Amiko.new(...) ; end 3 def send_email 4 @amiko.authenticate(...) 5 @amiko.send_message(...) 6 end 7 end 8 # Change the controller method to use the adapter: 9 def advertise_discount_for_movie 10 moviegoers = Moviegoer.interested_in params[:movie_id] 11 mailer = if Config.has_amiko? then AmikoAdapter else MailerMonkey end 12 EmailList.new(mailer).send_email_to moviegoers 13 end When the Adapter pattern not only converts an existing API but also simplifies it—for example, the Amiko gem also provides many other Amiko functions unrelated to email, but AmikoAdapter only “adapts” the email-specific part of that API—it is sometimes called the Façade pattern . 1 class Config 2 def self.email_enabled? ; ... ; end 3 def self.emailer ; if has_amiko? then Amiko else MailerMonkey end ; end 4 end 5 def advertise_discount_for_movie 6 if Config.email_enabled? 7 moviegoers = Moviegoer.interested_in(params[:movie_id]) 8 EmailList.new(Config.emailer).send_email_to(moviegoers) 9 end 10 end 1 class Config 2 def self.emailer 3 if email_disabled? then NullMailer else
Image of page 434
4 if has_amiko? then AmikoAdapter else MailerMonkey end 5 end 6 end 7 end 8 class NullMailer 9 def initialize ; end 10 def send_email ; true ; end 11 end 12 def advertise_discount_for_movie 13 moviegoers = Moviegoer.interested_in(params[:movie_id]) 14 EmailList.new(Config.emailer).send_email_to(moviegoers) 15 end 16 end Figure 11.19: Top: a naive way to disable a behavior is to “condition it out” wherever it occurs. Bottom: the Null Object pattern eliminates the conditionals by providing “dummy” methods that are safe to call but don’t do anything. Lastly, even in cases where the email strategy is known when the app starts up, what if we want to disable email sending altogether from time to time? Figure 11.19 (top) shows a naive approach: we have moved the logic for determining which emailer to use into a new Config class, but we still have to “condition out” the email-sending logic in the controller method if email is disabled. But if there are other places in the app where a similar check must be performed, the same condition logic would have to be replicated there (shotgun surgery). A better alternative is the Null Object pattern , in which we create a “dummy” object that has all the same behaviors as a real object but doesn’t do anything when those behaviors are called. Figure 11.19 (bottom) applies the Null Object pattern to this example, avoiding the proliferation of conditionals throughout the code.
Image of page 435
Image of page 436

You've reached the end of your free preview.

Want to read all 517 pages?

  • Spring '19
  • Dr.Marcos

What students are saying

  • Left Quote Icon

    As a current student on this bumpy collegiate pathway, I stumbled upon Course Hero, where I can find study resources for nearly all my courses, get online help from tutors 24/7, and even share my old projects, papers, and lecture notes with other students.

    Student Picture

    Kiran Temple University Fox School of Business ‘17, Course Hero Intern

  • Left Quote Icon

    I cannot even describe how much Course Hero helped me this summer. It’s truly become something I can always rely on and help me. In the end, I was not only able to survive summer classes, but I was able to thrive thanks to Course Hero.

    Student Picture

    Dana University of Pennsylvania ‘17, Course Hero Intern

  • Left Quote Icon

    The ability to access any university’s resources through Course Hero proved invaluable in my case. I was behind on Tulane coursework and actually used UCLA’s materials to help me move forward and get everything together on time.

    Student Picture

    Jill Tulane University ‘16, Course Hero Intern

Stuck? We have tutors online 24/7 who can help you get unstuck.
A+ icon
Ask Expert Tutors You can ask You can ask You can ask (will expire )
Answers in as fast as 15 minutes
A+ icon
Ask Expert Tutors