Friday, May 12, 2006

.net 2.0 web service hair puller

Every couple of weeks I spend four hours doing something that should take five minutes. It just happened, and now I feel compelled to take another few minutes and explain so it doesn't happen to you. Not only did I waste my time, but the time of another one of our developers. What might waste four hours, you say?

We recently migrated our entire web site to .NET 2.0 and a new portal. Since we were building a new web site anyway we thought, "What the heck, let's re-factor the licensing subsystem. The database was hacked together over three years and we don't want no stinkin' .NET 1.1 code running on our shiny new site!" Well, this didn't turn out exactly as planned.

The SoapBox licensing web service is quite simple. There's a single method called "Activate" that takes in a unique hash of some information on the user's computer (so we can track duplicate usages) and the serial number. It returns an XML document containing all the license information, signed with our private key, that the SoapBox Server then validates with the embedded public key. That's it.

We get a call from a customer today saying they can't enter a license key into the MMC. They're getting a wonderfully descriptive "Object reference not set to an instance of an object" error. We immediately kick into debug mode. Afterall, if a potential customer can't enter in our trial key they're going to get upset and likely just give up on using it all together.

After a little debugging we found the web service wasn't returning the license xml document like it should have been. This was _very_ weird, considering our licensing page uses the same web service as our MMC and it was working just fine with the exact same parameters. Much head to wall interaction took place and we had another breakthrough, the web method wasn't receiving any data from the parameters. The serial number was null!

Now we bust out the packet sniffer. After careful examination, a new mini test application to call the service, and three Diet Cokes, we found the problem.

Apparently, during the migration and re-factoring process, we missed a character in a copy/paste operation. That's right, the trailing "/" on the namespace declaration for the web service.

This in itself is not such a suprise. However, the suprise is that .NET did not throw a "There is no matching web method you dummy" exception. No, it didn't throw an exception at all. Instead it called the correct web method, but did not pass in any of the parameters. Oiy.

It turns out our licensing page was working because the web reference was created after the new licensing service was put in place. It all makes sense now... Time for a beer.

Tuesday, May 9, 2006

from the trenches of my first software startup

I was born and raised an entrepreneur (I'm pretty sure that's how you speel that). During my lifetime my dad never had a single "real job". He has always been a small business owner. From a carpet cleaning business, to a trucking company, to a coffee shop, he was always working on something he could call his own. Every time we get together we end up talking about businesses we'd like to start. If only I had the time. . . Somehow, after seeing him (and my mom) constantly working at least 80 hour weeks, stressed out, and exhausted, I still decided I wanted to start a company.

At the end of high school, and for a while after, I had a computer repair business with a really cute name and no business plan whatsoever. This lasted about six months. It turns out to be real work, and it's quite difficult to find people that are good enough to do that sort of work for very little pay. I'm really very interested in how Best Buy pulls that one off, though I assume they just have a good process and the people don't need to be all that great (no offense geeks -- I owe you guys many hours of my time that has been saved because I didn't have to help out my mother in law with her digital camera).

Ok, back on topic, sort of. A few years prior to my repair business I had fallen in love with computer programming. I wrote little programs to do all sorts of interesting things. Of course, I didn't work on anything that took more than a few weeks of my time and only built things that were interesting to me. Ah, the good old days! I went into the professional world when I turned 18 and started writing code for a living. Wow, what a change. Who knew coding could be so much fun?! "Wow, I get to program against another database and improve business processes! Woohoo!"

Needless to say, the life of a professional internal software developer was not in my cards. Even though I was making way too much money for my age as a "consultant" (that's what the recruiters like to call you, even though you're really just staff augmentation and under a different category on someone's budget), at about age 20 I started getting very restless. Luckily I met some like minded individuals (Jason and Chris) and Winfessor (Coversant's old company name) was born.

For the last few years, in between consulting engagements (we're boot strapped), we've been building the SoapBox products. Of course, we haven't only been building software, we've been building a business. Lucky for me, my role is still primarily building the technology. It continues to be a wonderful, trying, stressful, exciting, sleepless, humbling experience.

Here are some tidbits, in no particular order, that I've picked up along the way, from learning both the easy way and the hard way. It's free (and probably bad) advice from my limited experience aimed at any programmers out there that want to start a company around a software product. I'll probably write some more specifics at some point.

  • Have at least one flagship customer to start with, mainly for promotional purposes, but ideally one that will help fund the project.
  • Work full time on it. Hire others to do your consulting or other revenue generating work so you can focus, or get funding.
  • Don't work so hard. There is always more work to do, even if you work 140 hours/week.
  • Start small (ideally around 6mo development) and iterate from there.
  • Build it like you would an enterprise project - component based, easily maintainable and easily expandable.
  • Hire people to do things you aren't good at or learn to do them. Web site, graphics, brochures, accounting, sales, etc. Writing code is an itty bitty teeny weeny piece of your business.
  • Figure out how to start getting revenues, quickly, and set reasonable goals.
  • Don't look too far out into the future. Have a plan, but don't be scared to change it.
  • Any software you build needs to be extremely easy to use and install. This alone will win many sales in a head to head battle with your competitors (yes, you will have competitors).
  • FOCUS! Do one small thing better than anyone else, and then move on to the next.
  • Don't pretend to be a big company. You have a lot of advantages being the small guy and people willing to work with small companies know it.
  • Do something unique that your market needs.

That's all I've got for now. We're constantly growing and learning. I imagine my advice will evolve as the Coversant experience continues. In the end, the freedom, excitement, and financial possibilities of a startup outweigh the pains, at least for me. I also just realized I use way too many parenthesis when I write (maybe I'll work on that).

Monday, May 8, 2006

FakeOutTheUserToThinkWeDontUseAnyMemory

There comes a time in every project where the developers realize we are building software for the users, rather than for ourselves. A user's perception can be the difference between a good and a bad reference, and we all know how detrimental bad word of mouth can be. This unfortunate reality hit me square in the face recently when I was told by a customer that "your application is bloatware".

Any desktop application with a user interface, written in .NET, that does anything interesting, can easily be mistaken for bloatware. It's quite easy to create a super elegant application with no memory leaks that appears to use 50MB or more of memory. I say appears, because the figure everyone sees in Task Manager is the "Working Set" size. Users (myself included, up until recently) see large working set sizes as a sign of bloatware and poor programming.

This is simply not the case. The working set is more along the lines of the amount of physical memory the OS thinks your application might need or needed at one point, including shared memory and all sorts of other complicated things that .NET developers aren't supposed to have to think about. If your system was in need of physical memory for other processes much of this perceived bloat would either be reclaimed and put to better use, or paged out to disk.

At the end of the day, the reality of the situation doesn't matter. Your users think your application is bloated. What do you do? Well, you FakeOutTheUserToThinkWeDontUseAnyMemory.


using System.Diagnostics;

namespace Coversant.Utility {
public static class MemoryUtility
{
private static volatile bool _enabled = true;

public static void FakeOutTheUserToThinkWeDontUseAnyMemory()
{
if (!_enabled)
return;

try
{
Process curProc = Process.GetCurrentProcess();
curProc.MaxWorkingSet = curProc.MaxWorkingSet;
}
catch
{
//Some users won't have permission to adjust their working set.
_enabled = false;
}
}
}
}

Yep, that's it. Call that method (.NET 2.0 only -- in 1.x you had to P/Invoke) and watch the magic happen. In our applications we set it up on a timer that runs every 30 seconds and after any events we know will raise the working set, usually after loading new assemblies or after a window is closed . Running this code causes Windows to free up as much of the working set as possible. Usually this sends most of your bloat to the page file where it will remain forever. In our case, the application had a 50MB working set and really only needed about 10MB of physical memory after it was running. There is, however, one big gotcha. An application can only attempt to adjust its working set if it is running with appropriate permissions (typically a local Administrator).

Yes, your users perceptions are reality. Using this trick/hack helps keep reality in line.

About the Author

Wow, you made it to the bottom! That means we're destined to be life long friends. Follow Me on Twitter.

I am an entrepreneur and hacker. I'm a Cofounder at RealCrowd. Most recently I was CTO at Hive7, a social gaming startup that sold to Playdom and then Disney. These are my stories.

You can find far too much information about me on linkedin: http://linkedin.com/in/jdconley. No, I'm not interested in an amazing Paradox DBA role in the Antarctic with an excellent culture!