Monthly Archives: April 2017

Winnipeg Azure Bootcamp 2017

The Global Azure Bootcamp 2017 hosted by the Winnipeg .Net User Group was a success. There was a good number of people in attendance for the event. The presentations were excellent which made it difficult to choose some standout topics. In saying that, here are a few items that I brought back from the event to dig in deeper.

Azure Functions with F#

The ability to create Azure functions which run F# has to be the big takeaway for me. An Azure function is Microsoft’s vision of a serverless architecture. The idea is we don’t need to worry about scaling web applications as that is handled automatically by Azure. Azure functions run based on a script file we code. F# has a very good story for prototyping using the REPL and F# script files (fsx). See what I’m thinking? This is a great opportunity to go from prototype to testing in the cloud with possibly little friction.

Let’s give it a quick go.

Open up your Azure portal and add a new “Function App”. Enter in the required details, App name, Subscription, Resource Group, … etc. Once everything is created you can click on your new function. Click the plus sign to the right of “Functions”, then scroll down and click “Custom function”. You can filter the “Language” to F# using the drop down. Select HttpTrigger-FSharp as the template for our function. Name your function and click create.

The new function comes with some template code in the online editor. We can replace the default code in the file “Run.fsx” with:

#r "System.Net.Http"

open System.Net
open System.Net.Http

let Run(req: HttpRequestMessage, log: TraceWriter) =
    req.CreateResponse(HttpStatusCode.OK, "F# and Azure Functions FTW!")

Click the “Save” and “Run” button and we should see our message in the result pane in the bottom right.

Azure functions and F# are going to be an unstoppable combination.

Docker Everywhere

We saw a great demo on the ability to upload and create docker containers in Azure. The presenter, Alexander Trauzzi, created a TypeScript application with Geotagging and deployed it in a docker image. He then loaded the same docker image to multiple Azure data centers around the world. After a bit of answering questions, the map of the world started to display little Azure clouds. It was very cool.

Alex setup a guide you can follow if you want to try the demo yourself.
https://github.com/atrauzzi/azure-bootcamp-2017/blob/master/guide_local.md

Testing in Production

Testing in production allows you to have multiple deployment slots for an Azure website and set differing amounts of traffic to each. There is no misconception with the name of this feature. You are literally testing in production, however this is more of a controlled production test.

In order to try this out, create your App Service in a standard or premium plan.

Here are some rough steps to get setup:

  1. In the Deployment group of your app service, click on Deployment Slots.
  2. Click on Add Slot to create a new deployment slot.
  3. In the Development Tools group, click on Testing in production.

You should now be able to click the drop down which says Choose deployment slot, and change the traffic percentage we want to route to that deployment.

This gives us a way to control the amount of testing traffic to the new version of our site. Once we are satisfied of the new site’s stability, we can use switch the sites using the Swap button from the app’s Overview.

Summary

My big three takeaways from Global Azure Bootcamp 2017 was F# with Azure Functions, deploying and running our Docker images in Azure, and testing in production.

Deconstructing Records

Deconstruction let us focus on the values we want to match in our patterns. We’ve shown we can deconstruct tuples, but what about records? Absolutely.

A record is a data structure with named values. Records are immutable by default. We use records in exchange of tuples. Records give better context to what data is being represented. We’ll use the Astronaut record defined below as our data representation.

type Astronaut = { Name : string; Year : int }

Suppose we want to print an appropriate message based on the astronaut’s name. We’ll do a simple greeting for all astronauts except for “Dave” and “Neil”. We can create our function with a pattern match as below.

let greeting astronaut = 
    match astronaut with
    | {Name = "Dave"} -> "I'm sorry Dave, I'm afraid I can't do that."
    | {Name = "Neil"} -> "The first person to set foot on the moon."
    | {Name = name}   -> sprintf "Hello %s." name

If you look at the patterns in the match you will note we are deconstructing the Name value from the astronaut argument. Someone reading the code can easily see we are interested in the astronaut’s name.

We could be even more specific with matching on our Astronauts by using patterns below:

let greeting astronaut = 
    match astronaut with 
    | {Name = "Dave"; Year = 2001 } 
         -> "I'm sorry Dave, I'm afraid I can't do that."
    | {Name = "Neil"}               
         -> "The first person to set foot on the moon."
    | {Name = name}                 
         -> sprintf "Hello %s." name

We’ve gone further in isolating the values we want for our patterns. The more values you add the more specific your patterns become. In the example above we have a case using the Name and Year deconstructed from the astronaut to get Hal’s response to Dave. All other astronauts named Dave will get the standard greeting.

Deconstruct OR what…

Let’s go back to matching on name only. What if our name isn’t proper case? What if Dave is actually a “dave” or “DAVE”? We may still want to match on those “Dave”s. Here is where some of the power of F#’s pattern matching starts to shine. We can write our pattern to include those other “Dave”s by combining deconstruction and the OR Pattern.

let greeting astronaut = 
    match astronaut with
    | {Name = "Dave" | "dave" | "DAVE"} 
        -> "I'm sorry Dave, I'm afraid I can't do that."
    | {Name = "Neil"} 
        -> "The first person to set foot on the moon."
    | {Name = name}   
        -> sprintf "Hello %s." name

We’ve certainly improved our pattern to include more cases of “Dave”. We can take our pattern one step further and make our patterns case insensitive. The first way will be more familiar for OOP developers. We can use the property accessor to get the Name to then lower and use the property again to print the name. The other way would be to use a pattern match in the function signature. We can do pattern matching and deconstructing in the function arguments.

let greeting astronaut = 
    match astronaut.Name.ToLower() with
    | "dave" 
        -> "I'm sorry Dave, I'm afraid I can't do that." 
    | "neil" 
        -> "The first person to set foot on the moon."
    | _      
        -> sprintf "Hello %s." astronaut.Name


let greeting' {Name=name} = 
    match name.ToLower() with
    | "dave" 
        -> "I'm sorry Dave, I'm afraid I can't do that."
    | "neil" 
        -> "The first person to set foot on the moon."
    | _      
        -> sprintf "Hello %s." name

It’s not overly common to use deconstruction in the function signature. It can lead to some ambiguity in the code. We are focusing on the values we care about, however the function signature may no longer have the same readability it did before with the astronaut value.

Summary

We’ve covered the ability to deconstruct records in our patterns. We aren’t limited to one value for deconstruction. We can match on any number of values in a record, and the number of values can vary between patterns. F# is not limited to only deconstruct records in the match with construct. Matching can be used by the function construct and in the declaration of function arguments. We can also combine deconstruction with OR to reduce the number of patterns and improve readability. It’s the ability to combine patterns which let’s the power of F# shine its expressiveness.

Beyond Constant Pattern Matching

Pattern matching is a vital aspect of functional programming. It can make our code more expressive by eliminating noise. We’ll look into a few more patterns that give us the power and flexibility to create readable match expressions.

OR Pattern

The OR pattern is used to group multiple patterns which return the same result. This can be considered a short hand for multiple patterns. A simple match expression verifying a number is below 10 and prime can be written multiple ways.

// Return value for each number
let isPrimeBelow10 = match number with
                     | 2 -> true
                     | 3 -> true
                     | 5 -> true
                     | 7 -> true
                     | _ -> false

// Using the OR pattern
let isPrimeBelow10 = match number with
                     | 2 | 3 | 5 | 7 -> true
                     | _             -> false

The second version of isPrimeBelow10 is easier to reason about as it declares the patterns 2, 3, 5, and 7 are grouped to the same result. The noise of all the extra -> true has been removed. This gives the reader a visual cue about the relationships of the patterns as well as reduces duplicate code.

Guards

Guards are used to match on patterns that require more than a constant. We use the when keyword followed by an expression which evaluates to a boolean. If the guard expression evaluates to true then that pattern matches. Let’s say we want to classify a value as normal if it is within 100 to 200. That would take a lot of patterns if we used the OR pattern exclusively. It also doesn’t solve the situation if we wanted to indicate whether the value was high or low. We can use guards to accomplish our task.

let withinNormals number = match number with
                           | x when x > 200 -> High
                           | x when x < 100 -> Low
                           | _              -> Normal

We have three patterns with two of them using guards. The first pattern binds number to the label x and evaluates x > 200. If it evaluates to true, the match returns High. The second pattern does something similar, with the exception of evaluating x < 100. The final pattern is a wildcard which returns if the previous patterns are not matched.

Guards allow us to do more than just match on constants. We can expand our withinNormals to be more reusable.

let withinNormals (lowLimit, highLimit) number = 
    match number with
    | x when x > highLimit -> High
    | x when x < lowLimit  -> Low
    | _                    -> Normal

We have the same three patterns but this time we are using the arguments passed in determine the lower and upper limit. Guards let us do more than match on constant values, they give us the flexibility to create reusable patterns.

Deconstruct

Deconstruction allow the pattern to focus on what is being pattern matched. We left off Pattern Matching with Constants with a pattern matched version of Fizz Buzz. Here is the implementation again.

let printFizzBuzz number = match (number % 3, number % 5) with
                           | (0, 0) -> printfn "FizzBuzz"
                           | (0, _) -> printfn "Fizz"
                           | (_, 0) -> printfn "Buzz"
                           | _      -> printfn "%d" number

The printFizzBuzz function takes a number and creates a tuple of the results of number modulus 3 and 5. Our patterns deconstruct the tuple and match those results with constants.

We can even completely ignore values from deconstructed objects. Here we only care about the third value in the tuple. We are using the patterns to deconstruct the tuple while ignoring the first two values in the tuple. Our patterns are only focused on the values important to it.

match tupleOf3 with
| (_,_,0)            -> "0"
| (_,_,1)            -> "1"
| (_,_,x) when x < 0 -> "Negative"
| _                  -> "Larger than 1"  

Summary

The OR pattern can be used to group patterns together which have the same return value. Redundant code can be eliminated with the use of the OR pattern. Guards give match expressions the ability to compare values in patterns and not restrict us to constants. Deconstruction let patterns focus on what is being matched instead of dealing with the whole object.