Supporting You Are Not So Smart

I've been following the You Are Not So Smart blog for a while now and frequently share its posts on Google Reader. The author, David McRaney, writes about human thought and behavior, drawing on research conducted over the last several decades. David describes it as "a blog devoted to self delusion and irrational thinking." It's a great read and I highly recommend it. There's a book coming out soon and I think this is a cause, and a creative professional, worth supporting, so I'm including the book's YouTube trailer below. Doesn't hurt that he's offering bribes for posting the video! It's only 3:37 long and well worth watching.




And a quick note for readers in the Richmond, VA area: I will be presenting Building Optimized Rich Web Applications with Java, an introduction to Google Web Toolkit at the Richmond, VA Google Technology Users Group tomorrow. It's not too late to sign up for the meeting, which is free to attend.

Google Analytics in Real Time

I just got accepted to the Google Analytics Real-Time beta. So, now I need everyone to go browse my blog so I have some real-time data to look at! And get your friends to come by, too. In the name of load testing, you know.

Charlottesville, VA beCamp 2011

Wow, what a great weekend at beCamp this year! I missed the setup and introductions because work kept me late Friday night, but I made it in time for proposing session topics (and pizza, of course). Running a session on Google Web Toolkit last year was a big thrill for me. I proposed GWT again, and ChromeOS, hoping to talk about my experiences with my Cr-48 since December. My GWT session got the same number of votes as last year, despite attendance being down something like 40% this year. Go me! ChromeOS didn't make the cut.

My first experience as a conference speaker was at beCamp 2010. In the spirit of the event, I proposed a session on GWT despite having no slides or other materials prepared. I got votes. I got scheduled. When I found myself in front of a dozen people with nothing prepared, I just started talking. I like GWT. I love using it. So, I went with that. What is GWT? Why do I use it? What do I love about it? That's what I talked about. And people asked questions. Lots of questions. I answered as many as I could as well as I could. People thanked me. This speaking thing wasn't so bad after all. I was even asked to give a presentation on GWT to the Richmond, VA Java User Group. I agreed. I obviously had a lot to say on the subject, and based on the response I was getting, people wanted to hear it. So I set about building slides for a presentation. I did my research. And in October 2010, I presented to about 25 people at the RJUG meeting. Nerves and a few technical issues aside, it went well. Now here I was, back at beCamp the following year, giving the presentation again. And people liked it. That feels good.

I gave the presentation using my Cr-48, only slightly disappointed that nobody wanted to hear about that too. But then after the session, I was approached. What was that notebook I used for the presentation? Oh, that's my Cr-48, a prototype Chromebook. I knew from the voting the night before that at least a couple of people were interested, so I was glad one of them had picked me out of the crowd later to talk about it. Then at lunch, more people gathered around interested in seeing it. Should I have put "Chromebook" on the topic card instead of "ChromeOS?" Are people more interested in the hardware than the operating system, or just more interested in seeing it in action? I'll propose the topic again next year, maybe under a different heading. I'll probably still be using the Cr-48 anyway, so if you're there and you want a look at it, come up and ask!

Thanks again to the organizer, Eric Pugh, all the sponsors, and everyone else who made beCamp 2011 possible. See you next year!

GMail TODO Script

After reading GMail Snooze with Apps Script I thought "Gosh, that's almost what I need to make GMail my go-to TODO list platform." Well, I finally sat down and closed the gap.

var MARK_UNREAD = true;
var MARK_IMPORTANT = true;
var ADD_TODO_LABEL = true;
var TIMEZONE = "EST";

function setup() {
  if (ADD_TODO_LABEL) {
    GmailApp.createLabel("TODO");
  }
}

function reviveTODOs() {
  var todayString = Utilities.formatDate(new Date(),
     TIMEZONE, "yyyy/MM/dd");
  var todaysLabel = 
     GmailApp.getUserLabelByName(todayString);  
  var page = null;

  // Get threads in "pages" of 100 at a time
  while(todaysLabel 
      && (!page || page.length == 100)) {
    page = todaysLabel.getThreads(0, 100);

    if (page.length > 0) {
      GmailApp.moveThreadsToInbox(page);
      
      if (MARK_UNREAD) {
        GmailApp.markThreadsUnread(page);
      }

      if (MARK_IMPORTANT) {
        GmailApp.markThreadsImportant(page);
      }
      
      if (ADD_TODO_LABEL) {
        GmailApp.getUserLabelByName("TODO")
          .addToThreads(page);
      }          
    }     
  }
}

Instead of using "Snooze x Days" labels, I use date labels like "2011/08/11" to remind myself to follow up on bills, respond to emails, etc. With this modified version of Corey Goldfeder's script, I don't have to remember to check those labels, they just pop back into my inbox automatically. I had a little problem with the markThreadsImportant call not seeming to work. Don't know what's up with that. But otherwise, it has performed well so far in testing.

Update: Be sure to set the timezone that the script will run in and the timezone used to format date labels to the same timezone. See Using Time-Driven Triggers.

Like this script? Have your own variation? Please share!

RVA GTUG - August 2011 Meeting

I'm thrilled to announce that on Thursday the Richmond, VA Google Technology User Group met for the first time. It was fantastic seeing familiar faces and also meeting some other Google enthusiasts for the first time. This is my first experience as a community organizer, so I'm excited to see how things will develop from here. We have good people who believe in the group and I'm confident we'll continue strong. Thank you to all of our members!

Special thanks to Genworth Financial for supporting the local Google developer community by letting us meet in their offices here in Richmond. If you or your organization would like to support this community, please contact me through my Google Profile or the RVA GTUG Google Group forum.

Anyone interested in membership in the RVA GTUG, please join the Google Group and introduce yourself. If you are interested in developing with Google technologies but aren't local to Richmond, VA, you can find over 260 other active and incubating GTUG chapters at gtugs.org.

Going in Circles with Google+

My Circle Problem

Trying to create Circles in Google+ can get confusing. The taxonomy of relationships - or at least my relationships - is very, very complicated. Let's start with a Circle for friends - but not all friends are the same, really, so let's make that close friends and acquaintances, two Circles - then a Circle for family. But who actually treats all family members equally when it comes to sharing? Immediate family, extended family, in-laws, etc... more Circles. Now co-workers, people I met years ago at a conference, people I've never met but sometimes care what they have to share, etc...

Relationship taxonomy is too complex! And then I have to decide, when I go to share something, is this for my close friends? My immediate family? My in-laws? Well... yes, some of them. Not all of them. But I can't be bothered to name each individual, that's what the Circles are for!

My Circle Solution

Create Circles based on content you share, not relationships.

What does that mean? It means, think of something you share - say, vacation photos. Now make a "Vacation Photos" Circle and add to that all the people you like to share those photo with: your parents, siblings, most of your close friends, the in-laws you like, and so on. Now make one for news about your garden, your stamp collection, or whatever other hobby you have, group you are affiliated with, etc. Add people who share that hobby, affiliation, or interest. See how this goes? Repeat as necessary. Now, when you go to share, you just pick the Circle you built for that topic.

I have one other circle, "Following" which is for all the people I want to subscribe to posts from, but probably won't share with directly. I can't see myself ever using the "My Circles" or "Extended Circles" sharing options - why not just make it public? If you "Follow" anyone like I do, and I expect anyone coming from Twitter will be into that habit, then "My Circles" or "Extended Circles" might as well be public.

Oh, and the redesign

I'm the first to admit, I'm not much of a graphic artist. I always tell my project managers to hire a professional designer so we can get great looking web sites. They never listen, so I get a fair bit of design experience in the trenches. At least, I learn some of the technical side of it. I still can't get the aesthetic bits the way I want them to save my life. So, I finally sat down and redesigned the Blogger template used on this blog. The look is based on another site I'm doing for myself, my first real personal web site. I'll probably write more about that later. It's a slow work in progress. In the mean time, enjoy the new look here. Or don't. Feel free to leave comments. I won't be offended.

Update on Picasa album re-sharing and Google+

This is the notice displayed on Picasa Web Albums since joining Google+. It reads:

You've recently joined Google+. Note the following changes to Picasa Web Albums:
  • Albums you've shared can in turn be tagged and shared by others.
  • For new albums, anyone an album is shared with can see who else it is shared with.
  • When you tag someone, they receive a notification and can see the photo and the related album.

I understand that sharing transparency and re-sharing are features that make Picasa albums more social, but I would really appreciate the option to turn them off. Sometimes I want to be less social. There's already re-sharing controls for individual posts on Google+. Why do you need to open up my albums too?

Google+ Invites: Here This Evening, Gone by Morning

I sent out my first invites for Google+ last night. I posted about it and expected I'd invite a few more people in the morning, only to wake up and find the invite option was gone. According to Vic Gundotra invites were switched off due to "insane demand." Hopefully we'll see them on again soon.

So far, I'm quite happy with Google+. The privacy model makes sharing scope much more prominent than other social networking sites (why name names?). It's easy to tell who a post will be shared with and I can change that scope as I see fit using "circles" (a.k.a., groups, lists, etc.). +1 is already implemented, of course. I'm looking forward to trying a "hangout" group video chat once a few more of my friends are on board.

Google+ Me

I received an invite to Google+ (Google's latest foray into social networking) this afternoon, just hours after it was announced. My first impression is that they're going to need to tighten up the default privacy settings. Just getting through the signup process meant agreeing to have my Picasa photos and videos displayed on my Google Profile page (which I immediately went to and turned these things off). And although my "circles" are empty initially, these are also displayed on my profile by default. Turned that off too. One thing I can't seem to turn off is that joining Google+ made it so that people I share my Picasa content with can then share that content with others. Not cool, Google. Give me back control of my content. I realize it's impossible to actually prevent my content from reaching third parties after I share it (shoulder-surfing, save, etc.) but I should have the option of whether to let other people re-share my photos and videos through Picasa.

I'm still looking around, but I haven't found a way yet to invite anyone else to join Google+. So, unless my friends and family sign up and get invited (unlikely given past experiences) I may be alone here for quite a while. On the plus side (pun absolutely intended) it says that non-Google+ users I add to my circles will still be able to receive links to content I share, they just can't interact with it the way a Google+ user could. Oh, well.

The Main() Conspiracy

Typical Java

I was browsing StackOverflow this evening when I came across this question. The question itself isn't anything special, but the quote from the Thread JavaDoc caught my eye:

"When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class)."

"Typically" calls main()? I mean, sure, you could call java SomeClassWithoutAMainMethod and the JVM would start up, cough, and die. But that hardly seems worth a parenthetical shout out in the JavaDocs, right? There's got to be more to it than that.

Static Initialization

So, how can we write a Java program that runs without a main() method ever being called? We'll need code that exists outside of a named method that we can get to run before the JVM discovers the main method is missing. What happens before main() is called? The class that is supposed to contain main() gets loaded. And how do you run code when a class is loaded? Static initialization!

public class Mainless {
        static {
                System.out.println("Mainless!");
                System.exit(0);
        }
}

And there you have it: a Java program with no main() method. The static initialization block runs when the Mainless class is loaded, before the JVM tries to call main (which, you'll note, doesn't exist). "But wait," you say, "I was taught in Java 101 that every program has a main() method!" And like much of what we learn in school, that isn't strictly true. Why the conspiracy to keep Java developers writing public static void main(String[] args)? Well, it does have practical uses. For example, you can't pass arguments to the static initialization block. You could set environment variables before running Mainless and access those variables, but that's just ugly. And, you have to call System.exit() at some point or you'll get an error message about the missing main() method.

The big question: why?

But, is there any point to this? Not as far as I can tell. There's no practical use of this technique that I know of. You save a little bit of typing and get an obscure piece of code that might confuse a lot of Java developers. And I'm sure somebody, somewhere, uses this fact in an obnoxious "gotcha" interview question. I hate those.

In case you missed April 1st

In case you missed April Fools' Day today, here's a recap of some of the foolery that came my way:

Cofoja - Java Annotations for Contract Programming

This afternoon, Google announced another open source tool for Java developers. From the examples they give, it looks like Contracts for Java, or "cofoja" is assertions for abstract methods. Interesting. Looking forward to trying this on my next Java project.

Obligatory First Post From Blogger Android App

Oh, right... content. Okay. I'm posting from the new Blogger Android app. I was going to link the blog announcement, but I don't see a way to add a link here. Oops.

This is a picture of a door, taken while I am writing this. Wait, where is the picture going to appear in the post? I can't tell! So... this app needs work. Oh, well.


Update: Back at the desktop, here's the link to the new Blogger Android app. And it appears that pictures show up at the end of the post. Enjoy the door.

public int Twitter

If you would like to get your public int updates via Twitter, you can now follow @publicintblog. In addition to the automated new post feed from Feedburner, I may tweet other little tidbits I find that don't warrant a whole blog post.

See you in short form.

WebGL on Cr-48

Google released the first Chrome OS updates of 2011 to the Cr-48 today. The new version on the development channel includes Chrome browser version 10.0.634.1. Chrome 10 has (among other new features) WebGL support, which I've been eager to try on the Cr-48. The results, I'm afraid, have been disappointing so far.

WebGL Aquarium

If you've seen WebGL, then you've probably seen this demo. You've probably also seen it produce surprising frame rates for browser-based 3D graphics. The hardware in the Cr-48, I suspect, just isn't up to the job. Even with only one fish in the tank, I got a depressing one frame per second. I think one was being generous.

Body Browser

I love this one - just not on the Cr-48. The app isn't just slow, like the aquarium demo, it's unusable. But definitely check it out for yourself if you haven't already. It's very cool.

I am hopeful that WebGL performance on the Cr-48 will improve. Chrome has already done a lot to improve browser performance and I expect that will continue. The Cr-48 will probably never run the next generation of web-based 3D games, but I expect that commercial Chrome OS products will have more powerful hardware.