The other day my friend Jero wrote an article explaining how to write a Google Function using Javascript. The goal of this article is to do the same exercise but using Azure Functions and F#.

First steps

First of all, you will need to set up a couple of things. Don’t worry, both of them are free. First of all you’ll need an Azure account. You can create one for free and have £150 credit (and you’re not going to spend a single pound doing this exercise).

Second (not entirely necessary as you can edit an Azure Function directly in the browser, but highly recommended) you need an IDE to develop F#. Download VSCode and install the Ionide extension and you’ll be in a perfect position.

If we want to develop locally we’ll need to install the Azure Functions CLI. Unfortunately, this tool is only available in Windows right now. This tool will help us a little bit on the function creation. Right now is a convenient way to create an Azure Function, but it’s not entirely necessary. At the end, is going to create some files that you can create manually if you want.

To install the Azure Functions CLI you need to follow the folowwing steps:

  • Install nodejs
  • Update npm: npm install npm@latest -g
  • Install Azure Functions npm package: npm i -g azure-functions-cli

Now we can create the Azure function folder. Create the folder where you want to work and type func init ManOrWoman. This will create a git repository with some files inside. Func InitNow you can push the repo to Github.

Continuous deployment

What are we going to do in this example, is enable the continuous deployment from Github. We will link our Azure Function to a repo in Github so that every time we push a change the function will be automatically deployed. Probably something you don’t want to do in your professional project but that is good enough by now. Hopefully, we’ll see how to deploy an Azure function in a more professional way in a future article.

Let’s go to the Azure portal and create a new Function App:

  • App Name: ManOrWoman
  • Resource Group: ManOrWomanRG
  • Hosting Plan: use a App Service Plan -> create new -> Free Tier (or a consumption plan)
  • Storage account: (create new) manorwomansa

When Azure finishes creating the function you can set up the continuous deployment using Github:

  • Click on Start from source control Start from source control
  • Follow the steps to set up a new github deployment

Now we’re ready to create the function itself. Go to your console (to your work folder) type func new and follow the following steps:

  • Select a language -> choose F#
  • Select a template -> httptrigger
  • FunctionName -> ManOrWoman

Push the changes and wait until they are deployed. Don’t worry, only takes few seconds. Now we’re ready to test the test function using a browser. If we try to execute the function using the browser and going to the URL https://manorwoman.azurewebsites.net/api/ManOrWoman?name=Vicenc we’re going to get a 401 Unauthorised as a response. This is because we have the authorisation set as function and therefore we need to provide a code (key) to be able to run this function. Something like this:

1
https://manorwoman.azurewebsites.net/api/ManOrWoman?code=<the_code>&name=Vicenc
You can find your code in the Azure Portal under Manage inside your function.

If we’d like to make this function public, we should go to our function.json file and change the authLevel from function to anonymous. Let’s change it, push the changes and try to access the function in this way: https://manorwoman.azurewebsites.net/api/ManOrWoman?name=Vicenc We’re good now and we don’t need to provide any key.

Code

Let’s code the function itself. What we’re going to do is given a name, check it the list of people’s name in Spain. To do that, we’re going to download the data from the goverment and export it as a CSV, one file for men’s names and another one for women’s names. We need to upload this files to our function environment and we’ll do that using Kudu:

  • Go to https://.scm.azurewebsites.net
  • Click on Debug Console -> CMD
  • Navigate to data
  • Create a folder called spain
  • Create two files, women.csv and men.csv
  • Edit the files and copy the content from the files you’ve recently created

We’ll need the same kind of structure in our local environment to be able to test the function. So, in your function folder, create the same folder structure (/data/spain) and copy there those two files.

As we’re using csv as our data source, we’re going to use the CSV type provider to read the data. Let’s start defining some types we’re going to use. Create a file called types.fs and copy the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
namespace Types
    open FSharp.Data

    type NameData = CsvProvider<"Order,Name,Frequency,AverageAge", HasHeaders = true, 
                                            Schema = "Order(int),Name,Frequency(int), AverageAge(float)">

    type NameStatistic = {Frequency: int}

    type Result = {
        Gender: string
        Frequency: int
        Percentage:float
    }

And now create a file called statistics.cs and copy the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
module Statistics
    open Types
    open FSharp.Data

    let getGenderStatistics (fileName:string) (name:string) =
        let names = NameData.Load(fileName)

        let nameData =
            names.Rows
            |> Seq.filter(fun r -> r.Name = name.ToUpperInvariant() )
            |> Seq.tryHead
        
        match nameData with
        | None -> None
        | Some x -> Some {NameStatistic.Frequency = x.Frequency}

    let getNameStatistics (name: string) (folder:string) =
        let statistics =
            [|folder + "men.csv"; folder + "women.csv"|]
            |> Array.map(fun x -> getGenderStatistics x name)

        let calculatePercentage (x:int) (y:int) = 
            float x * 100.0 / (float x + float y)

        match statistics with
        | [|Some m;Some w|] -> 
            match (m.Frequency > w.Frequency) with
            | true -> Some {Gender = "Man"; Frequency = m.Frequency; Percentage = calculatePercentage m.Frequency w.Frequency}
            | false -> Some {Gender = "Woman"; Frequency = w.Frequency; Percentage = calculatePercentage w.Frequency m.Frequency}
        | [|Some m;None|] -> 
            Some {Gender = "Man"; Frequency = m.Frequency; Percentage = 100.0} 
        | [|None;Some w|] -> 
            Some {Gender = "Woman"; Frequency = w.Frequency; Percentage = 100.0} 
        | _ -> None

Basically what we’re doing here is to find the name in both files, see where is more common, and return the result.

What we need to do now is to use this function in the run.fsx script. Edit the script with the following content:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#r "System.Net.Http"
#r "Newtonsoft.Json"
#r "Fsharp.Data"
#load "Types.fs"
#load "Statistics.fs"

open System.Net
open System.Net.Http
open System.Net.Http.Headers
open Newtonsoft.Json
open Statistics

let Run(req: HttpRequestMessage, log: TraceWriter) =
    async {
        log.Info(sprintf "F# HTTP trigger function processed a request.")

        let name =
            req.GetQueryNameValuePairs()
            |> Seq.tryFind (fun q -> q.Key.ToLowerInvariant() = "name")

        let folder = Environment.ExpandEnvironmentVariables(@"%HOME%\data\spain\")

        let response =
            match name with
            | Some x ->
                let statistics = getNameStatistics x.Value folder
                match statistics with
                | Some y -> 
                    let json = JsonConvert.SerializeObject(y)
                    let jsonResponse = sprintf "%s" json
                    req.CreateResponse(HttpStatusCode.OK, jsonResponse, "text/plain")
                | None -> req.CreateResponse(HttpStatusCode.BadRequest, "We haven't found the name")
            | None ->
                req.CreateResponse(HttpStatusCode.BadRequest, "Specify a Name value")

        return response

    } |> Async.RunSynchronously

In this piece of code, we’re just parsing the input, calling our code, and return the result. The “interesting” part comes when returning the result. As you can see we’re returning it as “text/plain”. That’s because how ASP.Net works internally. You will face the same problem developing a Web API project. If you’re doing that you can use Mark Seemann’s solution or Isaac Abraham’s solution If not, you have two options:

  • Specify the media type as “text/plain”
  • Use DataMemberAttribute to provide your own names.

I think the second option is the best one because we keep our media type as “application/json”. So, let’s make some changes: In types.fs:

  • Add: open System.Runtime.Serialization
  • Change the result type to: [] type Result = { [<field: DataMember(Name="Gender")>] Gender: string [<field: DataMember(Name="Frequency")>] Frequency: int [<field: DataMember(Name="Percentage")>] Percentage:float }

In run.fsx:

  • Add: #r “System.Runtime.Serialization”
  • Change the way we create the response to: match statistics with | Some y -> req.CreateResponse(HttpStatusCode.OK, y) | None -> req.CreateResponse(HttpStatusCode.BadRequest, “We haven’t found the name”)

Dependencies

Our last step is to specify the dependencies of the function. In our case, we just need the FSharp.Data dependency. Open the project.json file and add “FSharp.Data”: “2.3.2” inside the dependencies node.

Push the changes and… voilà!!

Result

Summary

In this article, we’ve seen an introduction to Azure Functions using F#. We’ve developed a toy project to learn the basics. But we can’t develop a serious project in this way, we need things like testing and a better deployment. Hopefully, we’ll see it in future posts.

When you’re not sure about how to do something, you generally do a checklist of steps to follow. The first day I went to my current client, I had a list of steps: buy the train ticket, go to Kings Cross, collect the train ticket, take the train, take a cab, ask for Mr X, etc. I’m not using that list anymore because I now know how to do it.

It’s a common practice in agile teams to have a definition of ready and a definition of done. The definition of ready defines what does a story have to have defined in order to be considered to be taken in the sprint. Typical things are acceptance criteria, business value, risk. The definition of ready defines what the team considers a story have to look like to be considered done. Typical things are unit tests, demoed to the PO, deployed to Pre (or ideally to Prod), reviewed. You can even customise a Jira template to include the checklist! Amazing! (NO)

The agile literature suggests that your goal should be to evolve these checklists when the team feels comfortable with the existing one and include more things and be more awesome. I don’t agree with that.

Your goal should be to get rid of those checklists. Your goal should be to be a team mature enough to don’t need to be remembered that to consider a story done has to be reviewed by someone else. Your team should be mature enough to define the acceptance criteria before accepting working on one story. You don’t need a checklist for that, you just need to be professional.

You should aim to get rid of these checklists, but they are useful in the meantime.

As more mature is the team, the less established process it needs.

Cargo cult is a movement that is found in societies that believe in often-apocalyptic religious prophecies that predict a return to power, the defeat of enemies, and/or the accumulation of wealth. This movement often occurs in colonial societies.

The first occurrences date from the end of the 19th century in Fiji, but the most important ones are the ones in the Melanesian islands after the World War II. During the war, both sides airdropped supplies and military equipment for their troops that often shared it with the local population. Some unspecified Americans were worshipped by the locals by claiming that they had brought cargo to their island during the war and that they will provide more cargo in the future. After the war, some islanders imitated the practices they had seen the soldier, sailors and airmen use. Those behaviours included mimicking activities, dressing as soldiers carving headphones from woods, building control towers or waving landing signals.

Cargo cult

There are some theoretical explanations of cargo cult. One of them says that cargo cult was a form of expression of personhood and wealth. Another one places more emphasis in the cultural change, and how they use memories to comprehend new realities, especially the secret of the European material possessions.

As a part of an agile team, we follow the cargo cult movement as well. We’re doing cargo cult when we estimate without any reason, when we don’t think why we estimate, what do we want to achieve and what do we do with those estimates apart from drawing a fancy chart. We’re doing cargo cult when we don’t estimate without any solid reason, just for following a new nice hashtag on twitter. We’re doing cargo cult when we write unit tests just for saying that we have unit tests. We’re doing cargo cult when we meet for a retrospective but we’re not taking any action after it. We’re doing cargo cult when we do a daily stand-up meeting to report status to our manager. We’re doing cargo cult when we do a practice just because we always did or just because we worship some book or some IT twitstar.

Made-up agile

Our case is much worse than that of those islanders. At least, they had seen something working. They saw aeroplanes landing or dropping supplies. They saw people giving them presents. Their life was better (or at least different) those days. On the other hand, a lot of teams are doing some practices without never seeing any benefit in our daily work and without even considering if it’s what we need or not. Do you need retros? I bet so. Are you improving the way you work because of them? No? Then why are you doing retros? Just for moaning during one hour Are you doing something significantly better than in your previous life because you’re now estimating and planning? No? Then why are you estimating and planning? Are your unit tests helping you in having a more robust code and being confident with it? No? Then why wasting time doing unit tests?

If you spend some time in one activity at work, whatever it is, you must get something of it. If you don’t, don’t pretend you’re something that you don’t really are. Agility doesn’t have to be your goal. Your goal should be to deliver the maximum value to your customers. And by doing agile practices you’ll probably achieve that. But if by doing an activity you’re not improving the way you work and you’re working exactly in the same way (or worse) that you use to, please don’t do it. If at the end you’re working in exactly the same way, don’t waste your time. I strongly believe that agile, and especially XP, will help you so much in delivering the maximum possible value to your customers. But you will need to work hard, improve step by step, analyse your results, tweak your process.

By just pretending following some practices, you’re not going to improve.

Agile meme

According to the Wikipedia, a cowboy (and a cowgirl) is an animal herder who tends cattle on ranches in North America, traditionally on horseback, and often performs a multitude of other ranch-related tasks. They were quite famous in the 19th century and we can still find them in ranches.

original cowboy

Hollywood adapted the cowboy lifestyle to create some stereotypes, both positive and negative. But, in general, a cowboy was a guy with a gun killing people, either because they were bad guys or because they were defending a good cause.

Hollywood cowboy

As we’ve already said, there are still cowboys nowadays, either on ranches or in your development team. What is a cowboy in your development team? They use to share some common characteristics or behaviours:

  • They don’t like to pair program with anyone.
  • They have a silo of knowledge that they are not keen to share.
  • They make changes in Production boxes by hand.
  • They only participate in team meetings to patronise the rest of the team.
  • They write long emails (or slack messages). Again, patronising the team.
  • They don’t ask the team for consense before making decisions that can affect the team.
  • They are often “good” developers.

And we can continue with that list forever.

We can differentiate two types of development cowboys:

  • The Lucky Luke type: They are good guys, they don’t kill anybody but they can destroy a project. They don’t really know they are cowboys and within a good environment, they can change. A good example is Brent from the book The Phoenix project
  • The Billy The Kid type: They like to be cowboys and they think cowboys are great. They can kill people, teams and projects. They especially like to hurt the project so they can demonstrate they are brilliant and they can “heal” it. They don’t like teamwork and they will show it as often as they can. A good example can be the guy who is sitting next to you.

There a couple of characteristics that make cowboys appealing to some kind of managers (those managers that you don’t want to work with): they are often “good” developers and they make changes directly in the production boxes. Some managers like this kind of hacks to overcome some problem. Even though there is no rush, they want to get rid of that problem quickly, so there’s nothing better than someone that hacks something in the production box, or make a quick change in the code and copies the file directly to production, or whatever. The problem is that by solving that problem quickly they are creating N problems more, where N is usually a big number.

Is there any way to remove this bad behaviour? The main one for me is to avoid these people working alone. So setting a WIP in your project that forces people to pair program (instead of using pull requests, that you should avoid) seems very reasonable in this situation (and not just for this reason). The main problem you’ll have with this people is knowledge sharing, so adopting XP practices is very compelling.

And don’t forget that although we need to try to make people work well in our team, we have the possibility of fire people. We’re not talking here about culture fit (which we can discuss if is reason enough to fire someone), but about someone who is undermining your project and your team.

duel

Pull requests are a common way to integrate your changes in another repository or branch in an Open Source project. They allow the receiver of the pull request to easily view and review the changes you made. Pull requests are great, especially when your team is not colocated, but also in different time zones. It seems that their popularity has extended to enterprise projects as well, even when the team is co-located. Is in this situation when I consider pull requests a bad smell of team dynamics.

Our story starts after the sprint planning. Every member of the team chooses a story to begin working on and creates a branch. After several days working in this branch (and maybe in other ones), he decides is a good time to create a pull request. The pull request can be something like this:

giant pull request

The poor team member that takes responsibility of merging the pull request spend the whole day reviewing the changes. You can imagine the quality of the review.

Another problem you can have with pull requests is that you can review easily the changes that the sender has made but, what if he missed making a change? Imagine that you are changing the actions of a controller to async methods and you miss a couple of them. When the reviewer reviews the pull request, she will see all the actions that you’ve changed (or added or removed) but it won’t be easy to spot those actions you missed to update.

So, what can you do to improve this situation?

The first option is to avoid the necessity of reviewing changes. Work in pairs when you develop a new story. I know that you can’t pair all the time but use this tool as much as you can. The results will be much better because pairing is much better than reviewing. Talking with your partner about design decisions, naming, etc. is much better than just reviewing some code with much less context.

If you can’t pair, at least review the code with its creator. Take a seat next to her, use your favourite remote pair programming tool or start a hangout/webex/whatever and go through the code. Ask for explanations of the decisions, test new approximations, discuss naming. But have a face to face conversation with her.

If for some inexplicable reason you can’t pair or review the code with its creator, use tiny pull requests. Obviously, this is a general advice, please define small and incremental stories that involve the less code possible. The code will be better and the life of the teammate that will review the pull request will be much happier.

I approve this pull request