Archive for August, 2010

Mobile Web App 1: Wireframing

Sunday, August 22nd, 2010

In my last post, I introduced the mobile app project that I’m going to undertake. Today I took the first step and sketched out the UI of my app. From this, I can get an idea of the number of different screens (don’t call them pages!) and how they connect, as well as the different UI elements that I will need to either get from a library or create on my own.

The home screen

This is what you will see when you open the app or visit the site, and are already logged in. (The whole login/account system is something that I haven’t looked at yet. I just know that I want it to be super-simple.)

It presents the four main things that you can do: browse your beer notes, add a new note, search for a beer, or look at a random beer from the database.

(Note that the title is wrong in these sketches. I was going to call the app Beer.Me until I realized that’s already taken.)

home screen

Adding a new beer

This needs to be super-simple, because when you’re hanging out with people or conversing, you don’t want to spend a ton of time typing into your phone. Key design principle: Don’t make your user look lame!

Because of that, the ability to grab a snapshot of the label using your camera phone is key. I could envision myself doing that to remember a beer that I liked, and then filling in the rest of the details later. (This implies that we need a way to remind the user of incomplete notes, and prompt her to complete them. This may or may not be another screen.)

I avoided the typical 5-point star rating scale, because I think it’s often overkill. I’m not sure that my opinions on beer are fine-grained enough to support five separate divisions of feeling; I tend to think of things as liked or disliked, with a few standouts that I particularly love. I threw in a “hate” button too, mainly for symmetry’s sake, or to remind yourself of something terrible that you never want to try again.

add a new note

Browsing your notes

Just as important as adding a new note, is the ability to go back and easily look over the notes that you’ve created.

The browse screen is fairly simple: it offers a segmented control with 4 different ways of organizing your notes, and below that a simple list. Touching a beer on the list will slide over to that beer’s note, in the standard iPhone-ish way.

Here’s a sketch of the screen organized by name:
browse by name

And here’s an example organized by the name of the brewery:
browse by brewery name

The two other views would look similar to this one, with subheadings on the list for category or for the date the note was entered, and entries alphabetically within that.

Viewing your own notes

From the browse list or from search, you would have the ability to view a note that you had previously made. This would include your information, of course, and also some global stats about that beer, if anyone else had noted it as well.

The global stats bar would double as a filter of the other people’s notes below it. You could tap on any particular rating and the section would filter to only show notes by people who had assigned that rating.

one of your notes

Viewing other beers

Of course, you might want to get information about a beer that you yourself haven’t tried yet. This part would only work if lots of people were actually using the app, which is why I see it as secondary. Nonetheless, by searching for a particular beer or by hitting the “Random Beer” button, you should be able to review the notes for any beer in the database.

This is what that screen would look like: it’s basically the same as the previous one, without the whole “your notes” section and with the addition of an info thingy telling who first noted this beer. (The hope is that including this would motivate people to note more beers, in the hope of being the first person to do so.)

not one of your notes

And there you have it. As noted, there are a few things missing, like a search results screen and any kind of account/profile management stuff. But I think that these are the core items that give me enough information to start planning out the app.

Coming up next: Picking a UI framework, or not.

Building a mobile web app, start to finish

Sunday, August 22nd, 2010

Given the way I keep falling into mobile work, I’m apparently destined to be a mobile web developer. (If you know me, you know why this is funny — I hate talking on the phone, and avoid it at every opportunity.)

Because of this, I’ve decided that I need more practice at creating cross-platform, web-based apps. I have some experience with the iPhone SDK from a project earlier this year, but I’ve come to believe that web-based and cross-platform is the ideal way to go.

I’ve decided to start a project to create a mobile web app from start to finish, and I’m going to blog about it each step of the way. I’ll talk about the various decisions that I face, like choosing (or not choosing) a javascript framework, and the challenges that I will no doubt run into.

The app that I’m going to make is based on something that I actually want for myself, which makes it easy to design. It’ll be an app basically geared toward beer snobs (or connoisseurs, if you’re being polite), that lets you keep track of beers that you’ve tried, take notes on them, rate them, and see notes and ratings from other people. There may be apps around like this already; I don’t really care. I’m not in it to make money, just to gain experience with mobile app development and create something that I personally like.

I’m tentatively calling the app BeerNotes. Over the next week or two, I’ll be working on the design of the app and making the various technical choices required to get started. After that, I’ll move into talking about implementation. So, come back to see how it goes!

YUI3 Hiddenhancements: Y.cached

Wednesday, August 18th, 2010

Ok, first things first. I totally stole the word “hiddenhancements” from the yayquery guys. If you’re not familiar with them, go and watch a show and then get back to me.

Back? Okay. (Enjoy having their theme song stuck in your head, btw.)

So lately I’ve been doing a LOT of work with YUI 3, which is totally rockin’, and I’m starting to realize that there’s all of this Really Cool Stuff hidden away in YUI Core and other parts of their API that isn’t really mentioned, well, hardly anywhere. So I’m going to be writing some of this stuff up.

(Of course, everything IS documented in the API docs, or at least mentioned. http://developer.yahoo.com/yui/3/api/ is your friend.)

Cache me if you can

So, Y.cached. What does it do? According to the API docs, it “Returns a wrapper for a function which caches the return value of that function, keyed off of the combined argument values.”

In other words, think of it as a filing system attached to your function.

If you pass in some arguments to a function wrapped in Y.cached, YUI will go off and check whether there’s a mailbox labeled with that set of arguments. If there is, it’ll pull out the stuff that’s already stored there and return it, without ever going into your function itself. If the value isn’t stored, YUI will pass your args through to the function, intercept the result when it returns, and store it away in a neatly labeled mailbox, so the NEXT time you call the function it can retrieve it.

So you can see how this potentially could help you skip a lot of duplicate work, if you’re calling the same function with the same values over and over again.

Of course, this doesn’t help you much if your function has side effects, or in other words, does anything other than process some args and return a value. (It also can’t help if you need randomness in your results.) But there’s a whole set of operations that do exactly that: process some args and return a value in a predictable way. For those operations, Y.cached can really speed up your code.

(You can pass in a third argument that will cause Y.cached to blow away the cache and call the function again, but if you’re using that a lot then you’re defeating the purpose.)

If you want to impress your tech lead or something, you can throw around the term memoization when referring to this technique. Then they’ll be all like, whoa this person knows his/her bizness! And they’ll think you’re smart, and then you’ll get a raise.*

*Not guaranteed to actually occur.

An example from YUI

Here’s an example from YUI’s event-target code.

//In this line, they're caching a function that does some string replacement with a regular expression
//With this caching, if you pass in the same string again, the regex won't have to be evaluated twice.
_wildType = Y.cached(function(type) {
        return type.replace(/(.*)(:)(.*)/, "*$2$3");
    });

// .... bunch of other stuff......
// ..... and then later on they call the function just like a normal function.
if (type.indexOf(PREFIX_DELIMITER) > -1) {
            type = _wildType(type);
}

And that’s basically all there is to it!

My current use case

Right now I am working on a widget that does client-side filtering of tables. This widget needs to be fairly generic, so one of the things I do is let people pass in a function that specifies how to filter for a particular command. This function takes a value and returns a boolean, in a way that should always be predictable. As soon as I saw this, I thought to myself, “Boom! Let’s use some totally sweet memoization to speed up this code!”*

Embarassingly, I don’t have actual numbers to show its effect. I might try to gather some tomorrow. But it made a notable difference in the filters’ responsiveness, especially in mega-slow IE7.

And it’s so easy to use, it’s like why not? Go forth and memoize!

* What? I get excited about things like this.

Fireflies – My #js1k Contest Entry

Sunday, August 15th, 2010

Most javascript developers have probably heard of the js1k demo contest by now. (You can check out all of the entries here.)

Here’s my entry, just under the wire at 1022 bytes. (The right edge is a bit cut off, because of my blog’s layout – sorry.) It was only possible with the help of the Closure Compiler from Google, which totally rocks my world.

I’ve decided it looks a bit like two swarms of fireflies chasing each other around. It’s adapted from the “Boids” flocking algorithm, which is applied to both the individual bugs and also to the swarms themselves to make them chase each other. (I found this explanation particularly helpful.)

Anyways, I doubt I’ll place because there are a lot of really amazing entries, but I had a lot of fun building this. It was a bit of a flashback to my old computer graphics days, in college.

My Biggest Fear as a Developer…

Sunday, August 1st, 2010

…is that 5 years from now, some other developer will be cursing my name for something that I did. (They may not actually know my name, but they’ll be cursing what they imagine it is.)

That something I built, or some decision that I made, went on to become set in stone and now is making their life more difficult. That something wrongly optimized, or just poorly done, is now actively hindering future progress.

Of course, none of us can predict the future, so this is basically unavoidable. Conditions always change, so what I’m optimizing for now is almost guaranteed to become the wrong thing at some point down the road.

So developers are always going to be cursing my name, at least a little bit. But how can we try to reduce this?

1. Seek out as many perspectives as possible.

When you’re doing something that could have big implications down the road, make an effort to get lots of feedback from people from different backgrounds and perspectives. (And then listen to their criticism and be willing to change your ideas – which can be difficult, I know.) Every person brings their own angle to a problem, and each angle can see different holes and cracks.

You need a panel of trusted experts who you can call on regularly, to vet ideas and tell you when you’re being dumb.

It helps to find people who will:
a) not play politics with your ideas, but evaluate them strictly on merit,
b) keep it constructive, and
c) give you honest criticism without holding back.

Chances are if you can get a whole group of designers and developers to agree that something is okay, it’ll stand the test of time a whole lot better.

2. Don’t overdesign.

There’s this great William Gibson quote that I absolutely love:

“That which is overdesigned, too highly specific, anticipates outcome; the anticipation of outcome guarantees, if not failure, the absence of grace.”

Design for grace. Make the bare minimum number of decisions required to meet the current need, and make those decisions easy to change. Leave daylight between every part of your system and every other.

There are a million different patterns around to help you do that. Use them, but don’t overuse them, and remember also that a lot of design patterns introduce complexity.

In the tradeoff between simplicity and flexibility, lean toward simplicity, so that other people can understand your system. Don’t try to anticipate future needs – you’ll get it wrong. Instead, create a simple and solid foundation so that future needs can be met by future developers.

Another quote that I love, from Antoine de Saint-Exupéry:

“Perfection is achieved, not when there is nothing left to add, but when there is nothing left to take away.”

3. Draw on principles from information architecture and usability to make your system sensible.

As developers, we’re lucky because we design for other developers. In a very real sense we are our users. But we’re still never exactly our users, and the view of a project when you’re eyeballs-deep in code is different from that of someone faced with learning to use a system from scratch.

Consider the basic principles of usability as they apply to code design. Develop sensible hierarchies. Use agreed-upon domain terminology when naming methods and variables. Design your API, don’t just let it evolve blindly. And yes, this is where the dreaded task of writing documentation comes in as well.

(I may be the only developer in the world who actually enjoys creating documentation. But I like writing and teaching and psychology, and creating good documentation draws on all of these. I find it an interesting challenge.)

I think that learning a few basics of IA, design, and usability will make anyone a better software architect, because it trains you to effectively consider another person’s point of view.


In the spirit of #1, what am I wrong about? What other things can we do to help our code adapt to future change?