F#, Chain Of Responsibility, And High Ordered Functions

I was working though Tao Liu’s F# for C#  Developers book

image

when I got to the chapter on F# and Design Patterns.  This is a great chapter.    Typically F# books introduce the language from the language on out.  This chapter takes a different approach – it shows the language in action using commonly accepted design patterns.  I was working through the section on the Chain Of Responsibility pattern when I got to this code snippet

  1. let check f (record,result) =
  2.     if not result then record, false
  3.     else record, f(record)

 

Looking at the code, I get that we are assigning a function called check that has a tuple with record called ‘record” and a Boolean called ‘result’.  However, what is that ‘f’?  Basically, what the F is that f in F#?  Looking at the REPL results, I see that it was this signature:

image

Basically, f is a function called ‘f’ that I am passing in.  I am then invoking this function here:

  1. let chainOfResponsibility = check validAge >> check validHeight >> check validWeight
  2.  
  3. let test1 = {Name="Test"; Age=45; Weight=175.; Height=175.}
  4.  
  5. printfn "test result = %A" (chainOfResponsibility (test1, true) |> snd)

 

So this is an example, I think, of two language constructs.  The first is high ordered functions – where check takes in a function as a parameter.  Next, this is an example of currying – where chainOfResponsibility only passes in the function, not the tuple.  I think.

To further research this, I looked up Chain of Responsibility on Wikipedia and took a look at the C# example.  To do it the C# way, created 6 files

image

with each file having the implementation found on the Wikipedia article.  The Logger class defines the behavior:

  1. public abstract class Logger
  2. {
  3.     protected LogLevel logMask;
  4.     protected Logger next;
  5.  
  6.     public Logger(LogLevel mask)
  7.     {
  8.         this.logMask = mask;
  9.     }
  10.  
  11.     public Logger SetNext(Logger nextlogger)
  12.     {
  13.         next = nextlogger;
  14.         return nextlogger;
  15.     }
  16.  
  17.     public void Message(string msg, LogLevel severity)
  18.     {
  19.         if ((severity & logMask) != 0)
  20.         {
  21.             WriteMessage(msg);
  22.         }
  23.         if (next != null)
  24.         {
  25.             next.Message(msg, severity);
  26.         }
  27.     }
  28.  
  29.     abstract public void WriteMessage(string msg);
  30.  
  31. }

 

and the individual implementations in the classes:

  1. public class FileLogger : Logger
  2. {
  3.     public FileLogger(LogLevel mask)
  4.         : base(mask)
  5.     { }
  6.  
  7.     public override void WriteMessage(string msg)
  8.     {
  9.         //Placeholder for File writing logic
  10.         Debug.WriteLine("Writing to Log File: " + msg);
  11.     }
  12. }

What is interesting to me is the Logger.SetNext() method is used to move to the next implementation in the chain.  I then set to write the example in FSharp using Liu’s template.  I did this:

  1. type Logger() =
  2.     let LogToConsole logLevel =
  3.         //Implementation
  4.         true
  5.  
  6.     let LogToEmail logLevel =
  7.         //Implementation
  8.         true
  9.  
  10.     let LogToFile logLevel =
  11.         //Implementation
  12.         true
  13.  
  14.     let check f (logLevel, result) =
  15.         if not result then logLevel, false
  16.         else logLevel, f(logLevel)
  17.  
  18.     let chainOfResponsibility =
  19.         check LogToConsole >> check LogToEmail >> check LogToFile
  20.  
  21.     let mutable logLevel = LogLevel.None
  22.     member this.CurrentLogLevel with get() = logLevel
  23.                                 and set(v) = logLevel <- v
  24.  
  25.     member this.WriteMessage () =
  26.         chainOfResponsibility (logLevel,true) |> snd

So there are a couple of observations.

1) F# is more terse – and more readable

2) Instead of creating a MoveNext function, the chainOfResponsibility uses the >> operator to move to the next.

3) These 2 code bases are not functionally equivalent – I have to keep working on the F# one.

4) How much fun is F#?

 

Polymorphic Dispatch, Open/Closed, Notification Part2

I received plenty of great feedback about this post on polymorphic dispatch, open/closed principle, and notifications.  I have made the following changes based on the comments

1) Send() should have the message as its argument so that for each message the collection does not have to be recreated.  The local variable that holds the message goes away:

public interface IAlert
{
    void Send(String message);
}

And an implementation looks like:

 

public void Send(String message)
{
    if (String.IsNullOrEmpty(message))
        throw new AlertsException("message cannot be null or empty.");

    SmtpClient smtpClient = new SmtpClient();
    MailMessage mailMessage = new MailMessage(_from, _to, _subject, message);
    smtpClient.Send(mailMessage);
}

2) I should not use an abstract base for the mail – because it tired me to a specific implementation (need a TO, FROM, SUBJECT).  Also, I should be favoring interfaces over abstract classes.  The benefit of reduction of code by using that abstract base is more than offset by the specific implementation and the making it harder to build extensible emails in the future.

3) My Twitter implementation was based on Twitter APIs for 2 years ago.  Twitter now requires OAuth.  A full blog post about hooking up to Twitter is found here.

4) Even though I am following the Open/Closed Principle (OCP) for notifications, I still have a problem.  If I add a new notification to the project, I can add the notification class and AlertFactory does not change (follows OCP).  However, the SqlAlerteeProvider does have to change (violation of OCP) to account for the new kind of notification.  For example:

public Alertee GetAlertee(Int32 alerteeId)
{
    Alertee alertee = new Alertee();
    alertee.AlerteeId = 1;
    alertee.FirstName = "Test";
    alertee.LastName = "Test";
    alertee.AlertList.Add(new LocalEmailAlert("Test","Test","Test"));
    alertee.AlertList.Add(new TwitterAlert());
    //Add new kind of Alert here
    return alertee;
}

I then thought about how to add the alert and have the factory not change.  I first looked at the Factory Pattern in Design Patterns.  This was no help because they too violate the OCP when they create the specific implementations of the subclasses (Creator class on p. 111)

Product* Creator::Create (ProductId id)

{

if(Id == MINE) return new MyProduct;

if(Id==YOURS) return new YourProduct

etc…

}

I also realized that I have been using the words “factory” wrong  my Factories are usually Builders.  In any event, the builder pattern also creates specific concrete classes and would therefor have to change as new types of alerts are added to the project.

I then realized that any concrete implementation will violate the OCP.  I see two ways out of the problem.  I could either make the individual objects responsible for their own creation (bad idea) or use an abstract factory pattern (GoF p.87) (not an all together a bad idea).  The abstract factory implementation needs to be alert specific.  So if you have TwitterAlert, you have a TwitterAlertFactory that follows the interface of the IFactory pattern.  The difference with my current implementation (SqlAlerteeProvider) is about implementing the object, not about implementing the data store.

Assuming this is right, what it means that every new alter that I add to the project is actually 2 classes.  Class 1 is the implementation of alert that follows IAlert and Class 2 is the implementation of alert construction that follows IAlertFactory. 

I don’t like this solution.  The problem is that I still can’t actually create alerts and assign them to users without changing code – now that code can be external (in Main) or in yet a third class that joins Alerts and AlertFactories together.   I suppose I can use a DI container but I will still need to alter the .config file and have a redeploy, so I get no practical value-added.  Just by moving something higher up in the call tree does not make it follow OCP.  The main function will still have to change and be aware of the types of alerts out there. 

I think I will go back to the provider model because it follows the MSFT patterns of use.  If I add a new alert, the Alert has to be added and the AlertProvider will have to change.  Not pure OCP, but closer – and the code is much cleaner than the typical if..then switch…case spaghetti that you typically find in most projects.