Earlier quoted context omitted.
So would you then have to do `getActualUsers(db.getUsers())` or `query(db.getUsers())`? Still smells like in such a case the developer avoids the complications of abstraction or OOP by making the user deal with it. That's bad API design due to putting ideology before practicality or ergonomics.
You would have an API that makes the query shape, the query instance with specific values, and the execution of the query three different things. My examples here are SQLAlchemy in Python, but LINQ in C# and a bunch of others use the same idea. The query shape would be: active_users = Query(User).filter(active=True) That gives you an expression object which only encodes an intent. Then you have the option to make bas…
Simplify your code: Functional core, imperative shell
151–160 of 219 posts
Re: Simplify your code: Functional core, imperative shell
#152I wrote our AI agents code with a functional core + imperative shell and I have to agree: this approach yields much faster cycle times because you can run pure unit tests and it makes testing a lot easier. We have tens of thousands of lines of code for the platform and millions of workflow runs through them with no production errors coming from the core agent runtime which manages workflow state, variables, rehydrati…
Great examples. We were taught to pass variables, scalar or compound, into API's. Most of us were never taught to pass functions. Even Python examples in trainings that look functional might not be. They put the function calls in as arguments. The beginner thinks the function returns some data, that would be in a variable, and they are implicitly passing that variable. Might as well, for readability, do the function…
The book Architecture Patterns in Python by Percival and Gregory is one of the few books that talks about this stuff using Python. It's available online and been posted on HN a few times before.
Re: Simplify your code: Functional core, imperative shell
#153While I largely agree with the philosophy, the example provided is not very practical. The code snippet `getExpiredUsers(db.getUsers(), Date.now())` is unlikely to occur in real-life scenarios. No one would retrieve all users and then filter them within the program. Instead, it should be `db.getExpiredUsers(Date.now())`. We should never be too extreme on anything, otherwise it would turn good into bad.
> No one would retrieve all users and then filter them within the program. No one _should_ do that, but that's a common enough problem (that usually doesn't get found until code is running in production). I suspect with the rise of vibe coding, it's going to happen more and more.
Re: Simplify your code: Functional core, imperative shell
#154Earlier quoted context omitted.
> Probably many reasons for this, but what I've seen often is that once the code base has been degraded, it's a slippery slope downhill after that. Another factor, and perhaps the key factor, is that contrary to OP's extraordinary claim there is no such thing as objectively good code, or one single and true way of writing good code. The crispest definition of "good code" is that it's not obviously bad code from a spe…
> However, DDD has a strong object-oriented core, to the extent it's nearly a purist OO approach Really? https://fsharpforfunandprofit.com/ddd/
DDD is described in terms of OOP, but really imo it makes far more sense in fp contexts.
Re: Simplify your code: Functional core, imperative shell
#155[1] https://en.wikipedia.org/wiki/Hexagonal_architecture_(softwa...
Re: Simplify your code: Functional core, imperative shell
#156Even large companies are still grasping at straws when it comes to good code. Meanwhile there are articles I wrote years ago which explain clearly from first principles why the correct philosophy is "Generic core, specific shell." I actually remember early in my career working for a small engineering/manufacturing prototyping firm which did its own software, there was a senior developer there who didn't speak very go…
> Meanwhile there are articles I wrote years ago which explain clearly from first principles why the correct philosophy is ... I think this is a very common mistake. You've spent years, maybe decades, writing code and now you want to magically transfer all that experience in a few succinct articles. But no advice that you give about "the correct philosophy" is going to instantly transfer enough knowledge to make all…
Good old "Programming as Theory Building". It's almost impossible to achieve this kind of transfer without already having the requisite lived experience.
Re: Simplify your code: Functional core, imperative shell
#157This sounds to me like the old hexagonal architecture [1] [1] https://en.wikipedia.org/wiki/Hexagonal_architecture_(softwa...
[0]: https://www.destroyallsoftware.com/talks/boundaries
[1]: https://www.destroyallsoftware.com/screencasts/catalog/funct...
Re: Simplify your code: Functional core, imperative shell
#158Earlier quoted context omitted.
You would have an API that makes the query shape, the query instance with specific values, and the execution of the query three different things. My examples here are SQLAlchemy in Python, but LINQ in C# and a bunch of others use the same idea. The query shape would be: active_users = Query(User).filter(active=True) That gives you an expression object which only encodes an intent. Then you have the option to make bas…
As in Django querysets. But starts to get messy with complex queries.
Re: Simplify your code: Functional core, imperative shell
#159Earlier quoted context omitted.
These are great and succinct, yours and your teammate’s. I still find myself debating this internally, but one objective metric is how smoothly my longer PTOs go: The only times I haven’t received a single emergency call were when I left teammates a a large and extremely specific set of shell scripts and/or executables that do exactly one thing. No configs, no args/opts (or ridiculously minimal), each named something…
I see a similar problem in infra-land where people expose too many config variables for too many things, creating more cruft. Knowing what to hardcode and what to expose as a var is something a lot of devs don't seem to understand; and don't realise they don't understand.
My favorite are things where security policy mandates something like private networking and RBAC, and certain resources only have meaning in those contexts, for heavens sake why are we making their basic args like “enforce_tls” or “assign_public_ip” or “enable_rbac” into variable params for the user to figure out
Re: Simplify your code: Functional core, imperative shell
#160I never liked encountering code that chains functions calls together like this email.bulkSend(generateExpiryEmails(getExpiredUsers(db.getUsers(), Date.now()))); Many times, it has confused my co-workers when an error creeps in in regards to where is the error happening and why? Of course, this could just be because I have always worked with low effort co-workers, hard to say. I have to wonder if programming should ha…
(Clojure) ;; Nested function calls (map double (filter even? '(1 2 3 4)))
;; Using the thread-last macro (->> '(1 2 3 4) (filter even?) ; The list is passed as the last argument (map double)) ; The result of filter is passed as the last argument ;=> (4.0 8.0)
Things like this have been added to python via a library (Pipe) [1] and there is a proposal to add this to JavaScript [2]
1: https://pypi.org/project/pipe/ 2: https://github.com/tc39/proposal-pipeline-operator