This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-03-06
Channels
- # announcements (4)
- # asami (11)
- # babashka (1)
- # beginners (70)
- # bitcoin (2)
- # calva (68)
- # cider (311)
- # clara (1)
- # clj-kondo (58)
- # cljsrn (18)
- # clojure (37)
- # clojure-australia (1)
- # clojure-europe (22)
- # clojure-poland (6)
- # clojure-serbia (2)
- # clojure-spec (9)
- # clojurescript (11)
- # conjure (4)
- # cursive (16)
- # data-oriented-programming (21)
- # datahike (1)
- # emacs (10)
- # events (1)
- # fulcro (9)
- # girouette (2)
- # graalvm (52)
- # graphql (2)
- # jobs-discuss (5)
- # lsp (8)
- # malli (8)
- # off-topic (17)
- # other-languages (46)
- # pathom (17)
- # portal (2)
- # shadow-cljs (11)
- # slack-help (2)
- # sql (47)
- # tools-deps (14)
- # tree-sitter (1)
- # xtdb (6)
A few thoughts and questions related to the value of “loose-coupling” between code and data:
In Clojure, a customer
namespace that manipulates a map that represents customer
data is loosely coupled with customer data.
While in Java, Customer
class with a static methods that manipulate a Customer
record (or an immutable data class) is strongly coupled with Customer.
One benefit of Clojure approach is that the namespace doesn’t have to “import” the class definition for Customer
On the other hand, a Java developer might argue that the contract between code that manipulate Customer data and Customer data shape is not explicit
For instance, if you want to rename a field in Customer data, how would you discover all the pieced of code that need to be updated
Rich likes to say:
> We should program the insides of our sytems like we progam the outsides
A Java developer might object: > Does it worth it to have code and data loosely coupled when they both live in the same program?
We don’t inherit data from our ancestor classes, we borrow it from the next application. 😉 More seriously data doesn’t live in the JVM most of the time. You just have representations of something external (either messages or some DB records).
Let's compare what happens if we change the name of a data field that comes from outside. In classic Java, you'd have to change the class layout and some of its methods. Would it be simpler in DOP?
Changing names == breaking things. (That’s how you end with misspelt http headers.) Coping with a new field is more interesting: new protocol version, or db schema update. What do you do of this new field your app doesn’t care about (say you are filtering/routing events: you need to lug the field around you don’t need to model it)
In classic java, does the code that implements filtering/routing events logic need to import class definitions for all types of events? I guess there are “design patterns” that make it possible to have different type of events with a common minimal set of fields to be processed by “generic” code.
How do they manage it in classic Java? They add the new fields to the Event
class?
Either they go with a stratified approach (discrete typed getters + generic get — possibly generic gets, one for each type: getString
, getLong
etc.)
What are discrete typed getters?
Is it something like m.getAsString("price")
?
Are the terms “discrete getter” and “typed generic getter” well known terms?
We don’t inherit data from our ancestor classes, we borrow it from the next application. 😉 More seriously data doesn’t live in the JVM most of the time. You just have representations of something external (either messages or some DB records).
Let's compare what happens if we change the name of a data field that comes from outside. In classic Java, you'd have to change the class layout and some of its methods. Would it be simpler in DOP?