traject, blacklight, and crazy facet tricks

So in our Blacklight-based catalog, we have a facet/limit for “Location”, that is based on the collection/location codes from holdings, and is meant to limit to just items held a particular sub-library of our Hopkins-wide system.

We’ve gotten a new requirement, which is that when you’ve limited to any of these location limits (for instance, only items in the “Milton S. Eisenhower Library”), the result set should also include all ‘Online’ items. No matter what Location limits you’ve applied, the result set should always include all Online items too. (Mine is not to reason why…). 

One thing that’s trickier than you might think is spec’ing exactly what counts as an ‘online’ item and how you identify it from the MARC records — but our Catalog already has an ‘Online’ limit, and we’ll just re-use that existing classification. How it classifies MARC records as ‘Online’ or not is a different discussion.

I can think of a couple approaches for making the feature work this way.

Option 1. Change how Blacklight app makes Solr requests

Ordinarily in a Blacklight app, if you choose a limit from a facet — say “Milton S. Eisenhower Library” from the “Location” facet — it will add on an `fq` param to the Solr query: say, “&fq=location_facet:Milton S. Eisenhower Library” (except URL-encoded in the actual Solr URL of course).

This is done by the add_facet_fq_to_solr method, and that method is called for creating the Solr URL because it’s listed in the solr_search_params_logic array.

So Blacklight actually gives us an easy way to customize this. We could remove add_facet_fq_to_solr from the solr_search_params_logic array in our local CatalogController, replacing it with our own custom local_add_facet_fq_to_solr method.

Our custom local method would, for facet limits from the Location facet only, do something special to add a different fq on to the Solr query, that looks more like: `&fq:location_facet:Milton S. Eisenhower Library OR format_facet:Online`.  For other facet limits, our custom local method would just call the original add_facet_fq_to_solr.

This wouldn’t change our Solr index at all, and would still make it possible to implement some other (possibly hidden back-end) feature that really limited to the original location without throwing “Online” in too, in case eventually people realize they need that after all.

I am not sure if it would effect performance of applying those limits; I think it would probably not, that expanded ‘fq’ with the ‘OR’ in it can be cached in the solr filter cache same as anything else.

I worry it might be a fragile solution though, that could break in future versions of Blacklight (say, if Blacklight refactors/renames it’s request builder methods, so our code is no longer succesfully replacing the original logic in the `add_facet_fq_to_solr` method) — and then be confusing for future developers who aren’t me to figure out why it’s broken and how to fix it. It’s potentially a bit too clever a solution.

Option 2. Change how location facet is indexed

The other option is changing how the location_facet Solr field is indexed, so every bib that is marked “Online” is also assigned to every location facet value.

Then, without any other changes at all to app code, limiting to a particular location facet value will always include every ‘Online’ record too, because all those records are simply included in every location facet value in the index.

We do our indexing with traject, and it’s fairly straightforward to implement something like this in traject.

In our indexing file, after the rule for possibly assigning ‘Online’ to the `format_facet`, we’d create a rule that looked something like this:

each_record do |record, context|
   if (context.output_hash["format"] || []).include? "Online"
      context.output_hash["location_facet"] ||= []
      context.output_hash["location_facet"].concat all_the_locations
   end
end

Pretty easy-peasy, eh? I think I would have had a lot more trouble doing this concisely and maintainably in SolrMarc, but maybe that’s just because I’m more comfortable in ruby and with traject (having written traject with Bill Dueber). But I think it actually might be because traject is awesome.

The only other trick is where I get that `all_the_locations` from. My existing code uses not one but TWO different translation maps to go from MARC data to Location facet values. The only place ‘all possible locations’ exists in code is in the values in these two hashes. If I just hard code it into a variable, it’ll be fragile and easily get out of sync with those. I guess I’d have to write ruby code to look at both those location maps, get all the values, and stick em in a variable, at boot-time.

No problem, just in the traject configuration file anywhere before the indexing rule we define above:

all_the_locations = []
all_the_locations.concat Traject::TranslationMap.new("jh_locations").to_hash.values
all_the_locations.concat Traject::TranslationMap.new("jh_collections").to_hash.values
all_the_locations.uniq!

The benefit of traject being just ruby is that you can just write ruby, and I’ve tried to make the traject classes and api’s flexible so you can do what you need with them (I hadn’t considered this use case specifically when i wrote the TranslationMap api, but I gave it a to_hash figuring all sorts of things could be done with that, as ruby Hash has a flexible api).

Anyhow. Benefits of this approach is that no fancy potentially fragile “create a custom Solr query” code is needed, and the Solr `fq`s for facet queries are still ordinary “field:value” with Solr performance characteristics we are well familiar with.

Disadvantages might be that we’re adding something to our indexing size with all these additional postings (probably not too much though, Solr is pretty efficient with this stuff), and possibly changing the performance characteristics of our facet queries by changing the number and distribution of postings in location_facet.

Another disadvantage is that we’ve made it impossible to query the “real” location facet, without the inclusion of “Online”, but that does meet the specs we’ve been currently given.

So which approach to take?

I’m actually not entirely sure. I lean to option 2, despite it’s downsides, because my intuition still says it’s less fragile and easier for future developers to understand (a huge priority for me these days), but I’m not entirely sure i’m right about that.

Any opinions?

Posted in General | 6 Comments

Agility vs ‘agile’

Yes, more of this please. From Dave Thomas, one of the originators of the ‘agile manifesto’, who I have a newfound respect for after reading this essay.

Agile Is Dead (Long Live Agility)

However, since the Snowbird meeting, I haven’t participated in any Agile events, I haven’t affiliated with the Agile Alliance, and I haven’t done any “agile” consultancy. I didn’t attend the 10th anniversary celebrations.

Why? Because I didn’t think that any of these things were in the spirit of the manifesto we produced…

Let’s look again at the four values:

Individuals and Interactions over Processes and Tools
Working Software over Comprehensive Documentation
Customer Collaboration over Contract Negotiation, and
Responding to Change over Following a Plan

The phrases on the left represent an ideal—given the choice between left and right, those who develop software with agility will favor the left.

Now look at the consultants and vendors who say they’ll get you started with “Agile.” Ask yourself where they are positioned on the left-right axis. My guess is that you’ll find them process and tool heavy, with many suggested work products (consultant-speak for documents to keep managers happy) and considerably more planning than the contents of a whiteboard and some sticky notes…

Back to the Basics

Here is how to do something in an agile fashion:

What to do:

  • Find out where you are
  • Take a small step towards your goal
  • Adjust your understanding based on what you learned
  • Repeat

How to do it:

When faced with two of more alternatives that deliver roughly the same value, take the path that makes future change easier.

And that’s it. Those four lines and one practice encompass everything there is to know about effective software development. Of course, this involves a fair amount of thinking, and the basic loop is nested fractally inside itself many times as you focus on everything from variable naming to long-term delivery, but anyone who comes up with something bigger or more complex is just trying to sell you something.

http://pragdave.me/blog/2014/03/04/time-to-kill-agile/

I think people tricked by others trying to sell them something isn’t actually the only, or even the main, reason people get distracted from actual agility by lots of ‘agile’ rigamarole which is anything but.

I think there are intrinsic distracting motivations and interests in many organizations too: The need for people in certain positions to feel in control; the need for blame to be assigned when something goes wrong; just plain laziness and desire for shortcuts and magic bullets; prioritizing all of these things (whether you realize it or not) over actual product quality.

Producing good software is hard, for both technical and social/organizational reasons. But my ~18 years of software engineering (and life!) experience lead me to believe that there are no ‘tool’ shortcuts or magic bullets, you do it just the way Thomas says you do it: you just do it, always in small iterative steps always re-evaluating next steps and always in continual contact with ‘stakeholders’ (who need to put time and psychic energy in too).  Anything else is distraction at best but more likely even worse, misdirection.

And there’s a whole lot of distraction and misdirection labelled ‘agile’.

Posted in General | Leave a comment

Another gem packaging of chosen.js for rails asset pipeline

chosen-rails already existed as a gem to package chosen.js assets for the Rails asset pipeline.

But I was having trouble getting it to work right, not sure why, but it appeared to be related to the compass dependency.

The compass dependency is actually in the original chosen.js source too — chosen.js is originally written in SASS. And chosen-rails is trying to use the original chosen.js source.

I made a fork which instead uses the post-compiled pure JS and CSS from the chosen.js release, rather than it’s source. (Well, it has to customize the CSS a bit to change referenced url()s to Rails asset pipeline asset-url() calls.)

I’ve called it chosen_assets. (rubygems; github).  Seems to be working well for me.

Posted in General | Leave a comment

vendor optical disc format promoted as ‘archival’?

Anyone in the digital archivist community want to weigh in on this, or provide  citations to reviews or evaluations?

I’m not sure exactly who the market actually is for these “Archival Discs.” If it was actually those professionally concerned with long-term reliable storage, I would think the press release would include some information on what leads them to believe the media will be especially reliable long-term, compared to other optical media. Which they don’t seem to.

Which makes me wonder how much of the ‘archival’ is purely marketing. I guess the main novelty here is just the larger capacity?

Press Release: “Archival Disc” standard formulated for professional-use next-generation optical discs

Tokyo, Japan – March 10, 2014 – Sony Corporation (“Sony”) and Panasonic Corporation (“Panasonic”) today announced that they have formulated “Archival Disc”, a new standard for professional-use, next-generation optical discs, with the objective of expanding the market for long-term digital data storage*.

Optical discs have excellent properties to protect themselves against the environment, such as dust-resistance and water-resistance, and can also withstand changes in temperature and humidity when stored. They also allow inter-generational compatibility between different formats, ensuring that data can continue to be read even as formats evolve. This makes them robust media for long-term storage of content. Recognizing that optical discs will need to accommodate much larger volumes of storage going forward, particularly given the anticipated future growth in the archive market, Sony and Panasonic have been engaged in the joint development of a standard for professional-use next-generation optical discs.

Posted in General | Leave a comment

A Proquest platform API

We subscribe to a number of databases via Proquest.

I wanted an API for having my software execute fielded searches against a Proquest a database — specifically Dissertations and Theses in my current use ase — and get back structured machine-interpretable results.

I had vaguely remembered hearing about such an API, but was having trouble finding any info about it.

It turns out, while you’ll have trouble finding any documentation about it, or even any evidence it exists on the web, and you’ll have trouble getting information about it from Proquest support too — such an api does exist.  Hooray.

You may occasionally see it called the “XML Gateway” in some Proquest documentation materials (although Proquest support doesn’t neccesarily know this term). And it was probably intended for and used by federated search products — which makes me realize, oh yeah, if I have any database that’s used by a federated search product, then it’s probably got some kind of API.

And it’s an SRU endpoint.

(Proquest may also support z39.50, but at least some Proquest docs suggest they recommend you transition to the “XML Gateway” instead of z39.50, and I personally find it easier to work with then z39.50).

Here’s an example query:

http://fedsearch.proquest.com/search/sru/pqdtft?operation=searchRetrieve&version=1.2&maximumRecords=30&startRecord=1&query=title%3D%22global%20warming%22%20AND%20author%3DCastet

For me, coming from an IP address recognized as ‘on campus’ for our general Proquest access, no additional authentication is required to use this API. I’m not sure if we at some point prior had them activate the “XML Gateway” for us, likely for a federated search product, or if it’s just this way for everyone.

The path component after “/sru”, “pqdtft” is the database code for Proquest Dissertations and Theses. I’m not sure where you find a list of these database codes in general; if you’ve made a succesful API request to that endpoint, there will be a <diagnosticMessage> element near the end of the response listing all database codes you have access to (but without corresponding full English names, you kind of have to guess).

The value of the ‘query’ parameter is a valid CQL query, as usual for SRU. It can be a bit tricky figuring out how to express what you want in CQL, but the CQL standard docs are decent, if you spend a bit of time with them to learn CQL.

Unfortunately, there seems to be no SRU “explain” response available from Proquest to tell you what fields/operators are available. But guessing often works, “title”, “author”, and “date” are all available — I’m not sure exactly how ‘date’ works, need to experiment more — although doing things like `date > 1990 AND date <= 2010` appears initially to work.

The CQL query param above un-escaped is:

title="global warming" AND author=Castet

Responses seem to be in MARCXML, and that seems to be the only option.

It looks like you can tell if a full text is available (on Proquest platform) for a given item, based on whether there’s an 856 field with second indicator set to “0” — that will be a URL to full text. I think. It looks like.

Did I mention if there are docs for any of this, I don’t have them?

So, there you go, a Proquest search API!

I also posted this to the code4lib listserv, and got some more useful details and hints from Andrew Anderson.

Oh, and if you want to link to a document you found this way, one way that seems to work is to take the Proquest document ID from the marc 001 field in the response, and construct a URL like `http://search.proquest.com/pqdtft/docview/$DOCID$`.  Seems to work. Linking to fulltext if it’s available otherwise a citation page.  Note the `pqdtft` code in the URL, again meaning ‘Proquest Dissertations and Theses’ — the same db I was searching to find to the doc id.

Posted in General | 1 Comment

Job in Systems department here at JHU

We have a job open where I work. The position will support ILL (ILLiad), reserves (ARES), and EZProxy software,  as well as do programming to integrate and improve UX for those areas of library workflow as well as others.


Johns Hopkins University has an immediate opening for a Software Engineer position in the Sheridan Libraries and Museums.  This exciting opportunity is located at the Homewood Campus in Baltimore, Maryland.  The incumbent will primarily be responsible for administering, developing and maintaining library systems to support three main services for all of the Johns Hopkins libraries: electronic reserves, inter-library loan and access to licensed resources.  The incumbent integrates supported library systems, such as ILLiad, Ares and EZproxy, with other systems at the university (ie. JHED directory, Shibboleth and Blackboard), in the library (ie. Library management system, Horizon) and with 3rd party licensed resources (ie. Ebscohost and JSTOR).  The incumbent works as a member of the enterprise applications team in the Library Systems department.

For additional information about the position and to apply, visit http://jobs.jhu.edu .  Locate Job # 60195  and click “Apply.”  To be considered for this position, you must complete an online application.

Qualifications:
– Bachelor’s degree required
– Five years of related work experience with computer systems and applications.
– Experience with Windows Server, IIS, MS SQL Server
– Progressive experience with programming language
– Knowledge of library systems, such as ILLiad, Ares, EZproxy, Horizon, etc.

Johns Hopkins University is an equal opportunity/affirmative action employer committed to recruiting, supporting, and fostering a diverse community of outstanding faculty, staff, and students.  All applicants who share this goal are encouraged to apply.

Posted in General | Leave a comment

‘hamburger’ button usability

There’s a UI element that seems to have really caught on, which I’m skeptical of.

A button in a navbar that looks like three horizontal lines, sometimes called the ‘hamburger’ button.  (thanks @dbs).

It often  opens a sidebar of additional options and was possibly first used to open a sidebar,  so is sometimes also referred to simply as ‘side navigation’ pattern.

As used prominently on Bloomberg.com:

bloomberg-expando

Or the new (and generally awesome) redesign of nytimes.com:

nytimes-navbar

Or the facebook mobile app (but, as far as I can tell, not the facebook website)

facebook-mobile

However, bootstrap uses this same icon  for something other than sliding out a sidebar of options. It’s still in the navbar — on small screens only and typically on the right side rather than left side as in previous examples — and it still makes some additional options appear, but by default not really in a sidebar style. Make your browser window narrow on getbootstrap.com to see and play with:

bootstrap-small-screen-expando

Whether used for a sidebar pullout or not, I am a bit skeptical of the usability here. Do users really know what this means, do they click on it?

Of course, users might come to recognize the ‘hamburger’ as more and more sites use it — certainly expert users like most of my readers are already quite familiar with it, but I suspect that many less sophisticated users haven’t caught on yet.

I haven’t been able to find any actual user-testing of the usability of these devices — I wonder why Nielsen hasn’t tackled it yet. But there are some other surveys of use and personal musings on it (made hard to find by lack of consensus term for the ‘hamburger’), here’s one good one from smashingmagazine, with some variations too, from over a year ago.

It may or may not be a problem for achieving recognition that the ‘hamburger’ is sometimes on the left and sometimes on the right. (Or that apparently Android has standardized on three-dots-with-swipe instead of three horizontal lines?)

Today I noticed the nytimes.com was providing popup hints on first page load (until a cookie says you’ve seen it), suggesting that nytimes has some reasons to believe users don’t notice the link or know what to do with it on their fairly new page design:

nytimes-prompt

A popup prompt like that seems at best a workaround to unclear UX, not a good solution. (I am also amused by “O.K.” rather than the more usual “OK” — following the nytimes style book, I’d guess?)

If you are scrolled all the way up on nytimes.com, the navbar changes in several ways, one of which is including a label on the ‘hamburger’ button:

nytimes-navbar-scrolledup

I wonder why they thought they didn’t have room for labelling it “Sections” ordinarily, but did when you are scrolled all the way up?

It might make sense to always include the label — if the screen is wide enough.

Of course, on narrow screens down to the several hundred pixels you get on a smartphone, you’ve got to do some things to compress your navbars as much as possible, which is perhaps the origin of the hamburger, and why bootstrap uses it.

I am particularly not fond of the bootstrap pattern, as far as what happens after you click on it, the weird expansion of  buttons in the navbar, rather than an actual sliding out sidebar. This is a different issue than “will the users know to click on the button”, I think what happens when you click on the button is just aesthetically displeasing — in some bootstrap-using apps, where the designers haven’t done enough to make sure it’s clean, I think it can be so aesthetically displeasing that it reaches the point of confusing, although I’m not finding a good example.

I’m not sure what the alternatives are. In some cases, there may be very application-specific solutions that can serve as alternatives to the hamburger — maybe you don’t need so many options accessible from the navbar at all, or can use completely different devices to get them?

Otherwise, I’d say try to always label your ‘hamburger’ if possible nytimes style — it seems that even the smallest screen should have room for a one-word label, no? But if you need to remove it tiny screens, it seems safer and clearer to still include it on larger screens, for designs where the ‘hamburger’ is present even on larger screens.

And as far as what happens when you click it, I much prefer an actual sidebar slide-out to bootstrap’s navbar-expand-slidedown, but you don’t get a sidebar-slide-out for free with bootstrap; it may be tricky to implement reliably in CSS/JS at all?  Anyone know of any good open source reusable implementations of actual sidebar slideout?

Posted in General | 1 Comment

Royal Library of Denmark goes live with Umlaut

The Royal Library of Denmark has gone live with an Umlaut implementation.

They’ve done some local UI customizations, including multi-lingualization. (We hope to get the i18n stuff merged into Umlaut core).

You can see their start page here.

Although at most libraries, users more often use Umlaut as a target of OpenURL linking from search platforms, rather than starting at the Umlaut start page. I’m not sure if the Royal Library’s use cases are typical in that way or not.  Royal Library’s Google Scholar preferences still seem to point directly to their SFX instance, not to their Umlaut instance. (And Google Scholar makes it increasingly hard for users to find and use this preference anyhow, honestly).

Posted in General | Leave a comment

Anecdote for when metrics go bad

More and more parts of our society are metric-obsessed these days.

While I’m in theory in favor of science, scientific approaches based on observation, data-driven decisions, etc.—I am also more and more cautious of the ways that metrics can be abused, be gamed, be interpreted incorrectly, and generally be insufficient proxies for the thing meant to be measured.   There are a bunch of possible reasons this can happen.

Just an anecdote, here’s a real phone call I just got:

“Hi, this is [X] calling from [Honda Dealership]. We’d like to thank you for bringing your car in for service the other day. You may be receiving a survey from Honda about your satisfaction. We just wanted to let you know that if you rate us 100% in all categories, then your next oil change will be free.”

Ah, yeah. Clearly the survey is from corporate Honda America or whatever; the phone call was from the dealer; and I’d guess that both the dealer as a whole and the individual staff at the dealer have various kinds of compensation pegged to these survey results.

(Incidentally, after seeing how over-priced the service was for the oil/filter change, air filter change in both cabin and engine, wiper refills, and checks of various lines and fluids — it’s very unlikely i’ll be going to the dealer again. It was at least 2x what it probably should have been, I am feeling serious pain in the wallet).

This kind of blatant manipulation certainly isn’t the only way that metrics-based approaches can end up misleading.  Talk to any teacher about “School Reform”, for issues with similar “performance-based compensation” — the problem isn’t just intentional abuse, but that the operationalized measurements may simply not validly measure what you really want to measure, for all sorts of reasons.  Inept application of statistical methods (which I think is awfully common even among scientists, let alone among Car Companies and Libraries) can compound the issue.

Then a larger philosophical issue is how choosing to look at things only in terms of quantitative measurements effects our judgements and perspectives. Someone recently recommended Michel Foucault to me on this topic, although I’m not sure which work of his would be most pertinent.

Use metrics for sure, but don’t be ruled by them, and don’t assume that just because something is reported to you in a quantitative fashion that automatically means it’s objective, accurate, or valid. (Or that any of those categories, ‘objective’, ‘accurate’, or ‘valid’, are simple yes-or-no, rather than questions of degree).

Posted in General | Leave a comment

An items out page

Our ‘items out’ page is one of the most viewed pages on our ‘catalog’. This makes sense, people need to see when their items are due, as well as to (try and) renew their items, which is also done on this page.

Since it’s one of the most used, it makes sense to spend some time trying to make it nice and usable.

We are on in control of the items out page in our Rails (Blacklight-powered) ‘catalog’ app, as a pretty thin UI layer on top of our ILS.  We use a combination of screen-scraping-like techniques and other horrible esoterica to provide our own UI layer. I think it’s worth it, due to how important this page is to our users, and it’s mostly worked out.

Well, at least we’re mostly in control of the UI, we are constricted in many ways by the underlying ILS, as well as by policies and business processes (that are, as a rule, much harder to change than technology, as most of my readers know!).

Anyhow, one of the first things we added to this page, which I’m still very proud of, is the addition of ‘relative time’ due dates like “1 week”, “6 months”, or “2 days”, using the Rails distance_of_time_in_words_to_now helper.

Here is a very early preliminary iteration of a someday-in-the-future new version of the page, part of an upgrade of our app to use a new version of Blacklight, and Bootstrap 3.x for the styling.

Screenshot 2014-01-16 14.32.14

That is actually using an html <table> there for layout, which I think is probably appropriate in this case, it is essentially tabular data. (It would be fairly straightforward to do it without a <table>, especially if you are willing to use CSS “display:table” (if you don’t care about IE7), but I think a table is actually probably right.)

Ah, but part of this redesign (again, for the benefit of my local colleagues reading this, I will emphasize very early preliminary work) is to make sure the website works well on small screens and touch screens and small touch screens — you know, ‘mobile’. And I fully expect that the ‘items out’ screen will be just as, or more, used on mobile as on desktop.

What do you do with that page on a very small screen? How about something along these basic lines:

Screenshot 2014-01-16 14.36.43

The first screenshot and the second screenshot are actually the same HTML, only transformed by responsive CSS, using basically the technique described in this blog post. 

The HTML starts out <table> and is responsively transformed to block and inline-block display by CSS at small screen widths.

In retrospect, it would probably have been a better idea to start out with the block-display ‘mobile’ version, and use CSS media queries to responsively change to a table at large sizes, and it may iterate in that direction. (There’s a note at the end of the responsive table blog post with a link to an example of a mobile-first responsive approach).

That wouldn’t work in IE7 as it requires CSS “display:table” to responsively make something into a table display — or at least it’d be  harder, you’d have to emulate a table with just sized divs. But once you’ve gone Bootstrap3, IE7 is pretty much a lost cause anyway. (Bootstrap3 says while IE7 isn’t officially supported, it ‘should look and behave well enough’ in IE7. But I suspect if you develop a site in bootstrap3 without testing in IE7 constantly as you iterate, most such sites are going to end up not working in IE7 and needing very significant reworking to do so).

But there would be some benefits to ‘mobile first’ here. It would mean that any browser which can’t handle media queries, or can’t handle setting “display:block” on <tr>’s and <td>’s — would get the more basic ‘small screen version’.  Which is probably a better fallback than getting the table version even if you have a small screen, and definitely better than completing messing up a browser that can’t handle “display:block” on table elements, which the responsive table blog post warns can be a problem in IE9 and down. (Yeah, we still got to support IE9!)

It would also be more consistent with bootstrap3, which is also designed ‘mobile first’, with initial CSS appropriate for small screens, and CSS media queries changing display on larger screens. Bootstrap probably chose to go this way for similar reasons; but once it has, and you are building out your own CSS on top of Bootstrap, it pays to try and be consistent with Bootstrap. I’ve found that, when developing on a bootstrap3 framework,  following my previous habits of designing for a large screen and responsively changing for smaller screens, can produce weird interactions with the bootstrap3 mobile-first CSS. Best to follow boostrap3’s lead when using bootstrap3.

Posted in General | Leave a comment