@drewverlee
I totally agree, adding a layer of functions raises the bar, so it needs to pay for itself.
In the episode, we were talking about a cohesive set of functions to operate on a "state", specifically the set of websockets that are currently connected. So the functions are not generic, they all take state
as their first argument.
These functions hide implementation details (allowing for growth, encapsulating logic), but they also serve as a list of all the valid operations. The state is just a Clojure map at the top, so there are an almost infinite number of changes that can be made with the core functions, but in the context of maintaining a set of websockets, the list of operations are finite (add socket, remove socket, update socket ping timestamp, etc). Giving these operations names (by making them functions) allows me to think at the domain level rather than the data manipulation level.
Then, when I'm working on the functions, I can have all of the internal logic in my head, but when I'm working on another part of the application that only needs to manipulate the websocket data, my mind is freed from thinking about those details.
Some functions may end up being just an assoc or filter, but usually they are more complex and the mental savings is higher.
I think were conflating things. adding functions gives us a symbol that lets us re-use a group of logic. If that logic just shadows existing functions then we have just changed names. Making the functions doesn't prevent users from mishandling the state atom. the functions don't prevent me from calling it directly, nor necessarily should they. To do that we could set an add-watch on the atom that prevents state transitions that aren't valid. Along with specs that could be used to generate examples and then we could enriches those with documentation. The functions can serve to allow for internals to change as long as they don't expose the implementation details. But that's almost preventing growth, e.g if done effectively how could outside users extand the api? A language's usefulness is its ability to communicate intent. The semantics of assoc are more widely understood then a specialized function, i think thats a benefit. To be clear, i don't think there is a silver bullet here, but i think i see us reaching for functions because of a bag of benefits and we don't calculate the drawbacks. Because the act borders on an art, its easy for the rhetoric to become dogmatic. I think it points to an issue at the underlying layer, where it becomes hard to communicate intent through the code itself and this issue is bundled with the issue of naming something which defies a simple explanation. The issue is that giving a narrative about the code (naming it) really has nothing todo with sharing logic. I think in the future programming languages and tools will let us separate these concerns so that we can handle each with more care.