Just finished an epic #fsharp coding binge this week. It was like plugging my brain directly into the machine. There was almost no impedance mismatch between forming a design intention and expressing it in code. I have never felt so productive.
The project is an internal tool that I can't talk too much about. Basically it's a console app that pulls data from different teams/departments and "joins" it together (normalizing disparate domain terminology) to produce various reports that it can dump to the screen or Excel.
Features that made this really easy:
- Type Providers (ExcelProvider FTW)
- Good old |> operator and your basic List/Seq/Array functions, which make much of the report-building logic look like KQL (more members of the team know KQL than F#)
- Sum types and match/with for domain modeling. It made defining and evolving DSLs super easy.
- Enforced file and declaration ordering, which was a forcing function for factoring the modules/layers correctly. I think of this not as a limitation, but an underappreciated feature.
- Object expressions. I found a nice pattern in the F# style guide for defining service interfaces and implementing them inline in a function like MyServiceModule.create
- Yes, even classes. It felt very natural to use them for services and domain types with run-time validation.
I feel like I've really hit a groove here, knowing when to use the functional features and when to use OO. Everything just fits, and nothing felt needlessly difficult.
Maybe my favourite experience was refactoring the report-displaying code from a bunch of messy printfn's into a TabularReport domain object that can be turned into either console output or Excel spreadsheets via implementations of an IReportRenderer interface. MVC for consoles :)
It supports column alignment (kind of a PITA in console apps), type-specific formatting for currency and percentages, and conditional formatting. This sounds hard, but it really wasn't.
For the Excel renderer, much credit goes to ClosedXml, which is an awesome library. closedxml.github.io/ClosedXML/
This was a blast. Now I can rest.
Totally forgot units of measure, which were very applicable to the types of calculations used in generating the reports. I ❤️catching bugs at compile time!

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Bruce Johnston

Bruce Johnston Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @bitsforthought

Sep 11, 2019
Wow, these results are sobering. In an effort to turn them around, I’m going to attempt a Twitter #monadtutorial. I realize this has probably been done before, but here goes anyway... 1/
This will not be Haskell-focused. Haskell was my first introduction to monads back in 1999, and it just confused the heck out of me. Instead I’ll use examples from #csharp and #fsharp, since they’re what I know best. 2/
First, ignore category theory jargon. Unless you’re doing actual math (or Haskell), “Monad” as a concept is far less important than its practical applications. So let’s start with what monads are good for, before getting into what they are. 3/
Read 28 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

:(