Skype Sucks for Business

I was really excited when starting my own small business to be using Skype for my telephony needs. It was really cheap, and I could get a real number and have it direct to my phone or to my computer depending on when I was logged in.

Too bad the support has sucked. My account password was stolen, and the culprit logged in and charged stuff to my stored credit card. Skype was happy to reset my password, but informed me that it was impossible to get a refund on these purely virtual unused goods.

At this point, I called my credit card company, and informed them of the fraud, and they took care of it. Skype didn’t like that very much however and completely disabled the paid functions of my account (which I had used my stored “skype credit” for).

So my business phone number went dark. They didn’t email me about this at all either. I don’t get a lot of traffic on that number so I didn’t even know it wasn’t working.

So that’s where I stand now. I’m on a live chat with a Skype rep trying to get it sorted out.

In the end, I suppose this is run by the same company that runs PayPal, and we all know how they are legendary for their uber-crappy support. I shouldn’t be that surprised.

Lesson of the Day: Don’t trust Skype (or PayPal). I can’t wait for Google Voice.

Update: Annnnd the chat just ended. Andre on the Skype Support Live Chat was way more awesome and helpful than the last person I spoke with @ Skype and actually helped me out. So there’s that.

Still, I’m not planning on using Skype for anything mission critical in the near future.

Talking at South Sound .NET User Group

Just a reminder that I’ll be at the South Sound .NET User Group meeting on December 10th, 2009 to talk about MVP in a WinForms desktop application.

Everyone talks about all the fancy new WPF stuff, but I’m really excited to be talking about WinForms here. I know that a lot of us are stuck using WinForms for quite a while, and we’ll all be maintaining WinForms apps for the foreseeable future. MVP is something you can apply to your WinForms code and create desktop apps that are testable, flexible, and maintainable. We all want this.

I’m hoping to do a live coding example with a small ToDo application there building the app up and showing how to wire up all the MVP-ness. Visual Studio is currently being uncooperative and it’s currently doing a repair, so we’ll see if that fixes it. Here’s hoping! If not I’ll just do it in MonoDevelop or SharpDevelop. It’s all gravy.

Here are the details:
7-9PM
Olympia Center
222 Columbia NW
Olympia, WA 98501

See you there!

Testing, Django Client, and HTTP Basic Access Authentication

I was writing a test using the django client against some code that uses http basic authentication. I had to dig for hours to figure this out, so I figured I’d post my solution somewhere.

def create_auth_string(username, password):
  import base64
  credentials = base64.encodestring("%s:%s" % (username, password)).rstrip()
  auth_string = 'Basic %s' % credentials
  return auth_string

# create auth string for header
auth_string = create_auth_string("user", "pass")

# This is where the magic happens
response = self.client.get('/url/requiring/authorization/', HTTP_AUTHORIZATION=auth_string)

Not complicated, but not documented anywhere I could find. Enjoy!

LogoYes.Com – You Have Failed

I have a client wanting a website on a very small budget, so I recommended using logoyes.com to create the logo for the business. They are cheap, and last time I used them was relatively straightforward.

Not this time. The payment processor marked my card as fraud for whatever dark reason payment processors do, and the software provided no means of recourse. The excellent customer service representatives were hamstrung by a web application which provided no ability to manage any of these common issues.

It reminded me a great deal of Ayende’s PayPal Post

Anyway, here is the email I sent to logoyes after borrowing my partner’s credit card so I could perform a business transaction:

Thank you [Very Nice Customer Service Rep Name].

As I said on the phone, I had to call several times in order to get this purchase sorted out. The customer service representatives were very kind, patient and helpful. I cannot speak more highly of the customer service representatives employed by logoyes.

However, as a software developer, I feel ashamed that someone in my profession was paid money to write the logoyes.com software. The fact that I can spend quite a bit of time creating a logo and getting approval from a client, only to have the payment processor mess up and not have that logo saved anywhere, or provide the customer service reps with any ability to help me in that situation is ridiculous.

I understand that payment processors are pretty tricky things, but a false positive on fraud is such a common occurence it’s a complete oversight to not have any other way for a customer (which in my case had already invested at least 2 hours into the process) to pay for their logo is incredulous.

I will not be buying another logo from logoyes, which is unfortunate because I’ve been pretty pleased with the results. However, for such a low cost product, I cannot risk investing more hours into the logo and suddenly have no way to download it. It makes no business sense.

Thank you,

James Thigpen

Accidental MVC

So this app I’m writing and maintaining at my day job. It accepts requests over this painful legacy protocol, performs some action based on that request, encodes the result in the same painful legacy protocol, and returns it to the client.

The way it’s designed, it has an array of IMessageHandlers that are each bound to a particular request type. So if a GETPRT request comes in, it loads up the GetPartMessageHandler which processes it and returns a result to send back to the client.

I had an epiphany a while back. This is MVC. If I didn’t have to deal with the legacy network protocol and weird encoding scheme, I could drop all this custom message handling code stuff in the dumpster and drop in one of 800 MVC web app frameworks and be done with it.

The command type, say GETPRT, could be mapped to http://server/GETPRT, and we could use our handy dandy routing engine to say route $GETPRT^ to the GetPart action on the PartController.

So in essence, I think I grew an MVC framework. It’s actually a little Django-ish, because I don’t really use controllers. But neat.

I wonder if I could have saved time if I had realized this would fit so well with MVC from the get go.

Running Multiple Hudson Instances Simultaneously

I wanted to run multiple Hudson instances side-by-side. It was easy enough to get them running kicked off via batch files, but I wanted them to run as services, because I’m lazy and greedy.

Turns out it’s easy, though non-obvious.

  1. Install 1 Hudson instance as a Service.
  2. Stop the running Hudson service (net stop hudson)
  3. Copy the original hudson installation ($HUDSON_HOME) to another directory where you want the new service to reside
  4. Modify the copied hudson.xml in the new hudson install directory to give it a new service name.  Change service/id from “hudson” to “hudson2”. Not the service name, the service id.
  5. Now run the following from the command shell in your new hudson directory: hudson.exe install
  6. Start your new server: net start hudson2
  7. Start your old server: net start hudson
  8. Finished!

Now if you want to uninstall it you simply run “hudson.exe uninstall” from the service $HUDSON_HOME directory. The mailing lists are good.

Infinite List of Database Users with Yield Return

At the ALT.NET Seattle conference, I went to a session by Nate Kohari on the awesomeness of the yield return keyword in .NET and how you can use it for all kinds of fancy stuff.

In the true spirit of over-engineering a solution, I have created this little property in one of my spec base classes:

   1: protected IEnumerable<User> DatabaseUserList
   2: {
   3:     get
   4:     {
   5:         while (true) yield return CreateUserInDatabase();
   6:     }
   7: }
   8:  
   9: protected User CreateUserInDatabase()
  10: {
  11:     var user = new UserBuilder().Build();
  12:     Repository<User>.Save(user);
  13:  
  14:     Flush();
  15:  
  16:     return user;
  17: }

We create what would be an infinite loop which creates Users over and over until the system runs out of memory, but since we’re using yield return, each user will only be created as we iterate over the list. Sexy.

Infinite data structures are a pretty common thing in functionaly programming languages with lazy evaluation. It wasn’t until this past weekend that I realized you could do the same thing in C#.

And using the delayed execution magic of yield return and our good friend LINQ, we can do things like:

   1: // Give me an IEnumerable<User> with 5 users in it.
   2: var users = DatabaseUserList.Take(5);
   3:  
   4: // Give me 1 user
   5: var user = DatabaseUserList.First();
   6:  
   7: // Force list creation, populates DB w/ 10 Users
   8: DatabaseUserList.Take(10).ToList();

So this will create users, stick them in the database, flush the database, all lazily as I iterate over a list of users. Is this a good idea? Probably not! But it’s hella cool.

ALT.NET Seattle 2009 – Why So Mean?

I am currently attending the ALT.NET Seattle Conference. The energy and passion is really invigorating. It makes me want to be productive.

Scott Hanselman hosted a session named, “Why so mean?” that was really good. It asked the question “Are we the barrier to entry for new people being introduced to the ALT.NET movement?”. There are some abrasive personalities in ALT.NET which some people feel (including myself) can be a deterrent towards introducing new people to the ideas and practices that we evangelize. Scott did a great job facilitating the session and sort of guiding the conversation.

A great number of good points were made. For one, we talk a lot about teaching new people how to do these things, but we don’t spend a lot of time discussing pedagogy (the science/study of teaching). There is a session tomorrow inspired by that realization that I’m really excited to attend.

Discussing the session over dinner, someone made an observation that I thought was a little sad. One of the last statements on the “mean people” in our community (technically the word “Asshole” was bandied about quite readily) made during the session was along the lines of “There will always be mean people so you just have to accept that,” which I think is a bit a cop-out. If we’re going to claim to be a community, we should take responsibility for those in our community, not just give them a get out of jail free card.

It wasn’t all doom and gloom though. There was a lot of good discussion about how we can make ALT.NET more approachable to new people. It’s hard to do that though. I personally am still a bit intimidated talking to some of these people. Everyone is super nice though. It’s a great group of people and I can’t wait for tomorrow to get some more hot nerd on nerd dialog.

Windows Task Manager Keyboard Shortcut

Maybe everyone else already knows this, but I just found out and I’m so happy.

CTRL-SHIFT-ESC brings up the Windows Task Manager.  No more CTRL-ALT-DELETE click the button dance.  Woo hoo!

Automatically Increment WiX Installer Product Version

Most build servers set an environment variable BUILD_NUMBER on every build that is auto-incremented. We can do this using WiX proprocessor. (Note, the link is for WiX 2.0 Manual, I couldn’t find a reference for WiX 3.0 Preprocessor.  Maybe it’s the same? Probably not.)

I wanted to increment my WiX installers Product Version field automatically based off this number.

Here’s the top of my Product.wxs:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

  <!-- Set version based on build_number env. variable. -->
  <?ifdef env.BUILD_NUMBER ?>
    <?define PRODUCTVERSION="1.0.$(env.BUILD_NUMBER).0"?>
  <?else?>
    <?define PRODUCTVERSION="1.0.0.0"?>
  <?endif?>

  <Product Id="THE_GUID_YOU_GENERATED"
           Name="My Application Name"
           Language="1033"
           Version="$(var.PRODUCTVERSION)"
           Manufacturer="My Manufacturer Name"
           UpgradeCode="THE_GUID_YOU_GENERATED">

...

The ifdef part is very picky. At first I tried <?ifdef $(env.BUILD_NUMBER) ?>, which totally doesn’t work. Then I tried <?ifdef BUILD_NUMBER ?>, which also totally doesn’t work. The above is the only thing I could get to work, which goes against what this guy says. The WiX documentation for the preprocessor is pretty shoddy.

Also notice that I am incrementing the 3rd of the 4 version numbers. Why? No idea. Maybe you can tell me.

So YMMV, Caveat Emptor, and all the crap.

WiX Arcanum!