Packages managed with pip and versions pinned with pipcompile. One ML production environment forces us to use conda we inherit from the pip environment and try to have as much done by pip as possible.
Formatted with black and flake8
Unit tests with unittest
Azure Dev Ops for running tests, security screening, and CI
The happy path for deployment is build docker images in AzureDevOps unfortunately we can’t do that for good reasons
I’m not a fan of typed Python, it doesn’t work as smoothly as you expect if you’re coming from a statically typed language.
Be careful enforcing pylint quality. It can be a great way to kill your teams velocity.
I’m describing a boring stack that works. All of these tools are 5+ years old and very well supported.
For those who have already done functional programming, they wont take more than 2 days to start getting productive. For those who have written a lot of code, it will take them ~2 weeks to pick up functional thinking.
Anyone who is still uncomfortable with F# after 1 month - well that's a strong signal that the dev isn't a fast learner.
Additionally, I've never had anyone reject our job offer because we do F#. I'm sure a whole bunch of people might only be looking for python or javascript jobs, but that's fine because I'm not looking for them. I always have more people who I want to hire but I can't due to budget constraints.
Source: direct experience - I run a pure F# company with a team size of ~80.
There are a few drawbacks, depending on your perspective:
- compilation is slower than c# and hot reload isn't supported (it's in progress)
- there are very few opportunities to use it professionally
- hiring devs can be challenging
I should remember it later and study more.
For a simple example, if you have one db file per user, as others recommend, how do you check that a username or an email is unique? Do you maintain a "global" db for fields with unique constraints? But then when those fields are updated you need to manage this at the application level, and atomicity can't really be guaranteed... Or is there another way?
You are also thinking of this defensively, "x value cannot exist here if it doesn't exist in y store". Just think how you'd access this, and you'll realize at worst this creates a void of data which your app likely handles anyway.
If there are numerous associations required across these silos. You don't have the right silos yet.
Removing the network latency is a massive gain, especially for small/medium apps, which is most sites. And if you find yourself asking this, the answer is yes, it will work.
SQLite will force you to rethink your architecture a bit, don't forget it doesn't HAVE to be _one_ file. This alone helps you scale further.
There are some chafing points: 1. Schema migrations 2. Configuration, PRAGMA's applied at design time or during each connection
Obviously, implementing them was possible, but what would consumption be like? It turns out, it's amazing. There were already some open-source options available, but none of them had an API that I loved. They often allowed direct access to the internal value, which I felt defeated the purpose.
So, I decided to create Danom with a few key goals in mind:
- Opinionated Monads: Focus on Option and Result rather than a more generic Choice type.
- Exhaustive Matching: An API that enforces exhaustive matching to ensure all cases are handled.
- Fluent API: Designed for chaining operations seamlessly.
- Integration: Works well with ASP.NET Core and Fluent Validation.
The pattern has exceeded my expectations, making functional programming patterns in C# not only possible but enjoyable. If you’re interested in bringing some of the functional programming paradigms from F# into your C# projects, I’d love for you to check it out.
You can find the project here: https://github.com/pimbrouwers/danom.
Looking forward to your feedback and contributions!