Wednesday, August 12, 2020

How to do handle Master-Detail scenarios badly

You have a list, grid, or some other collection in your software (app/website/other).
Someone clicks, taps, or otherwise selects one of the options and is presented with a new page/window/screen/display showing more information or a different view of the option chosen.

That's the basic "master-detail" functionality.
It's straightforward, but there are at least five ways to mess up this experience.
  1. Not remember the position in the list when going back to it.
  2. Resetting the scroll position of the list when returning to it.
  3. Reloading the master list when returning to it.
  4. Resorting the master list when returning to it.
  5. Removing detail from the list and then returning to the list and seeing it there still.

1. Upon going back from the detail to the original collection, the software does not remember which item was previously selected. The focus may be moved elsewhere, or the first item in the list may be selected by default. Such behavior makes it hard to browse using only the keyboard or assistive technologies.
This is exacerbated when the resetting of the list moves the scroll position.

2. You scroll down the list, so none of the items that were initially visible are shown. You select one, view it, and then go back. Imagine then if the list has reverted back to the "top." If you want to keep looking at the options available, it's necessary to scroll back past all the items you've already seen just to get to something new.
It gets worse when the list loads in "pages" of data at a time.

3. You scroll down the list. You get to what is currently the bottom of that list until the software automatically retrieves and then displays more items so you can keep browsing. After doing this a few times, you select one, view it, and then go back. If the master list goes back to the "top" of the list, to get back to where the item you just viewed is shown, the app must repeat the calls to load more "pages" of data. 
It gets even worse when the list isn't always in the same order.

4. You scroll down the list with an expectation to look at multiple items. You reach the first item of interest, select it, view it, and then go back. How frustrating is it then if the list is in a different order? Is it reasonable, practical, realistic, or even possible to remember which items have already been viewed? How can a person be expected to find and view everything of interest in a large list that is constantly changing?
Also bad is when lists aren't updated when they should be.

5. Imagine browsing a list of favorites or bookmarked items. You select and view one of the items. While viewing it you remove the bookmark or other indication that it should be in the special list. What then should you feel if the item you've just removed is still shown on that list?

What other examples can you think of how this experience is often poorly implemented?

Monday, August 03, 2020

Fixing a really common misunderstanding about nuget.exe

It turns out that a lot of people commit a copy of nuget.exe into their code repositories.
Some of them used to be mine. Not anymore.

screenshot showing the number of copies of nuget.exe found when searchiGitHubng

tldr: don't include a copy of nuget.exe in your repository. Instead, add a reference to Nuget.CommandLine and use the copy of the exe the package provides.

It's rare to think about how NuGet works. You can just add the packages to your project, they get downloaded, referenced and everything just works.

But there are some things you might do with NuGet where you can't rely on MSBuild (or similar) to take care of things for you.

You may have to call `nuget.exe` directly.
I've had to do this many times and when doing so it's raised a tricky question.
"Where is nuget.exe located?"
Across all development machines and build/CI servers, there's no single answer.
You can't rely on it being in a particular place. unless you put it there.

So, how do you put it in a specific place?
I've never found any documentation to explain this and so put it in the repository with the code/scripts/whatever that needed it.

It never felt like the right thing to do but I didn't know any better and it seemed to work ok.
As we saw above, I'm far from the only person to have done this.
The only time this became a problem was when I needed to change something that called nuget.exe and needed a feature that was added in a newer version than the one I had checked in. Not a big deal but another reminder that this isn't the best way to do things.

A couple of weeks ago I stumbled across the NuGet.CommandLine package. Again, documentation of this package wasn't something I could find but the name had me wondering. "Could this be the way to perform the command-line NuGet operations I've always wanted?"

Some investigation was needed.

I started by downloading the package and looking inside.

Nuget Package Explorer showing nuget.exe in the tools directory of the package

Bingo! That looks exactly like what I need.

Now, how to reference it?

Fortunately, this is where some documentation did come in handy.

By adding `GeneratePackagePath="true"` to the PackageReference element I could have a way to get access to the version of the executable from the package.

partial view of the project file showing the PackageReference entry with the GeneratePropectPath property set

Now to use it.

By adding this property a new build parameter is created. It has the same name as the package but with two differences. Firstly it's refixed with "Pkg" and secondly, is has non-alphanumeric characters replaced with underscores. so, in this instance, the parameter is called `PkgNuGet_CommandLine`.

With this all set, I could now reference the version of nuget.exe that was downloaded as part of the package by specifying `$(PkgNuGet_CommandLine)\tools\nuget.exe`. As an example, see this targets file, which I use to automatically pack and sign release builds of packages.

That was it. Simple really, but poorly documented. I was surprised how easy it was to fix and why I've never seen anyone mention this before. Maybe other people do talk about this. Maybe other people know this already. That the package has sooooo many downloads makes me suspect that many people do already know this. But the number of repositories containing this file on GitHub also makes me certain I'm not the last person to learn about this.
If you're in the position I was, I encourage you to make the switch to using the package reference instead. Not only will you save a bit of space in the repository but, more importantly, you'll be able to learn when newer versions of the exe become available when a new version of the package becomes available.


I originally investigated the above while streaming on Twitch.  I like to stream there while investigating or researching topics as it forces me to articulate what I'm thinking, doing, and looking for, without getting distracted. Hopefully, it serves as an interesting way for others to learn what I'm learning. Follow me on Twitch to learn when I next do things like this and we can all learn together.