Thank You for the answer!

After I reread my own comment I realized it sounded much more harsh than I wanted. Good you were not put off by the tone. Sorry for that.

I have to admit that my biggest pet peeve with working in Java projects are those high impact changes. I try as much as I can to propose "extending" changes, but working in a team means someone certainly at some point will propose "changing" how something works, without ever realizing all the consequences.

If by using Clojure you get the same benefits of what the best OO practices can give, than I'm willing to give it a try.

I do remember a presentation about working on immutable snapshots of reality, it was something along the lines "How do you normally check if a runner had both feet above the ground?". The example there was, that a typical imperative programmer just checks the first foot and then the other. Naturally, the second check happens some time after the first one. The selling point was that, in Clojure, that you operate on a immutable snapshot of a runner in time, so the feet are by default in the same point in time.

So, I'm liberated from thinking about a whole category of potential errors. I liked it a lot.

There are some other categories of potential errors as well. I mentioned them in my comment and you cleared that up for me.

Still I have another doubt, regarding a typical code reuse scenario. A simple example follows.

Let's say a programmer needs to ask the user for input. He writes a code, which pops up a user interface dialog and wires up an action to the buttons callback. All is fine. As the time passes, there is a need to provide more questions to the user. The dialog code grows. Someone files a bug, that, in a multi-monitor setup, the dialog shows up always on the wrong screen. The bugs get fixed. More dialogs are introduced. Another project starts up and wants to use the nice UI code. We designate it for a separate library. The first project must isolate and make everything generic. The requirement is that both projects must work on top of that library and the first one cannot loose any functionality.

This is where the tooling excels most. You just make the duplicated UI code look the same and use the "extract method" refactoring. The IDE tells you "I just found 5 duplicates, should I replace them all?". You answer yes. The IDE even tells you if there are any potential side effects. If there are none, you proceed. Then you use "use interface instead of method call" refactoring. In that way you can nicely extract contract between the client code from the library code. You move the stuff around, so that the library code lands in other project.

Then, You can just wire the library as a dependency in the Project B. It happens, that some needed functionality is not exposed. So you change the library and immediately see the impact on the A Project.

The case here is: you do not have to understand the A Project as a whole, since the tooling takes care of so much of the static dependencies. You just pull out the fun stuff and patch out the wounds. It does not require a lot of skill or knowledge, so a new project member can also be designated with a such task - not only the knowledgeable rock-star programmers that have the whole project in their head.

If you can assure me that in Clojure you can do the same in a safe manner than I'm all in. :) I'd appreciate any articles or stories explaining such scenarios in detail.