Wandering Thoughts archives


Programs that let you jump around should copy web browser navigation

As part of their user interface, many programs these days have some way to jump around (or navigate around) the information they display (or portions of it, such as a help system). Sometimes you do this by actually clicking on things (and they may even look like web links); sometimes you do this through keyboard commands of various sorts.

(The general common form of these is that you are looking at one thing, you perform an action, and you're now looking at another thing entirely. Usually you don't know what you're going to get before you go to it.)

Programs have historically come up with a wide variety of actual interfaces for this general idea. Over the years, I have come to a view on how this should work, and that is the obvious one; jumping around in any program should work just like it does in web browsers, unless the program has a very good reason to surprise people. Your program should work the same as browsers both in the abstract approach and also, ideally, in the specific key and mouse bindings that do things.

There are two reasons for this. The first reason is simply that people already spend a lot of time navigating around in browsers, so they are very familiar with it and generally pretty good at it. If you deviate from how browsers behave, people will have to learn your behavior instead of being able to take advantage of their existing knowledge. The second and more subtle reason is that browsers have spent a lot of time working on developing and refining their approach to navigation, almost certainly more time than you have. If you have something quite different than a web page environment, perhaps you can still design a better UI for it despite your much less time, but the more your setup resembles a series of web pages, the less likely that is.

At this point you might ask what the general abstract approach of web browser navigation is. Here are my opinions:

  • You can move both back and then forward again through your sequence of jumps, except for rare things which cannot be repeated. In a normal UI, non-repeatable things should probably use a completely different interface from regular 'follow this thing' jumps.

  • The sequence is universal by default in that it doesn't matter what sort of a forward jump you made and regardless of where it took you, you can always go back with a single universal action, and then forward again by another one. You can add extra sorts of back and forward traversal that only act on some sorts of jumps if you want to, but the default should be universal.

    (As far as the destination goes, notice that browsers have a universal 'back' action regardless of whether the link was to another anchor on the same web page or to an entirely different web page.)

  • By default, the sequence of jumps is not a global one but is specific to your current pane, whatever a pane is in your application (a window, a tab, a section of the window). What you do in one pane should not contaminate the forward/back sequence of another pane, because it's generally harder to keep track of a global, cross-pane history and remember where 'forward' and 'back' operations will take you in it.

    (There are clever uses of a global sequence and you can offer one, but it shouldn't be the default.)

  • It should be possible to have the destination of a jump not overwrite the current stuff you're looking but instead open in another pane. This should generally not be the default, but that's somewhat situational.

There are probably other aspects of browser navigation that I haven't thought of simply because I'm so accustomed to them.

There are still reasons to use different interfaces here under the right circumstances, but you should be quite sure that your different interface really is a significant advantage and that a decent amount of your target audience will use your program a lot. Editors are generally a case of the latter, but I'm not convinced that most of them are a case of the former.

(At this point in time I suspect that this is a commonly held and frequently repeated position, but I feel like writing it down anyway.)

tech/CopyBrowserNavigation written at 21:43:46; Add Comment

Go modules and the problem of noticing updates to dependencies

Now that Go 1.13 has been released, we're moving that much closer to a module-based Go world. I've become cautiously but broadly positive towards Go 1.13 and this shift (somewhat in contrast to what I expected earlier), and I'm probably going to switch over to Go 1.13 everywhere and move toward modules in my own work. Thinking about working in this environment has left me with some questions.

Let's suppose that you have some programs or code that uses third party packages, and these are generally stable programs that don't really need any development or change. In the Go module world, the version of those packages that you use is locked down by your go.mod file and won't change unless you manually update, even if new versions are released. In theory you can keep on using your current versions forever, but in practice as a matter of good maintenance hygiene you probably want to update every so often to pick up bug fixes, improvements, and perhaps security updates. As always, updating regularly also makes the changes smaller and easier to deal with if there are problems.

In the pre-module world, how I found out about such updates was that I ran Go-Package-Store every so often and looked at what it reported (I could also use gostatus). I also had (and have) tools like binstale and gobin, which I could use with scripting to basically 'go get -u' everything I currently had a Go binary for (which makes some of the problems from my old entry on using Go-Package-Store not applicable any more).

I'm not sure how to do this in a world of Go modules. Go-Package-Store works by scanning your $GOPATH, but with modules the only things there are (perhaps) your actual programs, not their dependencies. You can see updates for the dependencies of any particular program or module with 'go list -u -m all' (in a cryptic format; anything with a '[...]' after it has an update to that version available), but I don't think anyone has built anything to do a large scale scan, try to find out what the changes are, and show them to you.

(The current module behavior of 'go get', 'go list', and company also seems surprising to me in some areas that complicate interpreting 'go list -u -m all' output, although perhaps it's working as intended.)

Relying on Go modules also brings up a related issue of what to do if the upstream source just goes away. In the pre-module world, you have a full VCS clone of the upstream in your $GOPATH/src, so you can turn around and re-publish it somewhere yourself (or someone else can and you know you can trust their version because it's the same as your local copy). In the module world you only have a snapshot of a specific version (or versions) in your $GOPATH/pkg/mod tree or in the Go module proxy you're using. Even if you vendor things as well, you're not going to have the transparent and full version history of the original package that you do today, and the lack of that history will make it harder to do various things to recover from a disappearing or abruptly changed package.

(I'm a cautious sysadmin who has been around for a while. I've seen all sorts of repositories just disappear one day for all sorts of different reasons.)

(Perhaps someday there will be a Go module proxy that deliberately makes a full VCS clone when you request a module.)

programming/GoModuleNoticingUpdates written at 00:20:35; Add Comment

Page tools: See As Normal.
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.