Search feature–user empowerment or application laziness?

Recently I was asked to help implement a search feature for an application.

Brief: “The user can search for anything”.

Me: “What are they trying to find and why?”

I confess I’m not sure about searching. On one hand I think it is a great idea to be able to search across the application looking for data in whatever way I want. After-all that is my expectation now I’m used to Google/Bing, right? But then are my searches in Binogle the same as I want in my application? For example, imagine we have a hospital application and we have discovered a child has meningitis, doesn’t happen that often but enough that we have a hospital policy in place. If a child contracts meningitis then we have to send a letter to all patients in the same ward who were/are there at the same time as this infected child. Now we could choose not to do anything special, just let the Search take the stain.

1. Search child’s name – 12 hits, yes that’s the one, click on them, Ward 10 and was admitted 10-Apr-2017.  3. “+ward 10” 4. Date filter from 10-Apr-2012 to Now 5. That gives 30 results 6. Select all results, send to Report feature 7. Mail + email merge and send from Report feature.

An alternative approach would be to suggest that this policy is important and is time critical. We should make this a specific feature or at least a first class part of the Report feature;

1. Select Notifications->Send Meningitis Warning 2. Search child’s name, 12 hits, yes that’s the one 2. Send Warning

The second method is obviously faster and less error prone. The system understands it needs to look at the ward and the date, that knowledge is baked into the feature.

So back to my original question, why does someone want to search across the application? Do we do this because we are bad at analysis? Do we provide a search as a catch-all and check the statistics to see if a pattern emerges that could be promoted into a feature – would the users have left by then? What’s the harm in offering both approaches?

For me it boils down to two things; 1) Return on Investment – was is the benefit of a specific feature over a general wider brush 2) Do we even think about?

This post is really about (2). Some features are now so common that it’s hard to remember why we put them there in the first place. I would just like to use this to remind myself to always question a requirement, even when others think it’s a no-brain must-have feature.

Poor mans ORM

Recently I’ve been looking at and hearing about data abstraction code that basically just calls a stored procedure and populates an objects on the way back. No identity management, just a simple mapper. I thought about using AutoMapper but as an intellectual exercise I wanted to see how easy (or not) it was to write a single helper that could move data from the stored procedure to an object based on convention. Here is the result;

public TCollection Load<TCollection, TItem>(string procedureName, params object[] arguments) where TCollection : IList
{
  this.connectionString = ConfigurationManager.ConnectionStrings["MyProject"].ConnectionString;
  TCollection instance = (TCollection)Activator.CreateInstance(typeof(TCollection));
  IList list = instance as IList;
  if (list == null)
  {
    throw new ArgumentOutOfRangeException("procedureName");
  }
  procedureName = "mySchema." + procedureName;
  using (SqlDataReader reader = ExecuteProcedure(procedureName, arguments))
  {
    while (reader.Read())
    {
      TItem item = (TItem)Activator.CreateInstance(typeof(TItem));
      for (int i = 0; i < reader.FieldCount; i++ )
      {
        string fieldName = reader.GetName(i);
        object value = reader[i];
        SetValue(item, fieldName, value);
        list.Add(item);
      }
    }
  }
  return instance;
}

The code assumes you’ll be getting objects representing lists of something <TCollection,TItem> and that the properties match the result set columns. The ExecuteProcedure command takes the arguments and maps them to the stored procedure arguments, easy enough to write. The SetValue is a little more involved;

private static void SetValue(object instance, string propertyName, object value)
{
  Type type = instance.GetType();
  PropertyInfo property = type.GetProperty(propertyName);
  var descriptor = TypeDescriptor.GetProperties(instance)[propertyName];
  TypeConverter converter = descriptor.Converter;
  if (converter != null)
  {
    property.SetValue(instance, converter.ConvertFrom(value), null);
  }
  else
  {
    property.SetValue(instance, value, null);
  }
}
  

The code uses standard reflection methods to set the property of the instance. The complication is the converter. If you are using a type that isn’t directly represented by a .net variant of a SQLType then you’ll need to use a converter. For example the following Id type needs its accompanying type converter (thanks to Chris Hannon)

public class MyItem
{
    [TypeConverter(typeof(MyIdTypeConverter))]
    public MyId Id { get; set; }
}
public class MyIdTypeConverter : TypeConverter
{
    public override object ConvertFrom(ITypeDescriptorContext context,
            System.Globalization.CultureInfo culture,
            object value)
  {
      if (value is int)
        return new MyId((int)value);
      else if (value is MyId)
        return value;
      return base.ConvertFrom(context, culture, value);
  }
}
 

So there you go, not eactly pain free but if you have a number of stored procedures and classes and you’re not overly worried about the performance hit of reflection then perhaps something like this will fit.

Quick tip, compress images

Today I was trying to send a Word document that had a couple of innocuous looking diagrams in it. The document was 8Mb. The images was greatly inflating the size. Examining the images I could see that Word was dynamically scaling them down but how do you tell Word to just save the picture at the resulting scale? Well in Word 2010 double click the picture and select the ‘Compress’ ribbon button and NOT the ‘Size’ ribbon.

Adding TFS Test Case work item to your Process Template

There are times when you would really like to have the Test Case workitem in your TFS project, this is especially true if you are using Test Manager. Here is a process you can follow to achieve this;

  1. Find a TFS Project that has the Test Case, if not create an empty CMMI Project
  2. Export the required Work Item Templates (WIT) via Visual Studio; Tools->Process Editor->Work Item Types->Export WIT
  3. Choose the Project that has a Test Case WIT and Export ‘Test Case’
  4. Choose the Project that has a Test Case WIT and Export ‘Shared Steps’
  5. Import the files from (3) & (4) into the Project you want to have Test Cases via Tools->Process Editor->Work Item Types->Import WIT
  6. Export the Categories from the source Project using a command prompt from a machine with a TFS client;
  7. witadmin exportcategories /collection:<server name>\<collection> /p:<source project> /f:Catagories.xml

  8. Edit the Categories.xml to match your Projects items, in this example “Use Case” was changed to “Product Backlog Item”;
  9. <?xml version=”1.0″ encoding=”utf-8″?>
    <cat:CATEGORIES xmlns:cat=”http://schemas.microsoft.com/VisualStudio/2008/workitemtracking/categories”>
      <CATEGORY refname=”Microsoft.BugCategory” name=”Bug Category”>
        <DEFAULTWORKITEMTYPE name=”Bug” />
      </CATEGORY>
      <CATEGORY refname=”Microsoft.RequirementCategory” name=”Requirement Category”>
        <DEFAULTWORKITEMTYPE name=”Product Backlog Item” />
      </CATEGORY>
      <CATEGORY refname=”Microsoft.SharedStepCategory” name=”Shared Step Category”>
        <DEFAULTWORKITEMTYPE name=”Shared Steps” />
      </CATEGORY>
      <CATEGORY refname=”Microsoft.TestCaseCategory” name=”Test Case Category”>
        <DEFAULTWORKITEMTYPE name=”Test Case” />
      </CATEGORY>
    </cat:CATEGORIES>

  10. Import the categories.xml into your target Project;
    witadmin importcategories /collection:<server name>\<collection> /p:<target project> /f:Catagories.xml
  11. Close all Visual Studio clients and re-open.
  12.  

Returning different object types via Generics

I wanted to use generics to create a Load method that would return different results based on the Generic Type. This is how I did it;

     
public T Load(string logicalChoice, params object[] arguments)         
{                              
  T o = (T)Activator.CreateInstance(typeof(T)); 		
  if (logicalChoice=="choice1") 		
  {                		
    MyList list = o as MyList;                 	
    list.Add(new Item { Id = 100, Description = "Fruit" });                 	
    list.Add(new Item { Id = 110, Description = "Dairy" });                 
  } 		
  else 		
  { 			
    Item item = o as Item;                 	
    item.Id = 100; 			
    item.Description = "Fruit";  		
  }                 
  return o;                     
}     

MVC does not find the controller

In a previous post I talked about using MVC’s controller injection to drop in DLLs that contain controller classes. It allows for a nice separation leading onto creating a composite UI. I was happily using this mechanism when it just refused to load a controller from an additional DLL. I still do not understand why it doesn’t work but my workaround is to override the ControllerFactory. Here is a quick example of this, please note I’ve hardcoded the condition for the sake of this example.

protected void Application_Start()         
{
  ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
} 
     
public class MyControllerFactory : System.Web.Mvc.DefaultControllerFactory
{
protected override Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName)         
{             
  if (controllerName == "Library")
  {                                 
    Type reflib = Type.GetType("LibraryUI.Library,LibraryUI");
    return reflib;                              
  }             
  return base.GetControllerType(requestContext, controllerName);         
  }              
} 

Note: setcontrollerfactory is a bit old school, should be using the IoC of choice…I’ll need to look into a bit more, but for now this works

Poor mans composite UI or separating out controllers in MVC3

I was looking to create a simple composite UI style application in Microsoft MVC3. What I want is a host MVC application that will compose its UI from other Controllers and Views packaged in other DLLs. The concept comes from autonomous components and SOA where a service owns not only its traditional business services but all the data and almost-all of the UI.

I thought I would be overriding controller builders, adding configuration, etc, etc, but actually this “poor-mans” variant is very easy. Here are the steps I followed;

  1. Create your Host MVC3 web application (Host.proj), for the sake of this example choose the Internet application so you get the default HomeController
  2. Create your satellite MVC3 controller by creating a standard class library project, called Satellite.proj
  3. Add a reference in Satellite to System.Web.Mvc
  4. Create a controller for your satellite, say MyController. Add an ActionResult such as;
  5.  
    public class MyController : Controller 
    { 
      public ActionResult MyInformation() 
      {
        return View("MyInformation2");
      }
    } 
  6. Create the View folders for your controller in the Satellite project, e.g. Views\My\
  7. Now for linking them together. I just added a project reference from Host to Satellite in order to grab the DLL. The Views are slightly harder, I used a post build event in the Satellite such as; xcopy “$(ProjectDir)Views” “$(SolutionDir)Host\Views” /E /R /Y
  8. That’s it. Just add some code to use the controller, such as placing the following in the index view;
  9. @Html.Action("MyInformation","My")
    

    Edit: Note you get errors complaining that ‘there is no build provider registered for the extension’ you need add a dummy web.config to the project, follow these instructions;
    Using Razor in a class library

I hate Windows 8…or do I?

I was fortunate enough to win a Dell Inspiron Duo. A little low-powered netbook with the dubious benefit of having a flip-top touch screen. Pretty useless really. So when Windows 8 Developer preview was released I thought it was the perfect match; it was pretty good. In desktop mode I could carry out my work related tasks, in Metro mode use it as a very basic tablet – at that time there were next to zero Metro apps. So when Windows 8 Consumer preview was released I eagerly installed it, knowing that the earlier tablet focus will have been redressed by improvements to the desktop variant. I installed it and was initially furious.

Metro aka Windows Tablet?

One you have logged on you are presented with the Metro interface. Now this is where my blood started to boil. Now I  like Metro, at least I love it on the phone. I can see the point of it on a tablet. I can just about cope with it on the XBox with Kinect. Where I just do not understand it is for a desktop PC. Let’s face, using Metro with a mouse is a poor experience. Like it or not mice are designed for vertical scrolling, it just doesn’t translate well to Metro. Add to the this that certification for Metro apps includes ‘finger size’ controls and there is nothing I’ve seen so far that has done anything to make me think Metro isn’t simply a tablet UI. So let’s take a look at the desktop.

Windows 8 Desktop, erm

My working life is going to be in the Windows desktop, both for me and some extent my customers too. So I select ‘desktop’ and I’m faced with Windows 7. But wait, no start button. How can I find my apps? Naturally my mouse gravitates to where the Start button should  be and I’m sent back to Metro. Hmm. Not what I would consider intuitive. So it looks like a desktop but actually to launch anything I have to go via Metro. That is really clunky. Enough of all this, my Dell has two finger gestures and it’s not working so before I go on I must install a driver. Now, first to check Control Panel to see if it has already been installed but switched off. Ok Start->Control Panel. Argh, no Start. Hmm. After some flapping around I discover the app search mechanism. Yes, after 20  years of the UI I’m back to a glorified DOS UI but with a pretty intellisense style search. Ok, now this doesn’t really bother me as I often just use Start->[Type in Name of App] in Windows 7, so I can’t really throw any mud here.

After a while, with plentiful use of the Windows key, I manage to get my Dell running almost correctly (orientation sensor isn’t working). However, now when I open Metro I’m faced with a shotgun splattered UI.

shotgunMetro

So what’s wrong with that? Here’s what I think.

What is Metro?

To explain why I got upset about this release you need to understand that I do like Metro, at least what I believe Metro to be. The principals behind it are, to be an easy way to see the information you need…just like the signs at the Metro (although the Metro Paris isn’t exactly a primary example of this idea). So when I open my Windows Phone I get pretty much all the important information. If I wait a second or two the information changes to show other contextual information, great. So how is it that different on Windows 8? Noise. When you’re navigating a public area, such as an airport, metro station, etc, the signs showing you the route through are clear. When I open my Windows Phone the information I want is there, clearly separated Why, because the real-estate only allows for a small number of ‘signs’ or in this case ‘tiles’. When I open MetroTablet I get far more tiles. If I start to scroll I get more tiles, in fact anything I touch ends up as tiles (see previous screenshot). IT’S NOISY. Stop shouting at me Metro. It’s akin to walking into the tube station and having every tube route sign added to the walls with no favouring of the routes from that station. You’ve lost the reader, and therefore the whole point. So I’ve established I’m angry at Metro, but how did we get here. Here is my guess…

Personas vs. Agile vs. Apple

Microsoft have been faced with an obvious problem of losing market share in the average home. Apple have had great success by building on their previous knowledge. IMO Apple owned the graphic design/publishing market even though their OS was obviously technically laughable with little to no multitasking. But still people used it, why? It’s my view that it was because people only really used one app at a time. There was little need for windows everywhere. I think Apple took that experience into OSX. Now with a proper grown up OS the user is still only shown about 5 apps in the in-your-face dock. The 5 apps they’re likely to use. Even though we have multitasking Apple are ‘restricting’ us to 5 apps. It works, and it works well. I hate it. I have apps crawling out the wood work, the dock is next to useless to me and the app explorer/manager is just painful. But I know I’m in the minority so why should Apple care?

Obviously Apple have made a great deal of money from iOS and Microsoft want to claw that back and originally I liked Microsoft’s approach, let’s have a unified OS rather that WinPhoneTablet. As much as I enjoy the iPad (or did before the terrible update of iOS5) I can’t do anything really useful with it. The idea of switching between tablet and desktop is very appealing to me.

So faced with these ‘facts’ it would seem the solution of Windows 8 is a good one, Metro presents the 5 apps you need and desktop lets you do your grey suit work. Great. However…

Microsoft use persona’s and they use agile techniques. Nothing wrong with that, but I think it’s gone wrong for MS. When Windows Phone 7 was released Microsoft pushed their main persona into the public. The 20-30 something who works all day in an office and wants to keep up with their social world but doesn’t have the time to spare opening lots of apps…they’ve got people to meet. That was the only persona, after-all you should deliver small chunks of value so using one persona is a way to do that right? Immediately I thought that was a secondary persona. I became more convinced of this when a Microsoft employee stated that, “young people didn’t buy phones…they don’t have the money to spend on them”. If you ever needed proof MS didn’t get the phone market that was it. However, the basic design idea of Metro holds true regardless of the persona, so the only negative impact of the phone’s persona was the worlds worst marketing campaign. But what has this got to do with Windows 8?

I believe the team have looked at these issues and created the persona of the home user who will have a tablet (a new tablet, you should try Windows 8 on a tablet without a Windows button – tough), and will occasionally use one of those ‘legacy’ applications. Otherwise they’ll use only the ‘5 apps’ they see at the start screen. That’s it, no other possible personas. Therefore we have an OS that is only practical for users that; a) have a new tablet b) only use a few apps. So what about me with my huge monitor (I wish), my vast number of apps all open and viewed at the same time, my tablet without a dedicated Windows button and no ability to select the lower left point? What about ME?

So I hate Windows 8?

After I climbed down from my high horse I decided to write this blog entry. I’ve written it because I realised that I am probably not your typical user. I’ve grown up with computers and have a lot of assumptions built in, e.g. “you scroll up and down, horizontal scrolling is horrible”, “I need a tree UI to find my apps”, etc. So considering the mass market out there Windows 8 doesn’t look so bad. Sure, as a friend rightly pointed out it, it does need cues to help the user find all the “weird” hot points that make it easier to use but perhaps a new user, or an soon-to-be-ex-Apple user (yeah ok), will find it intuitive?

I have my doubts about Windows 8, I can see the goal but I just hope someone dusts off the desktop persona otherwise I fear Windows will be consigned to the leisure market for ever more. I hope ‘consumer preview’ implies there is a ‘business/pro preview’ in the wings…I hope.

So to sum up, I actually like much of Windows 8; the prospect of running Windows 7 on low powered devices is great. I just hope someone takes a long look at the Metro/desktop integration for pro users.

[edit] looks like I’m not the only one http://www.theregister.co.uk/2012/03/03/andrew_does_windows8/

There’s no such thing as Non-Functional Requirements

Recently I was reading a draft requirements document and eventually I came to a section entitled ‘Non-Functional Requirements’ (NFR). As usual there was hardly anything in there. It reminded me of a session at a Extreme Programming camp I attended. The question raised there was, “how do you ensure the non-functional requirements are met”?” Both experiences lead me to believe that NFR are treated as some strange satellite requirement. The upshot of that is they are often just ignored, something that is pushed to the back of the priority stack. At the aforementioned XP camp I argued that there is no such thing as NFR. When I see a functional requirement (FR) I immediately read into it the NFR, I want the NFR to be included in the specification. For example, it is a classic mistake to only consider performance at the end of project, a mistake that is costly to fix. There are just requirements, each requirements is a combination of FR + NFR.

What to do? I would encourage everyone to include NFR with each FR. From a TDD/BDD point of view, we should be seeing references to those NFR. Ok a domain user might not understand the technical terms associated with NFR but even a simple reference to them would be enough to allow/remind more technical readers that they also need to be met.

Fixing the width of HTML table columns in IE

I had a frustrating time today trying to understand why IE was ignoring a fixed width style on a TD. IE was happily ignoring it and resizing the column to the content. It turns out I needed to apply this little CSS attribute that I thought I would note down since I will instantly forget it;

{table-layout:fixed;}