|
> A common pattern would be to separate pure business logic from data fetching/writing. So instead of intertwining database calls with computation, you split into three separate phases: fetch, compute, store (a tiny ETL). First fetch all the data you need from a database, then you pass it to a (pure) function that produces some output, then pass the output of the pure function to a store procedure. Does anyone have any good resources on how to get better at doing "functional core imperative shell" style design? I've heard a lot about it, contrived examples make it seem like something I'd want, but I often find it's much more difficult in real-world cases. Random example from my codebase: I have a function that periodically sends out reminders for usage-based billing customers. It pulls customer metadata, checks the customer type, and then based on that it computes their latest usage charges, and then based on that it may trigger automatic balance top-ups or subscription overage emails (again, depending on the customer type). The code feels very messy and procedural, with business logic mixed with side effects, but I'm not sure where a natural separation point would be -- there's no way to "fetch all the data" up front. |
Stacked views are sometimes considered an anti-pattern, but I really like them because they're purely functional, have no side-effects whatsoever and cannot break (they either work or they don't, but they can't start breaking in the future). And they're also stateless: they present a holistic view of the data that avoids iterations and changes how you think about it. (Data is never really 'transformed', it's simply 'viewed' from a different perspective.)
Not saying that's the only way, or the best way, or even a good way! But it works for me.
I think it would apply well to the example: you could have a view, or a series of views, that compute balance top-ups based on a series of criteria; then the program would read that view and send email without doing any new calculation.