Over 10 years ago, I had this sort of a prediction that, with the massive adoption of a dynamic language like javascript on both client/server sides and test-driven development gaining a lot of ground, the future of programming would be dynamic and “feedback-driven”. As in, you would immediately see the results of your code as you type, based on the tests you created. To naively simplify, imagine a split screen of your code editor and a console view showing relevant watch expressions from the code you’re typing.
Instead what happened was the industry’s focus shifted to type safety and smart compilers, and I followed along. I’m just not smart enough to question where the whole industry was heading. And my speck of imagination on how coding would have looked like in the future wasn’t completely thought out. It was just that, a speck of imagination that occurred to me as I was debugging something tedious.
Now, most of the programming language world, seem to be focusing on smarter compilers. But is there some language or platform, that focus instead on a different kind of programming paradigm (not sort of OOP, FP paradigm, may be call it the programming workflow paradigm?). May be it comes with a really strong debugger tooling that’s constantly giving you feedback on what your code is actually doing. Think REPL on steroids. I can imagine there would be challenges with parsing/evaluating incomplete code syntax and functions. So I guess, the whole compiler/translator side has to be thought out from the ground up as well.
Disclaimer: There’s a good chance I simply don’t know what I’m talking about because I’m no language designer or even close to understanding how programming languages and it’s ecosystems are created. Just sharing some thoughts I had as a junior dev back in the day.
The main issue I have with this is the exclusive focus on happy path. The point of unit tests and especially mutation testing is to validate that every code path has a defined test and hence defined behavior. I wouldn’t want to give that up, myself. I’m a huge believer in type safety and immutable objects and other things that prevent architectural misuse.
Just to share a perspective from erlang/elixir: pattern matching to filter for only happy-path inputs and the principle of “letting it fail” (when the inputs don’t match the expected shape) works really well in some paradigms (in this case, the actor model + OTP, erlang’s 9 9s of uptime, etc). In that kind of architecture you can really only care about the happy path, because the rest is malformed and can be thrown away without issue.
I’d imagine there would be no need to give up type safety, unit testing and all that though. I’m thinking more about language and tool creators’ focus and efforts going mostly into compiler and type safety.
I’ve seen live updates for things like Go, NodeJS, Vue, Flutter, Angular, and you can recompile a Java class during debugging in Java (with limitations as certain things like static variables and methods need a full restart). More support and integration is certainly better but it doesn’t feel like it’s in a bad place to me.
I wouldn’t say it’s in a bad place either. Most enterprise grade technologies already have great debugging tools. Sure, those hot reloads, live updates are nice for UI development. But, I was thinking more of something built from the ground up to be, well, “feedback driven” in general. Most new stuffs that came out in the last decade touted their compiler as a killer feature first and rest of the tools are only developed as the ecosystem mature. May be that’s just the best way to go about creating new successful language ecosystems, I don’t know. Sorry if it feels like I’m being vague about the specifics. That’s because I really only have vague ideas about whole the whole thing would work.
This is what Smalltalk is all about, and it has been like that since it’s origin: you basically program in the debugger, you program running, you change something, you proceed the debugger, etc. That’s why technics like TDD, refactoring, and others were developed in Smalltalk and just later translated to other languages (and always lacking, since no one reproduces the live programming experience 100%). As the time passed, attention has moved to other languages and most people not ignores what it was to program like that. But there are still some implementations around: I work with Pharo (https://pharo.org), and I can to say is all what you ask for in this post :)
Compose and flutter both have “realtime” previews? And I believe react has something similar? They aren’t truely realtime, because usually there is a compile/execute step happening, but they can be fairly good for rapid feedback?
https://docs.flutter.dev/tools/hot-reload
https://blaszcz.uk/live-reload-with-compose-web/
For unit tests, there is https://infinitest.github.io/, which automatically updates your tests as you code. Never used it though.
I am familiar with hot reloads. What I had in mind was something more fine-grained, not just the UI. A simple example would be that I declared a function signature. Then I write a test. As I start to implement the function, there would be constant feedback visible based on the inputs to the functions from test I wrote. If I declare a variable ‘x’ by adding function params ‘let x = y + z’, the feedback view would show a watch expression of x based on the test’s input. If I changed it to ‘let x = y * z’, the watch expression would immediately change. I would be constantly seeing the result of my actions. May be this is asking for too much with the current technology we have. I don’t know.
Okay, sounds more like infinitest, but sadly that is Java only.
I’ve never really played with it, but jupyter might also be closish to your vision?
Let’s you do python stuff and see results of your code near realtime I think?
I’m not sure that what developers really, really need is faster programming cycles. Most teams could benefit more by controlling the process - from idea to deployed. How much technical debt is incurred because users/customers can’t prioritize features or give accurate requirements, there’s way too much WIP, features are huge, releases are huge and infrequent and the feedback cycles are far too long.
So yeah, as programmers it’s always cool to look at ways to program faster, but what’s the point in programming stuff nobody needs faster? Or programming the wrong things faster?
I’d be willing to be that if you asked any team, “What are the biggest impediments to delivering value to your users faster?”, the answer would be that you can’t cut code fast enough.
IMO Clojure really shines with a REPL-driven development, where you have a REPL to interact with a live running application. You can have a very productive workflow where you conduct little code experiments and incrementally build up functionality. Typically, in this workflow, you’re also sending code (as S-expression forms) to the REPL from your editor to inspect or test the output (some tools have inline display of the output like the Calva Clojure extension for VS Code ). Any tests you come up with in the REPL can usually be turned into unit tests fairly easily (e.g. copy/paste into a tests file) and those tests can be run automatically on source change in the background as well or from the REPL itself. There are also tools on built on top of the REPL that can be used for live inspection of data structures, data visualization/exploration, creating watches on variables, etc. Although the Clojure REPL is best used when developing Clojure applications, I’ve also found it useful for getting familiar with Java apps such as a complex Spring Framework web app that I had to work on.
For Python, I typically use Jupyter/IPython to hash out and test the functionality I need and I find provides a much superior experience to just using the regular $ python
REPL. With PyCharm, the Jupyter integration is really nice and makes the experience a lot more liquid than having to flip between a browser tab and your editor. It’s not quite as nice as a REPL integrated with your live running app, but I personally find it more productive than running a debugger or just spamming print statements and modifying and rerunning my Python script 100X.
I really hope that more languages start to better support for more exploratory, experimental development workflows since sometimes I just want to play around to get familiar with using a library or tool in a sandbox. I think there’s a lot of room to improve developer productivity through blending and integrating together REPLs, notebook-like environments, hot code reloading and other tools/techniques to enable rapid prototyping and faster feedback for developers. Tests and type checking are very useful when you’ve figured out what you need and need to have sanity checks, but can be a major hindrance in that “figuring it out” exploratory stage.