Category: Technology

Chasing the perfect User Interface

By Kiran, April 18, 2009 1:01 am

Hence, I am taking a break from my random stray thoughts for a change and writing this memo/mini-manifesto to myself to remind myself of things I (and my team) need to keep in mind while doing what we do.

We spend countless hours designing application logic, we spend months debugging rules and flows, we put together over five hundred tables to store our data in the blink of an eye, yet we devoted mere minutes to the user interface. Yes, healthcare software is complex and cumbersome and never complete, but that does not mean we can’t do what Apple and Intuit do for their customers. I had the chance to read two UI-centric articles today – on healthcare software (specifically openvista), and on the usage of subtle elements in web design, and I realized that there are two simple reasons we are not presentation-focused – we assume the users will live with whatever we give them, and we are too obsessed with whats under the hood.

Maybe I am the only one, but to me, software design is an abstract art – there are things that are visible and evident if you know where to look, but there is seldom a lot more under that iceberg that most people will ignore. The artist chooses which parts he wants to highlight and which part he wants to obscure; unfortunately most artists will want to simply show every stroke of the still-life and be done with it. If our software affects thousands of users and patients, then why do we overly focus on the data and totally ignore presentation till the last minute. Why are social networks and Web 2.0 sites so far ahead of us in understanding usability issues.

Here a few ideas that I think would help me and the rest of my group:

Minimalism – Apple and Google epitomize this in every product they design. Of course their products are somewhat simplistic in purpose and their product silos are very well defined, but what we fail to appreciate is that they create a layer of abstraction that completely encapsulates their users’ needs without exposing the underlying alchemy. An illustration that I saw a few months ago highlights this best:

Simplicity

While it is near impossible to be minimalistic and yet present every piece of relevant information, there can be a trade-off which lets users to progressively see more data. The key to achieving this is prioritizing information, and building interfaces around the actions that the users would perform 80% of the time. Or maybe we can take a different route – minimalize every snippet of data and present these pieces as part of a bigger picture. For instance, we don’t necessarily need to show the patient’s financial/insurance information unless there is any abnormal event evident in the data.

Aggregation – Intuit is the wizard of aggregation. As an avid user of both Quicken and Quickbooks, I can attest to their depth of understanding of use cases and data aggregation. They use graphs, and then they use graphs; your net worth, your cash flow trends, your spending breakdown – every meaningful micro and macro metric is right there. There is no need to know which report to open, no need to read the manual to figure out what the next step is, and no need to wait guess how to navigate.

See where your money is going

Data aggregation is an intensive process, but not difficult. What is difficult is putting that data through a set of filters and rules engines that can rate and parse out the most important pieces in real-time. We are already doing a good deal of aggregation within our cached objects, but unfortunately we are not persisting real-time aggregated information, which forces us to constrain ourselves to re-think every data element we want to include in our interfaces.

Personalization – The same login each time, the same set of information in the home screen, the same boring sequence of actions everyday. The most personalization that I have seen is the option to choose a custom set of tabs based on the roles defined for the user in some table. If an enterprise system is part of everyday business, it will become boring and monotonous after a while. Personalization to me is not just allowing the users to modify the organization and visibility of data, but instead to make the system feel a little more alive. So I have seldom asked myself, what could make a user smile every morning when they first login – a randomized salutation, a joke of the day, a funny logo, some random quote, highlighting a metric they are strong at, introducing a new competitive metric, or any other surprise. Clinicians are serious people, and they don’t always like automation; but from experience I have seen that when there is even just a morsel of “personalization”, their attitude towards IT completely changes.

Inclusivism – Like most healthcare software developers, we are the pros at making lists. A list for medications, a list for allergies, a list of past problems, a list of claims, a list for patient payments, and on and on. The lists are endless, but there is an innate problem with our lists – they give only partial information; is there is an unwritten rule out there which says every item in a list must lead to another interface which presents the details. I think we need to make more of our lists progressive, and not have the users to open additional interfaces. Additionally, our lists are mostly static and we hardly have action options within the lists, an “open”, “view” or “select” is more than seldom our easy way out. And the systems where lists actually include actions, tend to standardize the action directives. Take a list of medications a patient is on – the list would typically show the name of the med, the date prescribed and the dosage. What if the doctor had written a note about it, shouldn’t we want to include that data into the list itself; what if one of the meds was known to be a high-risk med with potential interactions, shouldn’t we indicate that in the list itself provide a link to details about such interactions; what if one of the meds is know to have a mild allergic reaction, shouldn’t it highlight this information and provide a quick way to indicate any new reactions. The examples can be countless, and the possibilities can be exponentially large, but it is important that we start thinking about semantic relationships when we are creating lists, rather than treat them as simply sets of discrete data.

Dashboarding – In the last 2-3 years, the whole world has gone gaga over business intelligence and executive dashboards. I reject the idea that a dashboard has to be limited to viewing data, it should instead be a combination – of data and paths to actions in one place. This usually seems very difficult to do because a comprehensive snapshot of data cannot necessarily be created in real-time due to the scale of data being generated by users. But there are ways are around it – possibly through a combination of aggressive caching and real-time warehousing. More importantly, the dashboard cannot be fixed and cannot be completely dynamic, it has to be a combination of both. If a dashboard is designed to be fixed, then there will be a lot of wasted real-estate, and if it is totally dynamic there is a good chance that less important data will beat the more important data to the front of the queue.

Extreme Linkage – Facebook knows how to link information about a user – from the profile, to comments, to links, to applications. Take a look at the very simple event description page from FB below:

http://celluloidjunkie.com/wp-content/uploads/2009/03/malcos-facebook-group-screenshot.png

Notice the number of hyperlinks hiding in this page disguised as regular information. Now imagine the same interface as designed by a medical software developer – there would be at least six separate buttons, four highlighted areas, a place to display error messages, the “Displaying the only photo” section would be a “Open Photos Page”, and the “Maybe Attending” section would be button redirecting to a grid of attendees with a colored status in the first column. Although the standards and medical thesauri are not yet at the stage where semantic descriptors can be associated with data elements easily, there are enough relationships between data that we internally describe anyway, the key is to harness those to link the pieces of the puzzle more accurately. So lets take a page from facebook, and link information more efficiently where users can find it without searching for that one button hidden beneath the clutter.

After all, the product is nothing without the marketing, and in that spirit, I will take it upon myself to pay that extra bit of attention to the user-interface design and take a respite from over-working the backend of applications that I design. Fini.

Avoiding flicker in winforms

By Kiran, April 11, 2008 10:07 am

Winforms applications flicker quite a bit when you have TableLayoutPanels, Panels, etc especially when the forms/controls are resized and/or have background images. The cause for the the flicker is simple – excessive repainting, both at design-time as well as the runtime. The solution – double-buffering; when repainting the graphics on a control, .net uses a in-built buffer for rendering the contents; by enabling double-buffering, the same control maintains two buffers – one for the original contents and the other for manipulating them. The two buffers however use more memory, but the results produced are almost flicker-free.

There are two fairly simple solutions to reduce (not completely eliminate) the flicker…..

a. Set the Styles properties on the parent form/user control to be double-buffered….


public MyUserControl()
{
	SetStyle(ControlStyles.UserPaint | ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
	InitializeComponent();
}

b. Don’t use the regular panels, instead create your own overridden ones which implement double buffering.


public partial class BufferedPanel : Panel
{
	public BufferedPanel()
	{

		SetStyle(ControlStyles.AllPaintingInWmPaint |
		ControlStyles.OptimizedDoubleBuffer |
		ControlStyles.UserPaint, true);
	}

	public BufferedPanel(IContainer container)
	{
		container.Add(this);

		SetStyle(ControlStyles.AllPaintingInWmPaint |
		ControlStyles.OptimizedDoubleBuffer |
		ControlStyles.UserPaint, true);
	}
}

public partial class BufferedTableLayoutPanel : TableLayoutPanel
    {
        public BufferedTableLayoutPanel()
        {

            SetStyle(ControlStyles.AllPaintingInWmPaint |
              ControlStyles.OptimizedDoubleBuffer |
              ControlStyles.UserPaint, true);
        }

        public BufferedTableLayoutPanel(IContainer container)
        {
            container.Add(this);

            SetStyle(ControlStyles.AllPaintingInWmPaint |
              ControlStyles.OptimizedDoubleBuffer |
              ControlStyles.UserPaint, true);
        }
    }

http://visualstudiomagazine.com/features/article.aspx?editorialsid=1273

Analyzing the viagra spam

By Kiran, November 4, 2007 10:30 am

Ok, its sunday and I am pissed to see three more “october 75% off” viagra emails on my corporate account, so i decided to do a little more research on these.These emails are definitely from a botnet of spam zombies, i traced all three originating ip addresses – they are from Chile, Turkey and South Korea. None of them are listed in the spam blacklists, so the only way to block them is to block anything with the keyword viagra in sender name, subject, email, body, etc.

Now for the interesting part – it looks like one spam malware is trying to hijack the other…..if you open any of the email and do a “View Source”, you’ll see that there is a bunch of text in the original spam (which is actually bank spam). The bank spam has a bunch of urls which claim to lead to bank pages, but in reality are all links to parked domains typically registered through godaddy. They are all prefixed with kanaweb.*.com like kanaweb.djfd.com, kanaweb.adnc.com, etc. I checked many of these domains like djfd.com and adnc.com, they are all registered to US folks. Apparently, this kanaweb prefix is common in spam and used with actual banks like bankone.com and chase.com. So these kanaweb emails are the original spam emails, they are all html formatted and contain a bunch of different links.

Now, these viagra emails are really smart; they take the bank spam emails and put some tags to cover up the rest of the text…..for example,

original email…..
<head>
some banner link
</head>
<body>
dear mr. somebody,
some text
some links
</body>

the viagra program hijacks this email and does the following…..
<style>
<head>
some banner link
</head>
<body>
dear mr. somebody,
some text
</style>
viagra image link here
<style>
some links
</body>
</style>

By putting these <style> tags around the actual text of the original spam, it prevents rendering any of it. It inserts a single viagra image link in between the html, making it the only one that is displayable. I looked up the viagra image hosting domains, they’re all in china and are registered to a “liu tao”, who is apparently a chinese film actress. So it looks like whowever these spam zombies are, they are hosting multiple malware programs…..one malware sends a bank spam, another malware which is probably monitoring outgoing smtp hijacks the bank spam and overwrites it with viagra spam. My hats off to the guys who do this kind of stuff, they must be real programming gurus. If only, they put the their talents to better use, we would all save so much time and money.

Raw printing to a network printer

By Kiran, June 17, 2007 8:36 pm

For the last two days, I have been trying to find a way to send raw commands through C# to a label printer shared from a remote location. Now, if I was printing ‘Lord of the Rings’ on an A4 on this printer, I wouldn’t really mention it here, would I? My printer is a DataMax E-Series label printer (with a parallel interface) which was shared from a desktop (i know we can use a ethernet print server, but trust me, it doesn’t matter) ; I had this printer added to active directory so that i can print to it directly from any server. By the way, I am trying to print barcode labels to this printer. I figured there is a right way to do this and a crappy way:

a. The right way – These label printers are usually industrial quality and come with a 200 page programming manual,     whereby we can send “raw” commands to make the printer sing, dance, and do the tango. Although the .net framework doesn’t have low-level printing functionality, we can import the relevant functions from the Win32 API. MS is kind enough to provide exquisite details on how to do this (link).  This works great – for local printers only; for some reason the OpenPrint function imported from winspool.drv doesn’t work with network printers in .net. Googling for this revealed several other frustrated users reporting the same. Some of these folks reported that they got the raw commands to work with network printers from VB6. However much I hate doing it, my last option would be to write a little VB component, probably create a .net wrapper and use it.

b. The crappy way – Printing directly using PrintDocument, as it does not give me access to the exquisite library of commands that i can use in raw mode. By the way, direct printing works like a charm, of course formatting anything to make it fit a label from code is a nightmare.  Though I make it sound bad, formatting might not be that hard – set margins, etc in the PrinterSettings class, override the print start/end/etc methods of the PrintDocument and render graphics of everything I need to use.

I will be using the direct print option as of now and try my hand at manual formatting, but I sure wish MS fixed the bugs with the OpenPrint and got it to work with network printers.

Open popups from the server-side (Ajax and Non-Ajax)

By Kiran, May 20, 2007 3:51 pm

I always wanted to open a popup in an asp .net page from the server side code, without having do a bunch of javascript hacks. This is very important in many situations; for example, you have a page where a user fills in a bunch of data and hits submit, you want to validate all these fields and if everything is good, you want to display a printable summary sheet in a popup. I work on patient/clinical systems and on many occasions, we are required to allow users to print professional looking forms so that they can file them in the patient charts. There is no way we can effectively design a page to be interactive and simple and at the same time be printable.

There are several options for doing popups in asp.net

  1. The most popular and simplest option is of course to call the javascript window.open function on a button – in asp.net the standard practice is to register the window.open on the page load

    public void Page_Load{if (!Page.IsPostBack)
    btnSubmit.Attributes ["onClick"] = “javascript:window.open (‘http://someurl.com’);}
    The biggest problem with this is that you have to know the url beforehand, if you want the user to enter some data before he clicks the button, you cannot do server side validations before allowing the popup.
  2. Another simple, but often overlooked way to initiate a popup from the server side is to register a popup url so that once the postback is complete, it can be executed on the client side. Here’s some simple steps to get this working….a. Create a hidden field on the page<input type=”hidden” id=”hdnPopupUrl” value=”" />b. Create a body onLoad handler function that reads the hidden variable and does a window.openadd the onload to your page body….. function myLoad () {
    if (document.getElementById ('hdnPopupUrl').value != '')
    window.open (document.getElementById ('hdnPopupUrl').value);
    document.getElementById ('hdnPopupUrl').value = '';
    }
  3. After moving from regular to asp.net to ajax asp.net, i realized that i couldn’t continue doing my popups because of partial postbacks. One of the choices I made when moving to ajax was to wrap my entire content (minus the theme, skin, header, side menus, etc) in an ajax updatepanel – although this is not considered to be a good option, i found that it simplifies the ajaxification of my project and yet allows me to switch with ease to a non-ajax version by simple disabling the updatepanel. As for popups, they don’t work anymore because the ‘onLoad’ function is no longer called on a partial postback. After much googling and searching the microsoft ajax reference, I realized that the solution was simpler than I originally thought…..a. On the server-side, register a new hidden label field and populate it with popup url using the registerdataitem function

    ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);Label lblPopupUrl = new Label();
    lblPopupUrl.ID = "myPopupUrl";
    lblPopupUrl.Visible = false;
    scriptManager.RegisterDataItem(lblPopupUrl, popupUrl);

    b. On the client side, handle the EndRequest event of the ajax PageRequestManager//Set the handlers for start and end of async postback
    var prm = Sys.WebForms.PageRequestManager.getInstance();
    prm.add_initializeRequest(InitializeRequest);
    prm.add_endRequest(EndRequest);
    function EndRequest(sender, args)
    {var dataItems = args.get_dataItems();
    //alert (dataItems["myPopupUrl"]);if (dataItems["myPopupUrl"] != null) {
    window.open (dataItems["myPopupUrl"], 'NewWindow');
    }
    }
  4. Finally, the Ajax Control Toolkit (http://ajax.asp.net/ajaxtoolkit/) has a extender called ‘ModalPopup’. Now the only problem with this control is that your popup is required to be a control within the page on which ModalPopup is called. Although I can’t do a true popup with this control, I thought it required a mention because it is a great way to do smaller popups within say a datagrid or a list where you want to do a minimal ‘New’ or ‘Edit’ windows without having to write separate pages.

Panorama Theme by Themocracy