Hacker News new | ask | show | jobs
by eddd-ddde 483 days ago
How does the REPL approach scale in very large codebases? I.e. code that talks to multiple services, complex configurations, etc..
5 comments

Scales very well.

Immutable data pairs great with REPL.

Because data are immutable, you don't need to care about where that data come from and where it will go. Just focus on what you need to do with that data at the point you work.

Everything is localized due to immutability.

I’ve started learning clojure recently and I haven’t quite grasped the REPL yet. I really like it, but so far the type of feedback it provides feels similar (and sometimes inferior to) a static type system. I mostly use it as a tool for answering “wait what data does this return?” And of course trying functions as I’m building them.

Are there any tricks or habits you learn with the REPL that go beyond what a static type system gives you?

I worked with a 60K LOC thing* that talked to multiple services and had complex configuration. Ran fine on my laptop pointed at the company's dev env.

The REPL let me test my changes while inside the thing as it ran. No problems. Someone wrote a nice *recording* debugger too which helped immensely -- no more "oops, I'm past the interesting part and have to start over"

* in prod we usually give it a small number of large instances

Forgot to add: multiple threads ... multiple DBs ... multiple topics on more than one kind of message queue ... hitting and serving REST endpoints -- all no problem for the REPL and the debugger[0].

If the thing was in Java, each fix attempt would mean waiting for startup and state re-creation. And each successful debug could have meant multiple sessions (vs visiting any mix of spots in a single recording)

[0] https://www.flow-storm.org/

I use Integrant to make systems out of components that are tied together at runtime. I have the option of running real versions or mock versions in tests or the REPL, with config drawn from the environment or config files or parameters. I can boot or reboot any combination of components at will. It’s fairly easy to divide and conquer this way.
I like integrant, but I feel like a lot of the examples I see use it for each web endpoint, which seems like a massive amount of overkill to me. I tend to use it just for the router, but it sometimes feels like I'm not using the library to its full potential with that.
Do you have an example? On the face of it I agree that seems like a baffling thing to do.
Even better than in small ones, because you don't need to spend 60 seconds building and restarting the application after changing one line: You simply redefine a single function at runtime and them can test the effect immediately.