Names Matter (How I Code)
I’ve had this website for about 11 years. I’ve been aware of blogging, in one form or another for about 8 years. But it wasn’t until this year that I started blogging. I resisted for many years. There were just so many ass-clowns with blogs. Why be another? Still, when I sit and code there are often ideas which will come to me and I want to get them out. And yet the topics I’ve talked about on this site (so far) are technical in topic but not in detail. There’s a reason for this. It’s hard to document the mental process you go through when you’re programming. I tried once this past spring when I was working on a small project with LINQ. But even though I typed out a lot of material, it was very hard to pull together something readable out of it and I eventually gave up. This time I’m trying a simpler topic and we’ll see how it goes. The writing is still rough because I wrote it on the spot and backtracked over code I had just written. Hopefully I’ll figure out how to do this more smoothly in the future because there are ideas and notions, both small and large, which I’m uncovering every day and would like to share and discuss.
***
I work with several different technologies on a regular basis. Lately I’ve been working on a .NET Windows app. It’s one I created originally in 2004 and have been maintaining for a client ever since. I’ve been adding some new database searching functionality to the app.
To display the search data in the app I have a series of tabs, all of which contain a customized listview. Each listview has a Display() method which takes in a list of things to display. The difference between each list view is the subset of the data shown and how each column is treated. (There are some columns with special handling.)
After a while I notice this pattern where I’m going to update only the currently visible list view, so I end up with a dispatch table which abstracts away exactly which Display() method I’m going to call.
I started off with a List for doing dispatch, with each tab’s index pointing into the table. But that bothered me.
Mainly, I wondered, what would happen if I added or removed tabs in the future? I didn’t savor the idea of mixed up tabs or a null pointer exception.
At first I thought a hashtable would have the same problem, but that’s because I was “complifying” it, and thinking about using a string for the lookup – either the tab name or tab text.
Then, “Duh”, I thought, “just use the tab itself as the key”.
And it really is a duh, because I’m pretty sure I’ve gone through this exact same internal dialog many times in the past. Oy.
So eventually I ended up with this:
protected delegate void ListProcessor(List<Item> list); protected Dictionary<TabPage, ListProcessor> listViews = new Dictionary<TabPage, ListProcessor>();
I’m still not so happy with the delegate since it is almost the signature for map(), and that seems like a smell. Also bugging me is some vague nag about polymorphism which won’t quite bubble all the way to the top of my brain.
So, anyway, I go on to set up my event handler which captures a tab change. Except there seems to be some kind of retardation here. If you handle TabIndexChanged, that doesn’t fire if you change the selected tab. You have to handle SelectedIndexChanged instead. Which, in retrospect, makes total sense. But the naming could be a lot better here. I’m still not entirely sure what TabIndexChanged does, although I suspect it has to do with tab-reordering. Still, names matter, and that one naming choice is confusing. Speaking of how names matter, here’s the handler I created for SelectedIndexChanged:
private void listView1_SelectedIndexChanged(object sender, EventArgs e) { UpdateCurrentListView(); }
I wish VS would let you enter the function name as soon as you break it out. I’m going to have to rename it anyway, might as well.
Since I’m calling UpdateCurrentListView() from another place, without the event signature, I can’t just point to UpdateCurrentListView(),
but I can give it the same name.
private void UpdateCurrentListView(object sender, EventArgs e) { UpdateCurrentListView(); }
Better? Worse? I don’t know. Ok, yes, I do know. Better. Just not WOW better. Anyway, onto the meat and potatoes of what I’m doing. Here’s UpdateCurrentListView():
private void UpdateCurrentListView() { listViews[tabControl1.SelectedTab](foundItems); }
It’s just one line of code, but even though I *just wrote it*, I knew I wasn’t going to know what it did in about 5 mins. I try really hard
not to let things like that go by. People have to read this stuff, and more often than not those people are me!
The name “listViews” made sense for the dispatch table when I was first setting it up and inserting functions into it. Actually *using* it didn’t make sense at all: “listViews” sounds like a *list* of *views*. In reality this is a list of functions.
I also am not a big fan of the automatically generated names VS gives things. It works well enough, but it doesn’t scale at all. You can only have so many textBox15’s before you gouge our your eyes and swear you’ll stop programming forever.
Then there’s the list of items that will be displayed. That list is shared among all of the views in the containing class. When I originally created it, “foundItems” seemed like a friendly name. But down here (at this level in the code) you’re not thinking in terms of things being found. You want to have a more generic idea of what you’re dealing with.
Some refactoring gave me:
private void UpdateCurrentListView() { displayOnTab[tabs.SelectedTab](SearchResults); }
I realized that while my dispatch table was technically a list or collection, the way I’m using it is as a multi-dimensional function. So why not just name it like a function?
So that’s what I did. Also, I’m only using one TabControl. Might as well go with a friendly name like “tabs”. And SearchResults is generic enough so that I don’t stop and think about the data but specific enough so I have a mental picture of what is happening in the UI when this code executes.
This reads fairly well, is only moderately redundant, and it has a decent English flavor: there’s a subject acting with a verb upon an object.
Good times.