Morning
Listening to the defn podcast with @viebel I think that an error many devs do when it comes to types is that we tend to be too specific, ie we talk about a “user” when we should have talked about “identifiable”. At least in our current codebase the specific types (like “user”) don’t travel too far nor between many namespaces, whereas the more general types (like “identifiable”, “subject”, etc) do.
Morning
I'll add another similar one ^ - writing functions that operate on whole data structures instead of just a part of that data. e.g. add-age
- takes a user and returns an updated user with the age calculated from their birthday. Instead write (age)
which takes a date and returns the age as of now.
This is known as stamp coupling. It's a "low" form of coupling, but it's still annoying. :D
Yes! it would be interesting with a fn like derive
, eg (derive user :age :date-of-birth age)
which would take the :date-of-birth
of a user, pass it to age
and then assoc
the return value onto the user under :age
(defn derive [m derived-key value-key derivation] (assoc m derived-key (derivation (get m value-key)))
I happen to know someone who has written exactly what you're after @slipset :) https://github.com/riverford/mappings
I guess lacking the specific merge
functionality, which surprises me.
Morning. I'm not following completely about stamp coupling. Can you explain it like if I am five?
Not familiar with that term specifically, but in general, one is completing the what with the where.
So at work we have some nested datastructures, consider a user with an address with a street:
{:name "Pez"
:address {:street "Fina Gatan 3"}}
Now, how do you write the function which updates the street of a user?I just realize that this example is terrible, as it’s basically an (update-in user [:address :street] bla)
, but if the structure was more complex, say :addresses
instead of :address
it would be better to have a update-address
fn which could be called on any address, not just the one which was inside the user
Hmm. I now feel guilty of this crime in squares.
You came amazingly close to the address where i grew up, btw.
I discussed this at ClojureD last year https://www.youtube.com/watch?v=Tq7r97G4b7Y at 15:54
Good morning 🙂
morning
i studied coupling/cohesion when I was developing clip. I read "composite/structured design" by Myers: https://en.wikipedia.org/wiki/Special:BookSources?isbn=9780442805845 In that book he outlines levels of coupling & cohesion and how they're found. Myers & Constantine laid most of the foundation for understanding how software systems are tied in this way. Their work is an interesting read to articulate things that have become programming lore/intuition. Wikipedia has the same information & more around OO programming. I'm not sure on the origins of those though. https://en.wikipedia.org/wiki/Coupling_%28computer_programming%29#Types_of_coupling
@pez to actually answer your question 😁 Stamp coupling is when you're coupled by extraneous information and data. The classic example would be my above add-age
. It's the second-weakest form of coupling, the weakest (best) form being "data coupling" - which is the age
function I outlined - it takes the minimal value required.
Ring request stuffing in middleware (shoving dbs, kafka conns, current timestamp, parsed data, event streams, clocks, etc. etc.) is a form of stamp coupling. My belief is that this contributes to the lack of "rails on clojure" - it's so hard to reuse ring stuff because it's so entangled with your specific request map.
Thanks, both of you! ❤️
good talk. thx for doing it
Thank you!