Do you ever start a project and feel overwhelmed? Wouldn't it be nice to pick apart a problem and learn about it bit by bit? In our latest episode, we roll up our sleeves and open our connected editor to shine a light into a murky situation. https://clojuredesign.club/episode/102-replify/ What library do you reach for to help explore a problem?
It's definitely a pleasant experience to be able to explore the problem with the REPL. Add to that the fact that Clojure is a functional language, and you have a nice recipe for exploration eventually congealing into something useful for the actual application. I had a thought this morning that the fiddle files kind of give you what Kent Beck gets out of TDD (he's got a "by example" book that goes through his process). Essentially, Kent uses TDD as a way to clarify his thinking, and limit what he codes (avoids a lot of speculative code). Fast tests give you something close to REPL feedback while you're exploring and feeling out the problem space. Actually, not really close, but at least in the same ballpark. I say not really close for two reasons: 1. The REPL is not only faster, but it eliminates some friction, like having to write the exploration as formal tests and then run them. If you want to promote some of that exploration to production code, it's likely not a 1-to-1, unless you spent the extra brain cells to "design" while you explore. 2. Clojure being a functional language means the exploration is either functions or data (or functions operating on data). There's very little cost on getting the "design" wrong. I can't count the number of times I've tried to TDD something that had to integrate with an existing system or component of an existing system (think your piece of the pie gets newed up via reflection so you don't control the constructors) and have discovered that my nice, elegant design didn't survive the reality of the environment. Writing this out makes me realize it's basically turtles all the way down: functional+REPL is a nicer experience because it decomplects exploration from design (but doesn't prohibit or increase the difficulty of either).
Do you often find yourself with a sort of general purpose "fiddle library"? Where do you keep that and how do you make use of it? Just a dev dependency from a git repo or something?
@jason.bullers Nice comparison to TDD. I hadn't thought of that, but yes, using the REPL and TDD both have "fast feedback" as a goal, and that's great for exploration. Clearly, the REPL allows for even more, but TDD is a nice coping mechanism in REPL-less languages.
My "fiddle library" is core. 😉 I'm half kidding. I haven't had the need for things across projects, but within a project, I'm make other files under the fiddle namespace and require them from other fiddles. Eg. "fiddle.fs"
In all my fiddling, I can only think of one thing that I would want to reuse across projects and it's very small. It was a caching facility similar to memoize but was easier to control the reset. This was useful when the data-load part of a fiddling call was expensive and didn't change much. I would cache the data at that level with this function and then I could iterate on the downstream code quicker. I think if I were to actually decide to use it, I would probably just copy that little namespace into my new project area instead of going through the scaffolding needed to use deps.edn to pull it in. All the rest of the fiddle code is bespoke to the projects I'm working on, and that's rather the point. I don't want to build up to much abstraction when the point is exploration.
> discovered that my nice, elegant design didn't survive the reality of the environment Oof, been there too many times to count... 😉
Hmm I see. I'm a bit surprised by not needing a common lib. Could be a distinction based on paradigms, or maybe application level programming vs fwk code. I've written a lot of pieces that, if I had to write them again from scratch, it would be a challenge. And since they were written for work, they'd be forever stuck there in that code base when I move on. Things like really good test fixture scaffolding with configuration and a fluent DSL, or even a custom DI container because it simplified organization of cucumber scenarios without requiring a full DI framework brought in as a dependency. Sure, I could rewrite them next time I need them, but man, figuring out how to do self types in Java again isn't my idea of fun.
Having the seeds of exploration when I figured those out would be valuable
@jason.bullers Maybe it's my years of TDD talking, but I think of TDD as different from my REPL usage. (Disclaimer: not a professional Clojure developer.) TDD gets me code coverage, artifacts for future readers that help with understanding the prod code, and prod design benefits. I find that my fiddling is useful too, but for the reasons described in the podcast. But they're kinda unstructured, so when I come back to them later it takes me a while to remember what the heck I was doing in them. Still useful though. But having said that, I use the REPL for exploring too!
Aside: I came from Scheme+emacs back in college, so the REPL and a REPL-connected editor weren't new. When listening to the latest podcast, I realized that I used those old REPL habits, including something like fiddle/rich comments, in Java code all the time! I'd have a text file full of Java code I could plop into a debugger to explore what was going on in the runtime. It's has more friction and is less flexible than the REPL. And it certainly wasn't a popular way to code.
@john.t.richardson.dev I think I'm probably in the same boat for TDD: I generally find I can't really do it for most things, at least at first. My general way of working is exploring through other means (reading, debugging, hammock time), getting a skeleton implementation in place, and then TDDing meat on it. When I mentioned it above, I was thinking in terms of sales pitches for TDD I had read in various books. There are points around using it to explore the problem, or to learn how third party libraries work. Basically tests as throwaway scaffolding. I haven't tried to backport REPL exploration, but I'm not sure I'd want to. It'll probably just make me sad with how much is missing 😄
@jason.bullers Yeah, we're on the same page! You're right that TDD stands in as an exploration device. It's clumsy for that vs the REPL. BTW: My apologies if I came on too strong. I'm sensitive from living in a legacy app codebase in my current day job, where testing is largely given only lip service by management, so I find myself explaining the rationale all the time. Don't want to let that bleed into here too!
@john.t.richardson.dev No problem 🙂 I've had a similar experience years ago, though testing was always considered important. The application is a desktop application and so the test plan was very much built around documenting manual test flows. The natural consequence of that was that, even if you wanted to start automating tests, it was exceptionally painful to do because certain business logic could only be triggered by button clicks, for example. It was a real challenge to figure out how to safely make the appropriate seams for automated tests, build a useful set of test fixtures, and change the culture. Thankfully, in my case, even though the battle was uphill, people understood the value. And doing the hard work to remove the challenges starts to pull more people to your side. Or you're unfortunately stuck against a brick wall, and then maybe your only options are to learn as much as possible and find somewhere else to apply those lessons.
@jason.bullers Yup! Same analysis. In my case the ideas are starting to bubble up, but cultural change is hard.