zasti - what?

zas - ti - ka”. It’s a word I made up. I made it up because 99% of the good words are already taken. And the other 1% are impossible to find or remember. So, I made up a word and that’s my website.

I post stuff about programming (mysql, javascript, php), photography, and anything else I find interesting (love, relationships, traffic, etc).

This website is built with a CMS I made in my spare time. If you’d like to learn more about the CMS, go to hepcms.com. If you’re looking for my old blog, it’s at s17.zastica.com. It’s provided for posterity, and is read-only (no commenting is allowed). All the old posts and comments are here on this site also, but since the structure changed you have to go search for them. I suggest starting with the archives.

The Real Rules of Programming Lecture

This past Tuesday, I had the chance to go and talk to PLU’s senior Computer Science Class. I was given the chance to talk about “anything technical”, so I wanted to talk about what it’s like in the programming world after graduation. Bjarne Stroustrup’s recent column on What Should We Teach New Software Developers? Why? was an interesting read and provided a starting point to talk about the transition from college to the “Industry”.

I introduced Dave’s 1st Law of Programming — “A technically perfect system that doesn’t work is no good.”, as well as 5 “Rules” for post-graduate work:

  • Everything you know is wrong
  • You’re always responsible
  • Normalize until it’s right, then optimize until it works
  • All of programming is design
  • To better understand software, you must understand people

I also talked about some things that we can from those rules

  • Be smart
  • Be faster, better, & stronger
  • Your code sucks, but that’s ok
  • Evaluate, explore, and test other people’s code and applications

I also introduced Dave’s 2nd Law of Programming — “Make it foolproof, and someone will make a better fool.

View the entire presentation (with jQuery slide/presentation goodness)

I want to give a special thank you to Drs Wolff and Hauser for allowing me to come and talk to their students.

Photos from Orcas Island

I recently went on a little vacation with my girlfriend up north to Orcas Island. The first night and morning we were there, a huge storm blew in. The interior bay of Orcas is big enough to be able to create its own weather patterns. By the time weather gets to Eastsound, it can be much worse than it would have been on the exterior of the island.

This photo was taken on the morning of the big storm, looking out from Eastsound to the big bay. The weather was still a little rough at this time.

This one is on the road up Mt. Constitution, early in the morning. It was a little foggy, so there were sun breaks through the fog and clouds.

Prints are available at $10 for 8×10, or $20 for 11×14. Email Me to learn more or order.

Stopping Spam with Akismet

If you’ve ever owned a blog or written for one, you know how much of a problem spam comments can be. In fact just earlier today, Harry Roberts of CSS Wizardry posted this on twitter:

css wizardry on spam

When I originally created this site and the HepCMS backbone that it runs on, I didn’t include any handling of comments except “Save, display”. There was an option to manually mark comments as spam after they were posted, but they always made it to the public pages. I did it that way for a couple reasons. First, I was curious to see how long it would take, and secondly, I was being lazy. Towards the end of last week, someone finally figured out how to automate adding comments to my site. And it only took them 3 months. In fact, if you own or run a blog, or any site that allows anyone to publish content, you’re going to have to deal with spam at some point.

I did a pretty good job of manually catching the spam, but once once the spammer had automated adding things, I had to improve my defenses. enter Akismet. Akismet is the spam catcher that is used in Wordpress blogs. Via the Akismet API, anyone can add Akismet spam filtering to their site. If you’re already using Wordpress, you don’t have to worry about spam because they already use Akismet to catch spam content.

Since HepCMS is built on CakePHP, I did some searching around for already built solutions. I found one particularily interesting, “An Akismet Behavior” by Tom O’Reilly. The part about using a behavior at the model level of my application is that it’s almost automatic. The only thing I had to do to get it up and running was to add a tiny bit of code to my comments model.

var $actsAs = array('Akismet' => array(
    'content'=>'comment',
    'author'=>'author',
    'type'=>false,
    'is_spam'=>'spam'
));

For handling spam, this is a pretty quick solution, yet very powerful. I only spent about 30 minutes researching, installing the code, and testing it out. Once I was done, I saw the number of spam comments drop dramatically, and none reached the public portions of my site. The bottom line is that if you’re running a site that allows anyone to submit content, you need to deal with spam, and Akismet is the perfect way to do it. If you’re using Cake to run your application, a behavior is the perfect way to deal with spam.

User Login Form Usability Ideas

If you have a site where users are able to have data associated with them, you probably have a login form. You may ask users to enter their email address, or a username for your site, or even an OpenID url. If they enter the correct information, they are granted access to otherwise protected areas of the site. But, if they don’t enter correct information for some reason, they get presented with an error message and have to try again. There are two major hurdles to login form design that I am going to address.

Show their username again

When a user’s login attempt fails, it’s a pretty standard practice to unset their username and password and force them to re-enter them both. This is a bad design pattern. Users should not be forced to remember and reenter their username. Consider this workflow:

  • A user comes to your site, and enters their username and password. The username is entered into a regular text input, so it’s plainly visible to the user and anyone standing over their shoulder.
  • The user’s information was incorrect, so the page refreshes, they see an error message. The user thinks, “Oh, I must’ve mistyped my password”. However, both the username and password fields are now empty.
  • The user tries to login again, however they are momentarily disoriented by having to remember which username they use for this site. Sometimes, users might even have multiple logins for the site, so they have to remember which one they just tried to login with, and even if that username is correct.
  • The user enters their username, and the password again, and hopes to get the information correct.

If the site left the username in the field, the user would not have to remember which username they tried to use, and could focus on typing the password correctly. By leaving the username in the form, you can eliminate a point of confusion for the user, and ultimately help users use your site.

Unmasking passwords

In one off his AlertBox columns, Jakob Nielsen takes the radical position that

Usability suffers when users type in passwords and the only feedback they get is a row of bullets. Typically, masking passwords doesn’t even increase security, but it does cost you business due to login failures. — Jakob Nielsen, June 23, 2009

Personally, I don’t agree with him 100%, but since he’s the world’s foremost expert in usability there must be something to his claim. Security considerations aside, masking passwords does hurt usability. (Masking passwords means displaying bullets instead of letters and numbers — ‘••••••••’ instead of ‘password’) Why? It’s because it forces your users to think about typing their password correctly, and thinking is bad for usability.

It doesn’t matter how many times I have to click, as long as each click is a mindless, unambiguous choice — Krug’s second law of usability

I don’t think that password masking is going away anytime soon, nor should it. It is still a security concern if someone can stand behind you and learn your login information. People routinely store all their life’s information in their email inbox, so if their email account was compromised by a nefarious individual… well it would be bad.

Neilsen goes on to say, “users are sometimes truly at risk of having bystanders spy on their passwords, such as when they’re using an Internet cafe. It’s therefore worth offering them a checkbox to have their passwords masked”. This is a Good Idea, and offers a sufficient compromise between security and usability.

So, for optimal login form usability,

  • Don’t remove passwords after failed login attempts, and
  • Unmask passwords by default, but give the user the option to mask the password, for example when someone is nearby.

Add Dates to Your <title>s

One of the things I noticed from my old blog was that old content can often get mistaken for new content by people who do not read your blog regularly. The main reason is that people can see, right in search results, how old the post is and how significant it might be. Check out this image:

example image

There are two search results here — one that has a date and one that does not. The first one doesn’t give the user any indication of how old that page might be, while you immediately know that the second search result was created on Dec 14, 2009. six months from now, that page might be irrelevant, users can decide for themselves whether they want to visit the page.

If you’re using CakePHP like I am, this is very easy. In your posts controller’s view() function, add this line of code. (Assuming that $postdata is the database entry.)

$this->pageTitle = ''.$postdata['Post']['title'].' - '.date('M j, Y', strtotime($postdata['Post']['published']));

And then in your app_controller.php file, do something like this with the beforeRender() function. beforeRender gets called automatically by Cake just before any view begins to render.

function beforeRender() {
    //create page title
    $title = 'Zastica ';

    if(!empty($this->pageTitle)) {
        $title .= ' &bull; '.$this->pageTitle;
    }
    else {
        $title .= ' &bull; '.$this->params['action'];
    }

    $this->pageTitle = ucwords($title);
}

What happens is that if you set a pageTitle in any controller or function, it is automatically formatted, and your site’s name added. If you don’t set it, it just becomes “SiteName • $action”. As you can see in the image, “Zastica • Seattle” vs. “Zastica • Business Card 1.0 - Dec 14, 2009”.

The bottom line is that it helps users figure out how relevant your site’s content is from search results.

Finding Posts in Multiple Categories

When you’re browsing around a blog, it is a big help to be able to browse posts by category — it helps you find related posts you might be interested in. For example, if you’re reading a post on something having to do with mysql, you can click on a link to see other similar posts.

That’s pretty easy, and you can do it like this:

$sql = 'SELECT post_id
FROM categories_posts
WHERE category_id = '.$cat_id;

But what if you want to see posts in two categories, say mysql and php? You can’t adjust the query to use an AND, because that just wouldn’t work, and you can’t use the IN keyword, because that equates to a logical OR. So what do you do? One possibility is doing two separate queries and comparing the results. That’s not terrible efficient especially when you get more categories to compare. So, here’s what I did:

$sql = "
    SELECT Post.id
    FROM (
        SELECT post_id, COUNT(category_id) as num
        FROM categories_posts
        WHERE category_id IN (".implode(",", $cat_ids).")
        GROUP BY post_id
        HAVING num=".count($cat_ids)."
    ) postids
    LEFT JOIN posts as Post ON post_id=Post.id
";

The inner query uses the IN keyword to find all posts in any of the categories, and then groups them by the post id and counting how many rows were found. Then the HAVING keyword filters the post group results to only those rows that have the same number of results as categories I asked for. So, If I query for posts in “mysql and php”, it finds all rows with either, groups them by the post_id, and then counts up how many rows are grouped.

If a post was tagged with just PHP, the number would be one. Just MySQL would be the same. Posts without either MySQL or PHP wouldn’t show because of the IN command, but any post with both PHP and MySQL would have a 2, and be found by the query. The outer query is designed to return the list of post ids similar to Cake’s query results, so the data can be reused later to get comment and author data.

Welcome to 2010

After my sophomore year in college, I spent most of the summer living in Colorado with my girlfriend (at the time). I worked at a candy store during the day, and a brewery waiting tables at night so I could pay for school. I worked 6 days a week, and as I drove into work in the morning, the song Sunrise by Norah Jones would play on the radio. (Every day. It was like they didn’t even shuffle their play list.)

Since that summer, Sunrise has had a special significance for me. It’s a mellow song, and it reminds me of the calm the mornings of a town in the Colorado Rockies. The calm before everything goes absolutely nuts, the afternoon thunderstorm, and hordes of tourists on candy highs or little old ladies who make sure I bring them “exactly 3 sugar packets” for their iced tea.

Writing

I didn’t write much this last, which I attribute to my hectic work schedule and long commute. In November, I re-launched my site and am working on posting on a more regular basis. I am hopeful that by blogging more regularly, I can improve my writing skills and by connection my speaking skills as well. I want to start speaking and presenting this year, but it’s a long road to becoming a master web developer. Still, a journey of a thousand miles begins with a single foot step so you gotta start somewhere.

Working

In my day job, we opened an office in Spokane, so things have been mixed up a little bit. Still, we’re proving each day that we’re among the top development companies in the region.

In my spare time, I’ve launched a few new sites. Most didn’t work out, but a couple did. I’ve also started doing my own design as well. I’ve had a few chances to try it out, and I think it’s going well.

I also got a couple photos published in a couple magazines, and launched a new site for my photography business. I learned that perhaps a photography business isn’t really suited to me, but it’s really just a hobby. No harm, no foul.

Seattle

Living in Seattle has also been incredible. I love it, but it makes my commute awful. The area is awesome and lively, but it does have drawbacks. The apartment I live in was sold to new owners, and the new landlords ran the old (awesome) manager out. As a consequence, I’m looking into moving again. Hopefully this time, it’ll be into a place that I own instead of a place that someone else owns.

Dancing

I barely got out to dancing at all this last year. I was injured some of the time, and lost momentum the other times. I want to get back to dancing regularly in 2010. I’ll have to work at that a little better, but it’s worth it for the exercise and the social activity.

Onwards…

Over the last year, I’ve had many ups and downs. Some challenges I have faced well, and some I haven’t. Overall, I am happy with how everything turned out, but I hope that I can make the next year even better.

Using the Flickr API to Show Photos

Hosting and serving images or photography, and doing it well, is one of the ‘hard’ problems of web development. Most things like serving text content is trivial, but images are another story. To do it well, you have to resize the image, make sure it’s viewable on the web, store lots of data, and deal with the consequences of tranferring large amounts of data from your server to the user’s browser / computer. I was talking with Mark Atwood, and he suggested using Flickr to host my photography.

Flickr, as you probably already know, is the most popular social photography site, and they make it incredibly easy to post and share photos. Getting data from one site to another can be a pain, but fortunately, Flickr provides an API. All I really wanted to do was create a div with a specific id, and have my site grab all the photos from Flickr and display them. I wanted it to look like this:

<div id="photoset-72157622891400543" class="flickr-photoset"></div>

To do this, all I really had to do was make an ajax call to my server-side Flickr app, and then stick the photos in the div. Then, I used jQuery UI’s dialog box to popup a bigger photo when you click on it.

Check out this example of photos from my latest vacation to the Oregon Coast:

The Ampersand Broadside

I managed to snag one of Ligature, Loop, and Stem’s Ampersand broadsides. (Broadside is just another word for poster. It’s a letterpress printing thing.) The Ampersand print was a limited edition of 25, with ampersands (the ligature of the characters e and t, like in et cetera. It means ‘and’.) from different fonts, showcasing the different styles of the character.

Overall, the quality of the print is very good. Entire print is debossed, and the registration of the ink and the debossment is perfect — meaning that either the inking and the debossment was done at the same time, or that the printer was very very good. Either way, very good quality. It also has a very nice wax seal on the bottom, and the number 6 of 25 written in pencil.

One of the top edges of the print was mangled in the shipping process just a little bit, but some smoothing out made it much less noticeable. I wish that it was signed, however. The wax seal is a good addition, but for a print, it doesn’t replace a printer’s (or artist’s) signature.

The whole shebang:

http://www.zastica.com/files/uploads/c75e95fc3cd7298e2628e37e9bba4eee.jpg

Close up of the Ampersand text

alt text

The wax and number

alt text

alt text

alt text

Detail of some of the ampersands:

alt text

The corner that got mucked up. The damage is in the top right corner. It’s not too bad, and is actually prett hard to see in this photo.

alt text

Anyone know what Butter Label is? Their site was not terribly descriptive…

alt text

Business Card 1.0

Check out my new business card. I got tired of having to write down my email address or phone number on a random scrap of paper, so I went ahead and designed a “business” card for me. It’s not really for my business, since I don’t have one (except for my day job, and I’ve got other cards for that), it’s just a card for me.

Check it out:

It’s pretty simple, with just text, and the celtic knot on the right. On the other hand, it’s unique and the design is pretty striking. (If I do saw so my self.)

View more posts in the archive