Fork me on GitHub

I havent’t read book, but it strikes me how much they try to get the simplicity that we already have i Clojure.


I'm writing a big new service backend in Java, after a few years of writing them in Clojure and only maintaining existing Java backends. It's really making me realize how much more complexity Java adds. Immutable defaults is really a game changer.


Even seemingly simple things. For example, a class takes an init Map as constructor and sets that map on its internal Map field. Then methods on the class are use to modify this map internally. What could go wrong? Well if the caller creates the map with Map.of() then they are passing an immutable Map, and later at runtime when the methods try to modify it, because that's the map it added to the class at construction, it will throw an error.


So now, one has to manually implement deep copy code in the constructor to copy all key/values deeply from the provided map into a map they internally instantiates.


It's things like that I never needed to care about haha in Clojure.


Another example, you have an entity you model in your application, say it represents a TODO list. You have a repository class that is supposed to save this entity to JSON and then to disk, and later load the TODO list back from disk and return the entity from it.


Ok, but your entity is supposed to encapsulate its data, and only provide methods to change it like addItem, reorder, etc. But if you do that, then where do you put the toJSON and fromJSON method? It can't be outside the class, because it doesn't have access to its internal data unless you make it all public and break encapsulation. But if you put it on the entity class, it couples the class to the specific way you store the TODO list, say later you change to XML, or actually want to store it in a MySQL table? So you can't modularize things as easily, it seems to just want to couple everything.


Yes, I totally agree (I did Java enterprise for 19 years). Even a basic thing as how to implement the equals and hashCode methods is a problem. In the test context, you usually want to compare all fields, while the ORM (e.g. Hibernate) requires you to use the ID (the primary key in the database, if it’s an entity class). Which means you either have to break encapsulation or the single-responsibility principle. There are also problems with inheritance related to this, so it’s actually a real mess.

💯 4
java 1
Martynas Maciulevičius19:09:42

You could do a DTO for the REST, then convert it to your POJO, then do another DTO for the DB (also use ORM because everybody loves ORMs). With only a couple of static factory functions you could retain encapsulation in your Business logic layer (oh hey we have layers now). But what are you actually trying to protect against by using encapsulation...? You've now tripled your sources because you wanted to hide some fields from your devs. Also don't forget setters and getters for your fields and annotations for all the things. And Spring.


Yes, DTO is one solution, but it just shows how more complex patterns need to be added to solve complexity created by previous constructs. The reason you need encapsulation is because it's all mutable of course 😛, if you lose track of where it can be mutated, you can get yourself into trouble. The other issue is the coupling, the domain entities are supposed to be the inner layer, if you refactor them, it shouldn't have to break the outside layers. And finally, there's a kind of code discovery issue. When someone has to choose where to make the change, if they see that they have an object with a method on it that is the method they'd need to change the data how they want, it looks to them like that makes sense. So its tempting to say change the object where it wasn't supposed to be changed if in your editor you see that in method X you have object Y with a method DoWhatIWant, why would you not make the change there?

Martynas Maciulevičius19:09:46

But what is the alternative to DTO is you want to have "inner" entities? Probably there is none. And I would probably have to do it in Clojure as well :thinking_face:


In Java? Ya, I have not found an alternative to DTO, though I use records for them now, that's about the only change. In Clojure, none of this is an issue, since you are actually just working with immutable maps. You can just return the map to the outside, and if you want, you can just remove the keys that are internal when you return it.


It's kind of similar, just so much simpler in practice. Like in Java, for each entity I also have a corresponding record, and I need a mapper back/forth. And also when you create the DTO, you might need to perform deep-copy if you want to prevent changes, or make sure your DTO only has getters and all fields are private otherwise.


"peer-to-peer, gatekeeper-free community-run networks and social spaces for everyone" implemented in Racket "At the heart of Spritely is Goblins, its distributed object programming environment. Goblins provides an intuitive security model, automatic local transactions for locally synchronous operations, and an easy to use and efficient asynchronous programming for encapsulated objects which can live anywhere on the network."

🔥 2

Neat! You might also be interested in @U09K620SG’s and/or the language, both doing very cool things with programming languages designed from the ground up for distributed environments (in different senses as I understand it -- Photon for client/server, Unison for distributed runtimes in general).


Interesting! That is also what we are aiming for with the replikativ libraries.

nice 2

I haven't had occasion yet to play with the replikativ stuff, but it seems incredibly cool.


Wow, looking at it seems like it's come a long way since I last looked at it, too 👏