Saturday, July 25, 2015

Will I speak at your conference?

I've spoken at quite a few conferences in my time as a human- I started back when I was in Google developer relations, and speaking was actually in my job description. After I left Google, I was flattered to find that conferences kept inviting me to speak. I said yes to many of them, since I get a lot of great things out of speaking at conference.

But lately I've started to notice that I don't enjoy that much at conferences. In fact, it's often the opposite. I spend the majority of my time in the hotel room, hacking on work projects while wishing that I was back home. What changed?

1) I really, sincerely enjoy my work - designing the computer programming curriculum and experience for Khan Academy. When given the option between designing a presentation to give to a conference audience and designing an online course for thousands of eager students, I prefer the latter. I've always been better at creating the 'educational' flavor of learning experiences versus the 'entertaining', and that's exactly what I get to do at work. So I find that when I'm speaking at a conference, I postpone making the presentations because I'm excited about KA course work, and I am too easily tempted to hack on KA work during the conference (especially when the alternative is a scary networking event!).

2) I really, sincerely enjoy my home life - my family and friends, and in particular, my partner. I have a partner now that I want to do so many things together with -- romantic things, coding things, arty things, travely things. If I'm away at a conference, I'm missing our date nights, our dinners, our event planning time, all of that. Sure, I could theoretically "appreciate the time away", but there's only so much of that I can appreciate. At this point, I'd rather appreciate the time together.

3) I don't have many new technical topics to talk about. We do use nifty shiny new technologies at Khan Academy like Facebook React, but most of my code is Python/Flask/Backbone. Some of it is React, but my colleagues have much more to say about it than I do (and they're speaking, yay!). I spend most of my mental effort thinking about teaching the basics of coding, not thinking about new coding practices and technologies.

So, will I speak at your conference?

If it's local to me, and if it's a topic that I've already spoken on, then it's quite likely that I'll say yes.

If it's local to me, and you want me to speak on a new topic, then I'd have to consider if I have anything to say about that topic and have the time/desire to make those slides. Also, you should tell me what that topic is. :)

If it's in a far away land (a plane flight), then it's likely I'll say no. I get too homesick when I'm away now, and my partner can't afford to pay for so many flights. If you're actually able to pay his way as well, then hey, I'm liking your offer more and more. Otherwise, I'm honored you want me, but alas, it is probably not meant to be.


Thursday, June 11, 2015

I don't always have to be The Entertainer

"The Entertainer came out tonight."

That's what my partner told me a few times, after dinners with old friends of mine. He says he doesn't quite recognize "The Entertainer", that it's not the version of me that he's grown to know over our past 8 months together, and that he's bothered by some of my behavior in that version of myself.

It took me a while to figure out who this Entertainer was, and why it might be bothersome, but I think I've got it now.

As a kid, I determined pretty early on that the way to get friends was to impress people. I remember coming up with party tricks for the cafeteria lunch table in elementary school (I would offer to eat everyone's brown paper lunch bags and rate their deliciousness). I remember offering my house T1 line to potential house-comer-overs in middle school (back when home internet connections weren't a thing). I remember bringing bags full of candy and toys to school for *every* holiday, offering them to every one of my classmates.

...And it worked! Well, at least, it did superficially. I always had full birthday parties, I always had a place to sit at lunch, I always won our class presidency elections. But now that I look back, and realize how few "friends" I kept in touch with since then, I wonder if it really worked? Was I actually friends with all those people? Did I actually even know anything about all those people? What if I just spent my childhood entertaining them, and never remembered to have a real conversation with them?

It's hard for me to really say because my memory is so poor to begin with, but I *can* evaluate my current life and how I'm relating to the people around me. I've realized that I know very little about most of my Khan Academy and GDI colleagues, and anything I do know was information they proactively shared. I suspect I resort to being "The Entertainer" around them, like at the lunch table, because that's the way I've learned to relate to the world.

But why? Why do I feel such a strong urge to entertain? Like most of the things I'm discovering about myself lately, it seems to be a social anxiety that comes from a fear of unworthiness. I think I'm afraid that if I don't entertain, then I haven't earned my place at the table. If I do, then I've proven myself worthy of love and attention - even if it's only a particular version of myself, even if it means most of my connections are devoid of true 2-way interactions.

I've decided that I don't always have to be The Entertainer anymore. I can be the Listener -- the Curious Cat -- the Eager Participant -- the Smile&Nodder -- a self that is comfortable with my place at the table. I don't think its going to be particularly easy for me to become a Listener; I don't have a whole lot of practice. I seem to be able to become a Listener in the presence of my partner, for whatever reason, so I'm going to try to call on that self when I'm not around him.

I will be happier in the long-run if I can become comfortable with not being The Entertainer. I want to relate to people in a way that isn't fueled by my fear of unworthiness, but fueled by a genuine desire to connect more deeply with them.

Tuesday, June 9, 2015

Why am I so afraid of mingling?

I was at a meetup tonight, and after a round of introductions, the host said "and now we'll mingle before the talk!" At that point, I literally hid in the bathroom. I waited there until the sounds of mingling died down, and I knew it was safe to rejoin and watch the talk. This wasn't the first time I've hidden in the bathroom during the mingling part of a meetup. It wasn't even the second or third time. Bathrooms and me, we're old friends.

So why am I afraid of mingling? Let's break it down:

  • Fear of the approach: I have to pick somebody to go up to, and hope they also wanted me to approach, or are okay with me approaching them. I have to tell myself that they're not going to groan to themselves "ugh, I didn't want them to approach!" I know that, rationally, I shouldn't feel so unworthy of their desire to speak with me, but emotionally, I have that tendency. I am working through that, in therapy and a Radical Acceptance reading club with my partner, but I'm not to the point yet where I can think to myself, "sure, anyone would love to talk to me!" and wholeheartedly believe it.
  • Uncertainty on the topic: Assuming I manage to approach someone, I then have to figure out the right conversation topic. At the meetup, the introductions included a "Ask me about ___" prompt and a "One time, I built ___ " prompt, designed to give us topics to talk about. Because of that, I think I could have approached a few people with a topic that I knew was relevant to my interests, and I'm thankful they provided that fodder for us. I also heard a nice prompt suggested tonight as a general conversation starter, "What's something you've learned recently?" I'd like to try that out, at meetups that don't provide any introduction fodder.
  • Fear of the finish: I have yet to figure out a good way to wind down a topic and leave it on a positive note. Instead, my 1-on-1 conversations often feel like they wither and die a slow, agonizing death. I've gotten suggestions like claiming you have to go to the bathroom, but I don't know that I'm a good enough liar for that, and that I can reasonably use that for every conversation. That's why I much prefer time-bucketed conversations or group conversations that allow for easy in-out transitions.

I know that my anxieties around mingling are fears that I need to work through, as they're tied to my underlying social anxieties in life. But I also believe that events can make networking less intimidating for those of us with these anxieties, and that's why I'm a big fan of more structured mingling. For example, at this meetup, they could have blown a whistle at the end of 4 minutes, and forced everyone to mingle with a new person, and that would have helped with my fear of approach and finish.

I wrote up more about making networking easier in this earlier post, and I think that the pre-matched speed networking is still my favorite of all the structured mingling attempts I've experienced. I hope more events experiment with that. Just in case I'm not the only one that hides in bathrooms. :)

Thursday, April 23, 2015

Towards more "Yes, and"s and less "but"s

Today we had a little Improv 101 workshop at Khan Academy, led by our colleague Kitt Hirasaki. I'm interested in improv both because I find it incredibly fun and stimulating, and also because I'm interested in the way it can help me improve the way I deal with every day life.

One of the great games we played was "Yes, and." In that game, two people go up and the first person starts off with a line of dialogue that hopefully sets out some aspects of the characters, their relationship, and the setting. The next person continues the dialogue, and regardless of what they say after, they must start their line with "Yes, and". This goes back and forth, continuing the scene, until it comes to a logical conclusion.

The idea behind that "yes, and" is to force the characters to fully embrace the reality introduced by the other character, and to build on it. They might still disagree on something in the scene, but they agree on the reality of the world they live in, and that makes it more believable for themselves and the audience. It makes the game collaborative instead of combative, and just feel more positive overall.

Since it promotes creativity and collaborative, the "yes, and" game has since been picked up by entrepreneurs and life coaches as a tool for businesses and organizations, and I just found there's an entire book named "Yes, and".

But back to me and my reality.

After the improv workshop, I went out to dinner with my partner. We were talking about something we weren't fully in agreement on, and happened to fall into the "yes, and" game, which made it feel more collaborative. We couldn't keep that up for long and it turned back into our usual dialogue style, and that's when I started noticing something: I start an awful lot of responses with "But." I haven't done a statistic analysis, but it felt like way more than the average response should start with.

Why? Probably because starting with "but" proves that I've found the hole in someone's statement -- which proves that I was smart enough to find that hole -- which proves that I'm worthy of love and admiration. I'm reading Radical Acceptance right now, which is helping me realize that much of my behavior is me trying to prove my worthiness, instead of me participating wholeheartedly in things I enjoy.

I would like to participate more, to collaborate more, to create more. Tomorrow, I'll try starting less of my responses with "But"; and perhaps even start them with "Yes, and." That may not be the game that gets me to change my worth-proving ways, but it's a start.









Tuesday, June 24, 2014

Simplifying the Terms of Service

At the GDISF study group last night, one of the attendees was working on the Terms of Service for a new site, and she wanted to give the users a way to see the layman-friendly version of the terms. She was inspired by the "Simply Put" right hand side of the Pinterest site, and was experimenting with other ways to present that.

Pinterest:

I'd never seen that sort of thing before, and I think it's pretty neat, so I asked on Twitter for more examples. Here are a few they shared:

500px:

CodePen.io:

Aviary:


Related to this, there's the Terms of Service; Didn't Read initiative that comes up with layman-friendly version of the top TOSes, and there's a list of related efforts to simplify terms and identify ambigious terms from CommonTerms.

How do you make your Terms of Service layman-friendly? Tell me in the comments!

Thursday, February 27, 2014

The Long Lunch Table

For the last two years, I've had the pleasure of working for companies that are still small enough to fit in a room; small enough so that everyone can squeeze at the same lunch table. Even at Khan Academy, where we now have almost 50 people in the office, we have a long table made up of many tables, squished together so as to appear a continuous structure. I never really thought about that until today, when we were talking about plans for our new office.

You see, our small company is getting bigger, and we're moving into a larger space. We have to decide which of the traditions and configurations to bring over from our current space, and which to leave behind as a thing-we-did-when-we-were-smaller. One of those is the team lunch. Our office admin announced to all of us that they're working hard to make sure that we can continue to all eat lunch together. A devil's advocate amongst us responded with "Why? Why do we need to eat lunch at the same time and same table if we can only hear a 4 person radius around us?" He had a good point, yet he also provoked a visible gut reaction in many. But, why? What reasons did we come up with?

We kerfuffled for a bit, trying to justify our insanity on holding onto our irrational needs, until my colleague spoke up. He told the story of lunch at his last company, which was a few times larger. They had a long lunch period, with many small lunch tables in a big cafeteria, and employees were expected to lunch at different times, to distribute the lines over time. Employees would walk in, look around at the lunch tables, not see anyone they knew - or not see anyone they felt confident in table-crashing - and go back to their desks. Eventually, many of them defaulted to eating lunch at their desks. Lunch had gone from being a social affair to being a daily reminder of loneliness.

In fact, when he recalled this, I remembered feeling the same way at Google. Sure, I would know people scattered around the tables in the cafeteria, but it took guts to feel like I could impose myself on any given table. There were days that I couldn't muster up enough of those guts; and those were the saddest.

And now, finally, I realize the simple brilliance of the long lunch table and the single lunch period. When you get your food, you don't have to gather the confidence to approach a table - you just look at the long table, pick the next logical available seat, and sit there. That's what everybody does, and there's no expectation that you have to ask to do that, because, what else would you do?

Maybe the long lunch table is why I look forward so much to lunch every day at Khan Academy. It's certainly not that I dislike my work, but I adore our lunches: I don't have to stress about where to sit, and I know that wherever I sit, I'll be surrounded by some subset of my smart and funny colleagues.

Here's to hoping that we can keep our lunch table long for as long as possible.

Thursday, January 30, 2014

Improving front page performance: removing images, 5 ways

We regularly hold Fix-Its at Khan Academy, where we take a day to work on the little things that pile up, the bugs and tweaks and optimizations we don't find the time to do otherwise. On Tuesday, we had a Fix-It dedicated entirely to performance, and we made a Trello board of performance improvement ideas, many of them around speeding up our server-side calls.

I decided to tackle the frontend, starting with the very first experience a user has on Khan Academy: the logged out landing page. My colleague told me there were some images that could be delay loaded on it, a technique that I'm familiar with, so I logged out, opened up the Chrome Dev Tools Network panel, and checked out the HTTP requests (particularly the pre-DOMContentLoaded ones). Sure enough, lots of image requests!

Here's a screenshot of the page, with the various images circled in red:



Some of those images are "above the fold", meaning they're visible without scrolling, while others are "below the fold", requiring varying degrees of scrolling to see. This is an important distinction to make, because most users do not scroll on our landing page - most will go straight to signup, which is what we want to happen, and have optimized for in numerous A/B tests. Depending on their position on the page, I used different techniques to deal with each image. Let's go through them, shall we?



TinyPNG

For many of the techniques below, I first put the images through TinyPNG to optimize their size, and often achieved 50%-75% compression, without discernible loss in image quality. Plus, I made a Panda happy!


Top Logo: CSS Data URI

HTTP Requests saved: 1

The top logo is displayed on every Khan Academy webpage, so it will need to get downloaded by ever user in some form. Since we're already sending down a CSS file on every page, and the logo is a fairly small file (2KB, after compression), my colleague suggested just inlining it as data URI in the CSS file.

Thanks to the magic of all of our conversations happening in HipChat, I then found out that my colleague Craig Silverstein actually made it so that our CSS build process will automatically Data URI an image that's used as a background-image, as long as it's sufficiently small size and only included in one CSS package or if it has a /* data-uri */ comment next to it. If I hadn't had that option, I would have used one of the online converters - but I'm happy I get to keep our CSS files clean and readable!


Login icons: Sprites FontAwesome

HTTP Requests saved: 2

CSS sprites are a now classic technique for saving HTTP requests for the commonly used little images on your site, condensing them all into one image and using background-image/background-position magic. That seemed like the obvious approach at first for the remaining above-the-fold images on the page, the login icons and the purple leaves background. I optimized the images, uploaded them to this online CSS Sprite generator, and set their new CSS rules, happily turning 3 HTTP requests into 1.

However, my colleague then informed me that we actually had FontAwesome icons (in our custom build!) that looked nearly the same as the Google and Facebook login icons, and he'd been meaning to change those over. We already send down FontAwesome with every page, because we use their icons so heavily, so it made sense to give up images entirely and just use the FontAwesome classes.


Featured Images: Delay Load

HTTP Requests saved: 4

We display three images related to featured content just below the fold, which we don't want to sprite because we change them up a fair bit, but we also don't want to load for all the non-scrolling users out there. So I implemented this delay-loading technique for the images, which basically entails adding a scroll handler, checking if the desired DOM elements are within view or within some threshold of being in view, and swapping out their background-image or src if so, based on data attribute values.

Here's the generalized delay loading code that I wrote as a simple jQuery plugin:

Here's example HTML for one of the images:

<div data-delayed-bgimage="https://www.kastatic.org/images/featured-actions/pollock.jpg">
</div>

And here's the JS that calls the delay loading plugin for those images:

var maybeLoadMedia = function(nearThreshold) {
    $("#homepage [data-delayed-bgimage]").each(function() {
        $(this).delayLoad(nearThreshold);
    });
};

// On scroll, use very large threshold. Most people don't scroll homepage,
// but if they do, we want them to see everything.
$(window).on("scroll.load-media", _.throttle(function() {
    maybeLoadMedia(600);
}, 100));

// Start with no threshold, items must be visible
maybeLoadMedia(0);

Youtube Video: Delay Load

HTTP Requests saved: 1+

Way below the fold, we embed an iframe of Sal's TED talk. It's a great talk, but once again, most users won't make it this far. We use the same technique as for the images, with one difference: for img tags, we start them off with an empty src attribute. However, that's not a valid value for src for the iframe, so we start the iframe off with src="about:blank". Ben Vinegar, an iframe wrangling expert from Disqus, suggests it's even better to completely create the iframe from scratch, but since the src swapping worked, I went the simpler route this time.

Here's what the HTML looked like:

<iframe width="560" height="315" frameborder="0" allowfullscreen
  data-delayed-src="//www.youtube.com/embed/gM95HHI4gLk" src="about:blank">
</iframe>

And the JS was pretty much the same:

var maybeLoadMedia = function(nearThreshold) {
    $("#homepage .youtube-video iframe").each(function() {
        $(this).delayLoad(nearThreshold);
    });
};

$(window).on("scroll.load-media", _.throttle(function() {
    maybeLoadMedia(600);
}, 100));
maybeLoadMedia(0);

Social Icons: Delay Load

HTTP Requests saved: 0 (all were async tags)

We also display a host of social icons next to the video, and we have to load in the relevant JS APIs for each of those, often via dynamically appending a script tag. We set the async attribute on all of those, so they were not affecting our DOMContentLoaded time, but hey, might as well delay load them! No sense in making users do HTTP requests for things they won't need.

var maybeLoadSocialMedia = function(nearThreshold) {
    if ($("#homepage #social-actions").inView(nearThreshold)) {
        _.defer(function() {
            Homepage.initSocialButtons();
        });
        $(window).off("scroll.load-social-media");
    }
};

$(window).on("scroll.load-social-media", _.throttle(function() {
    maybeLoadSocialMedia(1000);
}, 100));

Subscribe icon: FontAwesome

HTTP Requests saved: 1

I started off by delay loading the RSS subscribe icon, but it felt like overkill and I realized there was a much easier approach: just use the FontAwesome subscribe icon, and color it orange. Ta-da, nearly the same!

It was easy to do with this HTML:

<span class="icon-rss-sign"></span>

...and this CSS

.icon-rss-sign {
  color: orange;
  text-decoration: none;
  margin-right: 5px;
  font-size: 18px;
}

Invisible image: Delete!

HTTP Requests saved: 1

After I'd optimized all the images I could see, there was still an HTTP request for an image that I couldn't ever see: our loading gif. I spent a while trying to track down what code was loading it, to see if it was validly being used at some point during the page rendering process. I finally discovered that it was in a CSS rule for an element that was visible on the page - but its visibility was set to hidden. Apparently, browsers (or at least Chrome) will download background-image's for hidden elements. Luckily, I then discovered that it was "dead" CSS - the rule that would toggle its visibility was never getting triggered. We'd stopped using the loading image without removing the associated CSS rules, and that was costing an extra HTTP request. I happily and promptly deleted it, whee.



The Exciting Results!

If you've been keeping score, my changes removed at least 10 HTTP requests, if not more (like additional ones triggered from the Youtube iframe). I recorded load times across 5 page loads in Chrome Dev Tools both before and after the changes, and here are the results:

# of Requests DOMContentLoaded (average) load (average Time between them (average)
BEFORE 65 3.02 5.66 2.64
AFTER 28 1.86 2.00 0.14
% REDUCED 57% 39% 65% 95%

The full spreadsheet is here, and I've also downloaded the HARs from all the loads.

There is still much we can improve - there's a lot of latency and variability in the initial download of the HTML page itself, plus we're passing down several CSS, JS, and font files. But still, it's impressive what we could do in a single day, with just the images. Thanks to those techniques, the page makes it to the DOMContentLoaded event in nearly half the time, and to the load event in less than half the time.

Got any other techniques to share, or tips for how you improve your site's performance? Tell us in the comments!

.