24
Feb 10
3

Final – Design Per Day

After nearly a year and several more revisions, I finally implemented a design I actually like (for now). I’m happy with pretty much everything. I like the colors, the general layout, and the font, while basic, is nice. I am not a “typeface guy,” so if you have a recommendation on what I should use, I’ll listen.

One piece I’m particularly happy with is the section under the “No Unread Threads” heading. It has always bothered me that when a user with no unread threads visits the site, or once a user is finished reading his threads, the site loses a lot of its immediate value. Without a list of things to do, the user typically leaves the site. He’ll be back soon, but why not try to keep him there a little longer. Giving just a few options in that blank state will hopefully spark a little more activity.

All the previous designs were made with unread threads displayed, so here is another shot with a few of them for a more direct comparison.

I still find red to be a difficult color to work with. Finding the right shades of red, tan, and gray that all blend well is a challenge. As I said earlier, this will do for now. There are more important matters to take care of before needlessly changing the theme again.

11
Nov 09
0

Tortoise, Windows and svn2git

If you have been thinking about making the switch from Subversion to Git, now is the time! svn2git is a great tool to make your transition much easier. It will import an existing Subversion repository into Git while maintaining all of your change history. It will even create branches and tags in your Git repository that match those from your Subversion repository. Check the readme to get started.

You may want to start the conversion on a weekend as it does take some time to complete. It took overnight to complete the conversion of a 300mb Subversion repository with roughly 6000 commits and 30 branches.

If you are running Windows, I’m guessing you are using TortoiseSVN, and you will probably want to use TortoiseGit. It is very similar to TortoiseSVN so you should not have any trouble adjusting assuming you understand the basic workflows of Git. One important thing to note is you will want the AutoCRLF setting set to true in your Git config. TortoiseGit can help you set this setting in the Settings -> Git -> Config dialog. You’ll see a checkbox labeled AutoCrlf and odds are it is already checked. Unfortunately, this checkbox is not guaranteed to be an accurate reflection of the real setting, so open up projectroot/.git/config in a text editor and add autocrlf = true underneath the [core] section if it is not there.

One last tip on the conversion, follow these instructions from Github if you experience problems with files marked as modified when they do not appear to be.

The problem is that your core.autocrlf option is likely not enabled. This setting tells git to convert the newlines to the system’s standard when checking out files, and to LF newlines when committing in. Once this is set, you need to reset your repos. The best way to do this is wipe out your working tree (all the files except the .git directory) and then restore them.

Good luck with your transition.

Tagged: ,  
5
Nov 09
0

Less than Null

Here’s a fun javascript tidbit that can bite you if you aren’t careful:

>>> null >= 0
=> true
>>> null <= 0
=> true
>>> null > 0
=> false
>>> null < 0
=> false
>>> null == 0
=> false

I can’t think of any way to make this more inconsistent. In C# the expression will always evaluate to false (and you get a compiler warning, but let’s not get into that). In ruby, a NoMethodError is raised because the < operator is treated as a method on the nil object.

Unfortunately, due to the weakly-typed nature of javascript you are more likely to run into this problem than you might think. Because

>>> "0" == 0
=> true

there is a good chance you will find yourself comparing strings to integers, and eventually, null to integers.

No idea where the designer of javascript came up with this functionality, but now that I found it, I’ll be watching out for any potential null comparisons in the future.

14
Oct 09
2

jQuery Weighs Less

Well, that may not be 100% accurate. Unobtrusive JavaScript is likely to weigh less in a Rails application, but that doesn’t get fan boys riled up enough.

In a standard Rails application, Prototype is included by default as the JavaScript library and several of the html helper methods used in the views will generate Prototype code for you. A great example of this is link_to_remote which generates a link that will make an AJAX request to the desired url.

This Rails view snippet was found in my forum app:

<%= link_to_remote "delete", :update => nil,
  :url => post_path(post), :method => :delete,
  :confirm => "Are you sure you want to delete this post?" %>

And it generates this html mixed with some very obtrusive JavaScript:

<a onclick="if (confirm('Are you sure you want to delete this post?')) {
    new Ajax.Request('/posts/1', {asynchronous:true, evalScripts:true,
      method:'delete', parameters:'authenticity_token=' +
      encodeURIComponent('abcde')
    });
  }; return false;" href="#">delete</a>

There is nothing really wrong with this code. It works fine and did the job while it was in production. The problem is this one link is found in every single post on a thread page. This means the giant link can be repeated on the page hundreds of times.

After I made the switch to unobtrusive jQuery, I wanted to see exactly what kind of a difference it made in page sizes. I looked at three different thread pages, one with 1 post, one with 94 posts, and one with 306. Here are the page sizes (in bytes) and they show a pretty remarkable difference.

# of Posts jQuery Page Size Prototype Page Size % Difference
1 5,450 6,568 20.5
94 103,671 129,641 25.1
306 270,736 350,170 29.3

The difference ended up being quite a bit bigger than I was expecting and really helps sell me on jQuery. Unobtrusive Prototype could no doubt have dropped the page size just as much, but I’ll be sticking with jQuery from now on.

23
Aug 09
5

An Apple Tablet Won't Happen

Why won’t Apple make a tablet that is just like a bigger iPod Touch? Ask Steve Ballmer. The experience for developing for the iPhone is so awesome compared to other phones because there is only one screen size and resolution. Removing that part of the equation will place the iPhone on par with its Android and Blackberry competitors. One screen size across every device isn’t the only competitive advantage the iPhone and iPod Touch have, but is it worth it to find out exactly how important it is?

At JavaOne this year, a new design tool (similar to Expression Blend) for JavaFX was demoed and the developer showed off how easily you could change the view to match several different cell phone or desktop resolutions. I could feel the groaning as other developers in the room began to imagine themselves trying to develop like this. It looked like one of the most painful experiences possible (yes, even worse than making your site look perfect in IE6). I’m sure Apple could come up with some fantastic design tool that would be the best multi-resolution design tool in the market. It might even make life easier, or should I say “less difficult,” but it won’t fix the underlying problem.

Don’t expect to see the rumored tablet unless it runs normal OS X. Apple has made enough poor decisions already (with the App Store at least), that it doesn’t need to make any more and ruin a great development experience.

16
Aug 09
0

Implementing Who's Online with Rails and Memcached

I have wanted to add a “Who’s Online” feature to my forum site for quite some time. Users are more likely to stay and post if they know someone else is there to read what they write. In the first implementation of the site, back in the Rails 1.2 days, sessions were most easily stored in the database with the ActiveRecord SessionStore. This made fetching who is currently using the site easy as all of the necessary information was stored in the database.

Once Rails 2.0 came out, the default session store was using browser cookies. Now it was not so trivial to determine who is on the site. One option was to add a new column to the User model and update it every time the user accessed a page. While this would work, it would mean an extra SQL read and update for every page accessed. The server would have no trouble handling the extra load, but I decided to wait for a better option.

Having not seen a better option in the latest releases of Rails, I implemented my own solution and got my first experience with memcached along the way.

First things first, get memcached installed and running in verbose mode for development:

sudo port install memcached
memcached -vv

Next, set the Rails development environment (in development.rb) to use caching and memcached as the cache store:

config.action_controller.perform_caching = true
config.cache_store = :mem_cache_store

The real work is done by a method in application_controller.rb

before_filter :set_online_users

def set_online_users
  return unless logged_in?

  current_user.last_seen = Time.now
  users = Rails.cache.fetch("online_users") { [current_user] }
  @online_users = users.collect do |user|
    user if user.last_seen > 5.minutes.ago
  end.compact
  unless @online_users.include?(current_user)
    @online_users << current_user
  end
  Rails.cache.write("online_users", @online_users)
end

The final solution is a fast (not verified by benchmarking) solution with zero extra database access. Some readers might notice this is not a thread-safe solution. All lines between the fetch and the write call should be wrapped with a mutex of some sort, but I will leave that for another time.

If you the looking for extra reading, especially about memcached, Railslab: Epsiode 8 is an excellent resource for getting started with memcached and Rails.

Tagged:  
4
Aug 09
0

HappierHour Mobile Sneak Preview

The full web interface for HappierHour has been improving from month to month, but with the summer came significantly more “usability testing” from mobile phones. From the start, we tested on phones to ensure the interface would be mostly usable, but it is time to make a first-class mobile interface.

HH Home Bars list

Tonight's Specials New Special

Look for a release in the coming weeks that will include the new interface. If anything looks off or you want to request a mobile-specific feature, leave a comment.

27
Jul 09
3

No Updates, Thank You

Updates are an important part of the software industry, but for some reason, they are extremely feared. This guy who is switching away from Lotus Notes lists his reasons for leaving:


3. No more waiting for the AdminP guy/gal to do his/her work.
4. Way too many fixes on Lotus Fix List databases.
5. Killnotes.exe should be more of an attitude than a program.

I can’t understand why “way too many fixes” would be a problem. Certainly, way too many bugs, or way too much time to install fixes could be an issue, but those likely aren’t the problem because they weren’t mentioned. Far too many people have an irrational fear of software updates. When it comes to operating systems, updates mean the vendor did a poor job writing the software and is now finally getting around to fixing bugs that you never experienced anyway. In the web world, updates are agile and mean new features are being released. Why does such a dichotomy exist? Perhaps it stems from the interaction with the actual update process. If something is obtrusive and sucks, people hate it (and they should), but if something is so seamless and transparent that you might not even realize it’s happening, then what is there to hate?

Joel and Jeff discussed updates in their latest podcast and Jeff recommends the Firefox model where updates are as close to transparent as possible (for a desktop application). This is a great strategy and makes a lot of users happy, but unfortunately, it doesn’t always work for all companies, especially when they are trying to update someone else’s software. Read the first page of search of “microsoft firefox silent update” and you’ll be blasted with words like “sneak, sabotage, infiltrate, and invade” because a plugin was installed silently.

The best update model is the no-control model. Don’t give users the ability to see that an update is happening, let alone stop it from happening. This is basically the model of the web. When website owners decide it’s time for you to upgrade, you are getting that upgrade. But if you are using this model, you must be very confident that an update is going to work every where it is used. Having never written a piece of software that is used by millions of people, I can only assume this is a monumental task, but with some practice, it is no doubt achievable.

You don’t necessarily have to have a web application to get this model either, although it certainly helps. When every user is always running the latest version and doesn’t have the option to go back to previous versions, you save so much effort on support and maintenance. The benefits of supporting only one version of software far outweigh the risks taken to do so.

Maybe hating software updates isn’t such a bad thing after all. You have to know an update is happening to hate it.

15
Jul 09
6

Press F5 to Refresh

Not trying to kill anyone, but here is the refresh my blog so badly needed. The old theme made it far too difficult to find the RSS feed link. I typically use the special Firefox or Safari link to grab the RSS url, but finally realized Chrome does not do this, so a link that is a little more in your face will fix that.

RSS Link Chrome RSS

I did not do anything fun to design, but have been planning this for quite some time. I drew a lot of inspiration from the lightword theme. Feel free to comment and tell me if it does not look right in Windows or IE.

Tagged: ,  
14
Jun 09
0

A Comet-Enabled Lift Application

At JavaOne, I attended a session given by David Pollak the creator of the Lift Web Framework. In his hour session David built, from scratch, a functional, comet-based chat application. Although short, and relatively simple, David’s talk was compelling enough for me to at least investigate Lift.

I purchased The Definitive Guide to Lift while at the conference and was able to read (note I didn’t say understand) through most of it on the plane ride home. One chapter deals specifically with adding AJAX and Comet to your application enabling push support. It covers almost everything needed to complete the Comet app but it is missing a few important lines, most notably the call to start in ClockMaster.scala.

I posted a fully working copy of the code on Github for anyone trying to use the code from the book. Hopefully it will help anyone else who got stuck in the same place I did.