Feb 05

Deep Dive into a Hands-On F# Project

Deep Dive into a Hands-On F# Project

Alright, let me tell ya, F# might not be the cool kid on the block like C#, but man, it's been picking up steam thanks to a bunch of die-hards in the community. It's legit becoming a solid pick for practical projects. So, I'm about to spill the beans on the nuts and bolts of a full-blown F# project I tackled - backend, frontend, tests, build, infrastructure, the whole shebang. And guess what? I'm throwing in the source code too. 

Getting on Track with SAFe

So, the game-changer for my ingredient list was this thing called SAFe Stack. It's this dotnet CLI template that's like a Swiss Army knife for building SPA apps that buddy up with a backend. The SAFe project site? Oh, it's a treasure trove of tutorials and examples.

For newbies, SAFe is a godsend. You can pretty much use the template straight out of the box and dive into coding the fun stuff. For example, the site ke-bet.com is made using this technology. But the more you get your hands dirty, the more you'll want to branch out from SAFe.

That 'S' in SAFe's got some swagger - it stands for Saturn, a slick framework atop Giraffe, which is basically a functional wrapper for Asp.net.

Then you've got 'A' for Azure. Now, Azure and I didn't exactly click from the get-go, but if you're all in with Azure, there's this Farmer library cooked up by the same brains behind SAFe.

And the 'F'? That's for Fable, a wicked transpiler that turns your F# into JavaScript - it's the cherry on top of the F# ecosystem.

Backend Blues and Triumphs

So, for the API jazz, I hopped on the Fable.Remoting bandwagon. This gem of a library plays hide and seek with web server abstractions. You just define your contract types in a shared file between backend and frontend, and voilà, implement your API server-side. Remoting handles the rest - proxies, serialization, error-handling, logging, you name it. Plus, it's down with binary data too.

With Fable.Remoting in my corner, dragging Saturn - Giraffe - Asp.Net into the backend felt like lugging around extra weight. But hey, Giraffe's still hanging around for old times' sake.

On the data storage front, I rolled with the NoSql database DynamoDB. I grabbed the DynamoDb.Ok library to access data, which is all about that idiomatic monad-based Reader approach. But let's be real, I wasn't feeling it. Moving forward, I'm eyeing a future where I can ignore data access layer code altogether. Got some ideas brewing... might even spill the beans in a separate piece someday.

Haven't had to tangle with relational databases in F# yet. But I've seen folks in the community grumble about Entity Framework's limited F# type support and throw around recommendations to use Dapper instead.

Last year, the community got a boost with some solid pieces on dependency injection - three articles that really hit the spot. This flexible types-based approach? It's what we're using in this project.

For logging, I went with Serilog, which snuggles up nicely with Giraffe.

When it comes to talking to AWS, it's a mixed bag. I use the dotnet AWSSDK sometimes, but other times straight-up HTTP, because the SDK doesn't cover all the cloud bases.

Frontend Fables and Fairytales

The foundation of F# frontend land is Fable. Your code and most of the standard library get translated to JS. It's a breeze to play nice with JS libraries. There's a whole bunch of bindings for the cool kids on the block, like React and its posse.

The state of affairs is managed by Elmish, which is all about that Elm architecture. Fable.React and Bulma are the artists that paint your webpage.

But, you know frontend folks, always chasing the next shiny thing. Elmish + Fable.React + Bulma? So last season. If you wanna hang with the in-crowd in 2021, you gotta get down with Feliz + Fable.React.WebComponent + Material UI. And don't forget to peek at the new kid, Fable.Svelte. Makes my backend soul weep a little.

For chit-chatting with AWS, especially that message broker in AppSync, I got cozy with the Aws Amplify library.

Stress-Testing Like a Boss

So, you won't believe this – I decided to put the non-functional requirements to the test with some hardcore load testing. But you know what? I ditched the idea of dragging in some fancy third-party tools like JMeter. It just seemed like overkill for what I wanted to do.

Unit Tests? Nah, F# Got My Back

I never bothered with unit tests. And I gotta tell you, there's this awesome sense of safety that F#'s type system gives you. It's like having your own personal bug catcher – most dumb errors get snagged by the compiler before they can cause any real trouble. Throughout the project, I ran into just one major bug in production. That's a record for me! In other projects, I've played around with FsUnit and expecto. FsUnit is like the easy-going buddy that fits right in, while expecto is the flexible friend who can twist and turn with syntax. But between you and me, there's not a huge difference.

And as for testing tools on my radar to try out:

Build and Deploy: Keeping It Smooth

When it comes to package management, Paket's my go-to. And for builds? I'm all about the Fake script life. These tools are part of the SAFe template, but there's been some chatter about issues with Fake scripts not running smoothly, and it seems like we might move towards console app builds in the future. If that happens, I seriously don't see the point of Fake anymore.

For rolling out updates and deployment, I lean on AWS Cloud Development Kit. Officially, it doesn't give F# any love, but it works out of the box following C#, which is pretty sweet.

Tooling Up: The Good, The Bad, and The Glitchy

The good news first – SAFe's got this wicked hot reloading for client and server during development. Once you get a taste of that, there's no going back. It's like, how did I even function before this?

Now, the not so great news. The tooling's getting there, but it's still lagging behind C#. I'm slinging code in VSCode with the Ionide extension. But let me tell you, it can be a pain with the freezes, restarts, and the constant need to delete temp files. I've got this sneaky suspicion that in bigger projects, these issues could really mess with your zen. There's also Rider as an alternative to Ionide. Both have had updates recently, so fingers crossed things get better.

Besides Ionide, I use ILSpy to get into the compiler's head, you know?

Working with F# means you gotta adapt your debugging style too. Less step-by-step, more console output – that's my jam. But having to frequently search and sometimes replace text across project files feels so last decade. And let's not forget getting comfy with tools like FSI.

Wrapping It Up: F# in Early 2024

As of early 2024, here's the scoop on F# for application projects that are small to mid-sized:

Until C# catches up with these features, when all else is equal, I'm Team F# all the way.

UPD: Just a quick fact check – I originally mentioned that F# is seen as an experimental language in Microsoft's ecosystem. My bad, that's old news. F# hasn't been the new kid on the block for like a decade. Loads of companies are using it in production, and it's packed with so many neat features that it's actually pulling other languages like C#, JavaScript, and Scala along for the ride (yeah, seriously).

Leave a Reply