Mavnn's blog

Stuff from my brain

EmParsec Embedded Parser Library

You can find EmParsec on GitHub: https://github.com/mavnn/EmParsec

Type providers, by their very nature, tend to access data external to the .net ecosystem. It can also be very awkward technically to make use of dependencies during the actual type generation process.

This is rather a pity, because accessing all of that external data is much nicer and easier when you have a decent parser to do it with. And F# has very, very nice parser support via the FParsec library. Instead, many (most?) type providers end up creating mini-one shot parsers which can be a bit slow to write and don't tend to have features that come for free in a more complete solution such as nice error reporting.

Writing yet an other parser (YAOP) this week I decided that enough was enough. What I needed was a shared resource that people could pool improvements for that could be easily embedded in projects like type providers were it isn't desirable (or sometimes possible) to take external binary dependencies.

So I built it.

Angels From the Realms of Glory

An angel of the Lord appeared to them, and the glory of the Lord shone around them, and they were terrified. Luke 2:9

It's that time of year again, where the F# community get together to source a collection of weird, wonderful and occasionally useful blog posts on life, the universe and sometimes Christmas.

As mentioned in last years post, I like to go back to the source when it comes to advent posts, so lets dive back into the book of Luke (and learn about agent based programming as we go).

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

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.