Mavnn's blog

Stuff from my brain

Annoucing @mavnn Ltd

As I hinted in the last post, new (and to me) exciting things are afoot. I'm very pleased to announce the formation of @mavnn ltd!

That's great, but what is it going to do?

I'm glad you asked! @mavnn ltd is the continuation of a lot of the things I've come to care most about over my years in software development: building reliable, maintainable and well crafted code and teaching others to do the same.

You can check out the web page for more details, but basically there's three streams to what the company will be providing:

  • Building code that works
  • Offering consultancy on how your team can build better software with less friction (especially around automating build, deployment and testing)
  • Giving training in skills that will allow teams to build solid software using functional programming techniques and thinking

What are doing already?

I'm glad you asked that too! Stream one of the company ("Building code that works") is already well under way - we're very pleased to say that @mavnn ltd's first customer is Logibit, where I'm helping Henrik and Mikko build out the Qvitoo platform.

Although it's always nice as a small company to have contracts, we're particularly pleased to be working with Logibit: firstly because they're great people to work with - you don't need to work for them to find that out, just get involved in any of the myriad open source projects they're involved in!

Secondly, as a company they embody the things that @mavnn stands for: leveraging the ideas behind functional programming in deeply practical ways to build software that solves real world problems, and does so exactly as designed.

Can I hire you?

Yes! To avoid disappointment, though, I should make it clear that we have some ongoing contractual agreements and so will not be accepting ongoing full time contracts for the foreseeable future.

Training, consultancy, ongoing part time and short term full time contracts are all up for grabs though - including remotely and in some cases internationally as evidenced by our co-operation with Logibit. Contact us to find out more.

Beginnings and Endings

There's the normal mix of excitement and sadness as I announce that today is my last day with my current employers, 15below.

Sadness because the people here are great and I've learned an unbelievable amount while working here. Excitement because there's exciting things happening for the future. What are these brave new vistas? Well, that will have to wait for next week.

But for now, it's time for a brief thank you and review of what I'm leaving.

Thanks 15below for:

  • being an incredibly flexible, generous & family friendly employer
  • Lots and lots of learning from existing code, conversations, other people delivering internal training, letting me invite external speakers, and the rest
  • releasing some open source, even while in an "enterprise" market: github
  • letting me coordinate the internal developer education
  • sponsoring a bunch of conference speaking (there's more!)
  • trusting me to convert the build from msbuild to FAKE and kick start the journey to automated deployment (which was a slow and painful one in msbuild world…)
  • picking solid, generous people as staff - that's just one example from many, and the company often matches the giving of the staff

I'm hoping my last piece of work here, converting our main product repository to use Paket rather than nuget for dependency management is a gift that will keep on giving to the rest of the devs; here's to many more years of 15below bringing tech to the travel industry.

EasyNetQ Process Management

Obsolete blog post warning!

Since this blog post has been written, I've been working on RouteMaster. It's much better than what's described here, and you should check it out.

…and now, back to your original blog post.

TL;DR: I wrote a EasyNetQ aware process manager library. Read down for some examples, and leave feedback if you think anything should change before it's released.

EasyNetQ is a nice little .net client library for RabbitMQ. Originally designed for introducing Rabbit (and the concepts of a bus based architecture) to a company and programmers who hadn't previously used them before, it uses conventions to set up exchanges and queues - basing them on the names of the .net types that are being sent and subscribe to.

For example (from the EasyNetQ homepage):

1
bus.Publish<MyMessage>(message);

Will publish a message of type "MyMessage". Generally there's no need to actually specify the type here, C# will infer it for you, but it makes the example clearer.

Other services can subscribe to "MyMessage" like so:

1
2
bus.Subscribe<MyMessage>("my_subscription_id", msg =>
      Console.WriteLine(msg.Text));

Extracting Information From MsBuild

Recently as part of some research into making a large (very large) solution build more efficient, I started looking into whether there's anyway of getting MsBuild to do some of the donkey work for you. This is especially important in situations where you want to know what's being used/produced with this particular set of parameters.

Obviously dealing with every possible custom build target is out of scope, but you can get a surprisingly long way by taking advantage of some of the intermediate build targets used within the MsBuild Common targets files (imported into every *proj file created by Visual Studio).

Create yourself a little file called something like Analyse.proj, and put the following in it:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="WriteStuff" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(TargetProject)"/>
  <Target Name="WriteStuff" DependsOnTargets="ResolveReferences">
    <Message Importance="high" Text="References::@(ReferencePath)"/>
    <Message Importance="high" Text="Compiles::@(BeforeCompile);@(Compile);@(AfterCompile)"/>
    <Message Importance="high" Text="Output::$(OutputPath)"/>
  </Target>
</Project>

This is a mini-MsBuild project that imports an other project - the project you want to analyse. You can "build" this project like so:

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
PS C:\DirectoryWithProj> & 'C:\Program Files (x86)\MSBuild\12.0\Bin\SBuild' .\Analyse.proj /nologo /p:TargetProject=./Fake.Shake.fsproj
Build started 07/08/2015 15:05:27.
Project "C:\DirectoryWithProj\Analyse.proj" on node 1 (default targ ets).
WriteStuff:
  References::C:\rip\Fake.Shake\packages\FAKE.Lib\lib\net451\FakeLib.dll;C:\rip
  \Fake.Shake\packages\FSharp.Core\lib\net40\FSharp.Core.dll;C:\rip\Fake.Shake\
  packages\FsPickler\lib\net45\FsPickler.dll;C:\rip\Fake.Shake\packages\Hopac\l
  ib\net45\Hopac.Core.dll;C:\rip\Fake.Shake\packages\Hopac\lib\net45\Hopac.dll;
  C:\rip\Fake.Shake\packages\Hopac\lib\net45\Hopac.Platform.dll;C:\Program File
  s (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1\mscorli
  b.dll;C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFra
  mework\v4.5.1\System.Core.dll;C:\Program Files (x86)\Reference Assemblies\Mic
  rosoft\Framework\.NETFramework\v4.5.1\System.dll;C:\Program Files (x86)\Refer
  ence Assemblies\Microsoft\Framework\.NETFramework\v4.5.1\System.Numerics.dll;
  C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework
  \v4.5.1\System.Runtime.Serialization.dll;C:\Program Files (x86)\Reference Ass
  emblies\Microsoft\Framework\.NETFramework\v4.5.1\System.Xml.dll
  Compiles::;Fake.Shake.Core.fs;Fake.Shake.Control.fs;Fake.Shake.DefaultRules.f
  s;Fake.Shake.fs;
  Output::bin\Debug\
Done Building Project "C:\DirectoryWithProj\Analyse.proj" (default
targets).


Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.12

And as you can see, whilst it's a bit ugly it generates a whole load of useful information for you about how this build with these properties will be built.

That's all for now!

Serialization in .net

Leaving the confines of your own process's safe little memory space is always a potentially painful moment when you're coding up an up. Whether it's receiving data from the outside world, passing a message over RabbitMQ to an other in house service, or writing an audit trail that needs to be accessible for the next 20 years, there's a bunch of considerations that need to be taken into account when you hit the joys of serialization and deserialization.

API Design Workshop

Designing an API is hard.

You want to actually apply the principle of least astonishment - but you're the person who wrote the code. You're unlikely to be astonished. So you're trying to think how someone who didn't know what you know would think - which is never an easy starting point!

Similarly, you're trying to create the pit of success for users. Which means trying to make it very hard to do the wrong thing with your API. Preferably, in strongly typed languages, this should include using the type system to make illegal states unrepresentable so that code that compiles is very likely to work.

In general, the core libraries for .net are not bad at API design, but there are a few places where this isn't true. As an exercise, we at 15below are going to take one of them, split into teams and spend an hour or so seeing what alternatives we can come up with. Feel free to follow along at home, and if you do give it a try ping me a code snippet and I'll post it up with our internal attempts in a week or so.

Ecumenical APIs

One of the big sells of shared runtime functional languages such as F#, Scala and Clojure is that you can carrying on using the surrounding library ecosystem and your existing code. The different paradigm occasionally causes a little pain, but there are plenty of blog posts about how to wrap OO interfaces in a functionally friendly way.

This is not one of those blog posts. This is about making sure that your colleagues who are consuming your shiny new code in an imperative language (generally C# in my case) don't threaten to defenestrate you.

At 15below we've recently had need in some of our services of taking a distributed lock between servers. There are many services available designed for doing this, but after some deliberation we decided that we didn't want to add a new piece of infrastructure purely for this one purpose. So Sproc.Lock was born: SQL Server based distributed locking.

In this post, I'm not going to talk about the design of the service. What I'm going to write about is how I engineered the API to be pleasent to use from both C# and F#, giving a idiomatic interface from both languages.

LambdaCon 2015

This weekend I had the honour of speaking at LambdaCon. My own talk I'll be writing some separate posts on in the future, but I also wanted to jot down some notes on the conference before the memory faded.