Saturday, December 4, 2010

Samsung: Korean for Fail

I've just looked up "Samsung" on Wikipedia. They confirmed that Samsung is in fact a company. I checked because I'd started to believe that it was a long running practical joke.

I've just given up attempting to upgrade my Samsung Galaxy S to Android 2.2 (Froyo). I was hoping that Froyo would resolve some of the deficiencies of the SGS such as:
  • Periodic jam ups including a few when I was trying to answer a phone call.
  • Failure to automatically switch between 3G and Wifi (the work-around is to switch it to airplane mode and back or if that fails, turn the phone off and on again, what fun).
  • Popping up an alert (day or night) to tell you that it's finished charging. Please wake me at 3 in the morning to tell me you've finished charging, I'd hate to sleep through that event.
  • Requiring debug mode to connect to a computer running any OS other than Windows.
But of course if you run OS X or Linux you're out of luck anyway because it only provides support software for Windows software for essential operations like upgrading the damned thing. Not that it matters because it has such a shonky support software that it's hit and miss whether it will even recognise that a phone is connected at all. I've just given up trying to get it to work for now having read that many users have bricked their phones just attempting to do the manufacturer sanctioned upgrade.

I read reviews before I bought this thing. They raved about it's screen. Yes, the screen is nice. They pointed out how fast the processor was and I got the one with the built-in 16GB SD card. Having read the reviews, my biggest concern was that it didn't have a flash for the camera.

I know better now. It's the little things that make this such a pain to use. Things that must not occur to a reviewer in the short period of time he or she is using it.

Before I had this I had an iPhone 3G. I liked it. The browser was a bit slow compared to modern phones, it didn't have a compass so it wasn't great for navigation but it worked. There was a load of good quality software. I mean sure not everything in the Apple App Store is a gem but have you seen the Android Market? I'll take the curated experience thanks.

When I went to Android because I thought I'd be keeping all of what I had with the Apple and gaining better Google interoperability. It just isn't so. Samsung has made a powerful case for Steve Job's conjecture that you can't guarantee a quality user experience unless you provide the full hardware and software stack.

Is this completely one sided? No. Android's killer feature (compared to the iDevices) is the "back" button. I think that it's more than having a physical button, it's how the OS works but having a consistent way to go back to the previous app is a big thing and I miss it when I borrow my wife's iPad.

The freedom to choose install alternate input methods is also good (but not essential). Apple seem to resist that level of customization. Their "you don't need it" policy at work. Maybe if I'd bought an HTC Desire I'd be feeling better about the whole Android thing but Samsung have left me more than willing to give up some freedom just to get something that works.

What I find amusing is that Samsung sent a free Galaxy S to a few prominent twitterers who complained about the reception problems with the iPhone 4. I can only imagine that it was to make them appreciate how lucky they really were.

Thursday, November 25, 2010

Coding Karma's Gonna Get You

If you're writing a server based web application (in any language) and you're not following MVC principles, then please stop and go Google "Model View Controller".

I've recently inherited a site with pretty much no documentation and a mess of legacy PHP code with some Java and Perl thrown in. Am I having a good time? No, not really. What would have made it better?

Well, it's tempting to say documentation. If well written, that may help. An overview from a business perspective would have been really welcome. But even if I'd had that, it would help only a little to work out how the system itself works.

Every time I try to work out what's going on, I trawl through pages of procedural PHP interspersed with SQL queries to a non-normalised database. It's confusing and exhausting. Please don't inflict this on your successor.

Am I just whinging? Well...yes. But with a purpose. There is a certain amount of inherent complexity in any system but there's no need to complicate it further by not employing tried and tested techniques and mechanisms available to you. If you do, you're doing yourself, your employer and your successor a disservice.

Use frameworks people. I'd recommend Ruby on Rails. But if that's not for you, pick one that is. If your application displays a web page, takes some user input, accesses a database and displays another web page then please use an MVC framework.

Here's what a decent framework brings to the table:

 - DRYness. Don't Repeat Yourself. Copy and pasted code is annoying for the person who has to read it. Copy and pasted code is annoying for the person who has to read it.

For every request that comes in, your application will have to do certain things. Every time it accesses the database, there is a certain amount of common code that gets run. A framework's job is to implement this boiler-plate code and hide it so that your program consists of the things that differentiate it from every other web application.

 - Separation of concerns; If you're doing SQL queries in the same that generates HTML then (seriously) please stop coding now and do some reading. It's quite possible, and highly desirable to separate your CSS, HTML, Javascript, View, Controller and Domain logic into separate files.


 - Testing; Manually testing applications is expensive in terms of time. You really need a batch of tests that run every time you make a change to ensure that no existing functionality has been lost. The best time to write these tests is before you right the code. That's called test driven development and (done right) will save you and your users much time and frustration.

The fewer dependencies it has, the easier code is to test. If you need to setup a web server, database server, and an ActiveDirectory domain to test that your code works you're very likely not to do it at all. This was one of the reasons why separation of concerns (above) was desirable. The separate units can be tested individually without the overhead of bringing up a complete system. Your framework should provide tools and instruction in how to do this.


 - Convention; How much does it matter to you what you call the folder containing your controllers (that's the C in MVC)? Surely very little so long as:

 a. There is one and it only contains controllers.
 b. Its called the same thing and in the same place for every project.
 c. The next person to work on the project can reasonably be expected to identify it.

 - Business Continuity; Not only is the interchangeability of developers essential for the business, it's probably in your interest too. Do you really want to stay in this job forever? Do you really want to the be one person who can debug it? Your system will tie you down to it until someone eventually replaces it and you. A framework acts as a label in a job ad. Yes, I am a SpringMVC developer. Yes, I'm a Django developer. I understand the concepts and conventions employed by this framework. I know where to get help if I need it. I know that I can walk into that job and quickly understand your system.

 - Experience; If your framework is a good one, preferably developed over a period of time with many people in a meritocratic environment then the result will be far more refined than anything you could hope to achieve on your own. By all means, learn from first principles. It's good to understand the lifecycle of an HTTP request by writing a CGI script or even a PHP page. And when you're done, save it in a folder called "Learning" and start using a framework.

Friday, March 5, 2010

Missing images with JQTouch on Rails Production

It's generally a good idea to use the ":cache=>true" argument to stylesheet_link_tag to ensure that all your stylesheets are loaded in a single request in production. Eg:


= stylesheet_link_tag '/jqtouch/jqtouch.min.css', '/themes/apple/theme.min.css', 'mobile', :cache=>true

This can cause problems though if the stylesheet:
  1. References resources (such as background images) via relative URLs
  2. Lives somewhere other than public/stylesheets
The reason it's a problem is that the :cache=>true option causes stylesheet_link_tag to bundle all listed stylesheets into /public/stylesheets/all.css. Suddenly, every URL is relative to public/stylesheets.
I encountered this problem when using JQTouch in a Rails app.

The theme stylesheet for jqtouch was located in /public/themes/apple/ and it expected to find all images in an img sub-folder. This worked fine in development but in production, suddenly no images appeared.

My fix for this was simply to create a symbolic link in the stylesheets folder thus:

cd stylesheets
ln -s ../themes/apple/img img

This seems to do the trick, even on Heroku.

Ruby Dates to Javascript the Easy Way

Whilst writing the queue management for Cafebop in Javascript using the excellent JQTouch library I came across a problem that I thought would be trivial to solve. In the end it was trivial but maybe it's so trivial that nobody ever mentions it so I couldn't find any info on it.

Basically, I wanted to instantiate a Javascript Date object from a Ruby Date object via a JSON call. The problem is that Javascript's Date object constructor can't parse the default string output by Ruby's Date#to_s.

However, it can parse an integer which is milliseconds since the Unix epoch. Ruby's Date#to_i outputs the number of seconds since the unix epoch. So, using my mad arithmetic skillz, I figured I can create a Javascript Date with:

new Date(rubyGeneratedInteger * 1000);

So my usage of it went something like this. In my rails model, I generate an appropriate integer representation of the timestamp:



I make that available to a JSON client through the controller:

And consume it from the Javascript client thus: