5 ms·
I'm trying to evaluate clojure for standard enterprise applications. But I haven't seen anything on how to model entities and relations without a database:
by new_account5648 9y ago
I'm trying to evaluate clojure for standard enterprise applications. But I haven't seen anything on how to model entities and relations without a database:
Entities:Person, Insurance, Car
Relationships:
Insurance--hasHolder-->Person(m:1)
Insurance--insures-->Car(1:m)
Car--hasPrimaryDriver-->Person(1:1)
Person--drives-->Car(m:n).
Additional constraint: hasPrimaryDriver(C,P) => drives(P,C).
The domain has cyclic relationships, hence I cannot model it as a tree. If everything is immutable, I have to update all entities that reference each other when replacing one?! What's the standard clojure way to implement it?
- jasim 9y agoThis was one of the questions (unarticulated at the time) that kept me away from value-based (immutable) programming for a long time. The answer is straight forward: you use unique identifiers instead of references. A lot of your code would become similar to how you write SQL queries. You always use `id` to cross-reference entities. You can use whatever enumerable functions are in the language - List.find, Map.find etc. Now if you want to mutate a leaf node inside a tree, well that question is itself invalid. You can't "mutate" a "value". Can you say mutate the number 12? Or the letter 'B'? Imagine every complex data-structure was atomic like this: the array [1,2,3] always remain [1,2,3]. You can't mutate it because it is one single value; you can get information from inside it, but that doesn't mean you can go and change it. If you do want to change it, then you "transform" it into a new value. So instead of using `array.push` in Javascript, you'd use `array.concat` which provides a new value. Or even better you always use the rest operator `{...oldHash, someKey: newValue}`. This also means your complex, large tree structure is a "value". You can't mutate it. You can however transform it into a new value. So if your leaf node has to change, then it means what you now have is an entirely new value. The old value still exist; any variables that pointed to the old value still point to that, because, duh, values don't change. Rich Hickey has articulated all this really well in his talk "The Value of Values" (https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/ValueOfValues.md https://github.com/matthiasn/talk-transcripts/blob/master/Hi...) You'd now be rightly vary of the space-time implications of copying over large sets of data everytime you want it changed a tiny bit. This is solved in functional languages by using structural sharing. When you get a new tree value with just one node changed, the runtime would actually share most of the tree structure, and newly create just the one we want changed. It'll update the reference pointer of the root node, and the entire path that goes from the root till the leaf that changed. This means if you do a shallow comparison between the new tree value and the old tree value, you'll immediately know they're different. You can also safely assume that the entire path till the changed leaf has a new reference and you can do quick shallow comparisons. This is however an optimization and implementation detail. We're able to do this because structural sharing still allows us to keep the semantic model of everything is value for all practical purposes yet have the benefits of immutability. OCaml lets you do both though - it supports the imperative place-oriented way of programming and value-oriented programming. It encourages value-oriented programming through its syntax and runtime library, but when you need it (for performance reasons), it is there for you.
- cutler 9y agoI don't quite understand your question. Isn't entity relationship modelling an abstraction over the database rather than something separate? In Clojure raw SQL with something like HugSQL is more idiomatic than anything resembling an ORM though you can try to use Clojure as a simpler way of accessing Java classes, in which case all the usual suspects are available.
- refset 9y agoThis would do the trick: https://github.com/tonsky/datascript https://github.com/tonsky/datascript