Voicemail Problems with Skype

For small businesses in need of only a few phone numbers, Skype is a great value. I pay about $60/year for a phone number that rings wherever I’m logged into Skype, plus voicemail. When it works, which is almost all of the time, it’s fantastic.

The trouble is “almost all of the time.” So for Googlers benefit, here are three problems I’ve had with Skype voicemail over the last couple of years that aren’t answered by Skype’s FAQ and unlikely to get a straight answer from tech support in the first response.

These solutions are for the Mac client, but can probably be adapted to Windows. I doubt the files are different, but the paths to them will be.

Can’t hear any audio when you listen to a voicemail?

Calls go to voicemail immediately, without ringing?

For both of these, quit Skype, then delete the file ~/Library/Application Support/Skype/shared.xml.

Unanswered calls not going to voicemail?

Quit Skype. Open ~/Library/Application Support/Skype/your-user-name/config.xml in a text editor. Look for:

<Call>
  ...
  <NoAnswerTimeout>10</NoAnswerTimeout>
  ...
</Call>

The number is the delay, in seconds, before Skype will do something with the call. If this is missing, Skype won’t send the call to voicemail.

What Happened to Programming

Last week, Mike Taylor posed the question “whatever happened to programming?” (also see his followup). I think part of the answer is simply “it’s grown up.”

Programming, either as a hobby or a career, has only been around for a little less than 70 years. (The first was the Colossus, built and used by the British during World War II to read encrypted German messages.) This is very young when compared to other scientific fields: agriculture, construction, various engineering disciplines, etc.

I won’t disagree that building the very fundamental parts of a new application from scratch can be very enjoyable. Perhaps not printf(3), but certainly other parts. The problem is bug rates, though: any seasoned software developer knows that writing less code means less bugs. If high-quality libraries are available that provide 80% of the functionality of your new application, you will likely end up with a better product, in less time, than if you chose to write the entire thing yourself.

Consider the sorry state we’d be in if:

All farmers experimented with their own methods of weed and pest control (organic or not), instead of using techniques proven to work in the past. Our agriculture industry probably couldn’t meet the population’s demand for food.

Architects and builders “winged it” when building new homes and office buildings. Bugs in that industry would likely mean structural failure. Who would want to live in those houses?

How about automakers? It’s one thing to build a kit car as a hobby, it’s quite another to tinker with your designs when you’re producing cars on a massive scale for general use (just ask Toyota).

It may not be as glamorous, but if our collective bug count goes down and the software industry ships better products that don’t require constant patching, I can’t help but consider this a very good thing.

Small Business Accounting Software

I made a New Year’s resolution for 2010 back on October 1st: stop using the awful shovelware produced by Intuit (QuickBooks) and move to something else. I first wrote “something by a company that cares more about the Mac,” but let’s be realistic. Large companies seem to lose a sense for quality products and good customer service, so really this is all about “anything but QuickBooks”.

I’m moving away from QuickBooks because I paid for it in 2007 and it doesn’t work (seriously: it corrupts transactions) on Snow Leopard. Even the QB 2009 installer failed to work on Snow Leopard until they patched it, as they were still using the Java Bridge, deprecated by Apple way back in 2006 and removed in Snow Leopard. If I have to spend money on accounting software to run Snow Leopard, I’m going to look at all my options.

Light Year Software is, for now, primarily a consulting company. I sell my time, so an accounting package needs to support that. I do not carry inventory or resell goods. I don’t have to collect sales tax. While the business owns some equipment (computers), it’s very minimal.

The list of contenders is disappointingly short, though on the upside, it means I don’t have to try out as many of them: Gnucash (free), AccountEdge 2009 (USD$299) from Acclivity (formerly MYOB) and MoneyWorks Express 5.2 (USD$279) from Cognito.

Gnucash

This one was easy. While I’m a fan of open source, I only had to spend a few minutes with Gnucash to know it wasn’t right for me. It’s written using Gtk+, which isn’t surprising since it’s a cross-platform application, but I didn’t want to spend already unpleasant time using a thoroughly non-Mac UI. There are also some known issues that struck me as likely to be highly irritating. Finally, while I hope to never have to, I do want a safety net of a real company behind the software: phone support, a well-written manual, and an expectation of support for older, but not ancient, releases (after all, I’m in this boat because I didn’t want to update QuickBooks 2007).

AccountEdge and MoneyWorks Express

These two are similar enough that it’s probably easier to write about them together.

AccountEdge wins (barely) on first impressions. The main dashboard interface is more colorful and buttons look like buttons. Both applications use a flowchart style, visually presenting how you should move through the application. AccountEdge does a better job of it, though, because buttons are obvious, whereas with MoneyWorks, you don’t know what’s clickable until you hover over it.

MoneyWorks is a bit nicer when you get down into the forms, but only by a hair. The tab order is often unintuitive; for example: after entering a date for a transaction, tab takes you to the period drop-down immediately above it, instead of the next field down and to the left.

AccountEdge did a better job of hand-holding me through setup. There is a separate setup dashboard, each major section walking me through a wizard that prompts to transfer data from your old system into AccountEdge. MoneyWorks doesn’t have this, though it does have a nicer manual (PDF). AccountEdge’s manual is just a set of HTML pages, with a Javascript table of contents on the left that doesn’t always work quite as I expect. AccountEdge actually has a nice set of manuals, too, under Help → Manuals. I don’t know how I missed this earlier.

AccountEdge allows me to set up a billing rate per customer (or even per employee), which is very nice. MoneyWorks does not do this, instead requiring me, as with QuickBooks, to set up separate products for different billing rates. For me, differing rates are quite common. It can be hard to raise the rate for long-term customers, or I may wish to charge different rates for different types of work. MoneyWorks Gold claims better support for time-based billing, but it’s also USD$599, more than double the price. Express doesn’t let me enter dates for each line item on an invoice, which I think is important. This is a major strike against.

AccountEdge’s forms editor is awful. It’s impossible to see how objects are layered, and I found that line shapes didn’t show up at all, even when previewed. The first time I tried to customize an invoice, the result that was emailed to a customer was horribly misaligned, though thankfully still legible. A second try produced better results, but it took a lot longer than I expected. Thankfully, this is the kind of thing I hope to do very rarely. MoneyWorks’s forms designer looks quite powerful, offering what looks like a macro language to create the forms. I’ll be honest, though: I didn’t go into this in depth because by this point, after realizing the limitations on time-billing, I’d made up my mind to go with AccountEdge.

AccountEdge can email invoices and statements directly from the application, which is really nice, except that it uses Mail.app and the first defined mail account. For me, this means that business correspondence goes out using my personal account. That’s unacceptable, so I’m back to doing what I did with QuickBooks: print to a PDF, then compose an email by hand and attach.

One last “weak sauce” moment is with the MoneyWorks user support forums. Trying to be funny, they convert any instance of “MYOB” to “*Four-letter-word accounting software*”. It’s juvenile and unnecessary. To their credit, searches for “MYOB” do the right thing, so if that’s an important part of a search query, at least the right posts will come back.

So, that’s it. It’s early January, 2010 and AccountEdge 2010 was due to come out today. It is not yet available, however. The trial version I have will work for 30 days, and while Acclivity will give me a free upgrade to 2010 if I buy 2009 now, I’m going to hold off and make sure 2010 doesn’t do anything idiotic before spending the money.

Update Jan. 13: One thing I neglected to point out when I published this is that an often-cited reason for using or sticking with QuickBooks is that “my accountant uses it.” I was pleased to discover that both AccountEdge and MoneyWorks make free copies of their software available to accountants in order to read my company file. The same is technically true for Gnucash, but if I’m not thrilled to use it, what are the chances my accountant will be?

Update Jan. 27: First, I received an email from Tom Nash, a managing partner at Acclivity, who told me that they are aware of the mail account issue I noted above. According to Tom, the way it works is somewhat due to how Mail.app works. If you have multiple accounts, AccountEdge will use the same account that Mail.app will use if you press ⌘N to start a new message.

Second, I received my AccountEdge 2010 CD and, sadly, the form editor looks exactly the same as 2009. I still don’t see line shapes in the default forms, which means customization will likely still be a difficult trial-and-error process.

The Diminishing Returns of Long Hours

A lesson I learned during my years in university and had to re-learn once or twice while working in Silicon Valley is that working long hours is beneficial, but only for a very short period of time. One or two 60 hour weeks is enough, as is even a single all-nighter. When you’re sleep deprived, you don’t make good decisions, and software development is all about good decisions. There is never one solution to a problem. A good engineer picks one of the best solutions through creativity and experience. Sleep deprivation dulls the ability to do either well.

In Don’t be a Hero, Alex Payne makes the additional argument that an individual working these long hours is a sign that your culture has a problem.

Work/life balance is important. These days, I only work long hours if it’s because I made a mistake. Everything I do is, in part, an effort to avoid this: fair and realistic estimates, regular communication with my customers, and not slacking off early in a project.

Bash Substitutes for “seq” and Simple “sed” Expressions

There are two things I find myself doing from the shell just infrequently enough that I can’t remember the exact syntax. The first is generating a sequence and the second is repeated string transformation.

“seq” is a little GNU utility that generates sequences of numbers. I used to find this installed automatically by many Linux distributions, but lately (on Debian and Ubuntu, at least) it’s missing and I haven’t been sufficiently motivated to find it. No need: Bash has something good enough built in.

To generate the numbers from 1 to 10, inclusive:

$ echo {1..10}
1 2 3 4 5 6 7 8 9 10

The second thing is repeated string transformations, for example renaming a set of files to use a different file extension. This used to mean re-reading the sed(1) man page yet again and doing the transformation in a backtick expression. Again, no need: Bash can do this itself:

$ for f in a.foo b.foo c.foo; do echo $f ${f/%foo/bar}; done
a.foo a.bar
b.foo b.bar
c.foo c.bar

The syntax is ${parameter/pattern/replacement}. pattern only replaces the first match, unless it starts with /, in which case it replaces all matches. It can also start with # to force a match at the beginning of the string or % to match at the end.

Take a look at “Parameter Expansion” in the Bash manual for several other useful operations.

On the Pain of Developing for Facebook

I’m in the last stages of building a site that integrates with Facebook. It includes a Facebook Connect component and a separate Facebook iframe application. In the hopes that some of my experience will help someone else out there, I will share some of my suffering and how I worked through it.

This is a Rails 2.3 application, using the Facebooker gem, version 1.0.54.

Safari, iframes, and cookies.

Chances are high you’ve found this page via search, and that you are desperate to find a solution to allow your Rails sessions to carry over from page #1 of your iframe application to page #2 and beyond. Will Henderson has a solution when your Rails application uses the ActiveRecord session store, but new Rails applications use the cookie store. There is no session to retrieve from the database; passing a row ID with links doesn’t help.

I am fortunate that my iframe application has a splash screen, with only one useful link on it, to start the “real” application. I append every fb_sig parameter from the current request to the link. Once the user clicks that link, the iframe no longer falls under Safari’s 3rd party cookie policy, and so the next page can set cookies. Because all of the fb_sig parameters are there, Facebooker gives precedence to them, recreating the Facebook session without consulting cookies (which either don’t exist or are stale).

<%= link_to 'Start the app', params.merge(:action => :app) %>

Now, your app doesn’t always get these. When the application is first installed, you won’t get the fb_sig parameters. In this case, I force a redirect:

unless params[:fb_sig_ss]
  redirect_to "http://#{Facebooker.canvas_server_base}/#{Facebooker.facebooker_config['canvas_page_name']}/"
  return
end

However…

Facebooker’s Rack middleware trashes your params.

Facebooker includes a piece of Rack middleware that automatically validates the signature on fb_sig parameters, and aborts the request if the signature isn’t valid. This works great on the initial request, but fails on the second request, with exactly the same parameters.

The culprit is near the bottom of Facebook#call, in rack/facebook.rb, where it calls convert_parameters!. This method is trying to be helpful, turning things like Unix time_t into Ruby Time instances. If you are trying to pass these parameters along in a link, Time.to_s is not a Unix time_t, and so the signature validation will fail, and you’re screwed.

Pre-Rails 2.3, there is no Rack middleware, and signature validation happens in another part of the Facebooker gem, which does not trash the original params. It does the same conversion, but on a copy. As near as I can tell, calling convert_parameters! is unnecessary, and commenting it out solves my problem. When Safari loads page #2, Facebooker creates its session, which can be stored in the Rails session, using the cookie store.

Reconstituting a Facebook session in Flash.

The bulk of this iframe application is actually written in Flash. Every Facebook application has an App ID (essentially a public key) and a secret key. The secret key must never be allowed outside your organization or people can fake API requests from your application. Embedding your secret key in a Flash SWF is therefore not an option, because a SWF can be decompiled. Facebook’s solution to this is the session secret, passed as fb_sig_ss.

According to Adobe’s ActionScript 3.0 Client Library for Facebook API reference, one can use the FacebookSessionUtil class to recreate a session using only the public key and the session secret. This is not true. I have to pass in all of the fb_sig parameters to Flash in order to make it work. However you start your Flash content, FlashVars must include:

<%= params.collect { |k,v| "#{k}=#{v}" if k.starts_with?("fb_sig")}.compact.join("&") %>

A refreshed page lags a “logged-in” state change until refreshed a second time.

When a user logs out of Facebook and refreshes your Facebook Connect web site, it doesn’t reflect the user’s “logged-in” state change until another refresh. You can automate this and have the page refresh itself when necessary:

<% init_fb_connect 'XFBML', :app_settings => '{"reloadIfSessionStateChanged":true}' do %>
  FB.ensureInit(function() {
    FB.Connect.get_status().waitUntilReady(function(status) {
      switch (status) {
        case FB.ConnectState.connected:
          $$('.fbConnectLoggedIn').invoke('show');
          $$('.fbConnectLoggedOut').invoke('hide');
          break;
        case FB.ConnectState.appNotAuthorized:
        case FB.ConnectState.userNotLoggedIn:
          $$('.fbConnectLoggedIn').invoke('hide');
          $$('.fbConnectLoggedOut').invoke('show');
          break;
      }
    });
  });
<% end %>

There are actually two parts to this trick. First, :app_settings => '{"reloadIfSessionStateChanged":true}' triggers the automatic refresh.

Second, if you have some common part of your layout that switches on a user’s Facebook status, this precludes your use of page caching. For an otherwise static page, this is a real sacrifice. To work around this, I include both sets of mark-up, classed with either “fbConnectLoggedIn” or “fbConnectLoggedOut”, and invoke Prototype’s show() or hide() on them as part of the Facebook Connect initialization. As long as you are careful to use XFBML tags that don’t require actual values from a Facebook session (e.g. <fb:name uid="loggedinuser" ...>), this works very well.

New conditionally_cache Method for Fragment Caching

I just pushed a couple of updates to Banker. The boring one adds the missing “should_not” variants of the existing Shoulda macros.

The more interesting one is a conditionally_cache method for fragment caching. If you use pagination to split content across pages, this might be very useful for you. Pages 2 and later are rarely loaded, falling very quickly to the tiniest sliver of people that see page 1.

conditionally_cache adds a new first argument to the regular cache method. This argument is evaluated in a boolean context. When true, control is passed to the cache method as usual, performing fragment caching. When false, though, the block is captured and output as if the caching code were not there at all.

So instead of having no caching on your paginated results or wrapping your cache call in an ugly if statement, instead you can do this:

<% conditionally_cache params[:page].blank? || params[:page] == '1', 'page1' do %>
  ... usual HTML markup goes here ...
  ... this will be cached on page 1, but not elsewhere ...
<% end %>

Since pages 2+ are not cached, you need only expire the ‘page1’ fragment, and nothing else.

Rails Bug with render :text => proc in Tests

There is a bug in the current stable release of Rails, 2.3.4, when using render :text => proc { ... }. The Proc object is never called by the test framework, which limits what you can test. For example, the following two techniques will both fail:

  • Using assert_select or similar methods to check the content of the response.
  • Setting expectations with a mocking framework on methods that are called within the Proc body.

Lighthouse bug #2423 includes my reworked patch to fix this issue. A couple more people verifying the patch will help get it committed.

Xcode: iPhone Project Dependency on Mac OS X Project

This week, while building an iPhone application for a client, I wanted to run a custom Mac OS X command-line utility during the build phase of the iPhone project. I set up the command-line utility as a dependent project of the iPhone project, but it won’t build, telling me:

target specifies product type ‘com.apple.product-type.tool’, but there’s no such product type for the ‘iphonesimulator’ platform

There is no perfect solution to this problem, but here’s my workaround: rather than let Xcode build the dependent project for me, I simply added a call to xcodebuild as part of my custom script phase. As long as the input and output files for this phase are set up properly, the entire phase is skipped when the output file is up-to-date, and xcodebuild is pretty fast when the target binary is already built, too.

My final script phase looks like this:

(cd SubProject; xcodebuild -configuration Release)
SubProject/build/Release/SubProjectCommand