Feeds:
Posts
Comments

As stated in an earlier post, I said I would would continue reading “Don’t Make Me Think” by Steve Krug.  I completed chapters 2-5 with these salient points:

  1. Users don’t typically read pages but scan them.
  2. Users don’t study the page and make the best choice.  Rather, they choose the first reasonable option and go with it (a term he calls “satisficing”).
  3. Users don’t figure out how things work; they muddle through.

Thus, he offers the following tips (all of which requires the user to think less):

  1. Create a clear visual hierarchy on each page
  2. Take advantage of conventions
  3. Break pages up into clearly defined areas
  4. Make it obvious what is clickable
  5. Minimize noise

One big problem is when the user wants to do something that might fall under two different choices (the example he uses is a user looking for a chain saw, and having to choose between “tools” and “lawn and garden”).  Strive to make your choices as mutually exclusive as possible to prevent potential overlap over two choices.

Finally, he offers the following additional points (once again reducing how much users need to think):

  1. Reduces noise level
  2. Makes useful content more prominent
  3. Makes pages shorter – less scrolling
  4. Get rid of “happy introductory talk” that anyone who has used a web-site would understand
  5. Get rid of instructions – organize to make as self-explanatory as possible or if instructions are needed, offer them Just In Time.

In truth, I have already read chapter 6, but it is long and I am taking my new wife to visit Monticello in Charlottesville today.  I will be working on that on the way down, so I should post on it very soon.

I decided to play around the more basic aspects of Google Maps, and put together a working demo with a bunch of comments in the HTML.  It covers most of the basic parts to get quickly up and running.

You can view it in action at http://wdwescort.com/other/maps/maps_example.html, and then get the page source to roll your own.  Please note that if I move it later, I will add a comment.

I will add some additional capability this week-end when I play with this some more.

BTW – There is a Version 3 of Google Maps in the lab, but I am working with version 2 right now.

It appears in the browser as follows:

Google Map Image

Putty

Three years ago I remember feeling somewhat intimidated by the idea of trying to use Putty to work with a Linux build server (as I knew nothing about Linux commands).

It may not seem like much, but today I had a friend who wanted to play with some Linux commands even though they had a Windows box.  I proposed that they install a Ubuntu VMWare image, but then thought of something easier.  I added a new user account for them on my virtual Ubuntu server, gave them the userId, password, and IP to log-in and play on my system.

To do this, I installed Putty on my Windows VM image and used it to connect to my server and do the setup.  So simple, so easy – what could I possibly have been nervous about?!

Don’t Make Me Think

I just started reading “Don’t Make Me Think” by Steve Krug, which I like very much.  I have only completed the first chapter, but I like the central premise, which is as follows:

Don’t design your site in such a way that users have to think about how to move forward on their desired tasks.  If you do this, your site will be perceived as better functioning.

A lot of this has to do with some of the following as examples (there are many more in the book):

  • Easily understood labeling so that users don’t have to pause to figure it out.
  • Using buttons for actions as opposed plain text or flat graphics (so they don’t have to mouse over to see if clickable)

I remember doing an informal usability assessment of a product where I had struggled with flat graphic buttons that look like labels.  It looked slick, but I had to spend too much time trying to figure out how to work it.  This needs to be balanced with looking old-fashioned, as a good looking application can also cause people to perceive it to be better functioning.

After reading this, I find myself becoming more sensitive not only to the web site I am trying to create, but also one I was using recently:

  • I had to go through a series of steps, but I had no feedback on how many steps there were, and how far along I was.  Thus, I had this big unknown on how long I would be stuck in front of this application, distracting me from the task at hand.
  • What I was reading was displayed in slow steps; but when all the content was delivered, I was given no indicator on the task being complete or not.  Thus, I had to keep thinking about whether the sub-task was done, instead of being able to fly ahead.
  • I had a done button that was used for two different sequential tasks.  When I finished the first task, I spent a lot of time trying to figure out how to move on as this was not clear.

Jared Spool visited us at a previous company and asserted that one of the most important aspects of good usability was having all the engineers striving for good usability, as opposed to blindly working with a usability team.  How much stronger is that than giving a bunch of engineers a usability style guide and hoping to get usability from that?  I definitely buy into his book, and look forward on completing and writing more about it.

Thinking Operationally

This blog is hosted on WordPress, which takes care of so many operational details for me.  Essentially, if I can use a word processor, I host my blog on WordPress.

Now, I am creating my own virtual Ubuntu server on SliceHost to host my Rails app.  There is so much more to think about!  I have been using Neeraj Kumar’s excellent write-up on moving your Rails applications to a slicehost server, and have begun creating shell scripts for automation.

Of course, I have not done the Phusion Passenger and Capistrano stuff yet because I need to learn those technologies (I am reading the Pragmatic Programmer’s book on Deploying Rails Applications, which has been pretty good).  I find myself thinking of so many things:

  • I have scripts for creating a new virtual machine image, but what about recreating a new Ubuntu VM image that uses fixed versions of the open source software?  I don’t want to recreate later and have new versions introduce instability.
  • How do I configure Apache appropriately?
  • How do I set up my Ubuntu Server as a Git client of my Github repository?
  • How do I set up Phusion Passenger and Capistrano appropriately?
  • How do I set up the appropriate security mechanisms at the server as well as in code to thwart evil hackers?
  • How do I appropriately image my server?
  • How do I appropriately backup and restore my server, as well as backup the database externally?
  • What is my operational plan in case things go wrong?
  • How do I appropriately phase and test things as I move from Development through Production?
  • How do I appropriately heart-beat?
  • What am I forgetting to think about?

These are certainly not concepts that are new to me.  I had to think about the operational details and approaches for the features I developed at my previous SAAS position.  However, there was an operations and test team to work with.  Now it all falls on me so I need to dig a lot deeper.  Its going to be fun!

On a happy note, my solution is working in its production environment in a bare bones manner.  Essentially, the default install of Apache is returning “It Works!” when you access my site.  I have a ways to go…   :)

I remember trying to use vi, again, six months ago. I started typing, and the app exploded once again.

While configuring my Ubuntu server today, I have no choice but to use vi (I usually fallback on TextMate’s mate on my Mac). Just using the following, I was able to do everything I needed to do without leveraging vi’s other strengths:

  1. Bring up vi for your file (e.g., vi file_I_want_to_edit).
  2. Realize that you are in ‘command mode’; thus, do not try to edit your file, yet.
  3. Position the cursor to where you want to do some editing.
  4. Hit ‘i’ to edit before the cursor, or ‘a’ to edit after it. You should see “—INSERT—” on the bottom left of the screen.
  5. Edit away. Add new text, delete, or paste in things until finished – be creative! ;)
  6. Hit the ESC key, which moves you back into ‘command mode’ (“—INSERT—” is now gone).
  7. To save the file, hold the shift key down and hit ‘z’ twice.

While I did not take advantage of vi, I was able to do the basic editing I needed to do. Enjoy!

Uninstalling Gems

I need to get rid of some ruby gems to standardize my development environment before I begin creating my production environment on Slicehost.  I ignored gems when I first started working with Rails and just followed the given setup instructions, but now it is time to dig in.

My Macbook Pro had a pre-existing Rails environment.  Thus, I have tons of pre-existing ruby gems I want to get rid of first. However, when I do the following:

gem uninstall geokit

I get the following:

ERROR:  While executing gem … (Gem::InstallError)
Unknown gem geokit >= 0

To get around this, I needed to get the install directory for this gem and then specify it when uninstalling:

gem list -d geokit

*** LOCAL GEMS ***

geokit (1.4.1)
Author: Andre Lewis
Rubyforge: http://rubyforge.org/projects/geokit
Installed at: /Users/JRagan/.gem/ruby/1.8

Geokit provides geocoding and distance calculation in an easy-to-use
API

I then specified the actual path to uninstall it:

gem uninstall –install-dir /Users/JRagan/.gem/ruby/1.8 geokit

Successfully uninstalled geokit-1.4.1

Happy day!

I found this and well as a number of useful gem cheats at http://cheat.errtheblog.com/s/gem/

Except for what little Unix I had in college, I mostly used a Windows laptop until last year when I got a MacBook Pro.

Last week I read Mark Sobell’s excellent “A Practical Guile to UNIX for Mac OS X Users”, playing around with various commands and writing scripts.  I got an appreciation for how much UNIX had affected the design and naming of Java.

I was going to blog about it when I decided to add my picture to my blog, but I could not find it.

My first tool to solve this was using Finder with thumbnails, but  this was not working and was time consuming.

This gave me a real world use case to try and use Linux, which became my second tool.  If I was a master of Linux, I am sure I could have found a single line command to list all the directories that contain a JPEG file.  However, I am not that Linux master so the best I came up with was the following that listed all the full matching paths of any JPEG file:

find . -name *.jpg

The resulting list did not contain only the directories, so I threw together a Ruby script to strip off the file from the path and add it as a key to a hash if the key did not already exist:


s = "not_nil"
dirs = {}

while s != nil do
  s = gets
  if s != nil
    m = s.gsub /\/[^\/]*.jpg$/,''
    dirs[m] = 'value' if !dirs.key? m
  end
end  

dirs.keys.each do |key|
  puts key
end

I then went ahead and piped everything together:

find . -name *.jpg | ruby get_directories.rb | sort | less

This gave me a master list of all the directories I could look over to see if the file was there.

In the end, it didn’t help.  I then remembered the Faces feature in iPhoto, and found it two minutes later.  Turns out that was the right tool for the job.

When I first started working in Rails, I went with TextMate on my Mac.  I really like TextMate, but trying to debug problems was really, really painful and time consuming at first.

A few tips would have gone a long way:

  • I really did not understand how to use “script/console” to debug problems; now, I use it all the time.
  • I did not know how to use “yell”; instead, I spent a lot of  time searching for statements in really large log files.
  • I did not know how to leverage the console to see what was happening and which controllers were getting invoked.  Once I understood these things, debugging got to be a lot easier.

Now, I really do not miss having a debugger. As someone who has used Eclipse and similar environments for the last 15 years, I find this shocking!  I did a trial of Aptana, and after that was unable to re-install the non-professional version.  I now have Rubymine, but I rarely need debugging help.

Tonight, however, I needed a debugger to be more productive.  Instead of firing up RubyMine, I decided to give RDebug a try.  Though it is limited as a command-line debugger, I am very impressed.

I simply added require ‘ruby-debug’ to the top of my file.  For my breakpoint, I added the statement debugger, and then executed the program.  When it hit that line, it dropped into a command-line debugger.

There are a number of commands, but the following took care of what I needed:

  • (p)rint.  Prints out variables:  p foo.id
  • (n)ext.  Kind of like step over
  • (s)tep.  Kind of like step into
  • (c)ontinue.  Self explanatory
  • (e)valuate.  Self explanatory

At least 80% of the time, you won’t need a debugger.  When you do, the above should cover what you need for 80% of that.  Which means you should rarely need a more powerful debugger than ruby-debug.

When you first start to learn Rails, you read about Model Validation, which consists of statements such as “validates_numericality_of :the_field”.  This prevents non-conforming models from being saved.  Properly leveraged, these help ensure business constraints with an iron fist (excepting validation override).

Where to Best Enforce Business Constraints

Web apps constantly process form inputs and do the following:

  1. Ensure inputs conform to business constraints (e.g., is the value only 1 to 60)
  2. Give the user feedback on non-conforming inputs to allow changes.

This validation is typically done at one of the following three levels:

  1. Controllers.  This is the last place validation should be done, but it is often the most tempting.  Keep controllers as lean as possible and place business logic in models to conform to MVC.  If your system exposes an API, controller business logic will be missed or duplicated.
  2. Method within Model.  This is an improvement.  Controllers can invoke this method to ensure business constraints prior to the models being saved.  Furthermore, the logic remains in the model.   However, if the controller forgets to invoke this method, then the logic is missed.
  3. Model Validation Statement or Validation Method. This is the most iron-clad way to enforce system constraints.  If they do not conform, they simply cannot be saved (unless you use the Rails option to ignore validation, of course).

In addition, the testing of the model business logic can be handled in the unit as opposed to functional tests.

Potential Problems

When first moving existing validation logic into the third option, you should expect to spend some time updating previously less strict test data.

Sometimes you will run into problems with what I call phantom models, as follows:

  1. In response to multi-step user input, a blank phantom model instance is first created.
  2. After all appropriate inputs are received, this phantom model is updated.
  3. You later add validation(s) to the model.
  4. Step 1 no longer works because a blank model does not conform to the new validation.
  5. Thus, you need to either refactor, remove the validations, or add the blank model without validation being enforced (with the risks of invalid data in the database).

The control Rails gives you over generated error messages using declarations is also not ideal.  Consider the following for a field named minutes_running:

:message => “must be a whole number between 0 and 60″

This will generate the following message:

“Minutes Running must be a whole number between 0 and 60″

Want a different message that does not begin with the database field name?  I would love to know how.

Declarative Constraints

What I like best about doing this at the model level is the declarative approach.  You simply declare the constraints, which is simpler, faster than coding, and clearer later on to you and others.  If not powerful enough, you can also write validation methods and declare them as being part of model validation.

One mistake I made was not realizing how flexible and configurable these declarative statements are.  The following (trimmed) sample from a single model ends this article:

validates_presence_of :user_name
validates_presence_of :run_count,
    :if => :can_process, # boolean entity in model, could also use boolean method
    :message => "must be specified if this can be processed"
validates_numericality_of :minutes_exercising,
    :greater_than => -1,
    :less_than => 61,
    :only_integer => true, # no floating points allowed!
    :message => "must be a whole number between 0 and 60"
validate :some_method_with_complex_validation?

Older Posts »