LavaBlast Software Blog

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

Stop trying to build the next Facebook

clock November 9, 2010 12:58 by author JKealey

facebookyouredoingitwro There are a number of strategies to build a successful software startup but my favourite is to focus on a niche. Find a very specific group of people with a common problem and solve it well. As software startup founders, we have the luxury of picking very narrow niches (and still surviving) while non-software businesses need lots of capital. For example, you can build software to connect potato growers with buyers for a fraction of the upfront/ongoing costs of launching a business that provides innovative farming tools to potato farmers.  (Yes, potatoes are awesome.)

What’s ideal about niches is they allow you to start your business and survive, if you’re serious and dedicated. When leaving the comfort of employment and starting their first business, I feel that survival is all you should worry about. You’ll never become filthy-stinking rich and your face won’t be on the cover of any magazine, but you’ll make a living. Your lifestyle will be completely different: you’ll be happier because of your flexible schedule or, more importantly, your work will have a direct and visible impact on other people’s lives. Take this time to learn about being in business and grow as an individual: that’s all that is important. To use an oft used insect-related analogy, you’ll emerge from your cocoon as an entrepreneur after a couple years of trial and error.  (Other ones include Be A Cockroach but they smell.)

Now kick the training wheels off and really get started. You’ve gained some experience, built something and can start thinking about growth. You’re now in a much better position to decide what should be done to turn your business a multi-million dollar company. Most probably, you will have radically changed your original plan based on what you’ve learned. The dynamics of the game have changed: scalable growth, not survival, is your goal. 

In a niche, you can determine who to talk to (potential clients and partners) and can do so in a structured manner. Without one, you’re wandering. This is critical: you shouldn’t be building anything without getting validation that it is the right thing to build. Although we all like to think about software as innovative, the fact is that the technical risk is very low for most software startups; the real risk is market risk. Know the answer before starting your business: can you build something people will buy and can you sell enough of it to make it worthwhile? You can’t discover this on your own; lay out your idea on paper and talk to your target customers about it.

  • Don’t fool yourself into thinking your ideas are unique or that you’re spectacular.  Ideas are a dime a dozen; everyone has the same ones.
  • Given enough money, you can build and sell anything. Know how much you have and what you can accomplish at your size. Drop the ideas you can’t properly build or commercialize and move to something realistic. I’m sure you could genetically engineer unicorns if you had a billion dollars, but do you see Mark Zuckerberg peddling unicorn meat?.

This brings me to my main point: stop trying to build the next Facebook. By this I don’t mean “avoid building social networks” but rather “stop trying to be an exceptional anomaly” because you will fail. You’re not a contestant on “Who wants to be a billionaire?” and the odds are stacked against you. Anomalies are, by definition, rare. However, everyone has heard of these companies, making them appear as within reach and misleading hordes of would-be entrepreneurs. You should have large scale ambitions, but past a certain point you become a dreamer, not an entrepreneur.

Go niche. Work hard. In a couple years, you may be able to attack the larger market you originally had in mind because you now have both the expertise, the contacts and the funds to execute on your original larger-scale idea. Step out of the dream, enter reality and you may be able to set the stage to actually achieve what you dreamed about. Otherwise, you’ll end up like one of the weirdos screaming they invented Facebook in front of a local pub on St. Patty’s day. Additionally, if The Social Network is accurate, Facebook was actually niche-specific (Harvard only) in its early days.

I smile when I see businesses with niche focus and would have liked to have seen more at the latest Ottawa DemoCamp. Even if the product/niche evolves over time, I believe they have a greater chance of survival. Here are a few sites that exemplify the strategy:

Astute readers may have noticed that the above list includes a link to our software product for the franchise industry: FranchiseBlast. We spun-off some content from our corporate website onto its own website for marketing purposes and to reflect our current focus on software for mobile/service-based franchises. More on this in an upcoming blog post.

I’d like to know your thoughts on taking these types of niche businesses to the next level. Seems like the most common strategies are:

  • Same product, different vertical [if the company focuses on scaling product sales]
  • Generalization to many simultaneous verticals [same as above, but harder to accomplish]
  • Product diversification (new products) in same vertical [if the company provides value-added services in addition to a commercial product]

Are there any good success stories in this area? Spectacular failures? You tell me!



Collaboratively Defined Business Strategy

clock March 31, 2010 13:54 by author JKealey

 

bookingblast For those of you who’ve been keeping track, we launched LavaBlast Software back in April 2007. A year later, we posted three software startup lessons about how we got started and followed up the year after that with four more fun software startup lessons. Now that Year 3 is complete, I should write another set of software startup lessons, but that can wait. Today, I feel we’ve come full circle because we’ve begun working on the type of fun project that we would have enjoyed doing three years ago, but couldn’t afford the risk. In a sense, it feels like a full circle and a new beginning for LavaBlast even though we’re simply working on a new product.

BookingBlast is going to be legen – wait for it – dary. Read on to know more!

Starting from scratch

Pretty much straight out of university, we started LavaBlast Software. We had no money so we had to be creative. By creative, I mean we had to be cheap, work hard and work on something low risk to pay the bills.  The recipe for success is simple and we’ve said it before. Let’s just say we sell to businesses and we keep the intellectual property. This strategy has allowed us to start from scratch and making a living. 

We already have BookingBlast’s building blocks and now have enough runway to execute on our idea.

Ramping up

Some may stop here – but that’s not enough for us. We have greater ambitions - we’re looking for something bigger - for a greater reward. Based on the assumption that it takes a decade to launch a successful business, we’re not even a third through. We’ve passed through survival and have been growing steadily, but we’re now anxious to move to the next level.

We feel we can get there by converting the enterprise-level software we’ve been producing to date into more scalable Software as a Service (SaaS) products. We’ve been wanting to do this since day 1, but needed short-term revenues.  We’re now re-investing into LavaBlast to give us this flexibility. (I guess that visit to an unspoiled private tropical island will have to wait.)  We toyed with a few concepts during the past year, looking for software products that:

  1. No per-client customizations (greater scalability)
  2. Sold to businesses, not individuals (faster revenue)
  3. Shorter sales cycle, lower recurring dollar amount per sale (easier to commercialize)
  4. Related to our existing work and/or future strategies (reuse and upsell synergies)

 

Hold your horses! I’ll describe BookingBlast’s awesomeness in a minute.

Context & Goal

Our short-term goal with this project is knowledge. We’ve been building enterprise software for a while and want to dumb things down and start aiming for higher volume, but we need to adapt our know-how. We see BookingBlast as a practice run whereas our business is a marathon.

Our long-term goal is growth, in terms of revenue and the size of the company.  Lots of the enterprise-level work we’ve done can be commercialized to a broader market but we need a longer runway.

Spill the beans already! What’s BookingBlast?

BookingBlast allows service-based businesses to accept online bookings. Reservations are accepted only during available time slots and deposits are paid online, in advance.

To clarify, our software will allow customers to:

  • Book your child’s birthday party online
  • Book mobile clowns/magicians/comedians online
  • Reserve a massage / spa services online
  • Book your chiropractor from their website
  • Book a photographer from their Facebook page
  • … and accept bookings/reservations in many other industries.

That’s it. It’s not rocket science. It’s been done already – there are many competitors in this space – the market exists. The barrier to entry is low. But that’s not stopping us, because we have a plan. What better way to test our plan than to go out and execute it?  The worst that will happen is sales will be lower than desired and we’ll still reach our short-term goal of knowledge. We’re not betting the farm on this – it’s a stepping stone in the context of our longer-term vision.

How did you come up with your secret master plan?

We understand that this is a marketing play more than a technical one. We’re not inventing a killer product, although we can be innovative in our implementation. We decided it was in our best interests to share our plans for BookingBlast with people from diverse backgrounds and get them involved in the process. Ian Graham of The Code Factory always says the engineering students/graduates from the University of Ottawa are more secretive than the ones from Carleton University and we decided to prove him wrong. We openly solicited feedback on Google Wave and at TeamCamp. In the end, we found that we’re not that crazy after all as this validated our initial opinions. We did discover a few interesting twists which we plan on using, however.

Therefore, our plan is not secret – you’ll hear more about it when our product will be in beta. However, here a few lessons we learned from our experiences with collaborative planning.

Phase 1: Internal research

We looked around to find competitors and market penetration strategies. We discussed this internally over a coffee and did our homework. I produced a one-page executive summary of my initial plans.

Phase 2: Feedback solicitation via Google Wave

We published a private wave and invited two dozen random people. We made sure to invite people who were not extremely close to us because their feedback would be biased. We made it clear that the participants could feel free to ignore us as we didn’t care to force anyone into open collaboration, especially if they were busy with their own work. We found that the people least close to us were the ones who contributed the most to the discussion. Within 24h, the discussion had grown to approximately 8 times as long as the original executive summary. Within the next 48h, the discussion grew a bit more, with a few late-comers giving their comments.

The early discussions were the most valuable. They brought in new elements and got everyone involved. They definitely changed our strategy. However, as the discussion grew, I felt that most people lost interest because there was too much to be read. The barrier to entry had been raised, which caused most of the late-comers to elect not to participate. Initially, we thought this was a bad thing as we wanted more feedback, but in retrospect, we feel that what needed to be said was said early on. Had we discussed the same material with each person individually, we would have elicited the same comments over and over. Redundant feedback is not useful (other than for validation) and is a huge time waster.

In conclusion, open collaboration is a great technique to elicit feedback very quickly. I am greatly thankful to those who participated.

Phase 3: Feedback solicitation via TeamCamp

jkjp Ottawa’s primary co-working location, The Code Factory, hosts a bi-monthly event initiated by Chris Schmitt called TeamCamp. Once in a while, TeamCamp will have a pitch night where the participants pitch their idea to the group and get feedback. This is a very informal round-table setup but you get to chat with interesting people in Ottawa. A few weeks ago, I pitched BookingBlast to the group. This was great validation for our online booking software, as it proved that we had properly thought it out. Some new strategies were put on the table, but the biggest lesson learned is that you don’t need to spend months thinking about your project if you’re agile enough to adapt it along the way.

Furthermore, we finally had someone stand up and say our idea wasn’t good enough, something we had been waiting for since we started planning BookingBlast. Given the small scale of the project and the low barrier to entry, I was expecting most people to shoot our idea down quickly. Maybe I watch Dragon’s Den too much and read too many angel investor/venture capitalist blogs. In any case, this brought forth great discussions where it appeared other individuals were reading my mind while defending our online reservation software for me.

We’re now ready to start implementing the project! (In fact, we’ve already started and it is progressing nicely!) 

We need your help

We’ve posted a basic information request page on our website. If you know business owners that would be interested in participating in our alpha/beta programs, please have them sign-up to our newsletter.  We’re approaching the market in a different fashion that what the competition is doing, so we’d love to talk to business owners directly.

Since a good portion of our readers builds software for other businesses, we’d also like to talk to web developers that manage business websites.

Also, feel free to share your thoughts on BookingBlast and how to make it work in the comments. We’re thinking of openly blogging about thinks like SaaS pricing and gathering data concerning some of our strategies for future discussions and commentary.



Software engineers as salespeople

clock February 15, 2010 10:12 by author JKealey

LavaBlast is a small startup; we don’t currently have dedicated salespeople. I still do most of the selling at this point – I’ve got a background in software engineering, not sales. That may seem crazy until you realize that we don’t sell commercial-off-the-shelf software. If a prospect needs us to build custom software on top of our existing platform, the engineering team is involved in determining the scope (and therefore the cost presented in the quote). Because of the scope of the systems that we’re building, we have the “luxury” to spend more time on each individual quote and learning more about the prospect’s business. Adding a personalized touch in every quote gives us a competitive advantage compared to firms that pump out boilerplate text without analyzing the context.  I strongly feel that, for this type of sale, understanding the customer’s problems is much more important than having them understand your product. Furthermore, understanding/solving problems is definitely something software developers know how to do!

LavaBlast Software builds integrated software solutions for the franchise industry. Although the systems we build are similar because we reuse the building blocks which we’ve developed over the years, we understand that each franchise has different business rules. Understanding these rules before building custom software is of capital importance. This assertion holds regardless of what kind of software you’re building: everyone on the team should have a clear understanding of what needs to be built. Otherwise, you build software that only partially matches your user’s expectations and you need to go back to the drawing board to correct it.

Don’t get us wrong; we’re not fans of the Big Design Up Front (BDUF) approaches such as the waterfall software development model. We follow a more agile development methodology but there is one thing we do with each and every new franchisor client that approaches us: we model their business processes using a visual notation called the Use Case Map notation, a subset of the User Requirements Notation. This helps us understand their business and what they need built. We’ll come back to this notation in a minute.

Communicating business processes

Most business processes are simple (and should be), but a few are not as straightforward. Imagine an online store that sells quilts: the customer goes to the online store, chooses a quilt or two, provides payment, and the warehouse ships them. Simple enough? Add a few requirements to make it complex:

  • a customer can put a particular quilt (a unique hand-made design) on hold and provide payment for it within a week
  • customers can visit the warehouse and make purchases directly – it takes 24 hours for the website to be notified of stock changes
  • the store also receives telephone/fax orders
  • a customer can return a quilt for a full refund with 15 days, in person or by mail.
    These few extra requirements make the whole process a bit more complex.  In real life, there are always dozens of these added constraints. Some are very infrequent whereas others cause problems on a daily basis. Some can be solved by a better process while others can only be mitigated (especially things like delayed notifications) – you need to understand the context to be able to represent the current process and differentiate it from what you see as the ideal process to be implemented. However, as you are the developer and not the domain expert, you need to effectively communicate with the other stakeholders in order to create the best system. In most cases, your best guess is not sufficient.
    We’ve found that the best way to communicate these processes with our customers, who are not in the software world, is by using the User Requirements Notation. The notation provides a way to visually represent processes very quickly. Spending a few minutes designing a Use Case Map is akin to drawing on a whiteboard, with the added benefit of being a persisted artefact that can be “executed” to visualize certain scenarios. Additionally, the Goal-Oriented Requirements Language (the other half of the User Requirements Notation) allows the designer to compare different processes in terms of non-functional requirements such as performance, maintainability, security, etc.

Better than drawing on a whiteboard

Back in 2007, we’ve talked about the Use Case Map notation and jUCMNav in our initial blog post. To celebrate the release of jUCMNav version 4.2.0, we thought it would be nice to produce a series of tutorials that show you how to create your own model using jUCMNav. In case you didn’t know, LavaBlast’s co-founders have contributed massively to jUCMNav in the past five years. We’re responsible for 60% of the code in this open source project which we started during our time as undergraduate software engineering students at the University of Ottawa.

The following is a short 90 second video that gives you an example model and a very quick overview of what can be done with the notation and the tool. Stay tuned to our next blog posts to see us build this example from the ground up. The overview and the tutorial are intended for people with a background in software development. If you wish to introduce the notation to someone outside the development community, I would recommend starting with simple screenshots instead of showing the tool (which, in the end, should only be used by developers).

Conclusion

We hope you found this introduction interesting and that you’ll not only watch our upcoming tutorials but also download jUCMNav (an Eclipse plug-in) and play with it!



Penniless Startup Founders

clock November 6, 2009 09:02 by author JKealey

Where will this path lead you? This post is a follow up to one of our previous posts that discussed starting a software business during the recession. In this post, I want to focus on the cash flow aspects for very early stage software startups. A few years ago, we started the company with nothing in the bank and we've managed to not only survive but prosper regardless of today's tough economic conditions. It is possible to launch a software startup with no money: the tradeoff is time. It will take longer to get out of the very early stages.

Context / Introduction

Before starting, I'd like to point out that the tips that follow are only valid in a particular context:

Understand that these tips are for the very early stage

  • Your first business goal is to get out of the very early stage as soon as possible.
  • Lots of these tips concern petty little details. However, together these details matter when at the very early stage, when you're fighting for survival.
  • Survival is a huge milestone but it isn't the end goal

You have no money and aren't interested in loans.

  • If you have no money, this is probably your first venture. I strongly feel loans are a bad idea for your first venture, but others have different opinions.
  • Cash is a great accelerator - once you've launched your first business you'll probably have a need for speed and will either have cash or be more open to debt/equity financing because you'll have already learned what you have to learn in organic growth.

You're starting a software company.

  • It is possible to start a software startup with limited cash. You've picked a good industry. If you wanted to become a dairy farmer, you would need a massive initial investment. However, for a software startup, your investment will be time writing code - not acquiring assets.

Tip 1) Sell to the right group

Since this is your first business and you have no money, you need to establish a consulting sideline selling to businesses that will give you a good return for your time (even if you're building a product for individuals). You won't be able to pay your bills selling $20 licenses to individuals in the early stage. We recommend selling customized versions of something that will help you grow your core product, as long as you can keep the intellectual property. Read more about this strategy in our previous post.

Everyone values the dollar differently. The earlier stage you are, the harder it is to define appropriate pricing given your credibility level and you don't give the same value to each dollar as your customers. As you grow, you’ll find your sweet spot and will be able to focus on your consulting clients that are right for you.

Eventually, you should aim at moving out of consulting, as it doesn't scale.

Tip 2) Minimize your expenses

No, this isn't where we started LavaBlast! Assuming you have no money, it's important that you only spend when necessary. At a high level, you need to be versatile and be able to do as much as you can on your own. Later, you'll be able to delegate but not in the early days. Of course, know your limits and get pros to do things that are impossible for you to do properly.

  • Don't hire an accountant to prepare invoices for you. Learn how to use accounting software and do it yourself. Only hire the accountant for an annual review or for real accounting work. Once you know how, it will take you a few seconds or a few minutes to do the most common tasks - you won't be paying someone four hours of work at a high hourly rate. 
  • Don't hire a law firm to review a simple non-disclosure agreement sent to you by a customer. Learn to read legal text on your own. Only hire a law firm when you've got something important to prepare or review.

There are plenty of examples of ways not to spend money when you're just starting out and have none of your own. It's time to learn things on your own.

Be smart about the commercial bank account you choose

I've dealt with a few different banks over the years. If you're a tiny business, it is good to know a few simple facts and comparison points.

Get a business account with a variable monthly fee

  • Don't bite when they offer you a $50/month fixed rate. You won't have enough transactions to make it worthwhile to upgrade. When you reach that point, switch to the fixed rate plan that is a best fit for your business. You can easily save $480 per year.
  • Some Canadian examples: Desjardins: $7/month, TD Canada Trust: $12.50/month, Royal Bank of Canada: $6/month
  • Some variable plans charge transactions on top of the minimum monthly fee. Do your homework.

Know the minimum balance you need to get it for free

    Get an ING Direct Savings Account
  • Some customers may pay you in advance or you may get grant money. Bottom line: you may end up with cash that you can't spend for a few months to a year. (Actually, you can spend it if you know more will be coming in - depends on your management style.) If you do have it in the account, earn interest on it.
  • Business accounts often don't give interest. If they do, the interest is horribly low if you don't lock it in. (Not paying service fees is often more than the amount you'd earn in interest anyways).
  • ING Direct's account is free. They have the best rates I've seen for low amounts that can be withdrawn at any time.
  • Best of all, they have a referral program. Both the new member and the referrer earn $25. In today's market, this could easily end up being worth more than the interest you'll generate in your first year. Our orange key is 33514316S1 – go ahead, signup (personal or business) and you’ll help support us and receive $25! :)

Don't get a commercial credit card for your purchases

  • Unlike personal cards, they're not free and most don't have any rewards programs.

Do you really need to accept credit cards?

  • It is a good fit for some users or services, but know the costs. If you have few transactions but most of them are high value, you're better off with a wire transfer.
  • Some banks charge you more for wire transfers than others.
  • Remember that cheques are slow - you don't have access to the funds are week.
  • You'll be paying $20-50 per month plus 2-3% per transaction. This quickly amounts to several thousand dollars.

Will you be dealing with multiple currencies?

  • We're a Canadian company but we have lots of clients in the US and in Europe. In the very early days, we chose not to open two separate bank accounts (one in each currency) because of the associated ongoing operating costs and increased accounting complexity.
  • Banks all have different exchange rates. However, I've found one bank consistently gives us a significantly worse rate when receiving transfers in another currency. A few percentage points makes a huge difference as the size of the payments increases.
  • The larger your conversion, the better your rates. Talk to a specialist like @JamesonBankTrav.

Minimize your telecommunication fees

Don't get a commercial telephone line via large companies

You'll pay much more than needed. Investigate Voice Over IP solutions such as Skype. You can get your own telephone number and free long distance in Canada + USA for an annual fee of $60. This service saves you hundreds per year. Don't get a fax unless your customers nag you for your fax phone number often enough. If you need one, look at online services such as myfax.com which deliver faxes by email and give you toll-free fax numbers for less than what you'd pay to get a separate telephone line in your office for the fax, without the clutter of a deprecated device.

Don't sign-up for a massive cell phone plan if you've got empty pockets

Depending on what you do with your phone, you can save upwards of a thousand dollars a year by downsizing to a prepaid plan. Smartphones are great, but depending on your situation, it might be a wise choice to minimize those expenses. Let's hope you're not locked into a crazy-expensive three year plan! In the end, this is a personal decision which depends on your personality; once you've tasted a smartphone you may be unable to go back. Just keep in mind you might be paying much more for your cell phone than the much faster Internet connection you use all day.

Minimize your rent

Use a co-working facility

One tip often given to people starting their own company is to avoid renting office space too early in the process. Instead, work from home or from a more affordable co-working location. Not only do co-working locations reduce costs, they help you build your business because of the contacts you can make there. Once you’re read, upgrade to shared office space.

Don't minimize everything

In addition to being able to exchange services with other companies to cut costs, there are a few places where you can't afford to cut costs.

Your Image

One thing you don't want to be cheap on is branding. Your image is everything - quality needs to be high. Get nice business cards created by pros. Don't do your own web design if that's not something you specialize in. Your product will look amateurish and you'll lose sales. There are tons of affordable graphic designers out there: find one and have something nice created. Use online marketplaces such as 99designs. Since you're still a software expert, however, you should know enough HTML and search engine optimization techniques to be able to maintain your website. If you're a horrible writer, have someone review your content. This basically boils down to knowing your limits; there are some things you won't be good enough at even if you try.

Hardware & work area

We agree with Joel Spolsky's view that you should buy the best computer hardware and computer chair you can find. These are your primary tools and they are relatively inexpensive compared to your salary, even when you have very low revenue. One investment that is definitely worth it is a second monitor as it tremendously increases your productivity.

Your health

As much as your work environment is important, you should also value your health. Even if you're living on a very tight budget, don't eat hot dogs all day. Proper nutrition and good sleep cycles keep you in good health and makes you more productive. You should not be falling asleep in the afternoon. Starting your business is a marathon, not a sprint. Make sure your lifestyle is well adapted for a marathon.

Tip 3) Leverage your money

We've already covered this part in a previous blog post. Know what government funding opportunities are out there. Some require matching contributions. Some are based on your expenditures. Look around for these opportunities but mostly talk to other people to know what's out there and what's worthwhile.

Tip 4) Cash flow projections for dummies

You should always keep an eye on your cash flow, not just your revenue. I've created a very simple Excel spreadsheet to help with our cash flow projections. This one is simply a template with some random numbers in there. The one we use internally is a bit more complicated as it includes things such as currency exchange rates, taxes, etc. Build it however you like, but I've found that the two most important elements in there are:

1) Past Sales versus Projected Sales

What are my known sales (recurring revenue) versus what serious leads do I have in the pipeline. Being conservative, I base my business decisions on my past sales not my projected sales because I've learned that projected sales are often postponed. We have long sales cycles that culminate with a large sale which has a big impact on that month's revenue. Separating known sales from projected sales is of critical importance because of this because we either make the sale or get zero revenue from that customer in that month. If you're selling lots of lower value items (subscriptions to your service, for example), each individual customer has less impact on your total monthly revenue.

2) Runway

Given our current burn rate, when will we run out of cash if none of the sales in the pipeline are realized. This is useful to help you decide if you can hire and/or if you can give yourself a raise. It can also make you realize you're heading towards a problem and you need to correct the situation as soon as possible.

cashflow

It would be nice to have a simple, open source, application that helps business owners track their cash flow projections in this fashion. You could go overboard and integrate it with accounting software, but I think it's nice when it's simple.

Conclusion

The path ends up being longer than expected When you start your first company, and you have no cash on hand, you need to focus on making money and keeping the little money you have. Survival is a major milestone, but remember that it isn't the end goal. You'll learn tons of things along the way, and once you do leave the very early stages, you'll need to manage your cash flow properly. Later on in life, you'll probably start another business - this time you hopefully won't be as strapped for cash - and you'll be able to speed up the whole process.

I'm not sure what is harder between:

  • A) Going from nothing to survival
  • B) Going from survival to success
    I do know, however, that going from nothing to survival appears a lot easier if you have cash to start off with or if you've done it before. Since success is in the eye of the beholder, it all depends on what you want to achieve.


Software Startup Lessons (Part 6) –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 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


Software Startup Lessons (Part 2): Communication and Collaboration

clock March 17, 2008 09:39 by author EtienneT

Welcome to part two of our three part series describing the various lessons we learned during our first year of a software startup.  You are encouraged to read the first part if you haven't already!

Problem Statement

In Part 1, we described our business' context and how we eat our own dog food. Indeed, we use the software we produce on a daily basis, helping us create quality products. A parallel can be made with our distributed team's communication patterns. Simply put, we're not all at the same central office, talking to each other all day. Our structure resembles that of a franchisor with franchisees distributed a several physical locations. The main reason we are distributed is to keep costs down while we develop our core infrastructure, but it does have the interest side-effect of forcing us to use the same communication tools a franchisor would.

Not only do we not work in the same building, we're not even in the same city! Because we work in independent offices, we have a greater control over our environment, which increases our productivity. Spolsky often talks about how developers should have private offices because outside disturbances kick us out of our zone. You can respond to your email every 15 minutes, but you can't make someone wait at your door for 15 minutes while you polish off a complicated algorithm.

In any case, given the fact that most geeks are not social creatures, you probably think that doing the majority of your interactions over the Internet is great, right? In reality, it's not always convenient  but we've started to become really creative (and efficient) with the tools we found to maximize our interactions.

We spend most our time chatting coordinating on Google Talk and move to Skype when voice conversations are required. Over time, we discovered some pretty nice software to communicate and we want to share these tools with you in this article.

Problems:

  • How do we talk to each other and with people outside our company?
  • How do we exchange files?
  • How do we manage our requirements?
  • How do we demo our software, how do we program in pairs?

Lesson 4) Talking to People

Carrier pigeons might have played a vital part in WWII communications, but we're using more modern techniques.

Skype

imageSkype is the obvious choice for voice communication over Internet.  Don't tell us that you haven't heard about this tool before!  Because we are four partners in LavaBlast, we often need to have conference calls. All our meetings are done online via Skype conference calls, at no cost to us. Furthermore, we can call up a client on their regular phone using SkypeOut.  SkypeOut will call the client's real phone and will connect them to our conversation, at very affordable rates. Indeed, for $3 a month, we obtained unlimited outgoing calls to Canada and the US. Setting up a conference call is really easy and the quality is good (most of the time).  You simply need a good microphones and you're good to go.  In addition, if you have a webcam and a good Internet connection, the video quality of Skype is just amazing especially compared to MSN.  Talking to someone who also has a good webcam and a good Internet connection is almost lag free, in my experience.

Having a central phone number for a distributed office

Since we have a distributed office, we need to have a central phone number.  The most affordable solution that we found was Skype for business.  Basically you simply need to register a SkypeIn number anywhere in the US (not available in Canada yet) and when people call this number, it calls you on Skype.   The cheapest way to get your incoming phone number is to purchase Skype Pro (at $3/month) and purchase the number for $38 a year (and it was operational within minutes of purchase!). You can forward calls to another user or normal phone and even get voicemail with Skype Pro. Optionally, you may install the business version of the Skype program for additional functionality. Therefore, all the incoming calls go to our main salesperson and, if more technical details are required, the call can be forwarded to us.  Skype for business has a nice business control panel to control Skype credit purchases, phone number assignments, and much more. Additionally, because the phone number is associated to the company, we can redirect it to a new person if an employee is replaced or if someone is on vacation. We could have a 1-800 number, but I don't think we have the kind of call volume that would justify having one just yet.

We found the perfect phone number for LavaBlast: 1-201-467-LAVA (5282).  SkypeIn personal has a nice interface to check if a number is available, but the business panel interface doesn't.  If you want to purchase a specific number, I wish you good luck because you have to generate the numbers one by one!  We wanted a number that ended either with BLAST or LAVA;  we found the number with the SkypeIn personal interface and then tried to regenerate it, one number at a time, in the business panel.  We finally found one that ended with LAVA but couldn't find one that ended with BLAST.  The best way we found to generate multiple numbers was to press Ctrl and click like crazy on the generate button to open new pages in new tabs.  We eventually found the number we wanted!

Lesson 5) Exchanging Files

There are lots of cool startups focusing on better ways to exchange files and we're keeping an eye on them. For now, here's what we're using.

Subversion

As software developers, we obviously use source control to manage our code. No surprise here. We even deploy our web applications using Subversion.

FranchiseBlast

image We've developed a document repository in our franchisee/franchisor collaboration solution. We post our user manuals and a few other documents on there; it is our distribution center for completed documents.

Microsoft Groove

We use Microsoft Groove which is a party of Office 2007, as our main internal document management tool. Groove is much more than a document repository, but we only use this feature.  Groove is simple to use and install because it distributes the files on all the peers instead of having to setup a complex server. Furthermore, it is better than a shared network drive because it has change notifications plus it can be accessed even when you are offline. There are a few drawbacks, but in general, it's a good simple solution for the low volume of Office documents we work on. 

Lesson 6) Requirements Engineering

The first post on the LavaBlast blog was related to requirements engineering and how we managed our pile of requirements written on the back of (sometimes used) paper napkins. More seriously, we've found it very beneficial to collaboratively define our software requirements with our clients. Constant feedback is the key to writing good requirements, and using collaboration tools is a must.

Wikis

We've been playing with ScrewTurn wiki as our main wiki over the last year, for both for our internal use and to interact with our clients during the requirements engineering process. It is very easy to install (trivial) and it is very very fast. Editing a page is very pleasant because it is nearly instantaneous when you save a page... it just feels blazingly fast. Furthermore, because it is a free and open source project, you get to spend money on Super Mario Galaxy instead.

During our software engineering capstone project, we used TWiki as our primary requirements engineering tool, a couple years before the strategy was discussed in IEEE Software. Although we've enjoyed ScrewTurn's simplicity during the last year, I think we're ready to revert back to the more feature-rich TWiki. Installation is a pain (less now than before), but the syntax much more natural. Furthermore, we already have the infrastructure in place (using page meta-data) to let us manage our requirements.

Lesson 7) Desktop Sharing

Today, sharing your desktop is an essential operation for any software startup. You can easily demonstrate applications to potential clients or perform pair programming, without having to be at the same physical location.

Lotus Sametime Unyte

Trying to explain something to someone over Skype is not always fun, especially when the client is not a technical person. Because a picture is worth a thousand words, showing software is much quicker!  During most of our first year, we used Unyte to do just that.  With Unyte, you simply have to start the application, decide which window to share (or share the entire desktop) and then send a link to the person (or group of people) that need to see it.  Recipients click on a hyperlink and load up a browser-based Java applet to see the shared windows. It's as simple as that.  The client doesn't have to install anything and it's fast! The host will receive an alert when the viewers can see his screen.  Unyte, used in conjunction with Skype, is really a great mix for meetings and sales demonstrations. We used the version for five people and it worked well, until we found Microsoft SharedView.

Microsoft SharedView

A few weeks back, we discovered Microsoft SharedView while it was still in beta. SharedView is similar to Unyte, but 15 people can participate in a shared session.  The only big drawback is that everyone has to download the software.  So if you want to quickly present something to a client, it's a little bit more complicated if they have to install it.  However, SharedView does allow any participant to share their desktop for the others to see (only one person can share at any given time). During a software demo, we used this capability to have the client show us their current point of sale! Additionally, the software gives other people the possibility to take control of the session and perform operations on the computer that is sharing an application. You can also share documents pretty easily with everyone and send chat messages, but we still use Skype for voice communication. We now prefer SharedView to Unyte when it is a possibility to install software on every participant's computer.

Lesson 8) Blogging!

We've been able to connect with tons of great people thanks to our blog, and have lots of fun perfecting our writing skills. We find that figuring out what to say (and what your audience is interested in hearing) is the hardest task when you start a blog. We still don't know if we should focus on giving away code or writing more experiences pieces like this one. Let us know!

BlogEngine.Net

Our blogging software, BlogEngine.Net, is simply terrific.  Free, fast, really easy to theme, has some good extensions and integrates really well with Windows Live Writer.  One of the main advantages for us is that it is open source and it is written in .NET, allowing us to perform minor behavior changes as needed.   It still has a few bugs that can be annoying, but from what we have seen so far, it is performing really well.  It supports multiple authors, an important feature for us because we have two people posting on the blog.

Lesson 9) When not to use communication tools

The most important lesson we learned during our first year of operations as a distributed development team wasn't a revelation but rather a confirmation of our expectations. Communication and collaboration tools are great, but technology doesn't solve conflicts. We're a closely knit team and have worked together for a number of years, greatly reducing the number of conflicts we may have. The conflicts we have are generally superficial, but as an example, let's consider an architectural decision where the two decision makers have divergent opinions on the best solution. Although instant messaging is great for efficiency reasons, it is not the best medium to argument on the merits of your solution. Indeed, we've all seen the politically incorrect "Arguing on the Internet is like running in the Special Olympics; even if you win, you're still retarded". The main problem is related to the lack of emotional expressiveness of concise instant messages or emails and since it is discussed in great lengths by very good authors, we'll leave a detailed analysis of the situation to them! As a side note, firing people via email might have seemed like a good idea for RadioShack, but we at LavaBlast shall stay away from such brilliant strategies!

Conclusion

Communication is the most important part of starting a business. Even if you're the only person in your company, you still have to communicate with your customers! We hope that you'll discover at least one cool collaboration tool today! Remember to come back next week for Part 3 of our series.

kick it on DotNetKicks.com  



How Super Mario Bros Made Me a Better Software Engineer

clock February 28, 2008 00:07 by author JKealey

Super Mario Bros.Over the past month, I've been working hard on our business plan's second iteration. We've accomplished a lot in our first year and things look very promising for the future.  Writing a business plan helps an entrepreneur flesh out various concepts, including one's core competency and niche market. We illustrate in great detail what makes LavaBlast such a great software company for franchisors and the process of writing it down made me wonder about what made improved my software engineering talents, personally. Luckily for you, this post is not about me personally but rather an element of my childhood that impacted my career.

I don't recall exactly how old I was when I received an 8-bit Nintendo Entertainment System (NES) for Christmas, but I do remember playing it compulsively (balanced with sports like baseball, soccer and hockey!). The first game I owned was Super Mario Bros but I later obtained its successors to augment my (fairly small) cartridge collection. For the uninitiated, the NES does not incorporate any functionality to allowing saving the player's progress. Countless hours were spent playing and replaying the same levels, allowing me to progress to the end of the game and defeating my arch-nemesis, Bowser.

I enjoyed the time during which I played video games and it irritates me to hear people complaining about how video games will convert their children into violent sore-loser bums. In any case, I'd rather focus on the positive aspects of playing Super Mario Bros and other video games during my childhood. Just like mathematics develops critical thinking and problem solving skills, I strongly believe these video games influenced my personality to a point where they are probably defined my career. Disclaimer: I don't play video games that much anymore, but over the last year, I did purchase a Nintendo Wii and Nintendo DS Lite because I love the technology and the company's vision.

Quality #1: Persistence

Some people say I am a patient person, but I would beg to differ. I have trouble standing still intellectually, and although it is a strength in my industry, it isn't the best personality trait :) However, I am VERY persistent. I will attempt solving a problem over and over until I find a solution. Although I don't experience many painful programming situations on a daily basis, I very rarely give up on any programming problems. If I can't solve the problem immediately, it will keep nagging at me until I find a solution. A direct parallel can be traced with playing the Super Mario Bros series where the whole game had to be played over and over again to make any progress. (Anyone else remember trying to jumper over a certain gap in the floor in the Teenage Mutant Ninja Turtles NES game only to fall in the gap and have to climb back up again?) The games helped me train my persistence, a tool which any entrepreneur must use every day.

Quality #2: Pattern Recognition

Software engineering is all about pattern recognition. Refactoring the code to increase reuse, extracting behavioural patterns inside the strategy design pattern, creating object inheritance trees, or writing efficient algorithms based on observed patterns. I feel pattern recognition is one of my strengths, since I can easily see commonalities between seemingly different software problems. I believe this skill was refined by playing various video games, because the the player must observe the enemy's behaviour in order to succeed. In some games, agility doesn't really matter: it's all about knowing the pattern required to defeat the enemy (to the point where it sometimes become frustrating!). The most challenging parts of video games is when the game deliberately trains you to believe you'll be able to stomp an enemy by using a particular technique but, to your surprise, the technique fails miserably. You need to adapt to your environment, and think outside the box.

Quality #3: Creativity

Mathematicians and software engineers are creative thinkers, more than the uninitiated might think. I see software as a form of art, because of its numerous qualities that are hard to quantify. Software creators are artists in the sense that regardless of their level of experience, some will manage to hit the high notes while others could try their whole lifetime without attaining the perfect balance of usability, functionality, performance, and maintainability. Playing a wide breadth of video game styles lets you attack different situations with a greater baggage. I'm not totally sure how putting Sims in a pool and removing the ladder or shooting down hookers in Grand Theft Auto helped me in my day-to-day life, but it was still very entertaining :) The upcoming Spore game is very appealing to me because it combines creativity with pattern recognition, thanks to generative programming.  If you haven't heard about this game, I recommend you check it out immediately!

Quality #4: Speedy reactions

For Chris Brandsma: "IM N YUR BOX, WIF MAH WIFE" At LavaBlast, such as in many other software startups, it is critically important that all developers be fast thinkers. Indeed, when your core expertise is production, as opposed to research and development, you need to be able to make wise decisions in a short period of time. Personally, I can adapt to the setting (research environment versus startup environment) but my strength is speedy problem solving and I consider myself a software "cowboy". By combining my knowledge of of how to right reusable and maintainable code with my good judgement of what battles are worth fighting, I can quickly come up with appropriate solutions, given the context. In video games, the player needs to react quickly to avoid incoming obstacles while staying on the offensive to win the game. Of course, the mental challenges we face in our day-to-day lives of developing software is much more complex than what we encounter playing video games (which trains physical reaction time), but there is still a correlation between the two tasks.

Quality #5: Thoroughness

What differentiates a good software engineer from a plain vanilla software developer is their concern for quality software, across the board. Software quality is attained the combined impact of numerous strategies, but testing software as you write it, or after you change it, is critical. For the uninitiated, a popular methodology is to test BEFORE you write code. In any case, this talent can also be developed by video games such as the classic Super Mario World (SNES) where the player tries to complete all 96 goals (72 levels) by finding secret exits. Reaching thoroughness requires the player to think outside the typical path (from left to right) and look around for any secret locations (above the ceiling). Finding secret exits is akin to achieving better code coverage by trying atypical scenarios. 

Quality #6: Balance

Playing Super Mario Bros as a child helped me develop a certain sense of balance between my various responsibilities (school) and entertainment activities (sports, games, social activities). If you're spending 16 hours a day playing World of Warcraft or performing sexual favors in exchange for WoW money, your mother is right to think that you have a problem. Launching a software startup is a stressful experience, and it helps to be able to wind down with a beer and a soothing video game. A quick 20min run on a simple game before bed can work wonders! Of course, it is no replacement for sports or social activities, but it sure beats dreaming about design patterns.

What's missing? 

Super Mario Galaxy In my opinion, there are two major qualifies that video games don't impact. Having these two qualities is a requirement to becoming a good software engineer. First, video games do not help you interpret other people's needs. Second, video games do not help you communicate efficiently. What does? Experience, Experience, Experience. Being able to deal with people on a daily basis is mandatory, and the video games I played as a child did not help. However, this statement may no longer be true! Today, many massively multiplayer online games require good collaboration  and organizational skills. Furthermore, the new generation of gaming consoles are using the Internet to allow people to play together. 

Furthermore, I find games like the new Super Mario Galaxy (Wii) very interesting for future mechanical engineers. Indeed, the game presents a three-dimensional environment in an novel way, training the brain to think differently about three-dimensional space. You have to play the game to understand, but because the camera is not always showing Mario in the same angle, you have to get a feeling of the environment even if you don't see it (you're on the opposite side of a planet) or are upside down on the southern hemisphere. I can imagine children and teenagers playing the game today will have greater facility to imagine an object from various perspectives, while in studying physics or mechanical engineering in university.

In conclusion, I admit my whole argument can be invalided by saying that I played these types of games because I was inherently inclined to the software engineering profession, but the commonalities are still interesting to review! What are your thoughts on the subject? What do you think drove you to this profession (or drove you away)?

Legal Disclaimer: Did you know that the usage of the title of "software engineer" is much more regulated in Canada than it is in the United States? Although I detain a bachelor's degree in software engineering, and a master's degree in computer science which focused on requirements engineering, I can currently only claim the title of "junior engineer", as I recently joined the professional order.

Follow up: powerrush on DotNetKicks informed me that I'm not the only one who feels games influence software engineers

kick it on DotNetKicks.com



Manage your ASP.NET Web.config Files using NAnt

clock February 19, 2008 13:24 by author JKealey

Egypt trip in 2007 Nothing is more important than the software engineers in a software company. I just finished re-reading Joel Spolsky’s Smart and Get Things Done and it inspired this post. Not only do I admire his writing style, I share Joel’s vision of how a software company should be run. Pampering your programmers is the best decision a manager can make, especially when you’ve built a team that can hit the high notes.

One of Joel’s key elements to running a successful software company is to automate your build process up to the point where it only takes one operation. This minimizes the chance of error while enabling your developers to grey matter to something more complex than copying files. Although they might use the extra time to shop around for student loan consolidation plans (a practice called reverse telecommuting), in most cases they’ll return to writing fresh code or cleaning out existing bugs.

Today’s post is about one of the little things that made my life much easier as a developer: using NAnt to manage our software product line. I’ve come to realize that we encounter these little “sparks” every day, but we never talk about them. Sure, we’ve produce a number of complex software products and they are fun to describe, but I personally enjoy talking about the little things that save time, just like Henry Petroski verbosely describes common items in his books. Fortunately for you, I’ll keep the story short, unlike his description of the evolution of the paper clip in The Evolution of Useful Things (which is still an interesting read, by the way).

Background

We develop lots of ASP.NET websites. Our architecture includes database schemas and business objects shared amongst multiple projects and some common utility libraries.  Furthermore, instead of always inheriting from System.Web.UI.Page and System.Web.UI.UserControl, we have an object oriented inheritance tree as is good software engineering practice. We even have a shared user control library that gets copied over after a successful build. Furthermore, we use ASP.NET master pages and ASP.NET themes to structure our designs. As opposed to what you see in textbooks where themes can be chosen by the user according to their preferences (oh yes, please show me the pink background with fluffy kittens), we use themes to represent different franchise brands.

My point here is that we reusability is key to our solution. We build elements that we can use not only on the website but also in FranchiseBlast, the interactive kiosk, and the point of sale. However, the more you re-use, the more things get complicated. Indeed, the overhead caused by the added configurability we build into our reusable components is non-negligible. We're always on the lookout for new ways to keep things simple, while still reaping the benefits of reuse. We use the Strategy Design Pattern to encapsulate the behavioural changes in our systems and put our various configuration settings inside our Web.config file.

Hurdle #1: Different developers need different web.config files

Our configuration files have a few settings that we want to change on a per-user basis:

- Where should we email exception notifications?

- Database names & file paths

- Google API Keys

How do we manage this? If we put our Web.config file under source control, we'll end up with various conflicts when the developers change the configuration file to suit their tastes. I don't know about you, but I have better things to do than start memorizing API keys or digits of PI.

Solution #1

Our first solution wasn’t fantastic, but it was sufficient for a while. We simply removed the Web.config from source control and created new files, one for each developer (Web.config.jkealey, Web.config.etremblay, etc.) and one for the deployment server (Web.config.server1). When a change was to be made, we whipped out WinMerge and changed all the files. You can quickly understand that this process does not scale well, but it was sufficient for small projects with 2 to 3 developers.

Hurdle #2: Scaling to more than a couple machines

We deploy our point of sale software and kiosks via Subversion. It might be fun to use WinMerge to compare a couple Web.config files, but when you’ve got a hundred web applications to update to the new version, by comparing Web.config files, you’ve got a problem. Doing this by hand wasn’t very difficult but it was error-prone and time consuming. I don’t know if you have seen the Web.config additions that ASP.NET AJAX brought to the table, but upgrading from a release candidate of Atlas to the full release of ASP.NET AJAX was painful (we’re not talking about half a dozen settings in the AppSettings section).

Solution #2

1) Create a template Web.format.config that contains the general Web.config format, with certain placeholders for variables that vary on a per-developer or per-machine basis.

2) Create a web.default.properties that contains the default settings for the web.config

3) Create a web.developername.properties for each developer that simply overrides the default settings with other values when needed.

4) Write a script to replace the placeholders in the Web.format.config and generate your Web.config.developername files for you.

We implemented this strategy using NAnt. Our script does a bit more work because we’ve got interrelated projects, but I will describe the base idea here.

Examples:

Here is a portion of our web.format.config file:

[...]
<appSettings>
    <add key="GoogleMapsAPIKey" value="${GoogleMapsAPIKey}"/>
</appSettings>
<system.web>
   <healthMonitoring enabled="${healthMonitoring.enabled}">
       <providers>
           <clear/>
           <add type="System.Web.Management.SimpleMailWebEventProvider"  name="EmailWebEventProvider"
               from="${bugs_from_email}"
               to="${bugs_to_email}"
               subjectPrefix="${email_prefix}: Exception occurred"
               bodyHeader="!!! HEALTH MONITORING WARNING!!!"
               bodyFooter="Brought to you by LavaBlast Software Inc..."
               buffer="false" />
       </providers>
   </healthMonitoring>
</system.web>
[...]

Property files

Our default settings look something like the following:

<project>
    <property name="GoogleMapsAPIKey" value="ABQIAAAAkzeKMhfEKdddd8YoBaAeaBR0a45XuIX8vaM2H2dddddQpMmazRQ30ddddPdcuXGuhMT2rGPlC0ddd" />
    <property name="healthMonitoring.enabled" value="true"/>
    <property name="email_prefix" value="LavaBlast"/>
    <property name="bugs_to _email" value="info@test.com" />
    <property name="bugs_from_email" value="exception@test.com" />
</project>

 

Our per-developer files include the default settings, and override a few:

<project>
    <!-- load defaults -->
    <include buildfile="web.default.properties"   failonerror="true" />   
        
    <!-- override settings -->
    <property name="GoogleMapsAPIKey" value="ABQIAAAAkzeKMhfEKeeee8YoBaAeaBR0a45XuIX8vaM2H2eeeeeQpMmazRQ30eeeePecuXGuhMT2rGPlC0eee"/>
    <property name="bugs_to_email" value="jkealey@test.com" />
</project>

The NAnt script

We wrote a NAnt script that runs another NAnt instance to perform the property replacements, but the core code comes from Captain Load Test. It is a bit slow because we have to re-invoke NAnt, but it doesn’t appear like you can dynamically include a properties file at runtime. Feel free to comment if you find a way to make it more efficient. We don’t have our generated files under source control as we only version the property files.

<project name="generate configs" default="generate ">
    <property name="destinationfile"   value="web.config" overwrite="false" />  
    <property name="propertyfile"  value="invalid.file" overwrite="false" />  
    <property name="sourcefile"   value="web.format.config" overwrite="false" />
 
    <include buildfile="${propertyfile}"   failonerror="false"   unless="${string::contains(propertyfile, 'invalid.file')}" />   
    
    <target name="configMerge">    
        <copy file="${sourcefile}"  tofile="${destinationfile}" overwrite="true">
            <filterchain>
                <expandproperties />
            </filterchain>
        </copy>
    </target>
 
    <target name="generate ">
        <property name="destinationfile" value="web.config.${machine}" overwrite="true"/>
        <property name="propertyfile" value="web.${machine}.properties" overwrite="true"/> 
        <property name="sourcefile" value="web.format.config" overwrite="true"/>
        <echo message="Generating: ${destinationfile}"/>
        <!--<call target="configMerge"/>-->
        <exec program="nant">
            <arg value="configMerge"/>
            <arg value="-nologo+"/>
            <arg value="-q"/>
            <arg value="-D:sourcefile=${sourcefile}"/>
            <arg value="-D:propertyfile=${propertyfile}"/>
            <arg value="-D:destinationfile=${destinationfile}"/>
        </exec>
    </target>    
</project>

Hurdle #3: Software Product Lines

Egypt trip 2007 Up to now, we’ve talked about taking one project and making it run on a number of machines, depending on a few preferences. However, we’ve taken it one step further because our web applications are part of a software product line. Indeed, we have different themes for different brands. Different companies have different configuration settings and site maps files. Therefore, we needed to be able to generate configuration files for each brand AND for each machine. This also greatly increases the number of configuration files we need.

Solution #3

It wasn’t very difficult to expand to this new level of greatness thanks to the script presented in hurdle #2. We basically have default configuration files for each project (themes, sitemap, name, locale, etc) in addition to the files we’ve shown above. We simply have to load two configuration files instead of one.

We even wrote a batch file (SwitchToBrandA.bat) that generates the property file for the current machine only (via the machine name environment variable) and it replaces the current Web.config. By running one batch file, we switch to the appropriate product for our current machine.

Future work

Currently, it takes a couple minutes to create a new brand or add a new developer. It doesn’t happen often enough to make it worthwhile for us to augment the infrastructure to make it easier on us, but is a foreseeable enhancement for the future. I guess another future work item would actually be hire someone who is an expert in build automation, test automation and automatic data processing! :) These are skills they don't teach in university, but should!

kick it on DotNetKicks.com  



I, for one, welcome our new revision control overlords!

clock February 11, 2008 10:35 by author JKealey
IMG_0215
Be a lazy developer!  You know you deserve it.

I’ve been developing websites professionally for almost nine years now and although I still party like it’s 1999, my productivity has increased greatly thanks to better tools and technologies. Due to recent dealings with the IT department of another firm, I remembered the fact that although we think that all developers are using source control (CVS, Subversion, etc.), this is not the case. There are lots of corporate developers out there who don’t follow the industry’s best practices. This post is not about using version control tools for source code… it’s about re-using the same tool for deploying websites, instead of FTP. We assume you know what source control is and are interested in using it in novel ways. 

A few days ago we were visiting the facilities of a company which provides services of interests to one of our franchisor customers. As our specialty is the integration of external systems with FranchiseBlast, our franchise management tool, we wanted to know how the data would be able to move back and forth. One of the sophisticated options available to us was the use of FTP to transfer flat files in a specific file format, not that there’s anything wrong with that!  Indeed, when your core business doesn’t require lots of integration with your customers, no need to re-invent your solution every three years with newer technologies. You can afford to stick with the same working solution for a long period of time! (We will obviously continue to push web services, as it is much easier to write code against a web service than picking up flat files from an FTP server!).

Integration and automation reduce support costs for the franchisor

We’re always looking at pushing the envelope and we know that software integration and especially automation is the key to cutting down labor costs. If your business processes include lots of manual labor, we feel it is worthwhile to take the time to investigate replacing a few steps software-based solutions (focus on the 20% of steps that make you lose 80% of your time). Wouldn’t you rather play with your new puppy than copy-paste data from one place to another? A typical example for the integration we built into FranchiseBlast and the point of sale is the automatic creation of products in stores, once they are created on FranchiseBlast. Our franchisees save lots of time not having to create their own products and we avoid the situation where an incorrect UPC is entered only to be discovered months later.

Furthermore, although your mental picture of a franchisor might boil down to someone lounging in their satin pyjamas in front of the fireplace, sipping some piping hot cocoa, while waiting for the royalty check to come in, this is very far from the truth. Supporting the franchise is a major time consumer but if you can manage to reduce and/or simplify all the work done inside the store, you can greatly reduce time spent supporting the stores.

Enough about the franchise tangent; talk about web development!

Integration and automation does not only apply to your customers: any serious web development firm still using FTP to deploy websites should consider the following questions. By a serious firm, I mean you’ve got more than your mother’s recipe website to deploy and you build dynamic web applications that change regularly, not a static business card for your trucker uncle.

  • Are you re-uploading the whole site every time you make an upgrade?
  • Are you selecting the changed files manually or telling your FTP client to only overwrite new files?
  • Is someone else also uploading files and you’re never sure what changed?
  • Do you care about being able to deploy frequently without wasting your time moving files around?
  • Do you have to re-upload large files (DLL, images) even if you know you only changed a few bytes?
  • Did you ever have to revert your website back to a previous version when a bug was discovered?
  • Do you upload to a staging area for client approval, then deploy to the production server?

imageIf you answered yes to one of these questions, you’re probably wasting your precious time and (now cheap) bandwidth. Yes, I know it is fun to read comics while you’re uploading a site but you’re not using technology to its full potential.

Source control technology has been around for decades and hopefully you’ve been using it to collaborate with other developers or designers when creating websites. Even if you work alone, there are several advantages to using CVS or Subversion, for example. You may be wondering why I am talking about source control in the context of web deployment but I hope the astute reader will know exactly where I’m headed.

Why not deploy your websites using source control tools such as Subversion?

There are probably lots of you out there that already do this but there may be some people that never thought outside the box. By sharing this with you today, I hope to help at least one person cut down an hour per week spent in deployment. We’ve experienced the benefits and wanted to share them with you. 

We prefer Subversion over CVS for multiple reasons, but one that is of particular interest here is the fact that it can do binary diffs. If you recompile your ASP.NET website, you’ll generate new DLL files that are very similar to the previous ones. The same thing happens when you’re changing images. Thanks to this Subversion feature, you only have to upload the bytes that have changed inside your files… as opposed to the whole files!  Furthermore, as with most source control management tools, you can copy a file from one project inside your repository to dozens of others, without taking up additional space on the disk.

You can create a separate repository for your deployment files (separating them from your source code) and checkout the project on the production server. Later on, when you commit your changes, you can simply perform an update on the production server. You could even automate the update process using post-commit actions.

There are numerous advantages to deploying using a tool such as Subversion:

  • You only commit what has changed and the tool tracks these changes for you.
  • Only changes are transferred, not the whole site.
  • If someone other than you fools around with the deployed site, you can immediately see what was changed.
  • You can easily revert back to an older version of the site

You should automate the deployment to the staging area (using continuous integration or post-commit scripts) but keep deployment to the production server manual. Automatic deployment to your staging area means you can commit at 4:50PM on a Friday afternoon, wait for the successful build confirmation, and head off to play hacky sack with your high school buddies without having to manually redeploy the development machine. At 5AM on Saturday morning, when your early-riser client gets up and has a few minutes to spare before reading the paper, he can load up the development server at play with the latest build.

What about my database?

The concept of database migrations is very useful in this context; if you use tools that have database migrations built-in (such as Ruby on Rails), then you are in luck. Otherwise, it gets more complicated. We’re waiting for database migrations to be supported by SubSonic before investing much effort in this area (although I don’t recall ever having to revert a production server back to a previous version). For our business, this is a must have feature because it allows us to revert a store’s point of sale to a stable build should the software exploded in the middle of a busy Saturday. Even better, should a fire destroy the store’s computers, we can reload this store’s customized version within minutes. (We also do nightly off-site data backups of the sales information).

In any case, we recommend you take a peek at the series of posts made by K. Scott Allen, referenced in this article by Jeff Atwood.

How can I save more time?

IMG_0501 The answer is simple: by scripting the copying of files (locally) from your development copy to the checked out folder of the production repository. This can be as simple as using the build-in deployment tools available in your IDE (such as VS.NET’s deployment functionality) or writing a script that copies all files of a particular extension from one place to the other. Eventually, you’ll need to adapt your script to your particular needs, if you’re wasting too much time copying large files that never change, for example. This step depends on your project and its environment. I will describe in a future post how we use NAnt to manage our software product line. Kudos to Jean-Philippe Daigle for helping us out in the early days.

Concrete examples

LavaBlast deploys its point of sale application via Subversion; every computer we manage has its own path in the deployment repository. This allows for per-store customizability and is not as redundant as one may sound because of Subversion copies. Furthermore, when the POS communicates with FranchiseBlast, we track exactly which version of the software is running in that particular store (via the Subversion revision number). We also track a revision number for the database schema. Having this bird’s eye view of the software deployed in the franchise lets us easily schedule updates to subsets of the stores. At the point where we are now, we could easily write code that would signal to the store it should upgrade itself to a certain revision at a certain time & date.  Ultimately, instead of spending my time copying files, I am available to write blog posts like this one!

Conclusion

By moving away from FTP, we’ve considerably cut down the time it takes to deploy a website. We invested time in this infrastructure early on, allowing us to concentrate on design, coding, and testing as opposed to deployment. Of course, FTP still has many uses outside of the context we describe here! FTP has been around for a long time and will not disappear any time soon!

kick it on DotNetKicks.com


Month List

Disclaimer

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

© Copyright 2014

Sign in