Home > DrProject > And Search Returns…?

And Search Returns…?

October 16th, 2008

Here’s a design challenge for anyone who wants it: what should search return?  More specifically, suppose you have something like DrProject, which stores tickets and wiki pages in a relational database, and revisions to files using a standard Subversion repository. Tickets are identified by ticket number (it’s actually the pair [projectId, ticketId], but never mind that for now), while wiki pages are identified by their names (which are strings), and repository entries are identified by a combination of path and version number (e.g., [/trunk/license.txt, 33]). If one ticket, one wiki page, and one file contain the word “Turing”, what should ‘search(“Turing”)’ return?

Should it be a set of URLs?  I need those eventually if I’m building a web page to display the results, but that feels like mixing two levels—my instinct is that I should be returning “things” that are then converted to URLs.  (For example, if I’m running a command-line admin tool on the desktop, I probably don’t want URLs coming out of my search function…)

What about returning a set of pairs, where each pair is [type-of-thing, thing-id], e.g., ["wiki", "Authors"] or ["ticket", 127]?  That feels wrong because it will force all the client code (e.g., the stuff that creates URLs for HTML pages, and the command-line admin tool) to do a type-switch in order to fetch and process the actual items.

OK, so what about defining an abstract base class called ‘SearchResult’, then require each component of DrProject to subclass it, so that we have ‘TicketSearchResult’, ‘WikiSearchResult’, and so on?  These classes could provide ‘getItem()’ methods to fetch the content that matches, ‘toUrl(baseUrl)’ methods to create links, and so on.  That feels like a better fit than either of the previous ideas, but I’m still dissatisfied.  Is there a cleaner way to do this that I just don’t know about?  If so, I’d welcome a pointer…

DrProject

  1. October 16th, 2008 at 13:20 | #1

    Your search results should look as much like Google’s as possible. That is what people are conditioned to expect searches to look like. If you want to put a little tag to the left, so people can see “ticket”, “wiki page”, “faq”, “comment”, and the like, then go ahead. But I think that people want search results to look like other search results from other sites. Otherwise users will have to think, and they hate that.

    To do that, it definitely seems like search(string) should return a series of items that are, at the very least, convertible into URLs. Why not just return the objects themselves? A Ticket or a WikiPage or a whatever. Then each of them should have a method entitle URL() that will give you the URL for that item, but perhaps another entitled “__str__()” or whatever the local equivalent is for the language you are using that will give a good text representation.

    But it seems like search(string) should return a sequence of objects, and those objects should be THE objects, and not a double-indirection thing like TicketSearchResult, but instead just be Tickets and WikiPages, etc.

  2. October 16th, 2008 at 13:49 | #2

    Sounds like a potential fit for OpenSearch.

  3. October 16th, 2008 at 14:50 | #3

    I can see the pros and cons of both solutions.

    Returning the actual models.
    PROS: they’re already there, no need to create extra classes.
    CONS: it might be difficult to abstract the models. How tickets and wikis are searched is different (search fields). The search needs more information about the models to know which fields to search for.

    Creating custom objects.
    PROS: we have control over the logic for performing search by subclassing SearchResult. Polymorphism will allow the caller to handle search results uniformly, and if they want to get clever they can check the type and do something custom for wiki/ticket results. Seems like a good OO design.
    CONS: adds extra objects. Also, any time a new model is created that has to be indexed and searched, it also needs a corresponding Result object.

    I’m +1 towards the latter.

  4. DrObvious
    October 17th, 2008 at 00:21 | #4

    Answered your own question with SearchResult, but use composition, not inheritance. i.e. wrap the item in a search result.

Comments are closed.