Wednesday, June 30, 2010

Modern ABI & No More @Synthesize

I haven't talked about one of my favorite new features of Xcode 4 and LLVM, because I wasn't sure of the NDA status. However, the cat's out of the bag now, so I feel like it's safe to mention. The iPhone Simulator in Xcode 4 now uses the Modern ABI (yet it's still correctly uses 32-bit datatypes!), so we can use synthesized instance variables in our iPhone applications and use the simulator. On top of that, if you choose to use LLVM instead of GCC, one of the (many) benefits you'll get is that @synthesize declaration is now assumed. If you don't need to specify anything on the @synthesize declaration (like a different setter or getter name) and your property isn't @dynamic, you can justleave it off. This feature isn't turned on by default (yet), but see Pilky's blog post for instructions on enabling this feature.

Less code to write? Boo-yeah! Count me in!

I believe (though I haven't confirmed this yet) that you can write code this way and still target older releases back to 3.0. If anyone knows otherwise, please let me know and I'll spread the word, though.



Monday, June 28, 2010

Code As If…

Sorry for how slow things have been here lately; I'm still suffering from WWDC work backlog, plus I've been spending a lot of time on the new book. This is the first book I've tried to write while also doing full-time client work and it's taking a bit of a toll on me.

I've had a blog post floating around my head since writing Beginning iPhone Development that has never become completely formed. It's about how the process of writing about code has changed the way I write code. I think the thoughts are finally ready to congeal into solid form. So, here goes.

The other day, I saw somebody wearing a T-shirt that said "Dance Like Nobody's Watching". I'm not much of a dancer, but I like the sentiment. However, dancing is not coding. The worst thing you can do is code like nobody's watching. You should code like everybody's watching you.

One thing I noticed after I'd been writing code for public consumption for a while is that I've become much more critical of my own code than I was before I started putting it out there for the world to see. A lot of that comes from pure vanity - I want to minimize the number of stupid mistakes that people are going to call me out on. There are a lot of eyes on the code I write for books and for this blog, and some of those eyes belong to people who are, quite frankly, smarter than me.

It's impossible to always put out perfect code, but I do like to avoid giving the impression of being a sloppy coder or, worse, of being a complete hack. The process I go through with code that goes into a book or blog post goes something like this:
  1. Make it work
  2. Make it work well
  3. Make it read well
The process isn't quite as linear as that makes it look, but that works as a very basic statement of the process. The last step includes the idea of refactoring, but it includes more than that. It's proofreading my code after I'm happy with the way it functions in order to look for ways the code could be written better. I'm not talking about performance here, that goes under #2. This is purely about maintainability and readability. Are my methods and variables using logical names? Is my code easy to read? Is the formatting consistent? Was I being lazy anywhere and doing quick copy and paste coding. Step 3 is about trying to be my own worst critic. You wouldn't send a proposal or other written document out without proofreading it. Your code shouldn't be any different.

I thought that I would revert back to my old ways when I wasn't writing code for public consumption, but it turns out that once acquired, this habit is hard to shake. Frankly, like most developers, I had always assumed that the third step, or at least the more picayune aspects of it, were a waste of time when doing production work.

That hasn't turned out to be true in my experience. In fact, it's been quite the opposite. In almost every case, I spend less time writing code because my code is now more readable, more precise, and generally quite a bit shorter than the way I used to write code. Every time I have to change, fix, or extend existing code, I spend less time doing it, and those little bits add up over the course of even a short job. In the log run, all those little things pay huge dividends.

Here's an example I was working on this weekend for OpenGL ES 2.0 for iOS 4. I'm putting together an Objective-C class to make creating and managing multiple programs and shaders in OpenGL easier. One piece of functionality I wanted to include was the ability to get the program and shader logs out of OpenGL. Without that information, it's awfully hard to identify why a shader won't compile or a program won't link. The end result of my first two steps ("Make it work", "Make it work well"), was this:

- (NSString *)vertexShaderLog
{
GLint logLength = 0, charsWritten = 0;

glGetShaderiv(vertShader, GL_INFO_LOG_LENGTH, &logLength);

if (logLength > 0)
{
char *log = malloc(logLength);
glGetShaderInfoLog(vertShader, logLength, &charsWritten, log);
NSString *ret = [[NSString alloc] initWithBytes:log
length:logLength
encoding:NSUTF8StringEncoding
]
;
free(log);
return ret;
}


return @"No Log Data";
}

- (NSString *)fragmentShaderLog
{
GLint logLength = 0, charsWritten = 0;

glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLength);

if (logLength > 0)
{
char *log = malloc(logLength);
glGetShaderInfoLog(fragShader, logLength, &charsWritten, log);
NSString *ret = [[NSString alloc] initWithBytes:log
length:logLength
encoding:NSUTF8StringEncoding
]
;
free(log);
return ret;
}


return @"No Log Data";
}

- (NSString *)programLog
{
GLint logLength = 0, charsWritten = 0;

glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);

if (logLength > 0)
{
char *log = malloc(logLength);
glGetProgramInfoLog(program, logLength, &charsWritten, log);
NSString *ret = [[NSString alloc] initWithBytes:log
length:logLength
encoding:NSUTF8StringEncoding
]
;
free(log);
return ret;
}


return @"No Log Data";
}

It was obvious, even as I was writing this code that I wasn't going to leave it like this. You can get away with this kind of unnecessary duplication of code in most projects because it functions fine and most clients and many development managers don't have the technical chops to read your code, but it violates the DRY principle something fierce. This is hardly the worse example of copy-and-paste coding I've ever seen, but code like this shouldn't ever go into production.

I tested this code to make sure the methods worked, then I immediately refactored the two shader log methods by adding a private method declared in an extension. I then changed the two existing methods to simply call the private method, so I was then using the same code for both scenarios.

- (NSString *)shaderLogForShader:(GLuint)shader
{
GLint logLength = 0, charsWritten = 0;

glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);

if (logLength > 0)
{
char *log = malloc(logLength);
glGetShaderInfoLog(shader, logLength, &charsWritten, log);
NSString *ret = [[NSString alloc] initWithBytes:log
length:logLength
encoding:NSUTF8StringEncoding
]
;
free(log);
return ret;
}


return @"No Log Data";
}

- (NSString *)vertexShaderLog
{
return [self shaderLogForShader:vertShader];
}

- (NSString *)fragmentShaderLog
{
return [self shaderLogForShader:fragShader];
}

- (NSString *)programLog
{
GLint logLength = 0, charsWritten = 0;

glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);

if (logLength > 0)
{
char *log = malloc(logLength);
glGetProgramInfoLog(program, logLength, &charsWritten, log);
NSString *ret = [[NSString alloc] initWithBytes:log
length:logLength
encoding:NSUTF8StringEncoding
]
;
free(log);
return ret;
}


return @"No Log Data";
}

That's definitely better than the original version. I got rid of the obvious duplication between the two nearly identical shader log methods. The only difference between the original two methods was the GLuint (unsigned integer) value passed into the two OpenGL ES function calls.

This code still bothered me, though. Look how similar the shader and program log functionality is. It's identical except for the two function calls and, I realized, those two function calls take exactly the same parameters. It had been a while since I had used them, so it took my brain a few seconds to drudge up how C function pointer worked, but once it did, the path for refactoring this code became obvious. A single method could be used for all three of these cases if I took function pointers to the two OpenGL API calls as method parameters.

Now, this second refactoring is one a lot of people would probably say isn't worth the hassle. It's too much. It doesn't pass a "cost-benefit analysis". The result is not going to be that much shorter, so how can you justify the time? I used to think exactly the same way before spending so much time writing code for public consumption, but now I've become convinced that refactoring like this does pass the cost-benefit analysis. I wasn't putting enough weight on the value of good code when doing that analysis. When you come back to code weeks, months, or years later, you won't remember all the little details. With well-written code, you won't have to.

The truth (in my experience, at least) is that refactored code is enough easier to maintain that it's worth taking the time to do it. Like everything, the more you do it, the better you get at it, and the faster you can do it. Eventually, it becomes second nature. You end up writing better code in roughly the same amount of time that you used to write sloppy-but-functional code. Plus, every time you visit that code in the future, you have a little less code to search through. Whenever you have to debug that code, you have a little less code to step through. Every time you fix the code, you have less code to fix.

If I had an error in the original version of these log functions, I would almost certainly have the same exact error in three places. When I discovered such an error, do you think I would remember to fix it in all three places? Maybe, if I wrote the code recently enough to remember. If somebody else were fixing my code, do you think they'd know they had to fix it in three places? Maybe… but more likely they wouldn't.

Here's the final version of the method I settled on for the book¹:

typedef void (*GLInfoFunction)(GLuint program, GLenum pname, GLint* params);
typedef void (*GLLogFunction) (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);

- (NSString *)logForOpenGLObject:(GLuint)object
infoCallback:(GLInfoFunction)infoFunc
logFunc:(GLLogFunction)logFunc
{
GLint logLength = 0, charsWritten = 0;

infoFunc(object, GL_INFO_LOG_LENGTH, &logLength);

if (logLength > 0)
{
char *log = malloc(logLength);
logFunc(object, logLength, &charsWritten, log);
NSString *ret = [[NSString alloc] initWithBytes:log
length:logLength
encoding:NSUTF8StringEncoding
]
;
free(log);
return ret;
}


return @"No Log Data";
}

- (NSString *)vertexShaderLog
{
return [self logForOpenGLObject:vertShader
infoCallback:(GLInfoFunction)&glGetShaderiv
logFunc:(GLLogFunction)&glGetShaderInfoLog
]
;

}

- (NSString *)fragmentShaderLog
{
return [self logForOpenGLObject:fragShader
infoCallback:(GLInfoFunction)&glGetShaderiv
logFunc:(GLLogFunction)&glGetShaderInfoLog
]
;
}

- (NSString *)programLog
{
return [self logForOpenGLObject:program
infoCallback:(GLInfoFunction)&glGetProgramiv
logFunc:(GLLogFunction)&glGetProgramInfoLog
]
;
}


Now, if you work for somebody else, especially if you work in a large corporation, you may be measured on a series of metrics including something like "Lines of Code Written" (LOC). While I understand the need for accountability, most corporate metrics are (to be blunt) a bullshit abuse of statistics. The absolute worst metric ever devised is LOC. If you're working somewhere that's still in the coding dark ages and measuring you by LOC, run like hell, or at least lobby for a change in that policy. Measuring performance based on LOC encourages even good engineers to write sloppy, horrible code.

In my example here, I spent some of my time improving my code by removing 25 lines of code. I spent time taking it from 64 lines of code down to 39 lines of code. As an developer, I shouldn't be punished for doing that!

In real-life situations, we often convince ourselves that there's not time for refactoring while we code. After all, we have to make that deadline, and there's always a deadline! We can always come back and refactor the code later when we have more time, right?

Only you won't. You won't come back until you absolutely need to, and by that point, it'd probably be faster to rewrite it. If you work for somebody else, they're unlikely to let you go back and spend time "fixing" something that works perfectly well. That's especially true if you have a non-technical manager. Besides, you'll probably be onto your next deadline already and feeling time pressure all over again.

In the long run, good code is worth the time it takes. Often, it's worth it in the short run as well.

Make time to refactor, and not after the fact make it part of your development process. Do it up front, before it goes to test, because you won't come back. Proofread your code before you ever send out a build.

Or, in other words, code as if everyone was able to see and understand your code.

Addendum


There's another point I want to make. Not only should you code as if there were lots of eyes on your code, you should actually get lots of eyes on your code if you can. You will miss stuff even if you make proofreading and refactoring part of your development process. You will sometimes even miss stupid stuff. Case in point, I got an e-mail shortly after posting this from Brent Simmons of NetNewsWire fame. Brent very kindly took the time to proofread the code and pointed out one bug and several improvements that could be made.

Here are his suggestions:
  1. Return early if logLength < 1, so that the main functionality doesn't have to be indented.
  2. Return an autoreleased string, per Apple's coding conventions
  3. Return nil in the case of no log data, rather than a string that would have to be compared to determine if there was log data or not.
  4. Change the name of the char * and NSString variables to something slightly more meaningful. (Since the method is logForSomething, it returns a variable named log.)
I absolutely agree with every single one of these suggestions and am a little embarrassed about leaking the string, to be perfectly honest. Here's Brent's rewrite of my function that I plan to use in the book (with Brent's permission):

- (NSString *)logForOpenGLObject:(GLuint)object 
infoCallback:(GLInfoFunction)infoFunc
logFunc:(GLLogFunction)logFunc
{
GLint logLength = 0, charsWritten = 0;

infoFunc(object, GL_INFO_LOG_LENGTH, &logLength);
if (logLength < 1)
return nil;

char *logBytes = malloc(logLength);
logFunc(object, logLength, &charsWritten, logBytes);
NSString *log = [[[NSString alloc] initWithBytes:logBytes
length:logLength
encoding:NSUTF8StringEncoding
]
autorelease]
;
free(logBytes);
return log;
}


Thanks, Brent!


1 This may, of course, change if my tech reviewer finds an issue with it



Saturday, June 19, 2010

WWDC 2010 Post Mortem

WWDC. The Dubdub. Christmas in June.

If you've followed this blog for any length of time, you know Apple's annual developer conference is my absolute favorite week of the year, and it just seems to get better every year. For the days leading up to leaving for San Francisco, I'm like a kid on Christmas eve. I can't sleep from excitement and the time passes way too slowly.

Every year, there are less "must-see" technical sessions for me, personally. That was especially true this year because something like 60% of the attendees were first timers who haven't shipped their first app yet and the session schedule was designed accordingly, with quite a few beginner and intermediate level sessions. But WWDC is so much more than the sessions (and those come out on video anyway). Your first year or two attending, it's all about the sessions, but by this point for me, it's about the sessions that focus on new technologies, labs and, most importantly, a chance to catch up with people I only see once or twice a year. Well, it wasn't just new technology sessions. For obvious reasons, I also attended all of the OpenGL ES sessions this year, and they were great. They were much deeper technically than last year, and were much more focused on the OpenGL ES 2.0 programmable pipeline.

Even thought it was the same number of attendees as the last two years (5,200 attendees plus the various engineers and other staff), this year felt way busier than past years. Lines to get into sessions were often very long, and many sessions filled up. Some even filled up an overflow room. Although we've seen long lines for sessions going back to the introduction of the iPhone, it's never been like this year. Last year, for example, for the State of the Union addresses, I meandered into the overflow room ten minutes late and found a seat in one of several empty rows. This year, I sat on the floor of the overflow room for the overflow rooms. I guess that's good - people were serious about learning this year.

One negative aspect of the massive influx of newbs this year was a certain loss of etiquette. I've always been super impressed by the way my fellow WWDC geeks treat the staff and the facilities. I've never seen garbage left around or more than isolated cases of people being rude to the catering or cleaning staff. This year, unfortunately, that respect was somewhat lacking. During the keynote line, hundreds of people just left their litter laying around on the floor. It was really disgusting and I was embarrassed at that moment to be part of the group. And it didn't end with the keynote line, either, unfortunately. I saw many examples of people not bothering to pick up after themselves, or being rude to the staff. Even a few instance of people being rude to Apple engineers who were trying to help them with problems. I almost feel like I need to add a few items to my annual first timer's guide with things I had assumed any decent person would already know, like throw out your garbage, treat people with respect, and be nice to people who are trying to help you.

Let's be better next year, okay? Almost everybody I met or talked to seemed like super people, so I'm hoping this was just a one-time anomaly. I really, really would like it to be an isolated occurrence. Enough said on that topic.

Although the new iPhone 4 was the belle of the keynote ball, the real buzz at WWDC this year, as you probably know by now, was Xcode 4. For the first time in history, Apple has released the session videos to all registered developers for free, so if you haven't done so yet, you should go watch the Developer Tools State of the Union and the handful of Xcode 4 sessions. Apple's Developer Tools teams have been working really hard for quite a long time on this upcoming release, and even in the early preview state it's in, I already wish I could use it full-time. Fortunately, the Xcode team foresaw this and they made the project file format 100% backwards and forwards compatible between Xcode 3 and Xcode 4, so I can work in Xcode 4 then switch to Xcode 3 to do my ad hoc and release builds.

Honestly, one of my favorite parts of this particular WWDC was having the opportunity to buy a few rounds of drinks for some of the engineers who worked on Xcode 4. I'm not sure if those engineers have forgiven me yet, so I'm not going to call them out by name, but it's important to me during WWDC to show my appreciation to as many as I can of the people who make all the cool stuff I work with everyday. Steve Jobs gets a lot of credit, and rightly so, but he doesn't do it alone. It was really nice to see him call out some of the people who worked on iPhone 4 and iOS 4 during the keynote, but there are a lot of unsung heroes working at Apple, and most of them don't get a lot of recognition for teh awesome they bring. WWDC is the one week a year where we get to show our appreciation in person.

The User Experience lab appeared to be the biggest hit among the labs this year. Each morning, within minutes of the Moscone West doors opening up, there was a long line extending around the corner waiting for the UX lab to open. People waited in line literally for hours to get a UX review. I guess word got out this year about how good those reviews were. I know I saw several people raving about them last year. In general, I think people have really started to grok the fact that the labs represent an incredible opportunity to get questions answered by the people who really know the answers. If you're having a problem or an issue with a certain part of the system, likely you can find someone who actually works on that part of the system to answer your questions.

As for MartianCraft, we gave out all of our away team shirts pretty quickly this year. Sorry to those who wanted one but didn't get one. We way underestimated demand for the shirts and just didn't have enough with us to give them to everyone who wanted one. We'll be better prepared next year, and we're looking into making the shirts available online for anybody who's interested, but that probably won't happen until we've dug ourselves out from the hole that got created as a result of all three of us not working for a week.



Thursday, June 17, 2010

Grand Slam!

Apple has set a new record for WWDC video avialability this year, getting them out not even a week after the event ended. Amazing.

Even more amazing, they're not selling them this year. Registered developers can access them for free. Want to know what all the fuss is about with Xcode 4? Go watch the videos.



Monday, June 14, 2010

Announcing OpenGL ES 2.0 for iOS 4

Okay, it's finally time for me to announce Super Secret Project B, which is a new book I'm writing on OpenGL ES 2.0 for iPhone, iPad, and iPod touch.

Yes, I know I said I wouldn't be writing any books in 2010, but the nice folks at the Pragmatic Programmers approached me after I made that statement with an economically feasible way for me to write a book this year. I couldn't say no.

My original plan had been to take my OpenGL ES from the Ground Up blog posts, supplement them, and turn them into a book with step-by-step projects to reinforce the points of each posts. My week at WWDC has caused me to change that approach. I went to all the OpenGL ES sessions and spent a fair amount of time bending the ear of Allan Schaffer, Apple's Graphics and Games Evangelist, as well as a number of Apple engineers who work on or with OpenGL. After a lot of hard thought, I came to the conclusion that the approach needed to change. Although modern hardware supports the fixed pipeline, Apple has stopped making phones that require OpenGL ES 1.1. The iPhone 3GS, iPhone 4, and iPad all not only support OpenGL ES 2.0, but they all require it if you want to take full advantage of the hardware.

OpenGL ES from the Ground Up, however, focused on the OpenGL ES 1.1 fixed pipeline.

Since OpenGL ES doesn't maintain backward compatibility the way workstation OpenGL does, much of the material from the fixed pipeline, such as lights, the model view and projection matrix, and the stock functions for submitting vertex, texture, and normal data are all gone from OpenGL ES 2.0. Instead, you have to handle all that work manually when you write your shaders. Shaders add some complexity to the process, but give you a tremendous amount of power and the ability to write more efficient OpenGL code.

In the Desktop world, it still makes sense to learn immediate mode first, then regular fixed pipeline, and then finally the programmable pipeline, because workstation OpenGL maintains nearly 100% backwards compatibility across releases, and you can get up and running quickly. On Workstation OpenGL ES, you can even mix and match the different modes, accessing the model view matrix and lights from your shaders. That's not the case with OpenGL ES, so spending a few hundred pages teaching things that won't be applicable to the programmable pipeline seemed like a poor use of time, both mine, and my readers'.

But, for the new programmer, the programmable pipeline is really hard to grok. I've been banging my head this past week looking for a way to present that rather complex topic in a way that people without prior graphics or OpenGL ES experience will be able to understand.

Thanks to a lot of people willing to talk with me, I think I've come up with an approach that will work, and I'm really excited about it. So, if you find OpenGL ES confusing, especially if you find the programmable pipeline and shaders confusing, look out for OpenGL ES 2.0 for iOS4. I don't have a release date yet, but I will post here when I have updated information about the production schedule.



Tuesday, June 8, 2010

WWDC 10 Update

Well, we're well into the second day at WWDC and it is, as always, amazing, exhilarating, exhausting and, most of all, fun.

Unfortunately, there's not a heck of a lot that I can report on. Other than the keynote yesterday, which was heavily covered by both liveblogs and technical media. The iPhone 4 looks amazing. I haven't seen it myself, but I've talked to several people who have and without exception they just gush over the it, especially the screen.

But there's stuff going on here that's got me so much more excited than even the new phone. A lot of really smart people at Apple have been working very, very hard to give developers some really cool stuff and I just wish I could share it, because they really wowed me and many others I've talked to.

It's an exciting time to be an iPhone iOS developer.

Update: Okay, it's Xcode 4, it's not available to non-attendees, but it has been announced, so I can say what it is that has wowed us. Apple has completely revamped the developer tools with a new workflow. The current beta is still unfinished, but it's extremely impressive.



Friday, June 4, 2010

MartianCraft Away Team

red_shirt_tease.png

This is a teaser photo of part of the MartianCraft T-shirt that Rob designed for WWDC. We've got a small assortment of these to give away at WWDC. We haven't yet figured out how we're going to decide who gets to be red-shirts on our Away Team, but we'll get it figured out before Monday, and hopefully it won't require you to embarrass yourself too badly.

I'll post some more pictures as we get closer to WWDC.



Thursday, June 3, 2010

Briefs Rejected by the App Store

Rob Rhyne explains what's going on with Briefs, his iPhone-based prototyping tool. Unfortunately, it's not good news.



Oh, Hey! I'm Teaching Again.

banner.png

I'm teaching up with Julio Barros of E-String Technologies to hold a three-day iPhone SDK programming workshop in New York City the week after WWDC. The class starts on Wednesday, June 16 and runs through Friday June 18. No prior iPhone programming experience is required, though some prior programming knowledge and a general understanding of C-style syntax is recommended.



Almost WWDC

wwdc-2010.pngWell, it's the Thursday before WWDC and, as always, I'm swamped yet super-excited. The Pre-WWDC Pilgrimage is all planned. If you expressed interest, you should have received an e-mail with the details about how to pay if you want to take the bus.

I shy away from making predictions before big events because I don't have any inside information and I'm likely to be more wrong than right with anything but the safest predictions (like a new model iPhone being announced). However, I do think there's something big this year that hasn't leaked yet. Something completely unexpected. Chances are, if there is, it will leak the night before the keynote. The number of people who find out about new projects increases exponentially in the 24 hours leading up to the actual presentation, and leaks become nearly impossible to prevent at that point, but I have a gut feeling there's something we haven't heard about yet, but I haven't the foggiest idea what it might be.

Of course, I think a new iPhone model is almost a foregone conclusion, and perhaps some moderate hardware refreshes on the Mac side, though I think the focus of this WWDC is clearly going to be the iPhone OS. We might see a price drop, speed bump, or something similar on the Mac side, but I don't think we're going to see any Mac line completely refreshed or much time devoted to the Mac in the keynote. It's within the realm of possibility that the Mac Mini, which is sorely overdue, or the Mac Pro, which is also sorely overdue, to get revamped, but probably not. I expect Steve to spend a fair amount of time giving us details about how many iPhones and iPads have been sold, how many applications have been downloaded, and whatnot. I expect to hear more about GameCenter and to see some silly montage about some developer's success story with the App Store.

I've seen rumors about a iPhone OS-based AppleTV. Maybe. Steve's comments at D8 might have been the sort of mis-direction he's known for, and the AppleTV is definitely in need of a refresh if it's going to continue being sold, but I think Steve was telling the truth about the subsidized TV box market, so if there is an AppleTV refresh, it's going to be combined with something else: a partnership, new business model, or something that will make it a viable, profitable product.

Steve will almost certainly have us watch a new commercial, either for the new iPhone or some other new product. If he's really excited about it, he'll make us watch it twice.

For the most part, I really don't care what gets announced. The incredible interest in the iPad and growth of the iPhone as a platform already provide me with more to explore than I have time for. I'm looking forward to sitting in the RDF on Monday with 6,000 other Apple geeks. It's an extraordinary experience watching Jobs work, especially in person. He's a master showman, and my only complaint about the last few Stevenotes has been all the time he's given to third party developers who lack his presentation skills. I really do hope there's more Steve and less awkward third-party developers on stage this year, though I suspect the format will be similar to previous years.

Last year, I didn't do the Keynote line-thing. I visited with people in the line much of the morning because I was still on East Coast time, but then I went back to my hotel and had breakfast, then went back over to Moscone West just before 10:00. This year, however, I'm going to do the early-morning geeky wait-in-line thing. My fellow Martian Rob is attending his first WWDC and I feel like the line is something you have to do your first time, and I don't him to do it alone. Besides, it is fun. And, hey, maybe there will be strippers again, because strippers never seem out of place at a developer conference, especially walking around at 6:00 in the morning in 55° weather wearing bikinis and high heels, right?

If you're going to WWDC and want to say hi, the best way to find me is to follow me on Twitter. I spend most of the day at Moscone West and am pretty easy to find. If I'm not in a session, I usually park at a table to work and tweet my whereabouts.