After lesson 2.14.2, the Kladde books through a use case, and all notifications live in one class, BookingNotifications. That class has a smell that was already on the list in lesson 2.14.1: three methods, and in each a switch over the same channels. Now management wants a fourth channel, an activity log where it can read what happened to the bookings. In this lesson you rebuild the channels so that a new channel is a new file, and none of the old ones changes for it.

The smell: the same switch three times

BookingNotifications from lesson 2.14.2 has the same shape three times:

C#
foreach (NotificationChannel channel in options.Value.Channels)
{
    switch (channel)
    {
        case NotificationChannel.Mail:
            …
        case NotificationChannel.Webhook:
            …
        case NotificationChannel.Live:
            …
    }
}

once in BookedAsync, once in ConfirmedAsync, once in CancelledAsync. What do you have to do for the activity log?

  1. Extend the NotificationChannel enumeration with ActivityLog.
  2. Add a case in each of the three switch statements, and forget none. The compiler doesn’t help here: a switch statement without default over an enumeration isn’t an error when a case is missing.
  3. Extend the constructor of BookingNotifications with the log’s dependency. Every test that builds the class now has to supply it, the tests for the webhook too.
  4. Run the characterization test and all the tests of BookingNotifications again, because any of its lines may have changed.

That’s the pain: one new thing forces you to open three places that work. The O in SOLID, the open-closed principle, says: a part should be open for extension and closed for modification. A new kind of notification should be able to join without touching the places that work today.

The interface for that already exists: IBookingNotifier from lesson 2.14.2. So far it has one implementation that knows all the channels. After the refactoring, it has one implementation per channel.