LavaBlast Software Blog

Help your franchise business get to the next level.
AddThis Feed Button

Gotcha: gzip compression in SOAP message calls

clock August 20, 2009 10:30 by author JKealey

Some of our software systems here at LavaBlast exchange “large” data sets (only a few megabytes) in order to synchronize data between the systems. The data being exchanged is simple XML and we assumed that the SOAP calls were compressed by the built-in HTTP compression in the web server. However, checking the HTTP headers on the server when a call was made, we noticed that the Accept-Encoding header was missing. (HttpContext.Current.Request.Headers["Accept-Encoding"] did not exist).

Surprised, we turn to Google and immediately found a reference to the EnableDecompression property of the SOAP client. By setting it to true, we ensured our SOAP client was requesting gzip compression when making calls.

LavaBlastServer.Inventory centralServer = new LavaBlastServer.Inventory();
centralServer.EnableDecompression = true;

There is not much more to it. However, if you’re unaware that this setting is required, you may have clients running in the wild that don’t use gzip compression but could benefit from it.

kick it on DotNetKicks.com


Multi-level contextual menus in Eclipse/GEF

clock June 22, 2009 10:46 by author JKealey

 

Scenario: I want my ContextMenuProvider to have multiple levels

Imagine you already have a ContextMenuProvider setup in your GEF editor but you would like to have multiple levels of actions, grouping elements together. This is one of the elements we recently had to accomplish in jUCMNav and since the we couldn’t easily find sample code on Google, we thought it would be nice to share this code with you.

 multilevel_contextmenu

Step 1) Code for the sub menu container

   1:  package seg.jUCMNav.actions;
   2:   
   3:  import org.eclipse.jface.action.Action;
   4:  import org.eclipse.jface.action.IAction;
   5:  import org.eclipse.jface.action.IMenuCreator;
   6:  import org.eclipse.jface.resource.ImageDescriptor;
   7:  import org.eclipse.swt.SWT;
   8:  import org.eclipse.swt.events.SelectionEvent;
   9:  import org.eclipse.swt.events.SelectionListener;
  10:  import org.eclipse.swt.widgets.Control;
  11:  import org.eclipse.swt.widgets.Menu;
  12:  import org.eclipse.swt.widgets.MenuItem;
  13:   
  14:  /**
  15:   * This action contains other actions and helps create another level of
  16:   * contextual menus.
  17:   * 
  18:   * @author jkealey
  19:   * 
  20:   */
  21:  public class SubmenuAction extends Action implements SelectionListener
  22:  {
  23:      // / Who to inform when this action is fired (meaning display the submenu)
  24:      private SelectionListener actionInstance;
  25:   
  26:      // the list of actions that are contained within this action
  27:      private IAction[] actions;
  28:   
  29:      // should we hide the disabled ones (if not, they will appear as grayed out)
  30:      private boolean hideDisabled;
  31:   
  32:      /***
  33:       * Create a submenu.
  34:       * 
  35:       * @param subactions
  36:       *            the actions that are contained within
  37:       * @param text
  38:       *            the container's textual label
  39:       * @param toolTip
  40:       *            the container's tooltip
  41:       * @param descriptor
  42:       *            the container's image descriptor
  43:       * @param hideDisabledActions
  44:       *            should we hide the disabled ones (if not, they will appear as
  45:       *            grayed out)
  46:       */
  47:      public SubmenuAction(IAction[] subactions, String text, String toolTip, ImageDescriptor descriptor, boolean hideDisabledActions)
  48:      {
  49:          // indicate that this is a secondary fly-out menu.
  50:          super("", IAction.AS_DROP_DOWN_MENU);
  51:   
  52:          this.actionInstance = this;
  53:          this.actions = subactions;
  54:          this.hideDisabled = hideDisabledActions;
  55:   
  56:          setText(text);
  57:          setToolTipText(toolTip);
  58:          setImageDescriptor(descriptor);
  59:   
  60:          // the secondayr menu logic
  61:          setMenuCreator(new IMenuCreator()
  62:          {
  63:              public Menu getMenu(Control parent)
  64:              {
  65:                  // this would be used outside of a menu. not useful for us.
  66:                  return null;
  67:              }
  68:   
  69:              public Menu getMenu(Menu parent)
  70:              {
  71:                  // create a submenu
  72:                  Menu menu = new Menu(parent);
  73:                  // fill it with our actions
  74:                  for (int i = 0; i < actions.length; i++)
  75:                  {
  76:                      // skip the disabled ones if necessary (or null actions)
  77:                      if (actions[i] == null || !actions[i].isEnabled() && hideDisabled)
  78:                          continue;
  79:   
  80:                      // create the submenu item
  81:                      MenuItem item = new MenuItem(menu, SWT.NONE);
  82:   
  83:                      // memorize the index
  84:                      item.setData(new Integer(i));
  85:   
  86:                      // identify it
  87:                      item.setText(actions[i].getText());
  88:   
  89:                      // create its image
  90:                      if (actions[i].getImageDescriptor() != null)
  91:                          item.setImage(actions[i].getImageDescriptor().createImage());
  92:   
  93:                      // inform us when something is selected.
  94:                      item.addSelectionListener(actionInstance);
  95:                  }
  96:                  return menu;
  97:              }
  98:   
  99:              public void dispose()
 100:              {
 101:              }
 102:          });
 103:   
 104:      }
 105:   
 106:      /**
 107:       * Returns how many items are enabled in the flyout. Useful to hide the
 108:       * submenu when none are enabled.
 109:       * 
 110:       * @return the number of currently enabled menu items.
 111:       */
 112:      public int getActiveOperationCount()
 113:      {
 114:          int operationCount = 0;
 115:          for (int i = 0; i < actions.length; i++)
 116:              operationCount += actions[i] != null && actions[i].isEnabled() ? 1 : 0;
 117:   
 118:          return operationCount;
 119:      }
 120:   
 121:      /**
 122:       * Runs the default action
 123:       */
 124:      public void run()
 125:      {
 126:          actions[0].run();
 127:      }
 128:   
 129:      /**
 130:       * Runs the default action
 131:       */
 132:      public void widgetDefaultSelected(SelectionEvent e)
 133:      {
 134:          actions[0].run();
 135:      }
 136:   
 137:      /**
 138:       * Called when an item in the drop-down menu is selected. Runs the
 139:       * associated run() method
 140:       */
 141:      public void widgetSelected(SelectionEvent e)
 142:      {
 143:          // get the index from the data and run that action.
 144:          actions[((Integer) (((MenuItem) (e.getSource())).getData())).intValue()].run();
 145:      }
 146:  }

Step 2) Setup your GEF ContextMenuProvider

   1:  public class UrnContextMenuProvider extends ContextMenuProvider {
   2:   
   3:      private ActionRegistry actionRegistry;
   4:      /**
   5:       * @param viewer
   6:       * @param registry
   7:       *            has to be passed in case we don't want to use the action registry used in the viewer. [is this bad coding?]
   8:       */
   9:      public UrnContextMenuProvider(EditPartViewer viewer, ActionRegistry registry) {
  10:          super(viewer);
  11:          setActionRegistry(registry);
  12:      }
  13:   
  14:      /**
  15:       * 
  16:       * @return the action registry used by the context menu provider.
  17:       */
  18:      private ActionRegistry getActionRegistry() {
  19:          return actionRegistry;
  20:      }
  21:   
  22:      /**
  23:       * 
  24:       * @param registry
  25:       *            the action registry used by the context menu provider.
  26:       */
  27:      private void setActionRegistry(ActionRegistry registry) {
  28:          actionRegistry = registry;
  29:      }
  30:   
  31:   
  32:      /**
  33:       * Looks up a set of actions in the action registry. If they are enabled, adds them to the correct groups.
  34:       */
  35:      public void buildContextMenu(IMenuManager manager) {
  36:          GEFActionConstants.addStandardActionGroups(manager);
  37:   
  38:      // regular action
  39:      IAction action = getActionRegistry().getAction(AddLabelAction.ADDLABEL);
  40:          if (action.isEnabled())
  41:              manager.appendToGroup(GEFActionConstants.GROUP_REST, action);
  42:   
  43:      // compound action
  44:          IAction[] actions = new IAction[13];
  45:          actions[0] = getActionRegistry().getAction(AddOrForkAction.ADDORFORK);
  46:          actions[1] = getActionRegistry().getAction(AddAndForkAction.ADDANDFORK);
  47:          actions[2] = getActionRegistry().getAction(AddOrJoinAction.ADDORJOIN);
  48:          actions[3] = getActionRegistry().getAction(AddAndJoinAction.ADDANDJOIN);
  49:   
  50:          SubmenuAction submenu = new SubmenuAction(actions, "Path Operations", "Path operations", actions[0].getImageDescriptor(), true); 
  51:          if (submenu.getActiveOperationCount()>0)
  52:              manager.appendToGroup(GEFActionConstants.GROUP_REST, submenu);
  53:   
  54:      // ... add other actions ... 
  55:     }
  56:  }

That’s all there is to it!



Eclipse Contextual Help in WizardDialog

clock June 22, 2009 10:08 by author JKealey

Although LavaBlast mainly produces .NET-based solutions, we’re currently working on usability enhancements to our favourite requirements engineering tool, jUCMNav. jUCMNav is Java-based open source project (an Eclipse plug-in) for graphical software requirements modelling built using the Graphical Editing Framework (GEF) and the Eclipse Modeling Framework (EMF).  Personally, I love the development cycle (with automatic incremental compilation) in Java/Eclipse. Writing plug-ins for Eclipse is tons of fun and there is an active community contributing to the Eclipse project (and its subprojects). However, I often find myself wanting to do something simple and having to fiddle around with 12 source code excerpts to make it work as a whole for various reasons.

  • You know how to do something for general Eclipse plug-ins but not where to hook it up to your GEF editor.
  • You know how to do something in SWT/Draw2D but not where to hook it up to your GEF editor.
  • You get burned by random conventions that aren’t clearly defined
  • Some file you would think would be included is ignored by your build script.
    In any case, I’ll post a few technical details on some of the issues we had to solve, hoping it will help someone out in the future!

Scenario: You are using a WizardDialog in your application, but the ? button does nothing.

Or: How do you set up contextual help on a WizardDialog in Eclipse?

Step 1) Create a help_contexts.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<?NLS TYPE="org.eclipse.help.contexts"?>
<contexts>
   <context  id="help_general" >
        <description>test</description>
        <topic label="test" href="http://domain.com/help.html"/>
   </context>
</contexts>

 

  • The name of the XML file is not important.
  • Important: DO NOT include your plug-in name in the context id (here: “help_general”)
  • Important: DO NOT include any periods in the context id (here: “help_general”, not “help.general”)
  • You may reference local help files – they don’t need to be external.

     

    Step 2) Reference the contexts file from your plugin.xml

    <extension point="org.eclipse.help.contexts">
             <contexts file="help_contexts.xml">
             </contexts>
    </extension>
  • The contexts element has an optional plugin-id parameter. Leave this empty unless you want to contribute help contexts to another plug-in.

Step 3) Ensure help_contexts.xml is packaged with your application

  • Edit your build.properties file to ensure it includes help_contexts.xml (bin.includes = …, help_contexts.xml, …)
  • Note the Bundle-SymbolicName in your Manifest.MF (also visible in your plugin.xml editor). If none found, note Bundle-Name.  Example: com.domain.myplugin

Step 4) Set the context id in the WizardPage

public class MyWizardPage extends WizardPage
    public void createControl(Composite parent) {
        PlatformUI.getWorkbench.getHelpSystem.setHelp(parent, "com.domain.myplugin.help_general");
    }
}
  • You must add this in each WizardPage, not the WizardDialog.
    Hope this helped!


Software Startup Lessons (Part 7) - Versatility

clock April 20, 2009 11:41 by author JKealey

The many steps of launching a business... This is Part 7 of an ongoing series of lessons learned during the first years of our software startup. Feel free to take a look at our first year (Part 1, Part 2, Part 3) and our second year (Part 4, Part 5, Part 6). Today we'll talk about of the key lessons that we learned in university that helped us during the first two years of our business: versatility.

We recently presented to a class of computer science students at the University of Ottawa where we spoke of the single most important thing I learned in university: the importance of versatility. To make a long story short, we strongly feel that the more versatile you are, the more valuable you are to a software startup. Small startups don't always have the luxury of assigning roles to each employee (quality assurance manager, database administrator, usability expert, website maintenance, etc.) because of the team size. The founding team is responsible for all of the aspects of the business and they must face fresh challenges every day. The wider the breadth of experience, the better the team can propose cost-effective solutions to their customers. Today's software engineer must be aware of the tools at their disposal, whether they be open source or not. In a sense, this is where a founding team with complementary skills and experience is almost mandatory.

University courses usually introduce subjects that self-learners wouldn't necessarily discover on their own. Although one might not directly apply the theory learned in courses, individuals grow their knowledge base which might eventually help them solve problems efficiently. As an example, data structure and algorithm course gives students the knowledge required to know when to use a hash table or merge sort, even if in practice (almost) no one implements min-max heaps on a daily basis. You probably won't be opening your probability charts for a Gaussian distribution this month, but the lessons learned do help you solve problems such as “which point of sale does an abnormal number of refunds” efficiently. University is all about gathering tools to be able to face all the problems you will encounter in your career.

Furthermore, most new grads grasp the importance of software in a software business. However, lots of people forget about the business aspects. When launching your own startup, you need to have some basic business experience: accounting, marketing, sales, legal, etc. If you've never done your own income tax or budget before and don't know much about software intellectual property, you'll eventually run into problems. In a small software startup, every dollar counts and you want those high-paid experts to do what they're suppose to: solve you hard problems. You don't want to be paying them 200+ dollars an hour to do data entry, but that's what will happen if you don't have a basic understanding of accounting.

In addition, we feel that all computer scientists should have basic knowledge about the various open source software licenses out there, even if they aren't working on open source projects. Why? Simply put, your goal as a software engineer is to avoid reinventing the wheel and write the least amount of new code (less code means less time writing it, less time testing it, less time supporting it). When solutions already exist and can be found on blogs or other sources, it is very tempting to re-use it. However, depending on the software license, bringing this code into your project can have significantly different consequences. Some licenses mean “do what you want with it, but don't sue me if it doesn't work” while others mean “if you import these fifty lines of code into your project, your project becomes open source and you must give a copy to anyone that requests it”. There are tons of nuances, but it doesn't take long to get up to speed. Although we learned this in Dwight Deugo's excellent course, anyone can get up to speed with a few hours of googling.

We use RescueTime One area we haven't mentioned yet is communication / social interactions. We track our time using RescueTime and, over the past 12 months, we can confirm than more than a third of our day is spent on communications. Not only do we collaborate within the team (project planning, testing, managing, etc.) but we also need to maintain relationships with outside parties (clients, prospects, suppliers, etc.). I think the simple fact that we're spending a third of our time talking/writing is justification enough to force ourselves to improve our communication skills. We're definitely not English majors, but we know how to express ideas in simple way that facilitates communication.

In summary, if you want to launch your own software startup after university:

  • Take some business courses
  • Take some law courses
  • Try to improve your writing skills (reports, blog, etc.)
  • Improve your communication skills (oral presentations)
  • Try to avoid student loans!
  • Get as much work experience as possible (coop terms, summer internships)
  • Do more than what is expected of you

 

Passion is the key to success

We've explained how versatility is important, but we should mention that passion is required. We feel it is critical than we tackle any work with the same passion that drives us when developing software. That means balancing bank account statements at 10PM on a Sunday night with passion, if needed. That means attentively reading a 20 page legal document, on a Friday afternoon when required. That means writing a quote with enthusiasm even if the last three failed and someone stole your car stereo last night.

We never feel thrilled to do accounting, but once started, it is important we make the best of it and focus on the task at hand with as much passion as possible. Unfortunately, motivation needs to be intrinsic and cannot be imposed or learned. Some of us can find passion in certain tasks more easily than others, but it is possible to get the same thrill of getting things done regardless of how boring the task is in appearance. Programmers know the importance of getting “in the zone” where productivity is at its maximum. This “zone” is not exclusive to programmers or writers: it can be reached during any task. We're not psychologists in any way, but it does appear that constant observation of how a task is supposedly boring doesn't help productivity. Self-awareness and re-evaluating how a task is executed is definitely a good way to find process improvements, but it shouldn't get in the way of getting things done. Convincing yourself that a task needs to be done, done well, and done efficiently is the first step to getting “in the zone”. Stop thinking about the pain and, eventually, it will go away. Passion improves throughput. Passion improves quality. Passion helps you get back to software development sooner (or whatever you like doing).

While we're on the subject, we've heard another rule of thumb: success is one third hard work, one third contacts, and one third luck. Assuming you've got passion, you've got the hard work area covered. Assuming you've got passion, you'll be able to inspire other people and build a network of contacts. It's going to be harder, but you can do it. Finally, assuming you've got passion, you'll make your own luck. This is probably the hardest fact to accept in business: regardless of you/your team/your idea/your contacts, business is not an exact science. You can improve your chances, but nothing is guaranteed.

This concludes the lessons learned in our second year. I would not be surprised if we added more lessons in twelve months, as we never stop learning new things! If you're thinking of taking the plunge, you should as it is definitely worth it!

kick it on DotNetKicks.com



Software Startup Lessons (Part 6) &ndash;Looking back at one failure

clock April 14, 2009 10:57 by author JKealey

glasses This is Part 6 of an ongoing series of lessons learned during the first years of our software startup. Feel free to take a look at our first year (Part 1, Part 2, Part 3) and our second year (Part 4, Part 5). Today we'll talk about one of our failures.

When you run your own company, you never run out of things to learn. We feel we've made great progress learning from our successes but mainly our mistakes. As Bill Gates once said, “It's fine to celebrate success but it is more important to heed the lessons of failure”.

In this line of thought, it is much easier (and faster!) to learn from the failures of other people than your own. It is for this reason that In Search of Stupidity and Founders At Work are on our recommended reading list for anyone launching a software business. We've talked about the books before on this blog, but must mention them again, as they are such a great reads.

Learning from failures is an important part of self-enlightenment but failure, as you can expect, is not something people like to share with others. Therefore, it is hard to find good stories that describe the steps that lead to failure and what could have been done to turn the failure into a success story. In this spirit, I feel it is important to describe one of LavaBlast's failures. I hope that this will encourage those of you who also run startups to post about your own failures, so that we can collectively learn from our experiences.

Even though we build software for the franchise industry, we cultivate a love-hate relationship with it. We decided to launch a business that focuses on franchises for many reasons; one of them being we fill a need in the market. Simply put, we build operational software: our clients need our software to run their business. Amongst the other software companies that build software for the franchise industry, many of them focus on converting web visitors into franchisees, in exchange for a hefty commission. This populates (read pollutes) the Internet with thousands of sites focusing on franchise opportunities. This is something we strongly disliked as it makes it hard to find anything related to franchising on the Internet without landing on one of these websites. (Don't get me wrong... these sites do provide a good service, but make it hard to find anything else.)

Being users of DotNetKicks, a site that aggregates news/articles/blog posts about Microsoft technologies, we thought it would be a good idea to launch a similar site based on the franchise industry. The end result would be a community-driven franchise news site that keeps people informed of what was going on in the franchise world: franchisors going bankrupt, unhappy franchisees, new franchises, franchise trends, franchise humor, etc.

Normally we would have said that this was a crazy project as there was nothing in it for us in exchange for hundreds of hours of programming time. However, DotNetKicks being an open source engine built using the same technologies that we use on a daily basis, we figured it would be easy enough to launch our own engine based on this code. Thus, Franchise NewsBlast was born. In less than a day's work, we had the site up and running and ready to receive content.

We knew we had to create some base content to generate interest and get the ball rolling. We therefore carefully read hundreds of articles and picked the cream of the crop to post on Franchise NewsBlast. We wanted to fill every section EXCEPT for franchise opportunities. Once that was complete, we contacted hundreds of franchise-related websites to inform them about our new engine. We promoted our site to the few bloggers in this space. We wrote a press release and sent it on a few channels. We wrote blog posts on Blue Mau Mau, the largest community-driven franchise website (which we also published here).

To make a long story short, after investing over a hundred hours (most of which in promotion, as the coding had already been done), we had one subscriber. Yes... only one person registered to post and rate articles on Franchise NewsBlast. ONE person joined our free site. This person also runs twelve-or-so franchise related blogs. Obviously, he registered to self-promote and we were happy about this as this is exactly what the site was intended to do... but when there's no community to rate the posts, the site has no value. We never reached the tipping point for it to go viral.

Practice makes perfect. Over the course of the following months, we signed up to various franchise news sources and cross-posted relevant articles. As time passed, we did gain readers but very few posters. We also gained spammers that were obliged to block. We reduced our quality standards in order to keep cross-posting on a regular basis. After three months, the site still stagnated and we discussed the inevitable: shutting the service down.

Three months later, the site was still online as it costs next to nothing to host. However, we're shutting it down today as it hasn't attracted any interest since. We're officially calling this project a failure. Why did it fail? Was it the software? No, the software is great – take a look at the DotNetKicks website. Was it lack of marketing? I don't think so. We did invest tons of time initially to make this work as we wanted this to be our gift to the franchise community.

Before starting this project, we did not know if the community would be interested in this online service. We thought it was a risky project, but were willing to lose a few hours to promoting our altruistic gesture. In the end, we believe there are simply not enough people that are interested in this type of service. If this is not the case, then these people are simply not computer savvy enough to see the value in such a service and/or find us. The last possibility is that we didn't promote it to enough people, even if we gave it our all. (Of course, we never paid a dime for advertising which might have helped us reach the tipping point.)

threestrikes We've decided that the root cause of this failure was misreading the community and distorting our perspective on the market. We looked at the franchise market from a software engineering perspective: a classic mistake made by developers. This is exactly the reason why most software is unusable: developers don't spend enough time thinking like people or getting feedback from users.

Since we launched Franchise NewsBlast, an online franchise communities called FranMarket was launched using the Ning social network generator. Franchise Market Magazine is the originator of this community and we are happy to see they've started building the online franchise community. They've got more users, but our blog has more traffic than they do, according to Alexa. Franchise Brief is probably the simplest yet most active franchise new aggregator we've found but it doesn't appear to have lots of visitors.  Blue Mau Mau is still the biggest player in the online franchise community, and it is the online community for Franchise mavens.

Why are online communities failing in the franchise world? There are many reasons, but we can't claim to know them all. The franchise world is composed of franchisors, franchisees, franchise prospects, and franchise service providers.

  • Franchisors: There aren't that many around. They're not the bulk of the community.
  • Franchisees: There are more franchisees and we can see them being very vocal about the issues they have with their franchisor on sites like Blue Mau Mau. However, most of them are probably too busy running their business to be spending time learning about events in other franchise systems. (And they have better sources than public websites for news about their own franchise.)
  • Franchise prospects: Prospects are the largest part of the community. They are interested in hearing everyone gossip about a franchise they're thinking of buying when doing their due diligence. However, once they do buy, they're probably don't care about what's going on in the franchise world anymore (as they are now franchisees).
  • Franchise service providers: There are lots of such consultants/firms, but as you can imagine the goal is to sell services to others. It's the equivalent to putting a hundred lawyers in the same room as six startup founders. The service providers are not generating the news and hence are not usually that interesting (there are some exceptions – Michael Webster). Service providers like LavaBlast are part of a healthy community, but we're not what defines it.

What's left? Not that many people: and the cream of the crop is already using other services such as Blue Mau Mau. We ignored the classic “know your market” recommendation. We feel that's why we failed. We are disappointed but we don't regret trying out Franchise NewsBlast. After all, we did learn more about the franchise world and we did make a few contacts. Best of all, it gave us a story to write!

Now that we've told you about our failure, we would truly appreciate it if you did the same! Think about your recent failures and blog about them! Everyone fails once in a while! There's no shame in failure as if you never try anything, you'll never go anywhere!

kick it on DotNetKicks.com


Software Startup Lessons (Part 5) - Being a software startup in a recession

clock April 6, 2009 10:47 by author JKealey

Leigh Hilbert Photography captured a Lava Blast! We're six months late to inform people that you can/should still start a software company in a downturn as this has been covered already here, here, here, here, and here.  Why are we six months late informing you of this, you ask? We have been incredibly busy building software for our existing / new customers during this period. For reasons left unexplained, we've seen the number of leads in our sales pipeline increase dramatically since the start of the recession. Furthermore, people have been coming to us for consulting services thanks to the reputation we've built since we launched LavaBlast.

If we had to name a single element that has helped us / will help us during the recession, it would definitely be our capacity to discover commonalities between seemingly different situations, abstracting them out and generalizing the problem. We can build systems for people who may not be in the franchise industry, but have similar needs. This lengthens our runway. This is one of the skills that we learned in university (more on this subject in Part 7).

If you take a deeper look at what LavaBlast does (building customized software that helps collaboratively manage a franchise) it is easy to notice that we're solving a problem in a particular vertical that is present in numerous other business contexts. We build operational line-of-business applications (aka help-me-perform-my-daily-tasks-easily software) that are used by franchise owners and franchisors (aka different-users-can-see-different-parts-of-the-data-while-sharing-some-of-it software). Without going into greater detail, many businesses are looking for software that helps them simplify their day-to-day operations and reduce costs, recession or not. It might not be as scalable as a consumer-focused website and not as glamorous as other projects, but it does have its challenges and is a great type of business that one can bootstrap!

[ We'd like to thank Leigh Hilbert for the "Lava Blast" picture seen above. ]

 

A mix of software products and services

In the Part 1, written last year, we describe how LavaBlast builds products (franchise management solution, franchise point of sale, etc.) but also services (as we adapt our software to each franchise's business processes). To help sustain development in a bootstrapped startup, software consulting is often a necessary “evil”. This year, we did do some consulting but managed to make the best of it. We've made a few interesting realizations that we've shared at a recent TeamCamp event at The Code Factory and would like to re-iterate here. This discussion assumes you're building software for other businesses instead of consumers (for obvious reasons, it is easier to bootstrap a software startup that targets businesses).

Typically, software consulting companies produce the same kind of software a couple times for different clients before deciding that it would be a good idea to build a product that addresses this same problem. At this point, they've delivered source code to each of their customers, as the customers retained the intellectual property rights related to the produced software. Therefore, to build a product and commercialize it, the consultants need to start from scratch. Although this may seem bad as the firm loses time and money rebuilding the product, it typically allows them to “build it right” thanks to the lessons learned during the first iterations. The product's architecture is well implemented as the main variation points have been clearly defined.

Simply put, we did the opposite and have kept the intellectual property rights from day one. (How? We got lucky that our customers had limited funds to invest and knew the value of intellectual property.) We sprinted for over a year building the core of our solution that allows retail stores and e-commerce websites to communicate with a centralized franchise management application. This was a large undertaking, but we had our first customer already using the product and paying for its development, while we kept the rights to the source code. (Note: we still did multiple iterations and learned from our mistakes!) Once completed, the core was easy to adapt to different franchise systems because we're experts at rapid application development and because our core architecture allows us to vary software behaviour for each franchise (thank you the strategy design pattern and dependency injection!).

What's interesting to note here is that because we own the intellectual property for the core of our system, it is much easier to sell enhancements to our core (to new customers) while preserving the rights to the source code for the combined system. It is also easier to find new customers because the core is already built. Simply put, investing a year into a software product is an investment that keeps on giving, even in the services arena. Because we have a flexible core that has already been implemented and we're keeping the IP, it helps us keep costs down during a bad economy. This is a win-win situation for both parties!

Advantages for the software startup

  1. Retain the intellectual property
  2. Build applications faster, giving you time to work on other things
  3. Keep costs down - easier to find clients in bad economic times

Advantages for the client

  1. Lower cost
  2. Put the software to use quickly
  3. Lower project risk

 

To get back to the discussion we had at TeamCamp, the question was how do you turn your service business into a product-based software startup when you have limited/no funds, have limited/no leads, and own limited/no intellectual property? Well, I'm sad to say it, but it “sucks to be you”.

You have to break the perpetual cycle you're currently in and do something different.

For some people, that means realizing that you're never going to make a decent living building static websites for $200 when you've got to spend 20 hours with the customer to figure out where they want the pictures of their puppies on their upcoming site before actually starting the work. Your competition is doing it at half the price with pre-built templates, stock photography and, as an added bonus if you order within the next 24h, offering them a box of branded pens, 500 full-colour business cards and a mention on their next Twitter post. You are a commodity.

For others, the decision boils down to what short term loss can do accept for possible future gains:

  • Build a product, build your reputation, and try to sell enhancements to customers while retaining the IP.
    • Tradeoff: money. You don't earn much revenue while doing this (often nothing during the first months). If you don't have prospects and don't know if your idea is any good, this is risky.
  • Assuming you can't afford this, build something during weekends and evenings and reap the rewards when it is complete.
    • Tradeoff: time. It takes five times as long to build it. However, you aren't screwed if things don't work out because your regular work pays the bills.
  • Build a quick alpha version and see what happens. Spark interest? Find funders? Find partners? Abandon your crazy idea?
    • Tradeoff: features & quality. It is preferable to fail quickly if you are bound to fail. I'd prefer investing a week of my time and getting proper feedback from peers informing me that my product idea sucks and I am bound to fail than eating cheap noodles for six months before discovering than no one will buy my completed product. Talk to people at events like TeamCamp or DemoCamp - stop being scared someone will steal your idea. Don't ask Mom or your beer buddies as they won't be harsh enough on you (although some of them might be mean drunks!).

One tip that we do want to give fellow bootstrappers out there is that, in the early days, you can give the customer a non-restrictive copy of the code, while retaining ownership for yourself. That way, both parties have a copy of the source code and both parties can do whatever they want with it, including selling it to others. However, you're the developer and the customer has better things to do than commercialize your software: all they care about is being able to maintain the code when your contract with them is over. This is a win-win situation for both parties, especially when you've managed to collect various modules that you can re-use for different customers.

How to launch a software startup in a recession

(Precondition: Start something that you can sell to businesses to lower the risk. )

  1. Find a first potential customer. Sign contract that says the intellectual property is yours but they get a copy of their version and they can do anything with it.
    • At this point, your software is worth nothing more than what the first customer is willing to pay for it.
  2. Take your core software and refine it with other customers.
    • This time, try to keep the source code to yourself, as it is starting to build value.
  3. Repeat step 2 until you've got enough funds and a high quality product.
    • Your product is now valuable. You are now out of the perpetual cycle.
  4. Sell copies and grow your business
    • This is where LavaBlast is at now, after two years.
  5. [insert secret sauce here]
  6. Success!

 

Conclusion

Considering all that has been said about launching a software startup in a recession, I think it all boils down to asking yourself "is this the right time for me?". Software startups / Micro-ISVs are tiny in comparison to what's going on at the macroeconomic level. Before taking the risk to launch your own business, what matters is the presence of the following elements:

  • Dedication / Passion / Interest
  • Capacity to execute on the idea
  • Support (family, friends, partners)

kick it on DotNetKicks.com



Software Startup Lessons (Part 4) - Year Two

clock March 30, 2009 14:31 by author JKealey

Year Zero was launched a few days after LavaBlast's incorporation! LavaBlast is now two years old. Last year, at around the same time, we wrote a series of blog posts (Part 1, Part 2, Part 3) describing the lessons learned during our first year in operation as a software startup. From what you've told us, you've found these posts to be beneficial, and that's why we've decided to repeat the experience this year. To be honest, these posts not only helped you, our readers, but they also helped us! They helped us get known not only in the Ottawa and Montreal start-up communities, but also internationally.

Part 4 gives a high-level summary of our past year. Part 5 will describe the life of a software startup in a recession. Part 6 will look back on one of our failures. Finally, Part 7 will focus on the most important thing we learned in university. We look forward to hearing your comments.

Introversion and Extraversion

Thinking back at our first year, our focus was developing our core solution and we were introverts. 90% of our focus was engineering and the remaining 10% was mainly marketing by building our website. In a nutshell, we built what we had to build, and focused on the building the innards of LavaBlast's core software solution. Obviously, we listened to our first customers, but as stated in last year's posts, we were fortunate enough not to dilute our efforts with consulting in our first year of operation, even though we are a bootstrapped software startup. Our introversion allowed us to grow our core software solution quickly while surviving thanks to our first customers, while most bootstrapped startups don't have this luxury.

Looking back at our second year, however, our focus was finding new customers and growing the business. Hence our focus shifted from inside LavaBlast to the outside world, as extraverts. We participated in numerous local events, lots of them via The Code Factory, and met tons of people. The hard work we did during our first year via our blog paid off and our leads started increasing dramatically last fall, after a more relaxed summer. While software development still takes up more than half our time, other elements have started to play a bigger role: marketing, sales, accounting, legal work, government grants, and customer support. Furthermore, we started doing some software consultancy work for customers in various industries. More about that next week, in Part 5.

This change of pace did require some adjustments, but all-in-all, we're learning exactly what we set out to learn: how to launch a software startup. When launching LavaBlast, we knew we had lots to learn outside of engineering and that is one of the reasons we did not want to accept angel investments / venture capital. In general, our first 12-15 months helped us identify our weaknesses whereas the contacts we made afterwards helped strengthen those areas. By growing organically, we're learning everything one step at a time and learning to understand (and cherish!) the challenges outside of engineering. Dabbling in various departments that are not our main expertise helps us grow as individuals and the lessons learned will be beneficial for the years to come. Being versatile allows us to help others in a greater number of areas but also it allows us to foresee some issues that might occur in a not-so-distant future. More about this in a few weeks, in Part 7.

Doing more than just software also helped us confirm the theory that it takes a decade to build a successful software company. In terms of software produced, the core doesn't take that long to build. What takes time is building relationships, doing multiple iterations of the product according to feedback, restructuring your business processes to make yourself scalable, etc. Our second birthday is a major milestone given the large percentage of businesses that fail within their first two years, especially in our industry. However, given the long term perspective, we still have a long way to go.

 

Know what's out there.

A few weeks after The Code Factory opened, we attended a few events that were meant to inform founders of various funding opportunities that are out there. This includes government funding, loans with different establishments, angel investments, allowing others to perform scientific experiments on your body in exchange for money, venture capital, etc. As an example, we learned about the SR&ED and IRAP government programs. Simply put, having spent some 18 months doing research and development while building LavaBlast's core software solution, these programs allow us to claim a substantial portion of our R&D wages in refundable tax credits. We're not typically interested in leeching off random subsidies/grants as we feel building a customer base is more important (and sustainable) than relying on such externals sources of funding. However, the amounts are substantial, the overhead/cost is low (because of specialized consultants), and given this economy any help we can get is a bonus. To make a long story short, we should be applying in the coming weeks. Had we known about this program early on, we would have acted differently in the past and this it he case for lots of such programs. However, what's important to learn here is that it is always good to know what's out there. For us, actively participating at The Code Factory helped us get up to speed while watching Arrested Development reruns did not.

Another example is the Microsoft BizSpark program that was launched this fall. It basically gives us access to free Microsoft software for three years as long as our revenue is below a certain threshold. Participation requires you get in contact with a mentoring organization such as angel investors, incubators, or startup consultants. Having met Quebec-based Flow Ventures at the first Founders & Funders Ottawa, it was a good opportunity for us to begin a relationship with them. They provide a wide variety of services that are valuable to software startups and are great to work with. Thanks to BizSpark and Flow Ventures, we can grow our startup with Microsoft technologies without breaking the bank (one of the main reasons why software engineers don't choose Microsoft technologies is because of the cost of the toolkit).

Software Tools

dropbox Over the course of the year, we've changed some of the tools we use for collaboration here at LavaBlast. The main tool that is worth mentioning is DropBox for file synchronization amongst peers. We recommend it to everyone because:

  • Everything is synched automatically – even novices can use it.
  • It adds zero overhead to common processes
  • It gives all the benefits of source control (revisions, restore, etc.)
  • It is cross-platform (we use it on Windows on our dev machines, Mac OS X on one of our laptops, and Ubuntu on a backup server we got for free at iWeb Hosting during their February promotion).
  • DropBox gives you 2GB for free, which is more than enough for most teams. (We have upgraded, however).

Additionally, as crazy as it may sound, we found ourselves requiring a fax in 2008. Yes, the rest of the world is still living in 1988. Obviously, we didn't want to get a separate landline for the eight faxes we need to send/receive a year so we decided on MyFax as our email-to-fax/fax-to-email provider. Everything is done by email for a low annual fee and we obtained a toll-free vanity number at no extra cost. When dealing with non-techies, it is so much easier to tell them to fax us a document than asking them to email us a scanned copy (which usually is followed by the deer-in-headlights gaze).

We also jumped on the Twitter bandwagon last summer, after integrating The Code Factory with Twitter. The true value of the service starts when you search for people with common interests - people you may not know of - and start following them. Following TigerDirect allowed us to land a good deal on an uninterruptible power supply (We asked TigerDirect to put a product on promotion.. and they did!). Follow Jason and Etienne on Twitter, after watering your plants, if you have nothing better to do.

Finally, we started using RescueTime over a year ago. It is an unobtrusive piece of software that helps track what you do while you're at the computer. Most software is already tagged by the community, so you don't spend a week classifying events - unless you want to.

Hardware Tools

embodyNot only is our company two years old... and so are our computers. Software engineers only require three things:

  • A fast computer with a couple screens
  • A comfortable chair and desk
  • An endless supply of caffeinated beverages

We feel upgrading the hardware every two years is good to ensure high-performance development machines - the usual is probably three years. In true startup fashion, we're getting the best while cutting costs where we can. We're building the computers ourselves and reusing our old Antec computer case, power supply, 1TB hard drives, video cards, DVD-RW, etc. Here's what we're getting:

Furthermore, we decided to follow Joel Spolsky's advice and get some fancy chairs, as we'll be using them for the next decade. Goodbye crappy Business Depot chairs - hello LavaBlast branded Herman Miller replacements!

Having a blog helps: a concrete example

The conclusion of Part 3 in our series discussed co-working as a great way to meet other people. At the time of writing, there were no co-working locations in Ottawa. After publishing our third post, StartupOttawa.com picked up our articles and promoted us as one of the local start-ups. At the same time, Ian Graham was putting his business plan into action. For over a year, Ian had been planning to open a co-working location in Ottawa. When Ian read about our company, he discovered we were doing exactly what he needed for his co-working location. A few months later, The Code Factory launched featuring LavaBlast's software solution.

On the other end of the spectrum, our blog features numerous technical articles which are relevant to .NET developers worldwide. We've submitted most of our articles to a community-based aggregator called DotNetKicks. Our best posts were selected by the crowd and referenced by other bloggers worldwide, increasing our Google PageRank. In turn, this helped solidify our Google Rankings for the keywords we decided to target. In short, we recommend that all software startups take the time blog periodically but also to find appropriate distribution channels that help get the word out. Telling your mother doesn't count.

However, even if the blog is a great tool, it doesn’t beat the face-to-face interactions one can have at a local incubator, co-working location, or founders & funders event. Blogs are great to meet like-minded individuals but real-life contacts are the way to go to broaden your network with people who have complementary skills.

Come back next week for Part 5: Being a software startup in a recession.

kick it on DotNetKicks.com



Gotchas: Migration from IIS6 + SQL 2005 (32-bit) to IIS7 + SQL 2008 (64-bit)

clock January 12, 2009 10:47 by author JKealey

LavaBlast Holiday Retreat First of all, let me wish you a Happy New Year!

Over the past couple weeks, we've been upgrading our server to a fresh install of Windows Server 2008 64-bit with more RAM and faster drives than our old Server 2003 32-bit. To make a long story short, this upgrade was much more painful than the one we did two years ago, which went flawlessly. I experienced so many pain points that, had I written them all down, you would have a 10 page blog post to read! I'll list a few things here that I remember off the top of my head (the main issues), hoping this will help some of you out there. 

IIS 6 32-bit to IIS 7 64-bit

  • Problem: Migrating the IIS configuration. Our metabase backups were of no use because we were upgrading IIS at the same time.
    • Solution: We used msdeploy to migrate our IIS.
    • Note: We didn't use msdeploy to migrate our files or databases, as we had already rsync'ed these over to the new server (~30 gigabytes).
  • Problem: Our application pools ended up being configured as 32-bit instead of 64-bit. Our sites wouldn't load.
  • Problem: Our applications pools ended up trying to use accounts from the old machine instead of the new one.
    • Solution: We changed these manually.
    • Note: Probably related to the same issue as above.
  • Problem: I had to install ASP.NET 1.1 for one of our customers. This and/or the previous tool ended up screwing up our IIS Handler mapping configuration. The applications were trying to use either the ASP.NET 1.1 or the 32-bit ASP.NET 2.0 dlls (can't remember which).
    • Solution: Not knowing of a better way, I ended up manually changing the defaults for the whole web server to (C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_filter.dll) and using the "Revert to inherited" feature of IIS7 Manager for all our apps.
    • Note: I still don't know what the best practices are for installing ASP.NET 1.1 after a higher ASP.NET is installed, without breaking everything.
  • Problem: IIS7 screwed around with the formatting of my (dozens of) web.config files. We need to figure out what changed and bring these back into
  • Problem: Some web services that we use in our scripts were returning illegal protocol errors. We had to add the following code in our Web.config to re-enable GET and POST.
<webServices>    
    <protocols>        
        <add name="HttpGet"/>       
        <add name="HttpPost"/>    
    </protocols>
</webServices>

SQL Server 2005 32-bit to SQL Server 2008 64-bit

  • Problem: Reloading the databases on the new server via the command line.
  • Problem: ASP.NET could not access the imported databases.
    • Solution: We had to manually fix the security configuration for each database on the target machine so that ASP.NET could access it.
    • Note: I wonder if this is due to the way we are restoring our databases.
  • Problem: We had SQL Server Express installed. One of our demo applications used a connection string such as "Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\NORTHWND.MDF;Integrated Security=True;User Instance=True". The full-blown version of SQL Server doesn't support user instances.
    • Solution: We restored the database into SQL Server and are using it instead of the User Instance.
    • Note: I suppose you could also install the express version side-by-side if you wanted to.
  • Problem: We installed SQL Server Reporting Services (SSRS). By default, it binds to the ~/reports of all our websites, breaking a couple of our sites that were using the ~/reports subfolder. (It also binds to the ~/reportserver folder, but we weren't using that one).
    • Solution: We had to launch the SSRS manager to change the virtual directory that was used.
  • Problem: Some of our older applications used the SQLNCLI provider, but these now return "System.InvalidOperationException: The 'SQLNCLI' provider is not registered on the local machine.".
    • Solution: Installing the client (from the SQL Server 2008 DVD) only ends up creating a new provider "SQLNCLI10" that we can use in our connection strings instead of installing the older version.
    • Solution 2: We noticed that some code using SQLNCLI10 did not work properly. System.Data.OleDb.OleDbException: The fractional part of the provided time value overflows the scale of the corresponding SQL Server parameter or column. Increase bScale in DBPARAMBINDINFO or column scale to correct this error. We ended up changing providers, as this was too much of a pain.
  • Problem: We use automatic script generation in SQL Server Management Studio (SSMS). Tools ==> Options ==> Designers ==> Table and Database Designers ==> Auto Generate Change Scripts. However, the scripts that are now generated in our local SQL2k8 databases don't always work with the SQL2k5 databases we have deployed in the wild. We'd like the scripts to be compatible with both, so that we don't have to manually remove the problematic portions.
  • Problem: SQL Server 2005 cannot open our SQL Server 2008 backups, even if their compatibility mode appears to be 2005.
    • Solution: I don't know of a solution, do you? :)

Most of our other applications were transferred easily, except for TWiki which is always a pain to install on a Windows-based server. We still haven't resolved a CSS issue, but the tool now works! I hope this helps! Best of luck to you all in 2009! Feel free to comment about the problems you experienced during your recent migrations to these technologies.

kick it on DotNetKicks.com


Software usability is like eggnog

clock November 27, 2008 01:15 by author JKealey

Yesterday, I had the chance to participate in a formal usability study at the University of Ottawa. Marconi Lanna’s master’s project is an improved code difference visualization tool. I had already played with the tool in the past and found it interesting but only saw its true value during the formal usability test where I was given specific tasks to perform. I will keep the details about this tool for a later post when it becomes publicly available, but participating in the study helped me realize a few things:

  1. Creating a proper usability study is hard.
    • There are so many ways you can introduce bias in a test, it isn't funny. For this particular test, I feel that it was very close to being unbiased and most of my initial concerns were addressed.
    • One concern that does remain is the fact that the test cases were crafted by the researcher and could have been manipulated to generate a specific set of results. However, crafted test cases are required for any kind of comparison between the users. I personally feel the test was unbiased as it presented potential flaws in both the default tool and the proposed tool.
    • This particular test was for a tool used by software developers. As you probably know, some developers demonstrate productivity levels an order of magnitude higher than others.  You can imagine that this makes it hard to analyze productivity results collected during a study.
  2. Don't forget to make the test subjects communicate
    • If a subject does a task and says nothing, you don't learn 10% of what you could have learned about their thought process. In usability studies, the thought process is the most important thing to understand.
    • Everyone is different, and having them express their concerns/procedures helps you analyze the results.
    • This is not a discussion. Because of the desire for unbiased results during the questions, you cannot ask specific questions (which may lead to bias) or comment on the answers (which will definitely lead to bias). However, after everything is done and recorded, having discussions with the subject can enhance your overall understanding of what they said while thinking aloud.
  3. Working on usability is a self-improvement task that you must work on every day.
    • It's easy to continuously postpone enhancements to the the non-functional aspects (performance, security, reliability, usability, etc.) of a software system when you're a small startup.
    • You should log even seemingly superficial non-functional concerns in your bug database just as with any other issue. Customers that complain are rare and you must take their comments seriously.

Following my own advice, I want to look at one of the usability issues that I filed in our bug system a few months ago, our bug #1377. I like revealing some internal details of the issues we face and appreciate your input on our strategies. Note: if you're not interested in a real-world example at a complex usability issue, skip to the conclusion of this post as this could be a snooze-fest!

A closer look at one of our usability issues

Drink too much eggnog and you too will have usability issues Usability is one of our core values when building software. However, we sometimes slip up, as with anything! Looking back at the comments received over the last year by our users, I can clearly identify the single most important usability problem we have with our wide range of software solutions for the franchise industry. The issue is related to our party/event/appointment booking module which is a part of our franchise point of sale (POS) software. I'd like to drill down into this feature and present the usability issue and how it came to surface.

Background information

A POS system basically lets you sell items in a retail store. Our is integrated with a frequent buyer program, and we register information concerning each member in the database. Depending on the franchise brand, different information is tracked. (We can do cool things when customers are willing to provide information such as their postal or email address, but as a general rule, all fields are optional). We also have a party booking module which allows parents to book their child's birthday party at a store. The feature accomplishes two things: it acts as a calendar system (to avoid booking overlaps) and is integrated with the sale module to support deposits. Obviously, when someone books an event at a store and pays a deposit, the system needs to remember who paid what, so that when the big day comes, the deposit can be applied to the transaction.

To make a long story short, we offer a number of configuration options in the background to support different scenarios used by different franchises. Here are some examples:

  • Book a child birthday party in one of multiple rooms.  You reserve the room for a period of time for your exclusive use.
    • This is akin to booking a meeting room.
  • Book a space in one of multiple play areas. You reserve your spot in the play room, but the room is shared up to its capacity.
  • Book a particular employee for your haircut or spa services.
    • Rooms are not the only resource that can be booked. This ties in to the employee management system.
  • Book a table, a pitcher of beer, and that hot new employee to serve at your table.
  • You're booking a particular resource and pay a: 
    • Flat fee (party package)
    • Flat fee per guest
    • The fee will depend on what is bought at a later date.
  • Stores have the possibility to ask for a deposit, and if they do, it can be of a particular % of the transaction or a fixed dollar amount.
    • The store decides if deposits are refundable. (in the event of a cancellation).

As you can see, there are numerous elements at play here that make it non-trivial in our context, where we design the booking system to meet each franchise's particular booking needs. What is important at a high-level, however, is we defined the following use cases when researching the requirements for this module.

  1. (Deposit is required) A member is in the store and wants to book an event.
  2. (Deposit is required) A member is on the phone, wants to book and event and will come by later this week to pay for the deposit.
  3. (Deposit is not required) A member wants to create a booking.
  4. Employees want to peruse the list of bookings for a particular date range.
  5. Employees want to add an additional deposit amount to a transaction (regardless of the fact that deposits are required or not)
  6. Employees want to finalize an event, and apply the total deposit amounts to the transaction.
  7. An employee books a "fairy princess" birthday party for another employee, without their knowledge or consent, and invites their friends and family. The birthday boy frantically tries to cancel the event as soon as possible, to avoid long-term trauma.
  8. (and a few more, less important scenarios).

We chose to divide our scenarios contextually

We decided that the best way to solve this problem was to create two ways to access the booking information, one which is contextually associated to a store member and one for higher-level tasks.

  1. From the existing sales page in the POS (for all scenarios that work with money)
    • The cashier first selects a member from the frequent member program (or create a new account)
    • The system displays a new button called bookings
    • The cashier selects bookings and progresses through the following menus (create a new booking, additional deposit, cancellation, finalize event).
    • The system then returns back to the sale page, where the cashier can process the sale/refund.
  2. From the events page in the POS (for all scenarios that don't deal with money)
    • The system displays an Outlook-like calendar of all the events, allowing employees to peruse the events
    • Employees can view availabilities, change rooms, change employees, change date&time, enter additional event information from this page.
    • Employees can create an event without a deposit, which the system presents as being in the "Deposit Required" state.
      • This is to support scenario #2 listed above. You'd create a tentative booking, which you'd be willing to double book if the person never comes by to pay for the deposit.
      • Also, this is used by franchises that don't require deposits instead of going to the sale page, and becomes similar to a paper calendar in a hair salon.

The usability problem

After being in use for about 18 months, I can state that we need to step back and re-evaluate this feature, to improve its usability. The system works fine when used as intended, but I have observed the following issues:

  • If deposits are not required, untrained cashiers book events in the event page and never finalize them.
    • They do open up the sale page, possibly select the member, and sell whatever was bought without associating the sale with the booking.
    • This is bad because we're left with open events and can't track cancellation rates, sales per member, etc.  (bad for the store)
  • If deposits are required, untrained cashiers assume they need to go to the events module to do anything related to events.
    • They book an event, but the system marks it as "Deposit Required" and doesn't let them change the deposit amount.
    • This is bad as they are under-using the system, not following store policies, and sending in support requests to have the system explained to them. (bad for the store and bad for LavaBlast)

As a side note, I am honestly always surprised when a cashier expects to book an event, accept money but not track any information to associate the deposit with the person making the payment. That's like their store manager expecting them to come in to work and not bothering to write their name on their timesheet.

Root cause

  • We've divided the scenarios in two groups: the ones that deal with money and the ones that do not.
  • Combine this with the following facts:
    • Some stores don't use deposits. Therefore, money is only involved when finalizing the event at which point the main task is selling products/services, not dealing with events.
    • Even if we use deposits, we allow the creation of temporary bookings (in the deposit required state).

To recap, to improve usability, we've defined processes that contextually lead the cashier to performing their tasks. However, since the core starting point (deposit amounts) varies completely from one franchise store to another, our contextual division doesn't make sense.

Possible Solutions

  • Possible solutionsSolution #1: In the store events page, after selecting an event, give the option to the cashier to add a deposit, cancel or finalize the event. This would bring the user from the events page to the sale page and allow them to follow our defined processes.
    • Possible issue: We're making them switch contexts implicitly. When they're done, they would wonder why there were in the sale module instead of the events module. (do we force them back to the events module when they are done?)
    • Possible issue: they want to finalize an event that has already occurred (to get rid of "open" events, caused by the described usability issue).
  • Solution #2: In the sale page, make the booking button available even when no member has been selected. Once clicked, prompt to select a member or offer to peruse the list of bookings. Selecting an event would auto-select the member, and bring us to the usual process.
    • Can be combined with the previous solution.
    • Possible issue: This allows cashiers to do anything at any time while in the sale module and loses the contextual value of the process we've defined. One main problem in the POS industry is the constant desire to put all options on the page, flooding the user with too many options and making the POS hard to use and increases training costs.
  • Solution #3: Do the previous solutions and get rid of the top level events page.
    • If everything can be done from the sale module (and in most cases the sale module is where the cashier spends most of their day), why bother having a separate mode, that adds confusion.
    • Possible issue: cashiers won't instinctively feel that the sale page is where they want to go for event bookings, they might not even discover that events exist!
  • Solution #4: Cut the feature set to attack the root causes directly
    • If deposits are required, get rid of the feature that allows us to create temporary bookings.
      • Possible issue: people will complain that they can't do this anymore. As deposits are required, this is a case of tough love.
    • If deposits are never required, don't integrate with the sale module at all.
      • Possible issue: decrease the perceived value of the event module and lose a few potential reports (which are not in use at this point).

At this point, we'll probably end up implementing #1, #2, and #4. One of our core technological themes is usability, therefore we're willing to live with cutting a few features for an improved process. However, the issue is still up for discussion and I'd love to hear your opinions on this specific matter or on similar problems you've experience in your software startups.

Conclusion

We've built a flexible core to support the varied needs of franchisors. Everything works, but are we offering too many features to our customers? Should we cut back to make it simpler on everyone? In our case, I think so. If I had to sum up the usability problem discussed today into a high level lesson learned, I'd state the following: Don't separate use case scenarios into different groups if a configuration option invalidates the grouping premise.

During this holiday season, I think I'll take some time to re-read a few of my favorite books on usability:

  1. Steve Krug - Don't Make Me Think
  2. Joel Spolsky - User Interface Design for Programmers

Although these are great reads, they deal with the low-level user interface design problems, not with higher-level software engineering feature interaction problems in software product lines. I'd be curious to know if there any good resources on this subject (other than overly academic conference papers/workshops). I'd love to hear more first-hand, real-world experiences from other bloggers.

Easy to use software is like eggnog.

  • Reaching the desired results takes time. (The best eggnog takes at least three weeks to make).
  • Users will get a kick out of it. (With as much bourbon as milk, eggnog will definitely get people talking.)
  • At a high level, anyone can claim to be a pro. However, the devil is in the details.
  • You need to listen to your users to make the recipe better in the future.
  • What would the holiday season be without it? (okay, that doesn't make sense!)
kick it on DotNetKicks.com


LavaBlast Software named Startup of the Day by Microsoft

clock November 15, 2008 10:37 by author JKealey

FLY-002_StartupZone_Badge-CompanyOfTheDay_IR5a We recently joined the Microsoft BizSpark program after seeing posts about it on a few blogs (Flow Ventures and The Code Factory). To make a long story short, amongst the hundreds of startups that register each day from around the world, we've been selected as the most promising startup of the day. It is always fun to get recognition for our hard work!

In any case, you can view the interview here (today only!).

Have a nice weekend!



Month List

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2017

Sign in