Monday, August 27, 2012

Long time, no see

Wow. My last post here was over a year ago. Surprisingly, this blog is chugging along with its couple-of-hundred hits per day even now, thanks to all the Google-juice!

My last post was about Aceseller. A bunch of stuff has changed since then, and undoubtedly it's time for an update. ("Undoubtedly" in the sense that someone might probably care about it, but more importantly because I need this stuff documented.)

Aceseller was (and still is) an excellent idea. We just didn't have enough juice to make it work. By juice I mean several things. But let's not mull over that - in the scheme of things it isn't relevant. It's an idea that's up for grabs for a team that's more capable than we were. It will definitely make a bunch of people rich, while making a significant dent in how business is done in India. I'm still excited about the idea, as should anyone who ventures into this space. It's crazy cool! If you have the know-how to make it work, get in touch! (I'll likely crush your sprits though.)

However, due to several reasons, we had to call it quits. Everyone else in the gang went back to their jobs. Big blow. I decided to give it one more shot - this time solo - with Errorception. Turns out, it wasn't such a bad idea.

Errorception has been doing very well, but it didn't look like that for a long time. I went broke by the time I launched Errorception (the ~5 months of savings spent on Aceseller didn't help), and was forced to take up odd consulting jobs to be able to support myself. I have been adamant about not having co-founders or taking funding - I didn't want to substitute one form of slavery with another. Errorception isn't perfect yet - I don't know how anyone can call their product "perfect" with a straight face - but it's getting better everyday. I've been blogging about Errorception on the Errorception blog on a some-what regular basis. What I thought was an uninteresting space to be in turned out to be fiercely competitive and surprisingly fast moving. It has kept me on my toes.

So that's my update. It has been an exciting year, and it promises to get better. Here's to more exciting times!

PS: This is the third time I'm saying it on this blog, but I'll say it anyway: This blog isn't dead. I've got a lot to share, and I've got a lot of exciting things lined up for the future, and only this blog is the appropriate place to write about it. So, watch this space!

Tuesday, June 07, 2011

Announcing AceSeller.com

It's been some time now that I've been working on solving an interesting problem, and I think it's time to start talking about it.

AceSeller.com is a cloud-hosted service that aims to make it real easy for businesses to start selling products on their websites. It is targeted at small and mid-sized businesses that want to start selling online, but don't know how to. It is, from what we've seen, already the simplest to use and cleanest application that does this.

I'm doing this together with Sandeep Shetty and Jinesh Mehta. Between the three of us, we've got a great deal of experience with almost every aspect of running ecommerce sites. We are good friends, have tremendous respect for each other, and share a common passion for technology, simplicity, great user experiences and online businesses. This passion has already started reflecting in AceSeller.

We're working very closely with some businesses who have agreed to use our platform for launching their web-stores, and we are very excited about the great feedback we've been getting. One of these stores has already gone live on the AceSeller platform and is already processing orders, while several more are in the pipeline.

AceSeller is currently not open for sign-ups. We are working fervently on getting the little details right. However, if you want early access to AceSeller, please leave your email address with us, and we'll get back to you as soon as possible.

Our plans with AceSeller are huge. We've barely scratched the surface of what we want to offer, and this post doesn't do justice to even that little bit that we've already accomplished.

The amount of things we've learnt over the last couple of weeks alone is tremendous; I can't wait to start sharing that knowledge. There's so much to talk about - everything from the challenges we've faced in getting businesses online, to the user experience we want to provide, to how our technology choices came about and how we managed to race ahead to get AceSeller live. I'll keep churning out more details as frequently as possible. Stay tuned.

Tuesday, May 10, 2011

Thoughts On Taking the Entrepreneurship Plunge

tldr; Jump to the bottom ↓

I found myself at a time in my career when I had to look back and reflect, and decide what I want to do next. Remain an employee? Or leave it all and become an entrepreneur. It's hard to make purely logical decisions about these things, in part because your life and well-being might be affected, but mostly because you need to make projections into the future and the future presents itself as a hazy picture at best. A lot of this decision is based on gut feel. This post outlines my thoughts.

Financial aspects

This was obviously the most important thing that I was thinking about. Salaried jobs give you a decent amount of financial stability. This is in sharp contrast to starting up, which has near-zero financial security, at least at the outset.

However, financial growth in a salaried job is not in your control at all. Your salary increments depend on a lot of factors: What is the industry standard paycheck being given out, what's the salary of your peers and bosses, what's the revenue of the company, what's the funding status of the company, etc. Yes, your performance does matter, but even with excellent performance you have an abysmal salary increase every year. What's worse, no boss will ever tell you that your performance has constantly exceeded all set expectations. They'll always find some cop-out; things like: "Your performance has been good, but you should take on more responsibility."

That's an awfully bad deal — the factors that affect my financial growth are not in my control, good performance pays very little, and there are text-book methods to even reduce the payout for excellent performance! I've tried fighting this at all my past jobs, and I've always lost. It's a system designed to make you lose every time.

It's very easy to take this negatively. When you realize that your performance doesn't matter anymore, the quality of your work suffers. You start going to work simply because you are obliged to. You start hating Mondays, and look forward to Fridays.

I am not like that though. More than anything else, I have a strong primal urge to create stuff. I never let my obviously slow and completely-out-of-my-control financial growth affect my quality of work. Fortunately, this kept me in the good books of my bosses and my employers at all times. That makes everything fine, right? It does, except when you stop to think: Where is all this going?, and discover that you don't really know. You realize that if you could instead use your zeal, energy and passion elsewhere where the promise of financial growth is higher, you could maybe make a lot more money for the stuff you are doing.

May be, I should start up.

Of course, the promise of financial growth is just that — a promise. There's a huge possibility that it will not work at all, and I will have failed. But then I realized that if I fail, it'll be of my own doing. It will be my mistake that stalls (or negatively impacts) my financial growth. That's a lot more control than I've been used to! I only need to be able to learn from my mistakes and change what I'm doing wrong quickly enough. I should be very cognizant about what might be mistakes, and reduce possible risks from those mistakes. Easier said than done of course, but at least I would be in control.

Creating something

Let's now talk about that primal urge to create that I mentioned above. It's one of the reasons I work with technology — it's very easy to create things seemingly out of thin air, with very little effort at nearly no cost. It's an awesome feeling when you build something and watch the world use it. This, I now understand, is why programming is argued to be an art — you are always creating. I have that creative urge in me, and I intend to never let go of it. It's the single most important character trait that I will treasure and nurture.

So, how do you create stuff when you are an employee? Turns out, it's nearly impossible. Firstly, there are the business goals of the company, and you have to align personal goals with business goals. For most people, personal goals just means making money. But that's not the case when your biggest passion is to create things. What it means then is that you have to compromise. You end up doing things that might not be fun to do, because the business requires it. Like most other people, this is what I have been doing.

Secondly, on those occasions when you do get to create, you are not in control of the decisions taken. There are several stakeholders in practically anything you do. Their opinions have to be factored in as well. By itself, the idea rocks — creating stuff is a form of collaborative art in some sense. However, in practice it never ends up that way; people's egos, unclear vision, different motivations, etc. get in the way of the quality of the product. You end up creating something that is not as good as it could be.

So, creativity at work practically doesn't exist. As a creative person, how do you deal with this? What I used to do was wait to get back home, and then I'd work on my own little side projects. Most of these projects have never seen the light of day. There have been all kinds of projects I've worked on on the side over the last couple of years: creating protocols, implementing protocol clients, writing some funky server-modules, and building stuff on the bleeding-edge of web tech. These products were meant to be given out for free, and I could've built a business model around it in the future if I wanted to. Actually, it didn't even matter that I didn't get these live; I was happy enough to have satisfied my urge to create. On some days, I have found myself working on my side projects till the wee hours of the morning, getting very little sleep, spending time at work because I had to, only to come back home and continue having fun on my side projects till the morning. It was exhausting, but I enjoyed it because I could finally create.

Starting up

If I could channelize this energy, focus on something that can actually see the light of day, and get it to generate enough revenue for me, I could maybe survive on this. I'll be working just as hard, and will have more fun doing it.

It's an unsettling thought process that's been eating into me for several months now, and I've been meaning to act upon it. I've been discussing this with several people, and there's a lot I've learnt. There are several factors to be considered and risks involved. It hasn't been an easy decision. I would be leaving my cushy job to take on what would be my biggest risk ever. And then I realized something.

Starting up is not a risk at all.

What is the worst that will happen? Even if I fail, I'm only losing my financial security. That's a reasonably easy problem to fix. I could always take loans from friends and family. Or I could secure investment to buy me more time. I'd have to have a revenue model that will start generating money from get-go, and that in itself will reduce the risk significantly. There are several solutions, but the fact remains that it's an easy problem to fix. If all else fails, I'll still be at least as employable as I am right now. I'd end up doing a salaried job like I have been doing, as much as I wouldn't like it.

The worst that will happen is that I'll end up where I am right now. That's hardly a risk!

Last Friday was my last day as an employee. I've never been more anxious and excited. I've finally taken the first steps towards doing what I wanted to always: fully control my financial growth, create what I want the way I want to, and do this at minimal risk of my financial security. At the risk of sounding overly dramatic: last Friday was the first day of the rest of my life.

Watch this space for more announcements coming soon!

Friday, January 21, 2011

The Impact of HTML5^H: Feature Detection

Ian Hickson posted a day or two ago that the WhatWG has decided to drop the version number from HTML. On the face of it, it seems like a knee jerk reaction to fight an old rival that just announced the HTML5 logo, but it's a lot more than that. In Hixie's words:

The WHATWG HTML spec can now be considered a "living standard". It's more mature than any version of the HTML specification to date, so it made no sense for us to keep referring to it as merely a draft. We will no longer be following the "snapshot" model of spec development, with the occasional "call for comments", "call for implementations", and so forth.

What does this mean for us developers? It means that the spec will never be finished — the living standard bit — so there's no point waiting for an announcement saying that HTML5 is ready or anything to that effect. But that's just on the surface.

For front-end developers it means one more very important thing. It means that feature detection is more important than ever before. It'll be the only reliable way for us to determine browser support for features. Of course, we always knew that but rarely did we ever practice it. You think you might have, but the libraries you have been using didn't actually do this. Until very recently that is. jQuery removed all browser sniffing in jQuery 1.3 and the guys from Dojo have launched a project called has.js meant for library authors to incorporate feature detection. Of course, Modernizr has been around for a long time now, and its list of detectable features keeps growing.

But detecting features alone isn't enough. You need a way to work around them. This is where polyfills come in the picture. As Remy Sharp describes it,

A polyfill, or polyfiller, is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively. Flattening the API landscape if you will.

That way, feature detection happens at a lower level than the developer, and the developer can continue coding to the WhatWG/W3C specs. If this works as well as it says on the can, I think we can all move forward, and not worry about little pains like IE6.

What are the factors to be considered when creating a way to download a polyfill? The first is that there has to be a way to declare a dependency on a browser feature. Depending on browser feature detection, one or more polyfills might be downloaded for that browser. Secondly, the download of the polyfill will necessarily be asynchronous and the coding paradigm will have to take that into account. Thirdly, ideally the download of the polyfill itself shouldn't slow down the experience. This is impossible to do, but at least we should employ whatever techniques we have to reduce the impact of the download.

How would such an API look? CommonJS has been doing some great work with the Asynchronous Module Definition spec to help solve the general problem of dependencies in JavaScript. Maybe we can look at their API for help. To define a module, you'd generally write code that looks like the following (from their own example):

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
exports.verb = function() {
return beta.verb();
}
});

That looks simple enough. The first parameter of define is the name of the module, the second is a list of external dependencies that the module has, and finally it's the declaration of the module itself. Using RequireJS, the way to use such a module would be, (again, from their own examples)

require(["helper/util"], function() {
//This function is called when scripts/helper/util.js is loaded.
});

That's a simple enough API. Unfortunately, we can't use this directly for our polyfills, since we'll need to only download the dependencies if the browser doesn't already support them. So, maybe for our purposes, we'll need to have an API that looks like this:

require(["our/polyfill/helper"], function() {
requirePolyfills(["localStorage", "geolocation"], function() {
// Polyfills have been downloaded and applied now if necessary.
// We can code straight to the WhatWG/W3C APIs without worrying about browser differences.
});
})

The requirePolyfills function is responsible for downloading the polyfills necessary depending on browser support in an async manner, and then calling the function passed in to hand over control to the developer. The developer then doesn't have to worry about browser differences and can write simple code completely devoid of browser specific hacks. It gets me excited just to think of how awesome it will be to program once we've got browser differences out of the way.

Taking this a level further, this could be done by library authors itself, to ensure that the footprint of the library is as small as possible. This way Chrome users will have an excellent experience since there's no polyfill to be downloaded, while IE6 users will have the worst experience since many polyfills will have to be downloaded. If you think that's worse than the state of affairs today, consider that Chrome users currently have to download all the browser hacks for dealing with IE6 that exist in the library, and then the code-path never hits them. Wasted download, and the worst possible experience for all users thanks to IE6.

Libraries are slowly migrating towards the CommonJS AMD spec. Dojo just announced partial support for it in their latest version. The landscape is bound to get better. If polyfills were to be part of the library itself, it would be awesome. That way, we ensure that the library has the smallest footprint possible.

That leaves us with two more problems. First: we need to develop a public repo of polyfills that are very well tested. The quality of polyfills is not something that library developers should be fighting over. Also, there's no reason for a polyfill to be tied into a library's APIs. And there's no reason why one shouldn't be able to use a polyfill without a library. The second problem is slightly more tricky. The problem is that of network latency. You wouldn't want to download a bunch of polyfills over slow network connections. Ideally, it should be just one file containing all the polyfills required for that browser. This might necessitate a change the API I've mentioned above. Feature detection obviously happens on the client, but then the client issues only one request for the polyfills file. The request could look something like: http://example.com/polyfills?include=localStorage,geolocation. The server basically just concats the polyfills the client has requested, and sends them down in one file. Awesome.

Unfortunately here I've added a server component which suddenly makes this far less appealing to library authors, and for good reason. I don't know of a clean way to fix this, except saying that there should be publicly maintained servers that do this for everyone. Something like Google's CDN. This solution isn't ideal for several reasons, but it might be a good stop gap. Of course, there's also the possibility that open source implementations of such polyfill servers can be developed for several languages, maybe even just web servers — I'm thinking mod_polyfill or something similar.

The best solution is not clear yet, but we have an idea of what it might look like. We'll have to see how things evolve in the coming few months to get clarity on this. Meanwhile, what do you think about this? Do you think there might be a better way to solve this problem?

Saturday, October 16, 2010

Practical CSS3 Media Queries and Mobile Browsers

tl;dr: Jump to the end of this post ↓

I've been working on-and-off on a little project on the side, and have been trying to make it as buzzword-compliant as possible, because, you know, that's what all the cool kids are doing. Making it buzzword compliant meant that I had to use persistant connections to the server for real-time data exchange, use non-blocking I/O, I just had to use node.js, and throw in generous portions of NoSQL. So I did all of that, and now my server is worthy of a new starburst sticker.

Now that the server was mostly ready, I shifted attention to the client. Clearly, I had to use HTML5 and CSS3, think heavily about Web Performance Optimization, and ensure that the usability trolls don't get a chance to make me look bad. That was the easy part, since I have been doing these things for years. The fun started when I decided to flirt with an idea I had never played with before.

The Mobile Web

Mobile devices, it seems, have finally arrived. We have forever dreamt of an always-connected world, and mobile devices seem to be delivering on that dream. Indeed, we are on the verge of having more traffic from mobile devices to the web than from desktop browsers[citation needed]. In such a scenario, it's impossible to ignore mobile devices.

The problem is that no one knows what the mobile web means. In such a case, it's absolutely fine to interpret it the way you want to, and that's what I did. So, here's what the mobile web means to me.

The mobile web is that part of the web that works well on mobile devices.

Pure genius of a definition, isn't it? I know. Thank you. There's an ambiguity in the definition there though — what does it mean to work well? Turns out, no one knows that either. But there are some hints:

  • It should work fine in the mobile browser — no native apps, no downloads.
  • Context is king. The site should provide the right amount of data that is needed in a mobile user's use-case at that time.
  • The site should be touch friendly, meaning take care about hit areas and stuff because some people have fat fingers. Not me — my fingers are beautiful. Just thought you'd like to know.
  • Lightweight and fast. Because I want my data quickly, and I'm paying by the byte. This is true of the desktop as well, but especially true of the mobile web, because network operators try to suck as much as possible out of the wallet by giving as little as possible.

So, how do we go about building such a site? Generally speaking, this necessitates building a separate version of the site just for mobile browsers. Trust me, this effort is worth it. Don't believe all those standardistas who say change your CSS file, and everything will be magically fine. Their latest mantra is use CSS3 media queries and everything will be magically fine. Like most other things in life, nothing is that simple.

But there are times when that actually works. And this post is about those times. This post is only useful if:

  • Your site is already light enough and tightly focussed enough that the markup for your desktop version is going to be the same as that of your mobile version.
  • There's not really too much contextual data you need to provide to your mobile users, so again the markup is the same.
  • Your site is styled primarily with CSS. You are doing that already, aren't you?
  • You are lazy, and don't want to create multiple versions of the same content, otherwise known as maintainability or code reuse.

I'm definitely lazy, and I'm proud of it. I'd rather not write any code at all. If I have to write any code whatsoever, I'd rather write it such that (a) I never have to look at it again, (b) I keep using the same thing over and over again so I don't write the same thing ever again, and (c) I should write as little as possible. Fortunately, these are all considered good practices — maintainability, reuse and conciseness. I bet whoever said these were good practices was lazy. But as long as the rest of the world doesn't find out, this can be our little secret.

There's a problem with being lazy though. You have to work hard to be lazy. How ironic is that! And hard work is, well, hard. So, there's where I was, wanting to be lazy, tinkering with the idea of the mobile web, and looking at CSS3 media queries from the corner of my eye. Being lazy, before I wrote a single line of code, I wanted to know everything about challenges for mobile phones and media queries. I'll cut a long story short, and tell you my findings.

  • There's no standard screen size for the mobile. If you plot a graph of mobile screen sizes, the graph is going to be all over the place. That basically means you have to design for all screen sizes! This is going to be fun. Not.
  • Media queries let you target styles to different ranges of screen sizes. Awesome. Seems like a right fit for the job. So, we can have a different CSS file targeted to small screens, a different ones for medium sized screens (like the iPad), and the full of crap ones for desktop browsers. Neat. Except...
  • CSS3 media queries don't work in most mobile browsers and IE! Bam! Just when we thought we had a solution. Well, to be fair, it does work in some mobile phones — the iPhone's and Android's WebKit browsers being good examples, but both these browsers put together are such a small percentage of mobile users, it's not even funny. Blackberry's horrid browser, Opera Mobile and Symbian's native browser have the largest market share of all mobile browsers. We can't just ignore them, can we! Just like we reluctantly show love to IE, we'll have to show some love to these browsers as well. It's that kind of a relationship. (BTW, I think Opera Mini does support CSS3 media queries. I haven't tested this.)

So, I was going to throw the idea of media queries completely out the door, you know, baby and bath water and all that. This is when I saw an excellent talk by Luke Wroblewski. What he is advocating is that we should build for mobile sites first, and for desktops later. His arguments are mostly non-technical and about usability, design and innovation, but he underscores the importance of designing for the mobile. I get that, but it doesn't help me be lazy. Well, it could, but I didn't know how. It still looked like double the effort. Except, he had planted an idea in my head. You know, much like Inception. Come to think of it, Luke does look a little bit like DiCaprio, doesn't he? Cool!

Mobile First

So far, I was thinking of making separate CSS files for mobile and desktop, and doing so in parallel. That mostly meant I'd do the desktop version first, and the mobile version next. Then I'd target different screen sizes with media queries (which I discovered wouldn't fly) and voila it would work everywhere. Instead, Luke's talk got me thinking: what if I design for the mobile first, and then target desktop browsers with media queries. This would theoretically work, since most mobile browsers are old, and they get the vanilla CSS files. For newer mobile browsers and most desktop browsers since they are new as well, I'd serve the full css file targeting them with media queries. Newer mobile browsers will understand it's not for them, so they'll ignore it. Older mobile browsers won't understand it at all, and hence ignore it. Most desktop browsers would know that the CSS file is for them, and hence apply it. This leaves our old nemesis Internet Explorer, but we're used to that already. We'll solve that problem later.

Now, about actually pulling it off. I found this document at Dev.Opera that goes into a fair amount of detail about media query parsing differences between browsers, old and new. This doc would definitely help. Now, I needed to figure out how to structure the CSS. Remember my laziness? This meant that there should be as little repetition between the mobile version and the desktop version. What would generally be the things that remain common across the two types of browsers? There's actually quite a bit. There's color schemes, there's some type information, and possibly some CSS niceties like rounded corners, gradients and effects. What's going to be different? It's mostly going to be font-sizes and layout. Sounds good so far, let's start implementing it.

The code

Since we've decided to work only with mobile browsers first, and serve it CSS like it's the 1990s, the following markup should do it.

<link rel="stylesheet" type="text/css" href="narrow.css" />

I actually went ahead with this and built the whole mobile version of the site, and tested it in Mobile Webkit on Android and iPhone and in Opera Mini, which are the two browsers I had access to on a couple of devices. I kept the layout fluid, since I didn't know the screen size before hand, and didn't want the site to break in screen sizes I didn't have control over. I strongly recommend that you go with fluid width layouts for narrow screens as well. I even tried it in a couple of emulators and it all looked fine. Of course, some of the fancy CSS rules didn't work on some browsers, but that was ok — things still looked reasonably pretty and it looked mobile-web-optimized. Awesome. Now, I turned my attention to the desktop. This was when the Dev.Opera doc came in handy. This is what my markup looked like:

<link rel="stylesheet" type="text/css" href="narrow.css" />
<link rel="stylesheet" type="text/css" media="all and (min-width: 400px)" href="wide.css" />

See that media attribute there that says media="all and (min-width: 400px)"? That's the media query. It means target this CSS to all media that have a min-width of 400px. Why all media? Because I was being lazy and didn't want to work on a print version at the moment. Also, it seemed like the most reliable media type to target from Opera's documentation. Why base this on min-width? Because that's the best way to target different device sizes. Why 400px? Because in portrait mode it would apply the narrow.css (screen widths are generally 320px for devices that support orientation), but in landscape mode or for most desktop browsers, it would apply the wide.css file. This suited me, since I wanted to utilize the extra width in landscape mode better. YMMV, and you should play with this number to suit your tastes.

Also, since I was applying both the files and hence cascading their rules, I could already go with most of the stuff defined in narrow.css. wide.css only had to override some properties — mostly font sizes, block positioning and layout. Tested this, and it continued to work with all the mobile devices I was testing in as it was before, and worked on desktop browsers with the wide.css layout. I just had to add a few extra divs some HTML5 semantic markup to get some extra styling hooks. Success! And I'm continuing to be lazy since I'm reusing as much code as possible. There is a disadvantage to this technique though. It requires the download of two files. I could have combined them into one file, but that would've introduced some hacks as described in the Dev.Opera document. I am consoling myself by saying that wide.css is actually a very small file, and CSS files are downloaded in parallel anyway, so the impact shouldn't be huge. But that said, it is something to think about.

Wrapping it up

That just leaves us with one beast — the old nemesis — Internet Explorer. We've gone through all this trouble to support all sorts of crappy old mobile browsers, it only makes sense that we don't leave IE behind. Now, IE doesn't understand media queries, so how do we serve it wide.css? Turns out, we can use IE against IE, thanks to it's own conditional comments! The final markup looked like this:

<link rel="stylesheet" type="text/css" href="narrow.css" />
<!--[if lt IE 9 ]>
<link rel="stylesheet" type="text/css" href="wide.css">
<![endif]-->
<!--[if (gte IE 9)|!(IE)]><!-->
<link rel="stylesheet" type="text/css" media="all and (min-width: 400px)" href="wide.css">
<!--<![endif]-->

Let's dissect that. Firstly, serve the old narrow.css the way it was being served. No change there. Next, detect if the browser is IE and the version is less than 9. Why 9? Because MS is promising that IE9 has got media query support, so we'd rather use that over blindly serving the file to IE. If it is less than IE9, serve it wide.css no questions asked. If the IE version is 9 or greater, or if it's a non-IE browser, serve it wide.css with the media query.

This post is bound to be outdated before it's even out, since MS is launching Windows Mobile 7 or whatever it is called with a very uninteresting version of IE which is purportedly somewhere between 7 and 8. But I don't know yet how the browser is identifying itself, and hence can't exclude wide.css from it. If you find out, please leave me a comment, and I'll update my post with your findings.

In the end

We've successfully managed to:

  • Target mobile phones, new and old.
  • Match device orientation for newer phones.
  • Apply different CSS to desktop browsers.
  • Get it working even for the thing that is IE.
  • Keep Luke happy.
  • Done all of this without using any pesky JavaScript or server-side UA sniffing.
  • Continued to be lazy.

This has not been without drawbacks:

  • Two CSS files are downloaded to wide clients. To make things worse, some parts of narrow.css are overridden in wide.css, making the double-download even more painful.
  • Mobile IE gets the wide version, mostly because I don't know too much about it.

This works for me for the moment though. Would love to hear your thoughts.


Like this post? I blabber on a lot about this kind of stuff on the twitters. Follow me there if you like.

Sunday, April 11, 2010

Section 3.3.1 of iPhone SDK License Agreement

It has been an interesting week for iPhone developers. iPhone just released the developer preview of the iPhone OS 4, which has got features that are exciting to both developers and users. However, John Gruber discovered that Apple made a change to their iPhone SDK Licence Agreement with this release.

3.3.1 — Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs. Applications must be originally written in Objective-C, C, C++, or JavaScript as executed by the iPhone OS WebKit engine, and only code written in C, C++, and Objective-C may compile and directly link against the Documented APIs (e.g., Applications that link to Documented APIs through an intermediary translation or compatibility layer or tool are prohibited).

This amendment has far-reaching effects. The effects are so powerful that the FUD surrounding it over-shadowed the excitement of the OS upgrade itself. There's no doubt that there's evilness in this amendment to the ToS. The question is what part of it is evil, and how should we react to it. Let's analyze this amendment, and see what it potentially means.

On APIs

Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs.

This seems reasonable to me. It's Apple's platform, and they expose a bunch of APIs, and they only want developers to use those APIs. However, it stinks of potential anti-trust cases. However, this is not what got people pissed off for, so let's skip past this statement.

On language of choice

Applications must be originally written in Objective-C, C, C++, or JavaScript as executed by the iPhone OS WebKit engine, and only code written in C, C++, and Objective-C may compile and directly link against the Documented APIs

This is plain stupid, and only serves to push developers away. Everyone knows that the choice of programming language hardly matters in any meaningful way, and what the developer is comfortable with is what s/he should ultimately use. This clause doesn't allow for that, and there's no good reason why it shouldn't. Just plain stupid.

This kills the soon-to-be-released CS5 Flash-to-iPhone compiler, the MonoTouch project which compiles C# and .Net to the iPhone, and the Unity3D project that let you program 3D games in C#.

However, also consider that without asking you for your source code, how can Apple guess which programming language you used for development? It's all compiled anyway. It just doesn't make sense. I don't see how Apple can enforce this. We'll have to see how this develops.

On compatibility layers

(e.g., Applications that link to Documented APIs through an intermediary translation or compatibility layer or tool are prohibited).

This is the big one, and is the reason most people are pissed off, because it's implications are far reaching.

Firstly, consider the case where I want to build an iPhone app using Ruby, and I use a library that has wrappers on top of the Objective-C APIs. This is like the point above, where I should be able to choose my language and program in it. And like I said above, there's no reason to restrict this, and it's stupid on Apple's part to do this.

The other case is that of compatibility layers, where I code to an API much like above, but the compiler is designed to cross-compile to multiple platforms, not just the iPhone. This is the big one, and is what makes the future of platforms like Titanium and PhoneGap unclear. This means that as a developer, I only need to write once and the environment let's me compile and run anywhere. As we all know the write-once-run-anywhere dream has eluded us all the time — Java, Air and Flash being great examples of it. A look at applications like Eclipse, Open Office, etc., and virtually anything developed using Flash, and you'll see that it feels nothing like a native application on all platforms. This is neither the fault of the language nor the compiler, but that of the platform APIs (like Swing in Java's case). The problem is that since the platform API, which serves as a compatibility layer in these cases, tries to expose APIs that can work everywhere, they are forced to do a bad job of it.

Let me illustrate this with an example, to drive the point home. The Mac doesn't have a UI for combo-boxes, whereas both Windows and Linux do. What would a compatibility layer do in such a case? There are four possibilities:

  1. If the API makes it possible to use combo-boxes everywhere, it'll not feel native on the Mac, because the OS itself doesn't do these kinds of UIs. The platform will have to fake it.
  2. If it doesn't let you use combo-boxes anywhere, it'll seem less powerful on Windows for developers, and will provide a bad UX for users.
  3. It can choose to present completely custom UIs, which falls in neither camps, and hence fails.
  4. They could also say that you can use combo-boxes in Windows and not on the Mac, but that'll only make the programming experience horrible for developers.

So which approach is the least bad? Swing decides to compromise on UX. Flash goes the route of custom UIs.

An interesting case to consider is that of Google Chrome, which has done the absolute right thing. The core engine is C/C++, and UIs are coded separately for different OSs. However, this is clearly expensive to do, and only someone with Google's resources can pull it off.

Of course, there's also the possibility that Apple just wants to make it hard for developers to build apps that can run anywhere, by creating a lock-in. However, I don't think this is the case, because they are still allowing JS to run, and their browser is one of the best browsers ever that a developer can work with. This browser itself can be looked at as a compatibility layer that works across platforms. I've actually tried it — fairly complex applications built for the iPhone work just fine in Android-based touch phones with zero effort to port it. This is because when you develop for the iPhone browser, you are actually developing for Mobile WebKit, and has nothing to do with the iPhone Objective-C APIs per-se.

Aside: I've just negated my own point. I've criticized cross-compilers, and then said that the browser is a great environment to code because you are platform independent. However, I think that you should think different (pun intended) about browsers. This is because the browser is a sandbox that runs the Internet from the user's perspective, and it's expected that the UIs on web pages will be platform independent. That's not the case with native applications. Besides, the browser doesn't just run applications — they are also content distribution channels.

From the point of view of the UX of applications built using a cross-compiler compatibility layer, I sympathize with what Apple's done. Do I think such apps should be banned completely? I'm sitting on the fence on this one. I think the best thing to do would be to let the application fail in the market, rather than disallowing such applications outright. But then, I can see why Apple would ban it as well. Apple has always been a stickler for the UX of applications on their platforms. On the other hand however, they enforced this on the Mac OS by giving guidelines, not by disallowing such applications. So this thought is full of contradictions.

Then there's the case of the app store. The idea of a market place is awesome, but Apple's moderation is just stupid. Other issues apart (and there are several), it's a model that simply doesn't scale. Maybe Apple did this 3.3.1 thing just to ensure that they can moderate lesser apps and make their moderation generally easier to do? If that's the case, Apple is just reducing their problems and moving it to all their developers. Just another reason why Apple's moderation is stupid. Why Apple moderates is beyond me. No other platform that I know of does this, including Apple's own desktop OSs.

History repeats itself, sort of

There's a bigger concern I've got. Let me put it this way. I used to be a VB developer back in the day. When the Internet started becoming interesting, I found out that I could take my VB knowledge and port it to the web to build ASP programs. It was awesome, and I loved how Microsoft had made it easy for devs to move to the web as a platform. However, when the .Net framework was released, MS told developers like me that ASP was not cool anymore, and that we should choose either C# or VB.Net. VB.Net, for those who don't know, is nothing like VB. It's an entirely new language. Besides, MS seemed to put it's weight behind C#. Most developers were convinced that they should move to C#.

Not me. I was filled with FUD. I couldn't let a company decide what programming language I should use. What if I pick up C# and a couple of years later, just as I'm getting comfortable with it, they tell me that C# is not cool anymore? Am I shooting a moving target?

That was the time when I picked up my bags, and moved from the MS platform to open platforms. I picked up PHP because it's programming model resembled ASP, so the learning curve would be smooth. Of course, I still had to learn a new language, but at least this time it wasn't controlled by a company and I could use it just because there was community support. And PHP had (and still has) great community support. I had immunized myself from what companies have to say about my development tool chain. I was free!

In hindsight, this was the single most important decision I've taken that transformed my career. Not that I was any good at PHP. But the world of open platforms and open standards based development made me a better programmer.

Though the situation is not exactly the same in Apple's case, it's not too different. Here's a company screwing it's developers up because of what they think is the ideal vision for the platform. It's not a democratic decision — neither MS nor Apple consulted me when they were making this change. If I was now an Apple developer, I would hear alarm bells ringing, and would refuse to work in such a totalitarian environment.

But the iPhone is where my target demographic is!

Sure. I still think despite all of this that the iPhone is still a cool gadget, and users will continue to be attracted to it. And developers go where the users are. What's the point developing applications for platforms where there are no users! So, you want to build for the iPhone, but you don't want to build for the iPhone. How do you fix this?

The solution is simple. Move to an open platform. I'm not saying that you should stop building for the iPhone, and move to Android. That'd be stupid. I'm saying that you build for the browser, and serve both iPhone and Android users in one go. As a long-time web developer and currently exploring the mobile-WebKit browser, I can tell you that the mobile-WebKit browser is the best thing to happen to web development in a long time. It has imbibed standards support like no other browser has, even on desktop computers. HTML5 provides access to APIs that are mostly sufficient to build rich mobile applications. You've got excellent control on layout etc, since the CSS support is one of the best in the browser landscape. In fact, the browser in the latest phones is so good, I find it difficult to understand why I'd ever build a native application.

Here's a listing of some APIs that are available in the iPhone's and Android's browsers, that you probably didn't know existed. Yes, you can use all of these APIs today!

Of course, there are cases where you need to build a native application. Like if you want access to the camera. Or if you want to use the user's contact list. Or access the accelerometer. I'd still go native for those kinds of applications. However, very soon, that's likely to change as well, with the upcoming Capture API and Contacts API that are being spec'd. And I'm sure WebKit will one of the first browsers to adopt it.

On the whole, there's very little reason now to build native applications for the iPhone. Do it only if you know what you are doing, and you absolutely need to. Ask yourself before you start if you absolutely must go native. You'll discover that in most cases you won't need to. The browser is good enough. And you'll have supported other touch-phones while you are at it, for free, at its very least. At best, you've supported the entire mobile browser landscape, though that's a hard one, and realistically speaking you will compromise on the user experience.

One last concern remains. What if Apple decides to somehow ban browser based applications? Technologically speaking, I don't see how they can do that without reducing the power of the browser itself. One of the reasons the iPhone took off was because it shipped with a real browser. If they reduce the power of the browser, they reduce the usefulness of the phone itself. I don't see that happening. Secondly, the browser engine is actually developed independently of Apple — in fact Google contributes more to WebKit than Apple does. Unless Apple decides to revert to an older version of WebKit, or cherry-pick features from the public builds, they'll have to continue shipping the public builds of WebKit or feature-freeze on the current build. If anyone thinks Apple will (or can) control browser based applications, they're just plain wrong. The web is far too big for Apple to make such a move.

These are my thoughts. I'd be extremely interested in knowing what you think. Are you affected by this change? Are you going to move to the browser?

Sunday, October 18, 2009

geocitieslycostripod.com

Just deployed a new site to display my HTML5 learnings so far.

The idea is to demonstrate the proper use of the section, article, time, header and footer tags. I might have used a couple others. I've also used some CSS3 text-shadow rules for the first time ever in a production website. I hope to get positive comments from you about the site.

So go to my new site: http://geocitieslycostripod.com for the full glory of HTML5.

PS. Hey, I didn't say anything about Web 1.0 or Web 2.0 or anything!

Saturday, August 22, 2009

Songs In Code

Christian Heilmann of YDN fame, started a meme on twitter for writing songs in code, within the 140 char limit of course. Participation was simple: simply add a hashtag of #songsincode to the tweet. Quite soon, it became a trending topic on twitter. One way to look at it is that people on twitter have nothing to do, but the more likely one is that geeks found something to kill time with on a Friday.

Of course, quite a few gems came out of it. I'm listing a couple of my favourites below:

  • !my.isLover(billyJean) && billyJean.claims(my.theOne) && !my.isSon(theKid)
  • while (countdown > FINAL)
      countdown--;
  • public void setShirt(Shirt s){
        throw new ImTooSexyException(s);
    }
  • if (this.streets.name == undefined) {
        _root.where = this
    }
  • SELECT person WHERE AGE > 12 AND AGE <20 AND SMELLS LIKE '%SPIRIT%
  • <span style="color:#f00">
        <span style="color:#f00">wine</span>
    </span>
  • if(me.crazy.go()){
        you.call(meSuperman)
    };
    function meSuperman(){
        return '?' //Kryptonite
    }
  • .clowns{float:left;}
    .jokers{float:right};
    #me_you{position:fixed;margin:0 auto;width:100%}
  • var i = {shot:{sheriff:true,deputy:false}}
  • try{if(money>0 && work=='' && chicks=='free'){
        throw 'that ain\'t working'
    }}
  • class HotelCalifornia {
        void checkOut () {
            canLeave=false;
        }
    }
  • while(1){
        try {
            Britney.Sing();
        } catch (Exception ex) {
            throw new Exception("Oops");
        }
    }
  • UPDATE people SET parent_occupation = 'preacher man' WHERE has_pleased = 1
  • ["step", "move"].forEach(i.watchingYou);
  • (defun get (x) (if (neq x 'satisfaction) (error)))
        (get (not satisfaction)) ;
  • 99.times {Ballon.new(:red)}

Friday, March 20, 2009

Downloading JavaScript Files in Parallel

Update: There were some bugs in the code here, which have been fixed. If you were using the older version of this script on your site, you should update it.
Also, a lot of people have got back to me about them getting undefined symbols, so I've highlighted parts of this post that are absolutely critical for it's functioning.

Steve Souders, creator of YSlow, author of the book High Performance Web Sites, is back in action writing a book titled Even Faster Websites. In it he details what one can do after the 14 YSlow rules (laws?) have been implemented, and you still want better better performance.

6 days ago, Steve gave a talk at SXSW Interactive, the slides of which are available on Slideshare. In it, he goes on to suggest (slide 27), that we should load scripts without blocking. To me, this seems like a very interesting idea, and based on his hints in the next few slides, I started experimenting.

Let me back up a little. When browsers download scripts, they block all other resources from downloading until such time that the script has finished downloading. When I mean all other resources, it includes even other CSS files and images. There are several ways to reduce the impact of serial script download, and the High Performance Websites book makes a couple of good suggestions.

  • Rule 1 - Make Fewer HTTP Requests
  • Rule 5 - Put Stylesheets at the Top
  • Rule 6 - Put Scripts at the Bottom
  • Rule 8 - Make JavaScript and CSS External
  • Rule 10 - Minify JavaScript

There are several others, mostly around caching strategies and reducing HTTP overhead, but these alone reduce the impact of serial script download significantly.

Now, if you haven't already taken care of these rules of optimization, my suggestion will be hard to implement, or will reap no benefits. You can stop reading now, and go back to your site to optimize your code.

Regular <script> tags:

Serial script download

See that waterfall pattern of file downloads? Nothing else is downloaded when a script is being downloaded, not even other scripts. The time gap between successive downloads is the time taken to evaluate the script, roughly proportional to the size of the script. Notice also that this takes in excess of 600ms even when the files are being served from my local machine, effectively having near-zero network latency.

With script parallelization

Parallel script download

Now, this looks much better, doesn't it? Not only has everything downloaded in parallel, it has taken less than half the time for the same size of files. In fact, you will notice that some noise when recording this data made the files take longer to download in this case, yet the total time was less than half of the pervious case.

So, how did I do this? Read on...

One script tag to rule them all

Reading into Souders' suggested techniques (If you still have that slideshow open, go to slide 26), I decided that what I wanted was:

  • I want the browser busy indicators to show,
  • I want a script that doesn't care if I'm downloading from the same domain or not, and
  • I wanted to preserve the evaluation order in case of interdependent scripts.

So, I came up with the following little script:

<script type="text/javascript">
(function() {
var s = [
"/javascripts/script1.js",
"/javascripts/script2.js",
"/javascripts/script3.js",
"/javascripts/script4.js",
"/javascripts/script5.js"
];

var sc = "script", tp = "text/javascript", sa = "setAttribute", doc = document, ua = window.navigator.userAgent;
for(var i=0, l=s.length; i<l; ++i) {
if(ua.indexOf("Firefox")!==-1 || ua.indexOf("Opera")!==-1) {
var t=doc.createElement(sc);
t[sa]("src", s[i]);
t[sa]("type", tp);
doc.getElementsByTagName("head")[0].appendChild(t);
} else {
doc.writeln("<" + sc + " type=\"" + tp + "\" src=\"" + s[i] + "\"></" + sc + ">");
}
}
})();
</script>

It's a little ugly: There's a user-agent sniff happening in there and I've written it so as to use the least number of bytes possible (save for the indentation), but it works, and has no dependencies on any library. Just modify the array on top to place your list of scripts you wish to include, and let the rest of the script do the dirty work. If you need to include scripts from another domain, just use an absolute path.

This code was written keeping in mind that this should be the only piece of on-page inline JavaScript. This can then go on and fetch the script required in parallel, and those in turn can unobtrusively do their thing.

This works as advertised in IE and FF. I haven't tested the parallelization in other browsers, but at least it fails gracefully and preserves script execution order. This has now been tested in Safari, Chrome and Opera as well, and works as advertised everywhere.


Find this interesting? Follow me on twitter at @rakesh314 for more.

Wednesday, January 21, 2009

JsMemcached.js - A Jaxer client for memcached

Two days ago, on a lazy evening, I started work on my first solid Jaxer project — building a memcached client. As a testimony to the elegance of JavaScript, it took me less than 2 hours to get a basic memcached client up and running.

What is memcached, you ask? From the memcached website:

memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load.

What it does is, lets you use excess RAM on your server machines as temporary stores of data, so that you can avoid going to your DB when you want frequently accessed data. Needless to say, accessing data from RAM is much faster. Since the creation of memcached for LiveJournal.com, memcached has become the cheapest and fastest way to scale a website.

Now, my implementation is not feature complete, nor at peak performance, but I aim to take it there. Even so, I decided to get my code out and available for everyone to see, so that people can tell me what they think of it.

You can go to the Google code page for the JsMemcached-client project, or download the code right away. Though limited in features and with a possible bug in an edge case in the get call, you can start using this already.

This is my first open-source project, so please don't be too harsh in your feedback.

Help needed: I need to figure out how to performance-optimize this code. Either I need to get rid of that loop in the get call, or I need to write a wrapper around libmemcached. I would prefer the latter, since I have to add more features for feature-completeness. Any idea on how I can get Jaxer to talk with libmemcached (or any other such out-of-process thing)?

ShareThis