Readit News logoReadit News
desc · 6 years ago
It's useful for development environments to cache things which have not changed in order to shorten the feedback loop. Many do.

The problem is guaranteeing correctness. Correct cache invalidation is Hard(TM). Therefore, the CI system builds from scratch in order to guarantee a clean, correct and reproducible output from a given snapshot of the source.

As for 'live programming' against a running image, this write-up starts with the implicit assumption that this is always a good thing. While it can be useful on occasion, the reason for restarting the application after changing its source code is the same reason we favour functional, immutable styles: mutable state is a pain and it's best to push it out of the thing you're working with if at all possible. Modifying the running image risks ending up with internal states which no single snapshot of the source could ever have yielded.

skrebbel · 6 years ago
People love to complain about Webpack, but it pretty much does all of this out of box, all the way down to hot-reloading UI components. In that sense it's way ahead of all C++, C#, Java, etc build systems I know.

Doing an `npm run dev` type of command in a reasonably set up JS project is very much this staged execution model the author talks about. Everything gets cached, on disk and in memory, only changes are recompiled, and reloads are fast, partial, and often hot-swapped. It's quite close to the maximum level of "liveness" I can imagine.

It's kind of amazing how JS took over older and more established languages in this sense - and we're still not content (judging by how popular it is to complain about webpack). This is great.

tobr · 6 years ago
I’ve never had anything close to this experience with Webpack. In my experience all the magic “it just works” of incremental updates and live reloading is extremely fragile and just gives up silently all the time in large-ish projects. Adding to that, it’s incompetent at what’s supposed to be its core feature: bundling JavaScript modules. I would count it among the least reliable software systems I have to work with regularly.
commandeer · 6 years ago
I think what it does is amazing in terms of hot reload, etc. But yea, I always make sure someone on the team I am working on is a master at it, because some people are and some people aren't and if nobody on the team 'thinks' in the way webpack does, it can be terrible.
Cthulhu_ · 6 years ago
I understand where Webpack et al came from, but the more I work with it the less I like it. There used to be a time when the JS I wrote was the exact same that was executed. Now, even in development mode, it gets pulled through several tools (webpack/babel and a heap of their plugins, a minifier, source maps get generated etc) before my changes are visible, even in an incremental / hot reloading build.

It's not just build time, it's the indirectness. I'm seriously contemplating dropping it for a next project and just writing straight JS, whichever dialect (es6?) has the widest adoption.

SamBam · 6 years ago
Which is fine, if you have no need of any dependency management (stick everything in script tags and reference globals), your script is going to be made up of only a few individual .js files (every one has to go in the header), and you have no use for JSX or TypeScript.

For most people working on larger projects, though, the advantages of real dependency management (however broken NPM is) and transpiling JSX or TS is worth the compilation, which you get used to.

ratww · 6 years ago
If you don't need backwards compatibility, you can use ES6 modules directly in the browser [1] and even load NPM packages in module format from Pika or Unpkg.

Living without a bundler was alright.

At my last job we checked Google Analytics and almost 100% of our users were on greenfield browsers, so we moved to that and had no issues.

[1] https://www.sitepoint.com/using-es-modules/

mishoo · 6 years ago
You won't get what true "liveness" is until you work in Lisp or Smalltalk. The ability to change a function in a running program, without restarting it. Automatic reload might seem cool, but reload means your application restarts and loses state. Imagine you have some Web app and you open some menus/dialogs, perhaps it's connected to some server via WebSockets etc. and you find a bug somewhere, you go to the code to fix it, but reloading the page means you start from scratch and need to open again those menus/dialogs, and reconnect the sockets, in order to test your fix.

Common Lisp had true liveness for decades; it's almost mandated by the standard, it's designed in such a way that you can actually recompile a function, or even redefine objects, adding or removing properties or methods, at fucking runtime without restarting the application. Objects already instantiated will remain so and will be updated to reflect the change. You don't restart. That's the true "liveness", but seriously you don't get it until you try it, and once you get it you become depressed because you realize it doesn't really exist in any mainstream language.

JavaScript is some decades behind this dream, even with stuff like Webpack.

jcrites · 6 years ago
> You won't get what true "liveness" is until you work in Lisp or Smalltalk. The ability to change a function in a running program, without restarting it

This can be done in a number of other common languages today such as Java (JVM languages) and C# (probably all .NET languages). Most IDEs I've seen for those platforms support it.

Substantial enough changes to the code can require an application restart, but most changes you might make like changing the implementation of a function, adding new functions to a class, etc., will not. Hot Code Replacement (HCR) has been supported since Java 1.4: https://wiki.eclipse.org/FAQ_What_is_hot_code_replace%3F

Fully dynamic languages like Lisp and Smalltalk permit a greater degree of this than statically typed languages do, however, since they don't have types and a type system to wrangle with. When I've used it, hot code replacement supported most of the changes that conceptually make sense to support.

HereBeBeasties · 6 years ago
If you use webpack's hot reloading properly with something like React, then you get to keep your state - it's only the functions that get swapped out. So it's actually exactly what you describe, and it's brilliant - so much more productive. This isn't even all that new (in web dev terms) - I had this working probably four or five years ago now on a project.
fenomas · 6 years ago
Huh?

I do procedural music in JS/web audio, and my projects are set up so that changes to the logic and instruments all happen live, while the music continues to play.

How is that different from what you're describing? What specifically can't webpack/HMR do?

baddox · 6 years ago
It’s relatively simple to have live reloading of individual JavaScript modules in Webpack. If you change the text on a React button component, that module will be recompiled and its new version injected into your browser and re-rendered. The text on the button in your browser will change, but other state will not change (e.g. something in your Redux store).

I’m not an expert, but I think the way it works is that Webpack provides a way for JS modules to register callbacks for what should happen when Webpack detects changes in them and recompiles them. React then provides such a callback implementation for component modules that causes the individual component to re-render. Webpack’s development server also provides a way to inject new code into your app running in a browser.

Things get a little more complicated if you want to hot reload things that deal intimately with state, like Redux reducers or middleware. AFAIK people usually just have the browser do a full page reload when changes are detected in those modules. I think Webpack will actually automatically trigger a full page reload if it detects a change in a module which does not explicitly declare how hot module reloading should be handled.

I only mention React and Redux because it’s the only major stack I’m at all familiar with; I don’t know if other stacks provide similar functionality.

skrebbel · 6 years ago
FWIW hot reloading React/Vue components come quite close to this.
dragonwriter · 6 years ago
> You won't get what true "liveness" is until you work in Lisp or Smalltalk. The ability to change a function in a running program, without restarting it.

Erlang provides this as well, as do many dynamic languages. However, aside from certain Lisps and Smalltalk that are image based, and a few others, liveness and source persistence are typically traded off for each other. I can make a live change to a Ruby system if it is set up to provide a REPL, but unlike a live Smalltalk change I won't then have the source code for the changed but available the same way it is for the rest of the system. As a result, in many languages live coding features are mostly a tool for experimentation (usually in nonproduction environment!) on code that will eventually be incorporated into traditional source tree for a from-scratch build.

toolslive · 6 years ago
- IBM's visual age for java provided most of this for Java too. (yes, it was modeled to the smalltalk env with the same name)

- Zope (python app server) had a feature where you could debug a web application (in production) in a private session, so all code modifications you did in your session were private until you committed the code.

imtringued · 6 years ago
Webpack has 600 transitive dependencies. There is no way you can use that in a serious business if you care about security.
zelly · 6 years ago
Arguably Skaffold and other container tools are approaching Webpack in its nonstop build-edit-rebuild workflow. But it's still not part of the code's build process. I'd like to see something like Webpack for native code.

The hypothetical build system can, whenever files change, run the build again (in a container), execute tests (complaining when you break one), or let you keep the debugger open while you're editing (best attempt made to fast forward).

This is probably better suited for modern languages with proper modules and incremental builds, like Rust, C++20, Java9.

Insanity · 6 years ago
I'm not a web dev but used webpack some years ago. Is the issue not that webpack works fine once you finally get it working, and the complaints are about all the issues before it does?
skrebbel · 6 years ago
Yes it is, but this article highlights what an achievement it is that webpack is possible at all. I think Bracha would gladly struggle through some config if that was all that stood between him and his holy grail of liveness.

Plus webpack got a lot better even in that regard, and there's alternatives like Parcel pushing the curve. Web devs sometimes don't realize how good they have it :-)

baddox · 6 years ago
Perhaps, but you’d get similarly unsatisfactory reviews from any technology before you have learned how to use it. Criticism of how difficult it is to learn a technology is valid, but it’s not a valid criticism to say that a technology is not working well before you have learned how to use it.

Deleted Comment

kstenerud · 6 years ago
The biggest problem I see with live systems is this:

The longer you run without a restart, the more dependent you become on the current state. And the more dependent you become, the more likely it is that restarts will be catastrophic due to lost implicit state.

specialist · 6 years ago
Keen point.

There was (is?) a live code editing capable browser which updates the source code. My failing memory seems to remember creating a project and mounting directories. Chrome? Great idea, but IIRC, also very brittle. And because it had it's own notions of "project", there was some impedance mismatch with the IDE.

alkonaut · 6 years ago
Not sure I understand the concrete suggestion here. When I develop I have "live" edits. (JS reloads, C# edit-and-continue, jvm hot reloading etc). But that's stile prone to being out of date, which is why there is a server that builds everything from scratch ensuring that we can reproduce it (as the local developers' edit loop sells those guarantees for speed).

Obviously even a compiler on a server can be caching and clever and not rebuild everything (if you use a source package manager like cargo then you may run into this, but if you have a binary package manager like nuget then you don't - each compilation unit is either required to build or it isn't, and external dependencies are always just fetched).

nunb · 6 years ago
Gilad Bracha is one of the Smalltalk luminaries (his dialect is called Newspeak) and so he's really alluding to the ST way of doing things, where textual code is instantly compiled to machine-code or JIT-ed ... he's basically against the idea of a compiler as a separate binary that spits out an executable.

I believe that's why he goes on about 'live-ness' which is a very smalltalk concept of a "live-image" of the running program. I doubt what he means is directly translatable to the Javascript world, although perhaps a running browser with JS in it can considered to be the live-image (like, say, the Clojurescript/React/Figwheel way of working).

But as you note, in the JS-dev world, very often you do need to reboot and start again (say if an external resource like a CSS has changed).

benschulz · 6 years ago
I believe many posts here miss the core point. The article is talking about _liveness_, i.e. modifying the program while it is running. One example of this would be Squeak[1]. Another perhaps more relatable one is modifying your HTML5 app from the browser console.

[1]: https://squeak.org/

dbmikus · 6 years ago
In Smalltalk, does anyone actually modify the production application live? I would think you'd want to modify the live application in devel, and then copy it over.

At this point, you can either copy over the difference or just replace the whole production application. I'm not sure which would be faster.

I don't think liveness is important for a production system. I prefer production to evolve in discrete chunks. Liveness makes sense for development.

I suppose one other benefit of a live system is that you could deploy an update without without restarting the application. But at some level, you would be restarting part of the application, and you are just shifting the update logic from the networking layer to the function call layer or object layer or whatever minimal layer of swappable component you can deploy.

Kinrany · 6 years ago
I barely touched Smalltalk, but I think people value liveness as a feature for the user, not the developer. This is basically ultimate customization: you can change the source code of your local copy.
cjfd · 6 years ago
There are other ways to get liveness, though. You could make it such that multiple instances of the program can run and make, e.g., sure that new logins go to the new one. Once the last login has disappeared from the old program it can be shut down.

As many comments note, the proposal of this post seems a disaster regarding reliablity/predictability.

zelly · 6 years ago
It's most useful in design. Honestly it's not that useful otherwise and just kills attention span in my experience. Basically we went from doing design WYSIWYG-style to completely in markup languages and CSS. So hot reload bridges the gap.
7777fps · 6 years ago
Another example is running SQL commands directly against a live database, which is frequently given as advice of something that should never be done.

So why should I get excited about the ability to live edit when it's held up as bad practice in one of the few areas it's possible.

mhd · 6 years ago
Yes, it seems most of the posters are mostly familiar with the JS build … situation, where the last addendum of the post regarding multiple languages would apply anyway (as you're often building JS, HTML and CSS in one fell swoop).

Modfiying web apps from the browser seems to be a rare case, interestingly. I think there were a forays[1] made in that direction, but the need for external tools to shoe-horn a half-shod module system onto JS was the final straw for that. Never mind the convenience of some nigh-essential language features (SCSS, ES6).

[1]: https://www.amber-lang.net/

dbmikus · 6 years ago
This is what Bazel, Pants, etc (and I'm sure a bunch of other build tools) do for you. You define a dependency graph, then per commit you can see what targets have been modified and then you can run commands on only targets dependent on the modified ones.

I'm not sure why this blog post is written like these things don't exist.

EDIT: on a re read, I'm a bit off the mark. The author seems to want the compiler or interpreter that reads the code to automatically process the dependency graph of what changed (at the finest grain possible) and take appropriate action.

The company I work at has tools for automatically updating our dependency graph relationships, and then commits/diffs execute commands against the dependencies of modified targets as part of the code review and CD process. This is pretty close to what the author is suggesting.

I still think this blog post is written a bit too dramatically.

hibbelig · 6 years ago
> This is what Bazel, Pants, etc (and I'm sure a bunch of other build tools) do for you. You define a dependency graph, then per commit you can see what targets have been modified and then you can run commands on only targets dependent on the modified ones.

This is way less live than the author hints at. Let's take Emacs as an example -- it can be extended using Emacs Lisp. If I write such an extension in Emacs Lisp, and I find that one of the functions isn't right, I go to the function and hit Ctrl-Meta-x and then the function is redefined in the running Emacs, and so I can try again to see if it works now.

Or take the Fish shell as an example. It provides a method to define a function that is automatically saved. So you write a shell function "foo" and you try it out (in your interactive shell) and you see it's not right. You go "funcedit foo" which pops up an editor with the function in it. You make your change and save and exit the editor. You run the function again to see if it now does what you wanted.

A similar experience can be had, I guess, using a Java IDE when working on a web application, if your stack supports hot reload (with JRebel?). You run the application in the debugger, you find it's incorrect, you make a change to the affected method, you save and the IDE hot-reloads the new method into the existing web application and you just try again.

But for all of the above examples, it is still the case that there are two processes -- one redefines things while developing, and the other process kicks in when you turn off your computer and then turn it on again.

I think in Smalltalk, you make code changes using something like the "hot reload" thing, but the new code is automatically saved to "the image". And when you want to run the system, you open "the image".

hyperion2010 · 6 years ago
Another point that seems related is the difficulty of call/cc semantics when dealing with changes in state that are outside the semantics of the virtual machine. It seems to me that there is no easy way to avoid cases like described in the article without forcing explicit accounting of a massive amount of implicit state. Depending on your use case the tradeoff might not be worth it.

On the other hand, I would argue that the idea of a build is an entirely valid and useful construct, it merely represents a point in state space against which test cases (and production) must run. It is impossible to get away from that state. Some tools can make managing it easier, and some make it virtually impossible to manage. Imagine that we discovered a magical halting oracle and that we could compile everything instantaneously, we would still have to figure out what combination of states were valid, and we would call that the 'build'.

iainmerrick · 6 years ago
Yes, that's a good way of expressing it!

I was just thinking that a running application is a little kernel of Code (the stuff that gets checked into source control) and big wrapper of State (what the user is currently doing with it).

The build system view is that the Code is sacrosanct, and what we need to focus on is checking the right stuff into source control and trying to ensure the latest commit is always correct and self-consistent. We should always be able to throw away all the state and rebuild everything from scratch.

The live coding view is that the user is more important than the Code, so we should focus on letting them get stuff done as effectively as possible. And programmers are users too! Therefore we should be able to modify the code without losing any of the user's state.

Both views are correct and what's actually needed is a good balance between the two.

moomin · 6 years ago
I have two main issues here 1) liveness is great, but you run into fundamental problems when you upgrade a data structure that’s actually in use in memory. This problem is seen during deployment in a compile-time typed language and in production in a runtime typed language.

Also, the more we incrementally patch a live environment the harder it becomes to specify what, exactly, is running in production.