Pierre-Yves David

Core contributor to Mercurial, initiator and maintainer of ChangesetEvolution and Octobus a Mercurial consultancy company.

IRC: marmoute

twitter: marmoute

work: Octobus

Notes and Opinions about User Experience Design

Combining feature by adding `hg command --flags`

It is often tempting to combine command that are often used together through a flag. For example hg pull and hg update are often used in combination, so the hg pull --update flag was added, same applied to hg pull --rebase.

I think that this pattern should be added with care. The main risk is that the new flag will end up pulling a lot of unrelated complexity and associated flags within the original commands.

In the hg pull --update/--rebase examples this meands that --update special action (like merging files) to be dealt with by hg pull which previous did not need the context. Merging changeset comes with new config (like the one to select the merge tools, continue and abort, etc.). You can end up multiplying the complexity of the two commands instead of simply summing up that complexity.

Other good example are hg commit --amend and hg amend, the amend feature comes with various new flags (--current-date, --current-user) and other evolution related complexity (and future flag, e.g. to control orphan creation).

Does this means we should never do so? No, this is definitely useful in various case, we should just do it with care and stay aware of the potential complexity pulled into the command. Adding many more flag losely related to the command and only relevant in some case can make the help harder to follow and the overall user Experience harder.

In previous discussion, RyanMcElroy pointed out that this recurrent needs to combine multiple operation is a hint for the needs of a more powerful alias system. He says that having and easy way to make a "multi commands" alias, possibly while ensuring "atomic" operation could fit many of the use-case that trigger the needs for adding a flags to glue a command to another one.

Another side effect of adding "unrelated" flags to command is that is can drastically affect the "core" semantic of the command. For example, hg pull is a command that adds changeset to the repository, and has absolutely no business with the working copy. having the hg pull --update flag suddenly means it now have business with the working copy. This affect command "boundaries" and can lead to confusing UI. Note that thisis not automatic for example, hg commit is creating a changeset, without altering the working copy contents (the file content stay untouched), adding the hg commit --amend does not change this aspect of the command.

(I am using hg pull --update example because it is clear and simple, but I am not especially against it.)

Feature discoverability, command vs flags, etc

Getting user to discover new features or variant of existing feature is always a bit complicated. In that regards, it is often easier for a user to discover a new command --flags for a command it knows than to discover a new commands entirely. And this seems true.

For that reason, the project have been leaning more toward "less commands, more flags". This sometimes hits the issue mentionned above, where too much logic get pushed into a single command, with either too simplistic handling of some case or too many complexity coming along.

Another common design opinion is that having many different way to do the same things is confusion and should be avoided. Combined with the "less commands, more flags" this has lead to having the "flag" version only.

Over time, I have been thinking about experimenting more about an hybrid approach. Where we could put flag to had basic version of a feature on command where it is likely to be found. (e.g. hg commit -amend) and point to a more powerfull, but narrower commands (e.g. hg amend).

We actually ended up putting it in practice in the past without really realizing it. For example the following chain follow this principle hg commithg commit --amendhg amendhg amend --extracthg uncommit. Each new dedicated command introduce some new flags that did not made sense in the previous one.

It would be interesting to start incorporating this idea earlier in the UX design process and build meaning full "pyramid" of commands to build more and more advance feature at each level.

A possible application of that I have been thinking about recently is how we could have hg merge --linear and hg merge --onto (name can change) to easily bring rebase like feature to user, keeping the more advance case to be dealt with by more dedicated command (like rebase).