F# and SignalR Stock Ticker Example

I was looking at the server broadcast SignalR tutorial found here for a current project when I got to the StockTicker class.  In this class, the interesting code surrounds making a singleton instance because SignalR hubs are transient.  Here is the full text:

You’ll use the SignalR Hub API to handle server-to-client interaction. A StockTickerHub class that derives from the SignalR Hub class will handle receiving connections and method calls from clients. You also need to maintain stock data and run a Timer object to periodically trigger price updates, independently of client connections. You can’t put these functions in a Hub class, because Hub instances are transient. A Hub class instance is created for each operation on the hub, such as connections and calls from the client to the server. So the mechanism that keeps stock data, updates prices, and broadcasts the price updates has to run in a separate class, which you’ll name StockTicker.

So then it hit me – we need an immutable class that can handle multiple requests.  This sounds like a job for Captain F#!  Unfortunately, Captain F# is on vacation, so I went with Private 1st class F#.  So this is what I did.

I created an empty solution.  I then added in a C# Empty Web Application just to have a point of comparison to the FSharp project.  Then I added in a new F# MVC4 project from on the on-line template that Daniel Mohl created:

image

The problem is that the C# is the web app and the F# is just the controller.  Since I want a full-on double rainbow F# only MVC application, I tossed the template and just created a bare-bones F# project.  I then opened the .fsproj file and added a web ProjectType GUID (basically parroting what was in the .cs project file):

image

I posted this to stack overflow here.  So I am back to using C# as the Web application and F# as the plug in code.  I re-started with a couple of skeleton projects like so:

image

I then added a class for Stock like so:

  1. namespace Tff.SignalRServerBroadcast.FS
  2.  
  3. open System
  4.  
  5. type Stock() =
  6.     member val Symbol = String.Empty with get, set

 

I then added some unit tests to verify that I could create the Stock class and that I could assign the Symbol property:

  1. [TestClass]
  2. public class StockTests
  3. {
  4.     [TestMethod]
  5.     public void CreateStock_ReturnsValidInstance()
  6.     {
  7.         Stock stock = new Stock();
  8.         Assert.IsNotNull(stock);
  9.     }
  10.  
  11.     [TestMethod]
  12.     public void VerifyStockSymbolCanBeMutated()
  13.     {
  14.         Stock stock = new Stock();
  15.         stock.Symbol = "TEST";
  16.  
  17.         String notExpected = String.Empty;
  18.         String actual = stock.Symbol;
  19.  
  20.         Assert.AreNotEqual(notExpected, actual);
  21.     }
  22. }

 

And sure enough, they run green:

image

Just then, Captain F# swooped in from vacation and exclaimed “What are you doing?  The tenants of functional programming is immutability.  What happens if you change the Symbol after the object is created – does it really represent the same thing?  In fact, allowing the Symbol to be changed after it is created will lead to bugs and potentially unexpected behaviors in your system!”  With that, he left for a 10-day tour of the eastern Mediterranean.

I then changed the Stock class to be immutable like so:

  1. namespace Tff.SignalRServerBroadcast.FS
  2.  
  3. open System
  4.  
  5. type Stock =
  6.     {Symbol: String;
  7.      Price: Decimal;
  8.      DayOpen: Decimal;
  9.      }
  10.  
  11.      member x.GetChange () =
  12.         x.Price – x.DayOpen

 

and then updated my unit tests like so:

  1. [TestClass]
  2. public class StockTests
  3. {
  4.     [TestMethod]
  5.     public void CreateStock_ReturnsValidInstance()
  6.     {
  7.         Stock stock = new Stock("TEST", 10, 10.25M);
  8.         Assert.IsNotNull(stock);
  9.     }
  10.  
  11.     [TestMethod]
  12.     public void PriceChangeUsingValidNumbers_ReturnsCorrectChange()
  13.     {
  14.         Stock stock = new Stock("TEST", 10, 10.25M);
  15.         Decimal expected = .25M;
  16.         Decimal actual = stock.GetChange();
  17.         Assert.AreEqual(expected, actual);
  18.     }
  19. }

And then I ran my tests and got red

image

Ugh, I reversed the parameters – I intended to have the stock go up $.25.  Instead, the constructor expects the Price to come before the DayOpen.  This is not intuitive – you have implicit temporal coupleing in these parameters and since DayOpen occurs sooner in the space-time continuum, I reversed the parameters and the tests ran green:

  1. type Stock =
  2.     {Symbol: String;
  3.      DayOpen: Decimal;
  4.      Price: Decimal;
  5.      }

 

image

With that done, I looked at the last PercentChange  calculation.  The only thing remarkable about it is that the code in the on-line tutorial is incorrect.  The tutorial uses Price as the denominator, but my unit tests shows that it wrong:

  1. [TestMethod]
  2. public void PercentChangeUsingValidNumbers_ReturnsCorrectChange()
  3. {
  4.     Stock stock = new Stock("TEST", 10, 11M);
  5.     Decimal expected = .1M;
  6.     Decimal actual = stock.GetPercentChange();
  7.     Assert.AreEqual(expected, actual);
  8. }

 

image

If a stock goes from $10.00 to $11.00, it increases $1.00 and $1.00 divided by $10.00 is 10% – the stock increased 10%.

So I went back and changed the implementation to get the test to run green.

  1. member x.GetPercentChange() =
  2.     Math.Round(x.GetChange()/x.DayOpen,4)

 

image

 

So looking at this class, why is F# better than C#?

1) Less noise.  Compare the code between C# and F#

imageimage

All of the code in the Price setter is irrelevant.  In the F# implementation, you don’t need to worry about assigning DayOpen for the 1st time. 

 

2) Fewer Bugs: 

What happens if you are looking at Pets.com (IPET) on November 6, 2000 when it opened at $.16 and then went to $0.00 at noon when they finalized their liquidation?  You need to change your code b/c the C# implementation is wrong – the price was $0.00 and it was not the open price.

Also, what prevents me from changing the Symbol?  I could create a ticker class for APPL at $519 and then change the ticker to MSFT – volia MSFT’s price goes from $37.57 to $519.00!  And all of the unit tests for the Stock still run green.

3) More readable. 

Less noise – more signal (SignalR in fact)…

 

This blog post is getting a bit long so I will continue this project on another post.

Thanks to the RHCP, I listened to this 2-3 times when doing this blog post…

One Response to F# and SignalR Stock Ticker Example

  1. Pingback: F# Weekly #48, 2013 | Sergey Tihon's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: