Friday, July 31, 2009

On the Reporting Dashboard (design)

Here's a quick mockup of what I'm thinking the Report Dashboard should look like. I need some help with some of the most common queries that users ask about. You'll quickly notice that the dashboard is missing a graphical widget. Once I think of something to implement, I will add it. Let me know if you have any suggestions.

On the woes of usability (cohorts and indicators)

Finding a solution to the indicator report was a big step for me. However, the best thing that came out of the conversation with Mike this morning was something kind of random. For some reason, during the conversation about hard-wiring the "design indicator report" UI, I realized that we also needed to hard-wire the design of a few other pages, just to get the reporting system out the door and into the hands of users ... who could tell us what they really wanted. Which is the gold at the end of the rainbow. Get your application into the hands of your users and they'll tell you what they want. Hopefully.

So the basic conclusion that Mike and I came to today was that the user interface for the new reporting system should be somewhat hard-wired, at least to start with. We've been fighting with this idea for months now. Every time we've wanted to go down the path of "hard-wiring" a report or one of the reporting components, we've designed a cool new widget maker that would hypothetically handle the general case in a way that most users would be ok with. And so after a few conversations, we start heading back down the path toward a "more generalizable" solution.

I now hate generalizable solutions. They suck. They're ugly, they take too long to implement, and they always break. I'm not smart enough to think of every use case that might ever be needed. I've spent 2+ years working on reporting and I'm tired of thinking about vague/general user stories like "Design a Report". You go Design a Report! I just want someone to ask for a very specific feature, like "Give me the ability to retrieve a count of all patients in the HIV Program at the Rwinkwavu hospital". I can do that. I can implement that and make it look nice. And I can build it in a general-enough way so that only the UI needs to be hard-wired. I just can't (and won't ever again) design another generic UI. Go to hell general UIs.

I'm exaggerating. I'll be back to designing general UIs next week. But, I've found a way to handle some of the reporting UIs in such a way that we can build some very nice features for our users without spending months working on a general UI that looks pretty enough and is 100% extensible.

So to get back to the point. This conversation with Mike got me thinking about a part of the reporting tool that I have been dreading since I first conceptualized it. I'm speaking specifically about the Report Dashboard, the main UI that a user encounters when they want to use the new reporting tools. At first, I wanted to make this a portal page ... a place where users could add and configure "widgets" to allow them to view patient data in a very interactive, easy to use manner. I started thinking about all of the widgets we could have "Graph concept X along datetime, break down by Dimension Y" or "Show 10 most recent indicators" or "Show a truncated table of patients that Provider X is supposed to see this week". Any and all of these widgets would be cool and possibly useful. But no one has every asked for them, so I don't think it would be a good use of time building a generalizable portal framework for widgets that might not ever be used. Instead, we should put some effort into hard-wiring some of these widgets according to a user's specification and then try to find some patterns of reuse in those.

(image stolen from the DHIS web site -- thanks guys!)

I still plan to build this dashboard (I want it to look a little like the image above) but we don't have the foundation within OpenMRS for a portal type user interface yet. We have portlets, but we don't have the portal page that would hold the portlets nor do we have a way to configure the portlet to handle any case. For example, there's no way to turn a cohort or dataset based on any concept into a nice graph. But that time will come. I promise you.

However, what we need to be able to do from within the Report Dashboard is to allow a user, like Cheryl down in Rwanda, to quickly find out how many patients are currently enrolled in our HIV Program during a certain period. The cohort builder is great and gives us a good start to solving this issue. But the cohort builder is still too generic. It requires a user to ask a bunch of questions to answer their overall query. A user is left combining multiple queries to figure out how many Male Adult patients are in the system. Why not hard-wire a UI that allows the user to pick a Cohort and select a few dimensions (gender, age) and click "Run" in order to get a crosstab of patients broken down by these two dimensions.

We can easily handle this kind of query with our the reporting framework (our API is very flexible), but it's not at all easy for a user to put together all of the cohort definitions or logic queries through the cohort builder in order to answer this question. They need to calculate each of these numbers separately and then put together the pieces.

Or take this example.

Find out how many patients were enrolled in the HIV Program in Rwinkwavu between 07/01/2009 and 07/31/2009.

Why not hard-wire the UI to handle this kind of query? Clearly, we don't want to hard-wire the values in this particular example. But we want the general pattern to be hard-wired. We'd still generialize it enough and give the user the ability to specify the four variables: Program, Location, Start Date, and End Date. However, the query is a pattern that we know users will ask a lot.

And when a user comes to us and says: "This is great, but I want to be able to get all patients enrolled in the HIV Program AND On ARVs", we don't have to say "Oh F" and spend weeks trying to make the UI take an arbitrary number of Programs and States. We can simply add a new query to the report dashboard to handle this.

Find out how many patients were enrolled in the HIV Program and On ARVs in Rwinkwavu between 07/01/2009 and 07/31/2009.

While it would be great to handle this generically so that a user can ask any question, any time they want, this isn't at all realistic. However, if we could hard-wire a bunch of questions that users ask all the time across all of our implementations, then we'd be 90% of the way there. In addition, we'd remove the need for all of our users to define the same cohort builder queries over all of these implementations. And we'd get some pretty good feedback about what's missing.

That's not to say we don't want to extend the Cohort Builder to allow users to ask more general questions. We just need to give our users a better foundation to start with.

So what query would you like to run within your OpenMRS implementation?

On the woes of usability (from a developer's point-of-view)

I've been struggling with the UI design and usability for our reporting system for weeks now. We've built most of the UIs for the general administration tools for defining cohorts, indicators, datasets, and reports. However, these UI are the kind of pages that are completely unintuitive to a user: a listing page to display all reports and a details page to allow the user to view/edit the details of a report. We give away too much information, too many options and it's just an overwhelming experience for the user. And it's tiring for a developer. I want to build intuitive interfaces. I do. I want to make things easy on our users. I just don't know how. No matter how much I read about ux (user experience), I just can't seem to get it right.

So this morning, instead of banging my head against the wall for another day, I decided to have a discussion with one of OpenMRS's most gifted developers. No, not Ben Wolfe ... although, there's no doubt that he is a programming genius. No the conversation with with Mike Seaton. I asked him to give me a ring to discuss these issues. He's been working on reporting for our legacy Haiti system for years and knows a thing or two about indicators and indicator reports. I was expecting to have a quick conversation about the following mockup:

But we spend about an hour on the phone discussing the details of indicators and how we need to wire parameters (like start date) from the low level reporting components (an indicator) up through the indicator dataset definition and into the report. The screenshot above isn't terribly complicated, but it requires a little too much knowledge of what the lies underneath an indicator.

But as part of a larger process (creating an indicator report), this UI is just one little piece of confusion pie. At first glance (in my mind), the entire UI for creating the indicator report looks like a messy hierarchical chaining type thingamajig because I have been thinking about how one might design one of these reports from a bottom-up perspective. Here's the process, in a nutshell:
  1. User creates the cohort definition (Gender Cohort Definition with "gender" parameter).
  2. User creates the indicator (# Male Patients with "gender" set to "M").
  3. User creates the dataset definition and adds the indicator to it (My Indicator Dataset)
  4. User creates the report and adds the dataset definition (My Indicator Report).
Four different pages ... four different steps ... just to create a report with a single indicator. Why would you do this to the user? Why would you do this to yourself?

I have no idea.

Don't paint me in the moron category just yet. I knew there was a better UI. I had the image in my head, but I just got flustered with all of the "stuff" that needed to happen in order for that design to work. There's a lot of "stuff" that needs to be configured, configuration options that "should" be available to the user. To be more explicit, for each layer (cohort->indicator->dataset->report) there's some "wiring" that needs to happen in order for a report parameter (say "location") to be passed down through the hierarchy of objects to allow a value like "Rwinkwavu" to be used by the indicator or cohort definition when it's time to evaluate the report.

The thing that Mike and I figured out was that we really don't need to let the user configure everything when designing the report from scratch. At least not at the beginning. Let's give them just enough configurability (add an indicator) to get off the ground.
We can make some assumptions for them (you want the "location" parameter to be . Then, once things are flowing, we can let them dig down and get dirty with the report configuration. So here's the mockup I came up with from those conversations:

Now, I know this isn't revolutionary ... but it's hard to make the kind of assumptions we need to make to hide the complexity from the user. And there's still the issue of designing a somewhat intuitive interface for a user that wants to dig down into the details of each indicator in order to configure, say the "location" parameter to be hard-coded. But we'll get to that feature once there's a need for it. For now, the "edit indicator" feature will have to be left unimplemented. Sorry Mike - I know that wasn't the conclusion we came to, but it feels like the right thing to do, rather than adding one more confusing element to this page. This design feels right.

Let me know what you guys think.