I’m a C# developer since .Net came into life in 2002. I’ve built many systems using C#, and I like(d) it. C# is an excellent object-oriented programming language. For the last five years, I’ve built only backend systems with C# – the clients were web clients. The backends we built were almost entirely stateless. Either the client holds the state or the state resides in a database. So we started to write stateless C# code.
Today, we write lots of read-only data-container classes that are passed through a flow of stateless methods and lambdas. Luckily, C# got some new language features that help us a lot in writing simple and understandable code. For example, LINQ makes the processing of lists of data much more straightforward, pattern-matching made our business logic much more concise, nullable reference types eliminate NullReferenceExceptions.
The near past
Of course, we saw the obvious pattern here. These are all features inspired by functional programming (FP) languages. Just a little bit less potent than in a truly FP language. And much more verbose. Although I had never written any commercial software code in an FP language, I knew the concepts and ideas from my time at university, when we had to learn ML. So I started to pay more attention to F#. I was lucky to have a work colleague that organized some F# workshops in my company – hi Raphael Schweizer – and that I met Isaac Abraham and saw some of his presentations. They helped me to form a picture, how we could build our system in a functional-programming way. Or better, a functional-first way because F# knows about classes, interfaces and (almost) everything else, C# has to offer.
But of course, we could not just rewrite our complete code base. First, it would take much time with no direct value added to the product even if the hypothesis that the code would be simpler to maintain would become real. Second, I have other developers in my team who would have to support the switch from C# to F#. They would have to learn a new programming language and some new concepts.
Then, we started thinking about adding an entirely new part of the system. A part that we want to build architecturally separated from the rest, with only a minimal interface to the existing system. That’s when I talked Domenic – my primary peer developer – into thinking about an experiment to build the new part mainly in F# instead of C#.
There are more team members, but to keep this post in a readable size, let’s keep them out for now.
So I defined the following hypotheses, why we should build the new part in F#:
- The type system of F# let’ us model our domain more precisely and concisely resulting in reduced effort in creating business value and maintaining the product.
- F# supports the way we write code better than C# and reduces the mental load (writing in a functional programming way in an OO-first language)
- In F#, everything is an expression and pattern matching enforces exhaustive matching. The results are fewer defects and less testing because the compiler forces you to think about all return values and pattern matching cases.*
Domenic and I agreed that we want to execute an experiment to verify these hypotheses. The experiment consists of these steps:
- Learn the basics of F#
- Migrate a whole existing vertical slice of functionality from C# to F#
- Put the F# slice in production and monitor its performance
- Write the new system part in F#
After every step, we reflect on what we learned so far and whether we need to adapt the experiment, or maybe even abort it.
So the journey began…
* we had a couple of defects due to ignored return values and pattern matching where cases were missing
Find the next post in this series here.
Find all blog posts about our journey to F# here.
This blog post is made possible with the support of Time Rocket, the product this journey is all about. Take a look (German only).