Sunday, April 20, 2008

A "unix" UI rant

I think I'm finally getting the hand of the Unix/Linux mentality.

For years, now, I've maintained that trying to use Linux was about as much fun as a visit to the dentist. I think I'm finally starting to get it, though.

You see, Linux, in general, has a terrible UI. Not only that but it has been incredibly slow to improve. I fully expected, back in 1999, that'd this problem would be completely solved by now. With the massive rush of ex-apple programmers and general interest it shouldn't be too much effort to fix up Linux to be usable by people unwilling to dedicate several years of their life to learning it. yeah...

So anyway, today I managed to install a piece of software that was obviously programmed by some unix-type. I'm so proud of myself. It only took me two tries. The second try I approached it with the idea that 1) the programmer expects me to know about how everything and 2) put no thought into user interface.

Fun facts:

1) You needed to tinker with a config file that came with its own syntax.
2) The client and server concepts were backwards (*my machine* was the server and I had to ssh into the other machine and tell it connect to *me* so I could use it).
3) Security by insanity - do I know your login name? Yes? Ok, I'll talk to you. I mean, at least you could pretend it was a password; that's what it acts like.
4) The configuration was such that you needed to add two configuration entries to do something that really only needs 1 (for the most common use case). If you only added one configuration line your mouse cursor became trapped on the other screen. oh no!

The thing that really gets me though, is that once it was configured it actually works. I mean, there's nothing wrong with it! No stupid, bugs or miss-features it does what it was supposed to do. It's really a shame that this great software is hiding behind such a terrible interface.

Want to try it yourself? (the software or configuration odyssey. I'm not picky) The software is called synergy. It's purpose is to allow you to use a second computer, with a second screen as if it were really just an extra screen for your main computer.

You see, I run a PC most of the time, but I also have a mac that I want to use. I don't want to keep switching keyboards and mice, though. I'd rather just be able to mouse over to the mac screen and use it like that.

Those familiar with VNC can think of it as setting up VNC session on a monitor hooked up to a different computer. Synergy works better than that because isn't of using VNC to display the remote screen on your computer. You just use the physical monitor attached to other computer's and send your mouse and keyboard command are sent to it.

This works great if you have the two computers sitting on the floor next to you.

Now if you'll excuse me I have to flick the mouse over to the Macs screen because the screen saver has come on again..

Ok, so it has one (known) bug:
"The Mac OS X port is incomplete. It does not synchronize the screen saver, only text clipboard data works (i.e. HTML and bitmap data do not work), the cursor won't hide when not on the screen, and there may be problems with mouse wheel acceleration. Other problems should be filed as bugs."

Tuesday, April 15, 2008

OpenPro Computer - A mac clone!

Apparently Psystar is making macintosh clones. The OpenPro Computer model looks familiar. Oh yes, the case is the Antec P182. Essentially that same as my home PC's P180. Good choice.

Monday, April 14, 2008

"UI is the root of all evil" or UI is hard

A friend pointed this one out to me. It's an article about the dangers of not considering the GUI when doing development.

http://blogs.pathf.com/agileajax/2008/04/the-user-interf.html

In the context of my previous blog posting, think of it as what could happen if the UI design is late and your design process is not agile. :-)

(planning is good)

Sunday, April 13, 2008

Cooper vs extreme programming

I was at last year's SD Best Practices conference at Boston. One thing I remember was the two times I heard programmers complain about Alan Cooper's views on UI design.

The complaints were both by programmers directed at the aspects of Interaction Design which are incompatible with extreme programming.

First off, I've never been a big fan of extreme programming.

I believe that a great number of programmers have a code-first-think-about-it-later approach to programming. I believe this mentality is a big barrier to creating large, scalable, long-lived software. I find it disturbing that someone would actually advocate a process that actually *encourages* more of this.

I met 3 programmers at SD Best Practices that took extreme programming to mean absolutely no design. As if thinking ahead was banned outright. Talking to them brought to mind scenes from 1984 where instead of being banned from remembering, you were banned from thinking ahead. I don't buy it. To plan is to think ahead is to avert disaster. Imagine trying to build a building or plan a trip or save for retirement without thinking ahead! The extremist extreme programming mentality is that the future so uncertain that all planning is futile. This is only a very coarse approximation of what extreme programming actually advocates but what extreme programming actually advocates is complete overkill in most projects anyway.

At any rate, the Interaction Design (as explained by Copper) conflicts with XP (extreme programming as explained by Kent Beck) in at least two ways.

1. XP advocates user involvement in the design process. You ask the user, you give them a prototype, they tell you what's wrong, repeat until convergence.

User Interaction design says "don't ask the user!". The rational is that users don't know what they want! UI design is hard and should be done by a trained, professional Interaction Designer.

2. XP advocates short iterations and an iterative methodology that takes into account learned mistakes as the project progresses..

User Interaction mandates that the Interaction Designer do the design more or less in one shot, up front.


These two methodologies are not directly comparable. Not only are they trying to solve different parts of the software engineering problem but they are coming from a different set of assumption about what sort of environment they are operating in.

Interaction design is all about user interface design. It does mention how to go about developing software except where software development intersects user interface design. Doing design up front is a good idea with user interfaces because 90% of GUI design is optimizing for the most common cases. You either know what the common cases are or you have to go out into the field and observe the users at work.

The net result of this process is usually a design that is highly optimized to how people work. As with any highly optimized system, GUIs can have a large amount of cross cutting features; that is features that are interdependent. As a result of this, a small change somewhere could change the nature of the GUI completely. Adding one extra click or a pause or adding a step can have a huge impact if that case is common. As a result, user interfaces should be thought of as one holistic piece.

Consider this example: Radiologists look at X-rays and diagnose problems like broken feet and arrows piercing the head. Their workflow (simplified) is 1) load image 2) dictate image 3) next image. I've watched them at work and they work fast. They average about 2 minutes per case. If we had a workflow that added 1 extra click somewhere to that workflow we would have added somewhere around 7 * 60 / 2 =~ 200 clicks. Multiply this by the number of radiologist at work and that tiny, little design decision has single handedly caused hundred of cases of repetitive strain injury! You can do a similar time base calculation. if your extra click requires the user to think about what to do next.

This may seem trivial to some but we've actually had certain minimum workflow standard written into our contracts with some of our clients because they are sick of vendors pushing an extra click on them for no reason.

I've always viewed XP's desire to bring the user into the design process and have them practically design the UI as a first order approximation on how to design a GUI. XP's assumption about having continuous access to a user (or group of users) is very a-typical, in my experience. Also, users are very bad at vocalizing what they want of need:

http://andrewtrumper.blogspot.com/2008/02/why-ui-design-is-import-in-apis-and.html
http://headrush.typepad.com/creating_passionate_users/2005/09/listening_to_us.html
http://www.joelonsoftware.com/articles/fog0000000356.html

etc..

My favorite users-don't-know-what-they-want story comes from when I was developing a piece of image-burning software. The idea was that this software would be for burning X-ray (or other modalities) series to CD. We knew what sort of users we wanted to target. We thought we knew what they wanted in the software, since we had this big feature list. The only question remaining was what should the "GUI look like?". I looked at the feature list and the target user and I couldn't match them up in my head. I just couldn't believe that the users we were targeting really wanted this big complicated GUI. I decided to ask for an on-site visit. Before the on site visit I'd prepared a list of questions that I wanted to answer. These questions were about whether a certain features were desired or not and about the relative frequencies of various occurrences.

I was curious about what they'd tell me if I just asked them my questions point blank. Did you need this feature? yes! My test users wanted every feature, expect that ones they didn't understand. Did this edge case happen frequently? no! How often? Once every 6 months of so.

I then observed them for three hours. During the three hours each one of the edge conditions happened at least once. They also never needed the extra features. It turned out that the software they were using had the features I was asking about. However, even in cases where they should have logically used these features, they didn't because it wasn't worth the effort to configure them! AGH! I came away from this with a better, streamline GUI and the notion that users (at least these users) had no clue what they wanted.

The second major point of disagreement between ID (Interaction Design) and XP (extreme pornography.. I mean programming) is the use of iterations.

As I've mentioned ID isn't about how to build the thing; it's about the GUI. Nothing is stopping you from using iterations to build the big-bang-GUI. In fact, in my practical experience, you have to start building before the GUI is completely ready because it takes so-freaking-long to design the GUI. Yes, by all mean do iterations. Not doing iterations is silly. You might want to stretch out your iterations longer than the ones suggested by XP, though. XP mandates uber tiny iterations (1 week). With such iterations you're actually under-valuing planning.

Planning is good! Over planning is no so good. Being forced to over-plan then stick with that plan is extremely bad. In my experience, excellent planners (or planner *teams*, rather) can plan two months in advance with a good degree of accuracy. Good planners are about a month and ordinary, mere mortals can plan a week or two if they practice at it. All these estimates depend on the context, of course. Your planning horizon can vary tremendously depending on the problem, the degree of familiarity and the skill of the planner.

My favorite planning story is the time we planned out our "roaming preferences" feature. Essentially we managed to plan out about three months of work and have that plan executed with little or no change within 5% of the estimated number of hours. Hurrah! A hole in one! Then, in the next iteration, we tried to plan out 1 month of work and both the major aspects I was responsible for were completely wrong.. Luckily both things that we got wrong were wrong in opposite directions. One took 4 times longer than I though and the other tool about 1/10 the estimated time. The reason for this was that we had to make a modification that changed where the bulk of the work went so it's not really a co-incidence. We actually knew this was high risk going into it since we were modifying old code we didn't know very well.

Remember to include the risk component in your time estimates and proposed designs!

So, iterations are a way of mitigating against the risk of planning errors. They do this by scheduling points where the design and progress of a project can be re-evaluated and adjusted. The downside to short iterations is that it can artificially limit you to a fixed design horizon. Limiting your design horizon can introduce costly refactoring or code scaring. For a real-life analogy of the dangers of under planning, consider the joys of mountain biking with your eyes closed. Ouch!

Using super short iterations on a project with no risk is silly. Using super long iterations on a project with high risk is silly.

None of this has to do with GUI design. Even if your GUI design is low risk, other aspects of implementing that design might be high risk. The length of iterations for a project is a programmer thing. Interaction designers do their GUI thing and programmers mitigate against their potential errors and their own by having short iterations. The two do not conflict because they are tackling different aspects of the problem. The only major change for XP people is that the GUI design is done by someone else and becomes lower risk. (In practice, politics and errors affect this somewhat)

I like to say that even if you're not doing iterations the best way of actually these implementing these big designs is by making use of iterations.

In my mind, ID (Intelligent Design .. I mean Interaction Design) and XP do not conflict. ID is a way of creating a better GUI. XP is a set of techniques for mitigating against the troubles brought by changes by embracing them.

bye.

Wednesday, March 12, 2008

Lucid dreaming

Recently, at a party, I got into a conversation about lucid dreaming. A lucid dream is a dream in which you know you're dreaming.

I first became fascinated by this subject when I started to wonder why you always know that you're not dreaming when you aren't but why you don't when you are. Then I actually experienced a dream where I realized that I was dreaming and that really spooked me.

Why aren't all dreams lucid?

I didn't feel like I was dreaming when I was dreaming. Maybe I'm doing something equivalent to dreaming all the time - spending my life in a daze and not really knowing it. I decided that I was going to work on making all my dreams lucid dreams.

Talking to the guy at the party I was reminded that many people don't remember their dreams at all. Other have never had a lucid dream. Others don't believe it's possible.

Yeah, lucid dreaming is possible. It's not as fun as you might think but it's possible.

After practicing for a few years I managed to have lucid dreams about one every other night.

Many people seem to think that if they knew they were dreaming they'd be able to do all sorts of stuff they've always wanted to do. In practice, my experience is the dream already has an agenda and if you don't play along you wake up. That's not to say you can't do some cool things in dreams, it's just a lucid dream isn't your own personal holodeck.

Dreams are manifestations of your expectations.

Let's say you built a computer. This computer makes up models of the world. It tries to find patterns and guess what's going to happen. This computer is very good at it and after some amount of training develops a whole bunch of models of how things work. It knows when lunch is. It knows you like coffee at the start of the day. It knows if you let go of something in mid-air it falls. It's got a fairly good view of the world.

Now you want to take it to the next level. You want to make this computer interact with the world very quickly; without having to think about what's going to happen. You essentially want it to figure out that if I drop something fragile it should attempt to catch it! Fast! There's no time to think about what's going to happen when you let go then figure out it's going to fall then figure out that it's fragile then figure out that it will break and that you will get mad and yell at it. It needs to know the rule that: If fragile item falls you (the computer) catch it.

How do you do that?

Well, as I said, the computer knows about how the world works. So if you bring up its memory of the lab and then ask it: "What sort of things could happen in the lab?" it will know: the same few people tend to walk in, in the morning. Lots of these people have coffee. Coffee is always in cups. The sun shines through the window in the morning. People occasional brush past things and push things onto the floor. etc.. blah blah.

Really, you don't need to teach the computer about the world, you can simply run it's models of the world against itself and it will figure out (eventually) most of what it needs to know. So long as you take more or less random branches out of the possible scenarios you'll end up producing experiences that have never happened. This is useful to train against.

The human brain is a bit like this. It makes models of the world and builds up expectations. Dreams just run these expectations against one another... presumably to help you react better if this situation should come up in real life.

Actually, there's another important factor: emotion.

If dreams were only about expectations you would have really boring dreams. Most of the stuff we expect to happen is fairly dull. The thing with dreams is they often choose which expectation wins based on emotional response.

Here's an example. Let's say you were in high school and you're standing in the cafeteria. Consider these events:
- Someone you're friends with waves at you from across the crowd.
- Someone drops their tray.
- There's a good seat available for you a few feet away.

Not much emotional response. How about these:
- You buy some lunch but discover that your pocket has a hole in it and all the money is gone!
- All the seats are somehow taken.
- A teacher walks up an casually mentions you just got an A on a test you were worried about.
- Terrorists!

Dreams go for the big emotional responses.

If you become lucid you can't suddenly start trying to make things happen that are just "neat". "neat" doesn't play well in dreams. "Dangerous" is fine. "Angry" is fine. "Really totally awsome" is fine.. "neat" isn't.

.. and don't try things just to find out what will happen. It's a dream! Trying stuff in a dream just to see what will happen is like having the following conversation with yourself:

"So.. what will happen if I do this?"
"I dunno. What do you think?"
"No, I'm asking you."
"Well, what do you think the answer should be?"
"Actually, I'm just curious about what you think should happen."
"Well what do you think should happen?"

If you do this enough, you dream will go "ah, screw this" and wake you up.

In a dream your job is to react to things not make stuff happen. You can make stuff happen but you have to go along with the flow of the dream. Try to make it a reaction to something.

Oh no a tiger! Good thing I'm in a dream since that means I can fly away! (model of how thing works goes "yeah ok".. so you fly.. Good thing your instinctual brain never took physics).

That's about the long and short of it.

In the end I started having weird semi-lucid dreams. In this semi-lucid dreams I know on some level that I'm in a dream because I know that all the things I used to do in lucid dreams will work.. I also know I can just escape by waking up. Well, unless I have a really bad nightmare in which case I an usually so focused on the moment I don't get that strange "this place follows dream logic" feeling. What I think happened is my behavior adapted to included the fact that, in dreams, the rules are different.

Sometimes I think my brain has built its own parallel universe. I have a "dream montreal" that doesn't look like real montreal but is more-or-less consistent every night. I have a map of my home town that includes things which are completely wrong but very consistent between dreams. They aren't spatially correct but they are emotionally correct. That is, the distance between two buildings is a "short" or "long" walk. That the main street contains an "annoying" amount of traffic. That buildings in the new art of town are "taller" and "newer" than the old part. That some buildings are "tall" while others are "scary tall". It's hard to describe. It's not montreal. It's obviously not montreal.. but it feels like it.

.. oh and all the elevators are dangerous and unreliable. I know that if the elevator doesn't work it's because I'm dreaming :-)..

So how do you get into a lucid dreaming state?
Read this link:
http://www.lucidity.com/LucidDreamingFAQ2.html#techniques

The most important thing is to remember that you can never tell you're dreaming! Especially if you've woken up from a dream! Your body doesn't like waking you up for no reason so it will tend to fake waking you up. When waking up from lucid dreaming always make sure you're not still dreaming.

.. checking for dream signs requires excellent self control.. Actually I think the ability to extract yourself from the moment is the primary benefits to pursuing lucid dreams.

So read all that stuff and you will have a lucid dream tonight. Seriously. (Go flying in reaction to something. It's scary fun.).. good luck having a second lucid dream but the first one usually comes easy. :-)

good book:
The Head Trip - It deals with various states of consciousness including lucid dreaming. No LSD or drugs here. All these states are natural ones.

If you like lucid dreaming you might like to experience the watch. Another fun altered state of consciousness easily accessible by messing with your sleep patterns. :-)

Saturday, February 9, 2008

Why UI design applies to APIs and frameworks

That blasted book! (see previous post).. Now it's got me thinking about API and framework design..

Ok.. So I'm reading a chapter about David Heinemeier of 37signals. He's the dude who wrote ruby on rails. In it he says the following:

"You need to innovate on behalf of your customers, but they don't often know what they want. And it's the same thing for programmers. If you went around and asked them what they wanted in a framework, you wouldn't get a good product out of that. You need to be able to source input from alot of sources, and then have your vision of what it's going to be and then drive that."

(emphasis mine)

There's this idea floating around that the reason a software sucks is because the people make it don't pay listen to the customer. All the layers of bureaucracy between the programmer and the user causes a disconnect. If we could just talk to the customer directly we'd be able to ask them what they want directly and just program that.

This is partly true but there's a problem: users don't know what they want.

I have a feeling that many who have not actually done a software project with real users see this as an arrogant statement. It's not.

Users are not programmers. They don't know interaction design. They probably don't have very good aesthetic tastes. If you let your users build your specification for you, you'll end up hearing the dreaded "This is what I asked for but not what I want". This is why extreme programming, which advocates the above, has a short iteration time.

On the subject of framework design.. Every once in a while someone will post a bit about how painful it is to do something or other in Java vs Python. Most of the time it's something trivial that's not really a Java-as-a-languge issue but Java-as-an-API issue.

Java's API can be irritating at times. My favorite example of this is reading a file.

Let's say you were in Python and wanted to read a file as text. Here's what your code would look like ->


with open("hello.txt") as f:
print f.read()


Now for the Java version. Settle in because this is a bit long.

First off let's do this as a function that returns a String


public static String readFile(String fileNameToRead) {
return null; //for now.
}



Ok, so I didn't bother doing this for python. Beer with me here.. Mmm beer..

It's nice to get a quick poke about how verbose declaring a function is :-) .

Now We have a function let's create a file object:


public static String readFile(String fileNameToRead) {
File file = new File(fileNameToRead);
return null; //for now.
}


Unfortunately, the File object in Java doesn't have any method to read it's contents. To actually read a file we have to create an FileInputStream. Let's do that.


public static String readFile(String fileNameToRead) throws FileNotFoundException {
File file = new File(fileNameToRead);
FileInputStream in = new FileInputStream(file);
return null; // for now.
}


The problem with InputStreams in general is that 1) You can't get a String out of them and 2) if you ask it to fill and array of bytes it actually won't fill the array of bytes. It might fill the array to completion but it probably won't. It's your responsibility to loop over the "read" method in FileInputStream an accumulate all the bytes you want.

To heck with that! DataInputStream can read a full byte array so let's use that!

ByteInputStream can wrap ANY InputStream and add functionality to it. This means you can use it to read bytes from a network connection, file on disk or anything else. It's very cute.


public static String readFile(String fileNameToRead) throws FileNotFoundException {
File file = new File(fileNameToRead);
FileInputStream in = new FileInputStream(file);
DataInputStream dataIn = new DataInputStream(in);
return null; // for now.
}


Notice that we had to add the "throws FileNotFoundException" to the end of the method there. This is because we're doing IO which could fail. If it fails it throw an exception. Java won't let you compile until you've told it how you want the exception handled. Most languages don't do this and just let the exception bubble up and kill the program. We're just going to tell java to throw it up to the caller and let someone else take care of it.

Ok, now we have a DataOutputStream but we can't read a String using it. It actually has a method called "readUTF()" which returns a String but it doesn't do what we want because readUTF() expects the data in the file to be in specific format. That format is only written by the corresponding method from DataOutStream.writeUTF()..

Ok, lets create the byte buffer!



public static String readFile(String fileNameToRead) throws FileNotFoundException {
File file = new File(fileNameToRead);
FileInputStream in = new FileInputStream(file);
DataInputStream dataIn = new DataInputStream(in);

byte[] bytes = new byte[(int) file.length()];

return null; // for now.
}



Now we need to read in the bytes.. which is actually fairly easy now that we have our DataInputStream..



public static String readFile(String fileNameToRead) throws IOException {
File file = new File(fileNameToRead);
FileInputStream in = new FileInputStream(file);
DataInputStream dataIn = new DataInputStream(in);

byte[] bytes = new byte[(int) file.length()];
dataIn.readFully(bytes);


return null; // for now.
}


Notice the exption changed. This is because DataInputStream.readFully() throws its own exceptions. Since both exceptions are the same kind (IOException) we're just going to tell java that all IOExceptions should be dealt with by the caller.

Yay we have the file's bytes! Now bytes aren't a String so we still need to convert to a String...


public static String readFile(String fileNameToRead) throws IOException {
File file = new File(fileNameToRead);
FileInputStream in = new FileInputStream(file);
DataInputStream dataIn = new DataInputStream(in);

byte[] bytes = new byte[(int) file.length()];
dataIn.readFully(bytes);
return new String(bytes);
}


But wait, there's more! We still have to close the file! In the Python code this is done by the "with" statement.. We have to do this by doing this ->


public static String readFile(String fileNameToRead) throws IOException {
DataInputStream dataIn = null;
try {

File file = new File(fileNameToRead);
FileInputStream in = new FileInputStream(file);
dataIn = new DataInputStream(in);

byte[] bytes = new byte[(int) file.length()];
dataIn.readFully(bytes);
return new String(bytes);
} finally {
try {
dataIn.close();
} catch (Exception ignore) {
}
}

}


There we go. Now if anything goes wrong the file will be closed.

Wow... That's longer than the python version...

The thing is.. If this function existed in the API you could call it to print out the contents of a file by doing this ->


System.out.println(readFile("hello"));


This line does the same thing as the python version. They could have put this function in the core API. They didn't.

I'm betting that what python has to do to provide that functionality is very close to what we did here.

Java-as-an-API doesn't have a very good file-reading / string-manipulation toolbox. This is an API issue. It can still do everything but it's a huge pain. Python rocks for this.

On the other hand Java-as-an-API has a massive framework for making GUIs. Python-as-an-API doesn't.. You need to use a third party library.

Just one more thing before I sum all this up: Java both as a language and as a toolkit was the totally wrong tool for doing applets.

People wanted to make banner and cute animated graphics and such.. Look at what people are suing flash for today and that's what people wanted to do with java applets.

Java applets should have had an API for doing animation. It should have had an animation studio attached to it.

... oh yeah and it had to have drop dead easy deployment..

... oh yeah and it shouldn't have cause the web browser to freeze up solid for 30 second whenever it was used...

.. I could go on but this is all well known.

Sun didn't do their research. Don't be like Sun.

Designing frameworks is hard. You need to balance a host of things from flexibility to speed to ease of use to power and it just goes on. If you don't know who your building for and what they need you're doomed to failure. They can't tell you either because they havn't thought about the problem very deeply.

The process you need to use to build a good API is the same process as the one you need to use to build a good interface.

You need to know your UI basics either way.

ok, I'm done.

Skating in the park with flounders

Wee, I just got back from playing hockey in lafontain park in Montreal.. It's about 0 degrees outside today so it's perfect weather for skating.. Not cold enough that you start to worry about the consequences of breathing.. not warm enough to melt the ice. Excellent.

heh heh.. While trying to stop someone from scoring I tripped and fell into the net.. I scored myself.. Luckily I wasn't hurt. I realized that it was about to happen so I put my hands out in front of me just as I fell. Those nets are heavy and you can seriously hurt yourself it you bang your head against it. We don't play with equipment either so you got to be careful.


I'm still trying to finish reading "Founders at Work" which is a great book that interviews the founders of major tech companies about what it was like to start up a company. These guys are crazy. They work crazy hours on practically no sleep.

anyways... I'm having trouble finishing the book because after a few pages I want to throw the book aside and go found a startup company. It's just silly.. I'll be sat there reading then I'll stop and wander around the apartment thinking about what sort of thing I'd like to invent and how I'd market it etc.. Eventually I'd calm down and sit back down with the book where the cycle would begin again.. It makes reading the book very slow going.

Anyway, I'm going to make some hot chocolate, sit down by the fire for an hour or two and read.. about 5 or 6 page.. thereabouts.. yeah.. bye.