Mobile Web Design

The article series Mobile Web Design may be over a year old, but with the current land rush for .mobi domains, it's even more relevant today. It comes in three parts: State of the Mobile Web, Methods to the Madness, Tips and Techniques .

TIOBE Index: This Month's Hot Languages are Ruby and D

In any career, it's a good idea to keep track of trends in your industry. This holds especially true in relatively young fields with rapid change, such as software development (consider that some of the most popular languages today — Java, PHP, Python, Ruby, Visual Basic, C# — were created only in the last decade).

One good resource for keeping track of programming trends is the TIOBE Programming Community Index, a monthly ranking of the 50 most popular programming languages. The index's rankings are based on “the world-wide availability of skilled engineers, courses and third party vendors” as well as search engine results.

In this month's index, the people at TIOBE have declared Ruby and D as the “hot languages of today” , with Ruby coming ever closer to a spot in the top 10 and D making a significant climb. Here's how the top 20 languages stack up for September 2006:

Position
Sep 2006
Position
Sep 2005
Delta in PositionProgramming LanguageRatings
Sep 2006
Delta
Sep 2005
Status
1 1 Java 21.532% -0.91% A
2 2 C 18.059% -1.10% A
3 3 C++ 10.753% -0.41% A
4 6 (Visual) Basic 10.627% +4.12% A
5 5 PHP 9.128% +0.23% A
6 4 Perl 5.430% -3.84% A
7 8 Python 3.144% +0.11% A
8 7 C# 2.992% -0.30% A
9 9 JavaScript 2.442% +0.67% A
10 10 Delphi 2.105% +0.43% A
11 11 SAS 1.933% +0.63% A
12 12 PL/SQL 1.038% +0.08% A
13 27 14 * Ruby 0.938% +0.65% A-
14 14 Lisp/Scheme 0.649% -0.07% B
15 13 COBOL 0.562% -0.29% B
16 30 14 * D 0.554% +0.32% B
17 19 ABAP 0.552% +0.16% B
18 21 Visual FoxPro 0.550% +0.21% A–
19 16 Ada 0.536% 0.00% B
20 18 Pascal 0.516% +0.04% B

Fun with the Kiko API and Ruby, Part 1

Introduction

If you've been meaning to write an application that interfaces with Kiko, our web-based calendar application, this article series is for you! Over the next little while, this series of articles will explore the Kiko API in depth. Since we'll be working with simple examples in the Ruby programming language, it's also an opportunity for you to take Ruby for a test spin if you haven't done so already.

What You Need

In order to work with the Kiko API, you need:

  • Ruby. It's “the new hotness” in programming languages, and the programming language in which Kiko was implemented. The library that we'll be using to use the API is written in Ruby as well (we'll put out libraries for other languages soon). If you don't have it on your system, download it from the Ruby site. If you need gentle and whimsical instructions for installing Ruby, I recommend the tutorial titled The Tiger's Vest.
  • A Kiko account. You can sign up for one at the Kiko site.
  • The Kiko Ruby library. You can get it here; save it into the appropriate Ruby “lib” directory as kiko.rb on your machine (on my Mac, it's in /usr/local/lib/ruby/1.8, on my Windows box, it's in C:\ruby\lib\ruby\1.8).
  • An API Key. You can request one from the Kiko API page; it will be emailed to you in short order.

irb, the Interactive Ruby Shell

Ruby comes with irb, the interactive Ruby shell, which lets you enter Ruby code and see results immediately. To start it, go to the command line and enter irb (I'm assuming that you've already installed Ruby on your system). You'll be greeted with a prompt that looks like this:


irb(main):001:0> 


irb is now ready to accept Ruby code that you type in. It never hurts to break in a new programming language with “Hello, world!”:


print "Hello, world!"


Ruby will reply with:


Hello, world!=> nil


irb first responded by printing “Hello, world!”, followed by “=>” and nil, which is the the return value of the print "Hello, world!" statement. irb always responds this way. For instance, if we assign the value 99 to the variable beers_on_wall, this is what happens:


beers_on_wall = 99
=> 99


If you'd like a good introduction to irb, see the tutorial The Tiger's Vest.

Arrays and Hashes

I'm assuming that you're a programmer, so I'll just cover those things in Ruby that might seem unfamiliar or Ruby-sepcific.

Ruby arrays are like arrays in other dynamically-typed languages: they're orded lists, they can be declared on the fly and grow or shrink as needed. Array literals are contained in square brackets. Try this in irb:


grocery_list = ["apples", "bananas", "chainsaws"]
=> ["apples", "bananas", "chainsaws"]


How can you be sure it's an array? Easy — use the class method to ask grocery_list what type of object it is:


grocery_list.class
=> Array


Like most programming languages, Ruby arrays are indexed by number, starting at 0:


grocery_list[0]   
=> “apples”
grocery_list[2]
=> “chainsaws”
grocery_list[1]
=> “bananas”


You can use the length method or its alias, size to see how many elements are in an array:


grocery_list.length
=> 3
grocery_list.size
=> 3


Ruby's Array class is pretty handy; I recommend that you check out the “Array” page in the Ruby documentation to see what it can do. Of course, if you'd rather have Ruby tell you what it can do, that's always possible, since all objects have a method called methods, which returns an array of all methods to which the object can respond:


grocery_list.methods
=> ["respond_to?", "delete_if", "index", "select", ...]


Every object has a methods method, and everything in Ruby is an object. Even the number 5 is an object:


5.methods
=> ["to_a", "%", "<<", "respond_to?", ">>", "divmod", ...]


The other data structure you'll use often in Ruby is the hash, which is an unordered collection of key/value pairs. Depending on which programming languages you use, you may know them as “dictionaries”. Hash literals are contained within braces:


person = {"name" => "Joey deVilla", "rank" => "Generalissimo", 
"serial_number" => "007"}
=> {"name"=>"Joey deVilla", "rank"=>"Generalissimo", "serial_number"=>"007"}


Accessing the contents of a hash is easy:


person["name"]
=> “Joey deVilla”
person["rank"]
=> “Generalissimo”
person["serial_number"]
=> “007″


As you might expect, hashes know that they are hashes:


person.class
=> Hash


…and you can get the number of items in a hash, using either the length or size method:


person.length
=> 3
irb(main):022:0> person.size
=> 3


You can request the keys and values in a hash, which will be returned to you in an array:


person.keys
=> ["name", "rank", "serial_number"]
person.values
=> ["Joey deVilla", "Generalissimo", "007"]


Appointments, Appts and ApptInstances

In Kiko, we refer to entries you stick into your calendar as appointments. The meeting you have scheduled for next Tuesday at 10 a.m., the concert you want to attend next week and your best friend's birthday — all of those are appointments.

For every appointment in your calendar, Kiko associates two objects with it: an Appt object and an ApptInstance object. Having two objects for each appointment may seem strange at first, but it'll make sense in a moment.

The easiest way to explain what the Appt and ApptInstance objects are for is to use an example. Let's consider two different appointments: a concert that you will attend next week and your best friend's birthday.

Let's consider the concert. It's a one-time only event. It will have one Appt object, and this Appt object will have one ApptInstance object associated with it, as shown below:

Now let's consider your best friend's birthday. It's a recurring event — there'll be one this year, one next year, one the year after that, and so on. Like the concert, it will have one Appt object. Unlike the concert, the Appt object will have several ApptInstance objects associated with it: one for this year, one for next year, one for the year after that, and so on, as shown below:

Simply put, an Appt object represents the appointment in general, while ApptInstance represents a specific instance of that appointment.

That's enough theory; let's actually use the API!

Let's Take the API for a Test Drive

First, a little setup might be required. If you've just signed up for a Kiko account, your calendar will be empty. Just so we'll have an appointment to fetch from the calendar, manually add an appointment and make a note of its date.

In order not to mess up your schedule, it's a good idea to set any appointments that you're using for testing the API in the past. In this example, I've created an appointment for the morning of January 1, 2006:

Now that there's an appointment in the calendar, let's read it programmatically. Go to the command line and start up the interactive Ruby shell, irb. The first thing you'll want to do is load the Kiko library by entering:


require 'kiko'


You send API commands to Kiko through an instance of the KikoSession class:


ks = KikoSession.new 'your api key', 'your username', 'your password'


The KikoSession class' initializer method takes three arguments:

  • Your API key
  • Your Kiko calendar username (optional, defaults to nil)
  • Your Kiko calendar password (optional, defaults to nil)

Only the API key is required, but providing your username and password specifies that the default calendar on which to perfom operations is yours.

Let's programmatically retrieve the data for the appointment you created moments ago. In my case, I want to get all the appointments I've made for January 1, 2006. I'd enter this into irb:


my_day = ks.appts '2006-01-01', '2006-01-01'


The appts method retrieves appointments for a specified date range. It takes three agruments:

  • A start date
  • An end date
  • A username (optional, defaults to the username you provided when initializing the KikoSession object)

The appointment data returned by Kiko is now stored in my_day. Let's see what data type it is:


my_day.class
=> Hash


A hash, eh? Let's see what its keys are:


my_day.keys
=> ["ApptInstance", "Appt"]


Those keys should be recongnizable: their names are the same as the two types of objects that are associated with an appointment. Let's look at the my_day["Appt"] object first:


my_day["Appt"].class
=> Hash
my_day["Appt"].keys
=> [510205]


(Of course, when you check my_day["Appt"].keys, you'll probably get a different number than the one shown above.)

Let's see what's my_day["Appt"][510205] is and what's in it:


my_day["Appt"][510205].class
=> Hash
my_day["Appt"][510205].keys 
=> ["created_on", "date_only", "title", "attendees", 
"recur_rule", "updated_on", "id", "website", "description", 
"visible_to", "end_time", "location", "start_time"]


From the looks of it, we've finally reached the Appt object for our hangover recovery session scheduled on January 1, 2006. Let's get a look at the data:


my_day["Appt"][510205]     
=> {”created_on”=>Thu Sep 28 00:52:44 UTC 2006, “date_only”=>false, 
“title”=>”Recover from hangover”, “attendees”=>{513993=>{”user”=>{”company”=>nil, 
“created_on”=>Mon Sep 25 02:47:33 UTC 2006, “home_fax”=>nil, 
“job_title”=>nil, “last_login”=>Thu Sep 28 00:50:25 UTC 2006, 
“name”=>”Tucows Example”, “work_phone”=>nil, “home_mobile”=>nil,
“language”=>nil, “first_day_of_week”=>0, “timezone”=>nil, 
“work_fax”=>nil, “id”=>102572, “work_mobile”=>nil, “birthday”=>nil, 
“european_style_dates”=>false, “home_phone”=>nil, “pager”=>nil, 
“twenty_four_hour_time”=>false, “webpage”=>nil, “home_address”=>nil, 
“login”=>”tucowsexample”, “work_address”=>nil}, “accepted”=>2, 
“appt_id”=>510205, “created_on”=>Thu Sep 28 00:52:44 UTC 2006, 
“service_login”=>nil, “updated_on”=>Thu Sep 28 15:51:37 UTC 2006, 
“contact”=>nil, “contact_id”=>nil, “id”=>513993,
“owner”=>true, “user_id”=>102572, “labels”=>{}, “invited_by”=>nil, 
“service_login_id”=>nil}}, “recur_rule”=>”", 
“updated_on”=>Thu Sep 28 00:52:44 UTC 2006, “id”=>510205, 
“website”=>”", “description”=>”", “visible_to”=>1, 
“end_time”=>Sun Jan 01 12:00:00 UTC 2006, “location”=>”", 
“start_time”=>Sun Jan 01 11:00:00 UTC 2006}


That's a lot of data to look at. Let's thin it out a little by referring to the list of keys we got earlier and using some of them to retrieve the most basic calendar information: the name of the appointment, when it starts and when it ends:


my_day["Appt"][510205]["title"]
=> “Recover from hangover”
my_day["Appt"][510205]["start_time"]
=> Sun Jan 01 11:00:00 UTC 2006
my_day["Appt"][510205]["end_time"]
=> Sun Jan 01 12:00:00 UTC 2006


Let's take a look at the my_day["ApptInstance"] object now:


my_day["ApptInstance"].class
=> Hash
my_day["ApptInstance"].keys 
=> ["510205_2006-01-01"]


Note the name of the key: 510205_2006-01-01. 510205 was the key corresponding to the Appt object, and 2006-01-01 is the date of the appointment.

You've probably inferred that if we change our hangover recovery appointment into a recurring one (and why not? New Year's Eve happens every year!) and if we fetch several years' worth of appointments, we'd see more ApptInstance objects with keys like 510205_2007-01-01, 510205_2008-01-01 and so on.

Let's get a closer look at this object:


my_day["ApptInstance"]["510205_2006-01-01"].class
=> Hash
my_day["ApptInstance"]["510205_2006-01-01"].keys 
=> ["appt_id", "all_day", "orig_date", "id", "is_exception", 
"end_time", "start_time"]
my_day["ApptInstance"]["510205_2006-01-01"]     
=> {”appt_id”=>510205, “all_day”=>false, “orig_date”=>#<Date:
4907473/2,0,2299161>, “id”=>”510205_2006-01-01″, “is_exception”=>false,
“end_time”=>Sun Jan 01 12:00:00 UTC 2006, 
“start_time”=>Sun Jan 01 11:00:00 UTC 2006}


As you've probably guessed, the appt_id key gives you the ID of the Appt object that this particular ApptInstance belongs to.


That's all for this session. In the next article in this series, we'll look at the other things you can do with the API, namely creating, updating and deleting appointments.

BusinessWeek on .mobi Domains

BusinessWeek's article, A New Wave of Web Addresses, attempts to answer this question about .mobi domains: “Who's signing up, and why?”

Steve Yegge: "Good Agile, Bad Agile"

Over at Steve Yegge's blog, there's an article titled Good Agile, Bad Agile that's been getting a lot of attention for a couple of reasons. First, there's Steve's assertion that agile methodologies aren't; second, he describes what working at Google is like, and it sounds like a developer's wonderland. Steve's writing style, which I find funny, is a bonus.

Speed bumps indeed…

I’ve received the odd mention in the press – usually some obscure point about an irrelevant Internet governance or technical policy issue. I never expected to get any attention from the hardcore IT press for anything of technical substance – good, bad or otherwise. Having recently assumed responsibility for managing the retail aspects of the Mailbank business portfolio, I guess all bets are off now…

Based on messages being sent out from Tucows, the migration process has hit several speedbumps.

- via ITworld.com.

Joel Shore, the author of the article, goes on to nail the source of of our problems square on the head. My planning process was rushed, which lead to corner cutting, which lead to mistakes and problems and a decreased focus on getting the quality equation just right. This lead to avoidable mea culpa’s on the retail network status page and our customer bulletins – which eventually lead to Joel’s article.

The good news is that the fixes are well underway and ahead of schedule. The bad news is that we could have used the time spent fixing these issues on more productive activities – not to mention completely avoided invoking the wrath of our customers and Joel’s unflattering attention.

Take the time to dot your i’s and cross your t’s. Your customers will thank you for it.

For some more detail on the issues we’ve run ourselves into, you can check out our customer blog where I’ll be posting some more information the steps we’re taking to improve our quality control processes over the coming days.

(speaking of QA, when I clicked on the link on the ITworld website to send a copy of the article to the folks here at Tucows, here’s the response I got from their webserver  – click the thumbnail for a full view)

Itworld-error

(originally posted at http://www.byte.org/blog/_archives/2006/9/27/2367434.html)

Business Blogs and Customer Connectivity

WebProNews has an article titled Business Blogs and Customer Connectivity, which looks at the characteristics of sucessful business blogs. It says that many of the best “b-blogs” (business blogs) provide their readers with a look at the:

  1. Company represented.
  2. Individual heading that company.
  3. News that affects the company and its customers.
  4. Links that may be beneficial to the customers.
  5. Personality behind the logo.

.mobi News Roundup

John Battelle Interviews Matt Cutts

Over at John Battelle's Searchblog, there's an interview with Google's Matt Cutts (whose SEO tips we profiled in this article). In the interview, Cutts — “the human voice between Google and webmasters/SEOs” — talks about his role at Google, humans and algorithms at Google and what is considered webspam.

7 Things You Need to Know About Ajax

Don Hinchcliffe says the Seven Things Every Software Project Needs to Know About Ajax are:

  1. The Browser Was Never Meant For Ajax.
  2. You Won't Need As Many Web Services As You Think.
  3. Ajax Is More Involved Than Traditional Web Design and Development.
  4. Ajax Tooling and Components Are Still Emerging and There Is No Clear Leader Today.
  5. Good Ajax Programmers are Hard to Find.
  6. One Must Actively Address Ajax's Constraints of the Browser Model.
  7. Ajax Is Only One Element of a Successful RIA Strategy.