Reflexions on my 26th Year

Here I am again. This time I’m trying to make a pre-emptive attempt at getting this blog post done in time after last year’s snafu. This is the forth annual birthday-related blog posts where I reflect on how the year went, what I got out of it, and what my hopes are for the next year. I don’t think I’ve ever done anything voluntarily for this long, so it’s pretty awesome to see how this has evolved over the years. I mentioned last year that I had spent a few months thinking about what I would eventually write in the next reflective post, and this year was no different. I think the first time I brought it up was 3 months ago. That’s how big of a deal these posts have become for me. There’s still no defined structure for these, they’re more stream-of-consciousness than anything else. Hopefully a structure would evolve naturally over time. I don’t know. Maybe. Anyway, enough blabbering, onto it.

So. How did the year go? Pretty damn well! I remember last year wondering how 2013 could possibly be better than 2012. I had thought about it in the context of work, since work was going really well, and I entered 2013 with quite a bit of anxiety toward it. But you can’t really predict what’ll happen, what’ll matter, who you’ll meet, and what you’ll do.

A Fulfilled Resolution

I can’t quite believe that I actually followed through on a resolution! Last year, I wrote about my resolution to spend more time, energy, and money on experiences rather than possessions, and what will follow will hopefully demonstrate that. Whereas the years following my college graduation centered around work and my career, 2013 was a focus on enjoying my newfound health, my youth, my geography, and my friends.

When I think back to 2013, I see a blur of moments spent with friends traveling eastward to the Sierras, up to Marin, down to LA, on bikes, motorcycle, in cars and plains, on surfboards and photo walks. All the accomplishments of the year professionally pale in the comparison when put through the lens of hindsight. 

Skiing

My first skiing trip ever! My new year resolution to spend money on experiences was off to a good start. I’d go back to Tahoe for 4 more trips that year, having found out that I both loved skiing for its thrill and the mountain, and loathe it for the vertigo it gives me high up on the steep slopes. Skiing was a really big deal for me though, it fit into a narrative that would play out through the whole year, one of discovering the outdoors and increasingly identifying myself with them.

Meanwhile, as all this is happening, I ask Maddie if she wants to have Dim Sum one day, she says yes, and just like that, 2013 went from good to greatest.

Cycling

At this point, cycling is an integral part of my life. Last year I wrote about how much cycling I did in 2012, and I did twice that in 2013. It was awesome. I was hitting performance levels I never dreamed of a year before. The Summer of 2013 will long be remembered not just because of what I did or rode, but also for the amazing community that Facebook Cycling fostered around it. 

We rode down to work, up to Marin, down to LA, over in Yosemite, Tahoe, Santa Rosa, Montana, Wyoming, around LA. Through it all, I’ve come to see California as a home more than I’ve ever seen any other place I’ve lived. Every time I leave, I feel the draw of California tugging me back into the mountains.

What was a place of vistas became a place of peace. Where I once hid away from nature, I began to find myself seeking it. Every friday night, when we would go on a trip to the mountains, I would physically feel my stress, thoughts, concerns, and anxiety melt away with every mile crossed.  A mountain top now represents all the challenges I’ve gone through in life and eventually overcoming them.

I’d always hear athletes talk about the effects of their sports on their personal lives, and I always dismissed it. Over the past couple of years, I’ve come to understand what they’re talking about. I remember two rides more clearly than any other rides. The first one represented a disappointment. A disappointment that I would remember whenever I was facing a challenge, on the saddle or not. I was trying to from Muir Beach to Stinson Beach and back to SF. I’d never done that ride before, and didn’t know what was ahead of me. At some point, I gave up, turned around, and headed back home. When I got home, I looked at the map, and realized I had covered most of the way and I would’ve been able to finish the ride had I followed through. That disappointment cut deep for me, and I still remember it today. Another was when I almost gave up going up an unexpected hill for the first time. I tried convincing myself to quite multiple times, and I almost did, until I made it to the top. I’d never felt better about anything before. It sealed in my head the high of accomplishment. Up until then, I would get close to finishing something, just far enough to convince myself that I can finish it if I wanted to, not knowing that that last 2% is what really matter, it’s what separates the dreamers from the doers.

Health

The diet continued into its 3rd year. Now the goals are a bit different though: I want to get to 170lbs and stay there. I want to find a lifestyle that can help me maintain and not feel like I’m in a constant struggle trying to hold on to a number. This is how I did:

 A graph of my weight over the past year
A graph of my weight over the past year
 A graph of my cycling activity over the year
A graph of my cycling activity over the year

Here’s what’s interesting about these two graphs: Since they cover the same span, they mostly line up. You can see the correlation between my activity level between january and June, and my weight. I think part of what happened there was that I was riding very actively, and some of the weight gain is most definitely related to a gain of muscle. However, I think my body got very efficient at the form of exercise I was putting it through and I was using all this exercising as a way to justify eating whatever I want. I tried fixing that after Aids/LifeCycle (The peak of the graph), and it mostly worked. You’ll also notice around July a drop. That’s when I went low-carb. I cut out rice, bread, and pasta. I cut down on processed foods, and my diet started looking a lot like this: 

 My typical day of food since July: 1 cup of Steel-cut oatmeal with granola, some fruit (sometimes), a salad for lunch, a mid-afternoon snack, and protein/grains for dinner.
My typical day of food since July: 1 cup of Steel-cut oatmeal with granola, some fruit (sometimes), a salad for lunch, a mid-afternoon snack, and protein/grains for dinner.

Overall, the diet has been fairly successful at stabilizing my weight. I’ve actually never been this stable. However, it’s stabilizing about 8 pounds above where I want it to stabilize. Hoping that as I re-introduce exercise into the diet, it’ll stabilize in a better place.

Vacations

I discovered what a vacation was this year. Up until AIDS/LifeCycle in June, I hadn’t taken a real vacation…ever. Since that one, I’ve gone on 2 others, and I haven’t spent 3 weekends in a row in San Francisco. These vacations have kept me grounded and stable, have widened the range of my experiences, and are my most cherished memories from this year.

 I went camping for the first time
I went camping for the first time
 I woke up to Yellowstone National Park
I woke up to Yellowstone National Park
 We made dinner in the woods
We made dinner in the woods
 I tried surfing and realized it wasn't really my thing
I tried surfing and realized it wasn’t really my thing
 I learned how to pack a bag properly
I learned how to pack a bag properly
 My bike came with me
My bike came with me
 I paddle-boarded in Wyoming
I paddle-boarded in Wyoming
 I rafted in Montana
I rafted in Montana
 I rode my bike from SF to LA
I rode my bike from SF to LA
 I got a motorcycle (And sold it 6 months later)
I got a motorcycle (And sold it 6 months later)

 I bought a car to go on more vacations
I bought a car to go on more vacations
 And I used it to take a lot of photographs
And I used it to take a lot of photographs
 I finally went to Europe with Maddie. It confirmed I wanted to spend a lot more time in Europe.
I finally went to Europe with Maddie. It confirmed I wanted to spend a lot more time in Europe.

Work

I guess if you want to draw any conclusions about how this year went, consider that every “Reflexions on my..” post has been almost only about work, and in this one, I decided to put it last. I got to launch some awesome products this year, which was cool. I got to increase my internal multiplier, which was also cool since that’s what my goal had been. I transitioned to Instagram half-way through the year and have found the team to be profoundly brilliant. Love these guys.

I don’t know what to say about work. I’ve had about 15 epiphanies when it comes to product development, cultural development, how to ship software, how to run meetings, how to sell my ideas, how to plan ahead, etc etc. Each of those topics deserves its own blog post.

I think back now, half-way through December, to who I was at the end of last year, who I am now, and I can see the profound way that my experience at Facebook and later Instagram has helped me grow. That’s my leading and trailing indicator of the worth of the place I’m working, and it’s all thanks to the people I’m working with, the collection of people Facebook draws to it, and the open culture that allows for the free-flowing of ideas across such a diverse and smart employee-base.

I have some hard questions to answer to myself about the trajectory of where I’m going and the things I want to do. I’m not ready to talk about it now since these thoughts are still unformed in my head. They’ll get their own posts when their time comes.

2013 has been a great year. I’ve lived life like I haven’t lived ever before. I’m thankful for all the people who are a part of my life, I love each and every one of you guys.

A Journey of a Lifetime

riends,

I’d like to share a journey with you. It’s a journey that I’ve been on for three years. One that has transformed my life, touched the people I interact with, altered my perception of the world and most importantly, made me realize my dreams and what it takes to accomplish them.

I’d like to share the journey of losing weight and discovering myself.

The story starts out with a cliché: I was an active kid: Thin and active, until I discovered computers, at which point my weight began its steady climb throughout my teens and my early twenties. I had never been in denial about it, but I never decided to do anything about it. Sure, I had my resolutions: I lost 20 pounds at one point, had sputters of gym attendance, but nothing stuck.

See, a funny thing happens when you’re overweight: You morph your life around it. I didn’t have any active friends, and even if they were, I didn’t partake in that part of their life. The activities I was a part of didn’t require physical fitness, so my weight was never an issue. Plus, it was Michigan – Who wants to go run in the blistering winter cold?

My internship at Apple the summer of my Senior year of college was a wake up call for me. People in the Bay Area if you’re not aware, are all fit and beautiful. They run marathons, ride centuries, swim from Alcatraz on a weekend in the winter. That summer made me realize that I had been missing out on something basic and fundamental in the shared experience of life.

Fast forward a few months, I’m on the couch in Michigan, all packed up from my college apartment, looking for a place in the city to move to start my career. I think the first decision to lose weight came when I decided to rent an apartment on the hill before I even moved to the city. I thought the walk up the hill would help me get started.

May 18th came, I arrived at SFO, and my journey started.

My coworker at the time convinced me to take on a challenge of running 2 miles a day for a month. I thought he was crazy. Not only could I not run for 1 mile a couple of months ago, the simple act of walking to lunch gave me very painful shin splints. I couldn’t hold a run for more than 2-3 blocks, the cramps would be too painful.

Many sweaty mornings later, I successfully hit my goal. I started finding that waking up earlier is refreshing. My legs began feeling stronger, my heart and lungs were working better. Nike+ became my best friend, the atta-boys they play when I performed well became my endorphin hit of the day. Shortly thereafter, I signed up for my first 10K. The weight starts melting off. I lost 20 pounds easily, saw progress, and bought new, smaller clothes. Things began looking up.

My goals got loftier after that. I signed up for a half-marathon and a 10-mile run. I manage to up my distance enough to participate for the 10-mile run, but since I had not built up a strong foundation, IT-band pain kicked in and freaked me out. I sat out the marathon and stopped running.

Meanwhile, Cycling entered my life I discovered the joys of climbing mountains, descending, fooling around with my friends, tracking my progress, and bonding with all my cycling friends.

You have to remember that I grew up in the Middle East. People aren’t “outdoorsy”, spending time in nature isn’t a common thing to do; it certainly wasn’t something my family did. I moved to Michigan after Syria, where it was completely flat and uninteresting. The most average Suburban landscapes surrounded me. When I came to the Bay Area, I was lost in the mountains, the Ocean, the Bay, the Big Trees, The Golden Gate, the Hills. I discovered that I enjoyed, craved to be outside. To smell the trees, feel the wind, watch the rolling fog. Running and cycling for new, foreign activities to me.

I had found Paradise.

How can I not spend my weekends up in Marin? Down by Skyline? Around the city, absorbing the scenery that surrounded me. 12 mile bike rides became 20 miles, 30, 40. I began doing 50 mile bike rides on the weekends. My legs were stronger and stronger, my bike became my best friend, my cycling friends my family.

Fast forward to today, I just shaved my legs. I didn’t really do it because of any of the admittedly unfounded reasons. I did it because it represented something else to me. I did it because to me, it represented something. It represented a buy-in into the life, a sort of ritualistic mental leap. Cycling was no longer something I did on the weekends, cycling was something that defined me, and this was my way of showing it.

I’m thankful for the journey. It’s far from over, but it has already helped me rediscover life. Every day is a gift, every experience is a joy. Our life before adulthood is an accident, a byproduct of our parent’s decisions. Why should I not experience the thrill of skiing, the joy of running, the rush of surfing? I’m incredibly lucky to have the time, money, and physical ability to do all these things, to squander it would be shameful.

I’m thankful for my friends who have expanded my horizon. My friends at Apple who introduced me to running and cycling. My friends at Facebook who turned it into an addiction, who introduced me to Skiing, and all the friends I’m going to meet who will continue to enrich my life.

I was on a ride 2 weeks ago with the Rapha Cycling Club. Three years I have been in San Francisco, and I still stopped, took off my cycling glasses, took a breath of fresh air, and got goosebumps. I live here, this is my home. This is where I belong.

Foresight

Of course the presence of stubborn egos was going to create personality conflicts. Of course the CEO’s absence was going to increase the rift, which caused a communication breakdown, which lead to a catastrophe.

The waterfall model is bad, your org needs to be agile, product development is iterative. These things go without saying. We all know that effective communication is essential, a sense of purpose and meaning for a team is essential. A sense of ownership and passion is essential.

Hindsight is 20/20. It gives us a handsomely wrapped, concise recollection of what happened and who did it. Who is to blame and who is to thank. Yet reality never feeds us these lessons on a silver platter. Have you ever found yourself blind-sighted by your company’s hard times or failure? Have you ever found yourself wondering how a well-designed photoshop document ended up as a mis-aligned application? Have you ever found yourself in the middle of an employee exodus? None of us intentionally ignore problems, and most of us don’t intentionally sabotage our products. Yet these things happen.

My career, short as it is, has demonstrated a pattern that repeatedly occurs after bad situations: People move on. They psychologically shift to whatever is next on their plate and hope for the best. Taking the time to reflect, understand what happened and the conditions that led to a bad outcome is what leads to professional growth. That’s how intuition is developed: Wit, Wisdom aren’t divinely handed to us on birth, they’re cultivated, formed out of our experiences and the lessons we draw from them.

Foresight – the ability to anticipate and recognize problems and bad behavioral patterns and conditions before they have the chance to sprout and wreck havoc becomes a very powerful force when combined with hindsight. Hindsight helps you deal with issues when they happen, foresight helps you prevent those preconditions from happening in the first place. Whereas hindsight is a defensive mechanism, foresight is an offensive mechanism. Failure is the most effective form of growth. It provides us the experience necessary to develop our foresight.

Where did the Red Bull Go?

Red Bull is to engineers as gasoline is to engines. We’ve had a constant supply of Red Bull for as long as I could remember, yet the Red Bull was mysteriously gone that day. Cutting costs, it turns out. By the time you have to cut costs, you’re probably running out of money. By the time you’re running out of money, you probably missed a big sale, or you mis-calculated some event’s outcome. Whatever the reason, it’s a bad sign when the employees are surprised. Surprises are bad. Surprises mean information was not disseminated and people are not on the same page. Sometimes these things are inevitable, due to some act of (human) nature, but this wasn’t one of those cases.

It was a an early-stage startup, and my first experience at such a small company. Coming in, I had trouble shedding my mentality of waiting to be told what to do and expecting that the higher-ups were taking care of everything. I had gut feelings of badness, but I suppressed them. It struck me as odd that people didn’t feel scrappy. Our office was too nice, our equipment was too nice, we took our survival for granted. I didn’t do anything about it. Our management had interpersonal/communication issues. I thought it would figure it self out, so I didn’t step in. People were starting to get dissatisfied, I didn’t step up.

This is my hindsight. At the time, I was a double-digit employee, so you may say that I’m unfairly blaming myself. But the reality is, an organizations fate is determined by those who work there. I should’ve had the foresight to see how these conditions would combine and play out, to do something about it. I didn’t. Lesson learned.

How Could This Pixel Be So Broken?

Every now and then I come across a page/product/view that is so broken, I can’t help but wonder about the process of its development. Apart from deadline constraints (A topic for another post), shipping a broken UI means a few things: It means somebody signed off on a broken UI, it means an engineer either didn’t consult the designer or the designer didn’t review the engineer’s work. It means the engineer and the designer were working separately. Most importantly, it means the designer designed something, passed it off, and moved on. Sound familiar? It should for two reasons: This is how most software is built, this is the Waterfall model. 

There is nothing so universally derided as the Waterfall model in our industry, and nothing so ironically prevalent. It’s not an obvious thing to notice. For you to pick up on it, you need to be able to notice the UI details, you need to be aware of the root problem, and you need to observe the team dynamics. This isn’t a failure of tools or process, this is a failure of communication.

Often, what happens is that a bug finds its way to the engineer, they fix it, and they move on to the next feature, waiting to repeat the same mistake. The mistake here isn’t the padding on that view, the mistake is that there wasn’t a perpetual, ongoing conversation and review process between the engineer and the designer. It’s far too common for engineers to view designers as  asset-factories, or as Gods of product wisdom. We’re taught in college to treat specs as immutable and final, but in reality, they’re anything but. A designer’s spec is a proposal, to be refined ceaselessly by the designer and the implementor. Designers don’t hand specs to engineers, product teams together hand products to consumers.

Fix the cause, not the symptom.

Final Thoughts

I wanted share an insight that I found has been invaluable: The realization that problems don’t explode, they fester and build up, that there are early rumbling signs that predate the problem, that we all have the ability to influence the sequence of our events is powerful. There are no heroes of product development, there are just people who cared enough and passionate enough to do something about it.

I can’t give you a checklist of early indicators to watch for, there are too many and they’re specific to your situation. Your intuition is your greatest assets, and it’s formed by your experiences. Take a second to think back to a failure. What does hindsight tell you? What was the lesson? What were the early indicators of trouble? How could you have prevented them?

When the Chasm Comes Back And Hits You In the Face

I left Syria in 2003, I was 15 at the time. At that time, the best internet connection you could get was ADSL and it was about 1.5-2mbps in the best of times. For a techie like me, it was a living hell. I remember the first time I came to the US and saw broadband. I would  look away for a moment, then look back and wait not realizing that the page has already loaded. Anyway, I came back in 2005 and people everywhere suddenly had 3G dongles attached to their laptops and they were surfing the web at speeds that match the LTE speeds that we get on our iPhone 5s today.

This was the first time I saw the Chasm perform a proverbial reach-around. In this case, the laggers – Syria – had eclipsed the innovators – The US – in mobile internet connectivity. Nobody needed to ruin all the sidewalks in our ancient country to wire up cables, we got to skip that whole stage of internet development and jump straight to 3G. Add on top of it government support and a lot of foreign investment, and you got yourself a top-of-the-line cell network with cell towers throughout the cities. I’m seeing a “Chasmic reach-around” again these days, only this time, I’m the innovator who’s getting blind-sided by, wait for it, my parents.

In my cocoon of Silicon Valley, people are angry about Apple Maps and are using Google Maps instead. They use Skype to video-chat, Messages.app (or, gasp, SMS) to message, and they use Facebook/Twitter/Instagram to socialize. I arrive at DTW and my Dad picks me up from the airport. I get in the car and the first thing I notice is the cartoony arrow of Waze guiding him through the highways of Southeast Michigan. We get home, my sister shows me a cute photo of my nephew she just got on her phone. She dismisses the photo and I see she’s having a 15-person group conversation with all my cousins around the world on WhatsApp. My Mom gets a phone call, and the distinctive tone of Viber starts up. I was looking around, dumb-founded.

Two, three, years ago, my Dad’s technical expertise did not extend past his email client, his fax app (I know..), and Solitaire. Today’s he’s showing me how he uses these apps to communicate with our extended family throughout the world. The same story applies to all my uncles, aunts, cousins, etc.

None of them are using Facebook, Twitter, Instagram, SMS, or any of the other tools that we’ve built-up and gotten accustomed to over the past 5-6 years. We, the young generation, are Broadband in the US, and the older generation is 3G in Syria.

The obvious questions to ask are: Is this a global trend? What’s the data telling us? What does this mean for established tech companies? I don’t have answers for those yet, unfortunately. However, we are talking about Internet companies competing with other Internet companies here, and being nimble as an internet company is a lot easier than a broadband/hardware company.

The times, they are a’changing.

A Resolution with Resolve

Good evening ladies and gentlemen, Majd here, and it’s time for some new years resolutions. Hope you didn’t end up here looking for creativity and surprise.

I recently wrote a retrospective on the last 12 months, and included some high-level goals. I want to expand on those goals and add some more ones along with some context on why I chose these goals.

Spending Money Where It Counts

You know how you sometimes watch a video on the internet and it plants an idea in your head that you can’t shake? I recently had this experience. The video acted as a spark. I’ve had a ideal form and build up over time and this video gave me the little push I needed to go over the edge.

Here’s another instance where the same idea came up:  

participants who were in the experiential condition said that they were more likely to consider their money well-spent at that time but also that currently that their purchase was still making them happier, and it made others happier. And that was because they had an increased sense of vitality, an increased sense of vigor. And they also had a sense of being connected with their social world.

I’ve previously discussed my philosophy on seeking life experiences that otherwise wouldn’t be afforded to a person like me. Who you are is a happy accident of who your parents were and where your great-great-grandparents decided to move to. Your religion, identity, personality, and locality are decided on your behalf, and that’s something I’m not comfortable with.

So, my resolution for 2013 is to spend money where it counts: On experiences, and on others. I’m not sure what form that will take. Will I set up a budget to travel on a monthly basis? Where will I go? Who will I go with? For how long? I’ll cross that bridge when I get to it.

It Never Gets Easier, You Just Go Faster

Cycling is the next one. I want to take cycling more seriously this year. The past season was my first foray into consistent, frequent bike rides. I’ve met so many people I never would’ve otherwise met, ate like an animal and still lost weight, visited places I never would’ve been to before, and had a lot of fun doing it.

The big ride this year is going to be the AIDS Lifecycle. It’s a 7-day bicycle journey from San Francisco to Los Angeles. Can’t wait. But beyond distance and endurance cycling, I want to achieve a respectable average speed solo. That means a training plan, a structured exercise regiment that will measure not just my ability to perform on the saddle, but also my ability to adhere and maintain a training schedule. We’ll see how it goes. I already know I’ll be signing up for as many organized group rides and centuries as I can.

It’s Easier to ask for Forgiveness than to ask for Permission

I’m not quite sure what form this’ll take. It’s something I learned in the first year of my career and it’s something that’s helped me a lot last year. Another way to phrase this is, if I want something, and nobody’s giving it to me, I’ll take it by my own damn self. This has obvious applications to my job, but I think it also extends to social and emotional situations. It’s something that I’ve had to struggle with a bit traditionally, and I think it’s a skill worth improving. I’ll keep you posted on this one as it fleshes itself out in my head.

Onward.

Reflexions on my 25th Year

For the past two years, I’ve written a retrospective on my year. I didn’t want to stop the tradition, but I’m also in the process of transitioning my blog and couldn’t write it there, so I’ll share it here and cross-post it when the blog is ready.

2012 was an interesting year. Work-wise, it was a time of great adjustment. After 2 years doing web development, trying to make high-fidelity applications work on mobile platforms, I faced reality and moved back to native iOS development. I’ve already shipped work I’m very proud of, and I’m really excited about the next steps. 

I’ve also managed to get myself into a better fit. Earlier this year, I posted about wanting to be a designer in a couple of years. I’ve since rescinded that comment. I’ve come to realize that I was using that as a proxy to what I really wanted. What I really wanted was product ownership and a voice in product direction, and I realized that I don’t need to put my love of building product and engineering behind to achieve it. I admit that I traditionally always had a foot out the door. To be frank, I had one foot out the door when I came to Facebook. This good wave I’ve been riding and my complete immersion in Facebook’s culture has me both-feet-in and trying to take advantage of my situation.

On that topic, let’s talk about multipliers. This was another one of my big revelations this year. There are two kinds of career multipliers: Internal and external multipliers. Internal multipliers refer to the amount of product development that happens per unit of time. A new engineer has an internal multiplier of 1 – Every unit of time invested into the product, moves the product forward 1 unit of development. As you move up the hierarchy, your internal multiplier increases: A designer spends 1 unit of time designing a product, then hands it off to N engineers who spend N units of time developing it, the designer’s multiplier is N. A PM makes a decision, M number of designers design it, N number of engineers build it on Y number of platforms. The PM’s multiplier is N * M * Y.

External multipliers refer to the amount of time your work affects the world. For example, If I spend 10 hours working on a feature, then over the life time of the product, X number of people will spend Y amount of time using it. Therefore, my external multiplier is X * Y. This is where Facebook shines. The external multiplier of a Facebook employee (And Google, and Apple, and…) is immense. It still gives me goosebumps to think about the sheer amount of man-months the products I’ve built have sucked up from humanity. I hope the return on investment was worth it 🙂

My career goal for 2013 is to increase both multipliers.

Life-wise, 2012 was the year of the bicycle. I rode harder, faster, better, and more often than I ever have. As a result, my legs are huge, I’m healthier, happier, and most importantly, I’ve met and befriended a lot of people I otherwise wouldn’t have ran into. Thank you guys for being a big part of my year. Things weren’t perfect though. I’ve had a dark cloud follow me for the better part of the year. It has proven difficult to shake off, but I believe it has made me a stronger person and it has helped me strengthen my friendships. Without the support of everyone around me, the tough times would’ve been much tougher, and the good times wouldn’t have been as good.

My social makeup has changed a lot and I’ve been blessed to meet the people I met. Whether it’s the insane amount of bicycling (or what seemed insane to me) I did this summer (Thanks FB Cycling!), or the people who have helped me grow professionally and personally, the person I am as 2012 draws to an end is very different than the person I was when 2012 started.

Weight-loss is another recurring theme of these posts. I’m ecstatic to report that I’ve hit my goals. It’s been a two-and-a-half year long journey and without the support of my friends and coworkers I couldn’t have achieved it. I won’t go into details about this journey here, it needs its own space. But I’m there. I still sometimes look in the mirror and stand thinking about what my life was like in 2010 and what it’s like today. Thank you Chuck EdwallJuan Camilo Pinzón and Ken Goto for introducing me to running and cycling.

2013 is going to be a year of Gran Fondos, big bike rides, good times, and new experiences. I look forward to the challenges of 2013.

Special thanks this year to Joel SeligsteinJohn CiancuttiJosh WilliamsJasper Hauser (so many J’s!), Ari GrantFrancis LuuHugo Angelmar. You may not have known it, but our conversations and friendship have had a deep impact on my outlook and perspective, and for that, I’m thankful.

Conquering Defeat

introspection |ˌintrəˈspekSHən|: the examination or observation of one’s own mental and emotional processes.

Sometimes I feel like I need to limit my time interacting with technology to just the times I need to get my job done. I go through this phase every now and then where I realize that my dependency on technology may not be as strictly beneficial for me as I make myself believe.

I’ve long held the belief that any technology is good technology. Technology is inherently good, even if it’s used for bad purposes.

Every now and then though, something happens that triggers a realization that life extends past the computer. It’s almost sad to need to realize that, but such is the reality of dedicating your life to your work and passion. Such is also the blessing and the curse of what we do. It’s kind of an ironic cycle: I am passionate about my work, so I spend a lot of time doing it, which makes me less passionate about it in the long run (burn out). For me to avoid the burn out, which is the worst outcome of passion, I have to remind myself explicitly to step aside and metaphorically (sometimes literally), and smell the roses.

It might be a trip home to see your family, your parents coming to visit you, some personal issues, or some external issues. It can be a combination of those, but the end result is introspection. Introspection can be a scary and frightening thing. A lot of people spend a lot of time running away from introspection. I can relate to this comic and have referenced it a lot since first seeing it (in my work’s bathroom stall):

I think that comic captures something essential about our use of technology. Whenever technology becomes not a tool to get a job done, not a toy to play with, and not a passion to feed, but an excuse to run away from introspection, then it’s time to re-evaluate it. Taking a long walk at night alone, sitting along on the beach, going on a solo bike ride. Solitude does not imply loneliness nor boredom. Solitude can be a time of reflection. Running away from hard decisions and tough problems doesn’t solve them. In fact, it can worsen them.

Part of me wants to turn this into one of my month-long goals: No Twitter or non-work-Facebook for a month. No internet for a month, etc. But I don’t think that’s the problem nor do I think I would get anything from it. The problem isn’t technology, the problem is using technology to run away from thought.

Flow (this is the third time I reference that book now) describes this in the second half of the book. People who conquer solitude, emotion, and thought are the proverbial “Masters of their domain”. I’m only 24, I’m a baby in the grand scheme of things, but I’m old enough now to draw conclusions from my experiences, and one of those conclusions is: The brain can be either your biggest liability or your biggest asset. It can bring you down, and it can lift you up. The difference in my opinion is introspection. Being able to understand that what you’re feeling is not reasonable. that you’re emotion is unjustifiable, that you’re confusion is incomprehensible is actually a really powerful concept.

One of the other conclusions I’ve reached is not to dwell. The instant a negative outcome is irreversible, any mental capacity spent not deconstructing it and learning from it is a wasted brain cycle. Nothing is sadder than a wasted brain cycle. This has been my indispensable tool for dealing with negative outcomes: Not getting into a college I wanted, not getting a job offer I wanted, not getting a raise I wanted, or any other life circumstance.

Once you truly isolate yourself from your reality and can look at it objectively and from a third person perspective, things click and become clearer. Think about all the situations where a friend has been able to help you figure out something hard. The difference is they’re isolated from the incident. Being able to do it on your own means you can do it for all the situations that are too personal to share, and at your own pace.

You obviously can’t control your emotions. You can’t stop yourself from being happy, sad, angry, or bored. What you control is your reaction to that scenario. If you learn to tame and control your emotion, you become in control of your happiness.

A Tale of Ten Hobbies

The Problem

Over the past two years, I’ve been picking up hobbies left and right. I decide I want to “Get into X”, then buy all the gear necessary to exercise that hobby. Six weeks later, I move on and the hobby becomes a memory. Sometimes I cycle back to old hobbies, hoping to pick up a forgotten skill. As of today, the cycle includes: Figure Drawing, Cartooning, Watercoloring, Tailoring, Piano, Writing, Running, Cycling, Reading, Cooking, and Photography.

When I first noticed this tendency to drop hobbies shortly after picking them up, I dismissed it as a natural consequence of my desire to diversify my life’s experiences, and thus wasn’t something worth fixing. The point was to keep my mind sharp and active, not to get good at a certain hobby.

As I’ve matured though, I’ve realized that that line of logic was a cop-out I used to justify giving up. I never started a hobby expecting to drop it soon afterwards. When I do drop it, I usually do it out of boredom or frustration. Why is that? Why can’t I pick something up and stick to it long-term? Is that even feasible? How would I even fit time into my day for all these hobbies? How good do I really want to get?

After mulling those questions over in my head, I decided that the next time a cycle came about naturally, I’ll ride it through, and I’ll try to take note of what was going through my mind.

Soon after, I picked up photography: Bought the camera and a lens, started shooting, and sure enough 6 weeks later, it hasn’t left my desk in a week. I think I’ve figured out why I drop hobbies, and I have a hunch on how to fix it.

The Realization

Given a creative activity where the output is subjective, judging progress is difficult. Compared to a non-creative activity where the result is clear and progress is obvious, it becomes much harder to find motivation to continue investing time and effort when you don’t see that effort rewarded. For example, you either finish a 50 mile bike ride or you don’t, you either win a game of basketball or you don’t. Contrast that with judging a painting: When are you “finished”? How do you judge its quality?

“Beauty is in the eye of the beholder” is another way of saying that creative works are judged against a personal criteria of taste, quality, and style. As your skill and your exposure to a domain grow, your expectations grow and your tastes develop, but your skill may not grow at the same rate. That’s the case with me. Inevitably, I compare myself to the professionals who have had years of practice, and judge my amateur work against theirs.

Therein lies the problem. When I started photography, merely using a high quality camera with a shallow depth-of-field was enough to meet my expectation of a “good photograph”. However, as I interacted with more photographers, read about photo techniques, had my work critiqued, and refined my taste in photography, I realized that my ability to execute had lagged far behind my expectation. Every photograph became a failure, every photo walk a chore.

Every hobby I’ve picked up has a similar story, except for reading, writing and cycling. I think the feedback loop is so tight in those activities, that any input of effort, has a clear and obvious impact on the output.

This concept isn’t new. In fact, the realization came mostly from reading “Flow”, which I already wrote about in A Moment of Clarity in the Pursuit of Happiness.

The question remains though, what can be done to fix it?

The Solution

I don’t think I can reduce my expectations. I can’t unlearn what makes a good photo, painting, garment, or meal. What I can do however, is set quantifiable and achievable goals. I love cycling because I can measure my performance and compare it against my peers. The competitive challenge drives me and the data-tracking gives me feedback on my progress. Feedback is essential since it justifies my investment of time. Without the feedback, frustration and boredom kick in and I move on

I can set personal challenges that let me operate at the limits of my skill for any of my hobbies. For example, instead of trying to “make a good photo”, I can take an existing photo that I like, and reproduce it. I can set myself a goal of reading a certain number of “favorites” on Flickr. I can decide that I want to make some money from my tailoring.

Those are clear goals that I can work towards. Achieving a goal gives me the positive feedback I need, and increasing the challenge as my skill grow will close off the loop. Eventually, the skill will grow enough with practice to close the gap with my expectations. Until then, I need to put my expectations aside and work towards an achievable goal.

If you’ve ever struggled with the same problem, I hope this works for you, it’s certainly working for me.

The WebKit Inspector

The mobile landscape today is all but monopolized by WebKit, as a result, most of the tooling and infrastructure to support mobile web development on the frontend is taking place in the WebKit Inspector, so I’ll focus on it, and take a deep dive into its entire feature-set and how and when to use it.

Google and the Chrome team have been pumping a ton of resources into the WebKit Inspector. The changes have enabled a whole new class of complex and ambitious applications that would have otherwise collapsed on their own weight. This is great news, of course, but as I talk to more and more web developers about their process and tooling, it became clear to me that many of them haven’t caught up with the changes or aren’t making effective use of the tooling available. This blog post attempts to remedy that, not only by walking you through the inspector’s feature set, but also highlighting certain techniques for bug hunting and feature development that I’ve found to be indispensable. The post is meant to be scannable and shareable. You can click on any header to share a URL to a specific tip/technique or feature to your friends.

Before We Start

Before we start, I want to make it clear that I don’t claim to have infallible knowledge on tooling and process. If you find any of this information to be incorrect, out-of-date, or inefficient, please reach out to me and let me know, I’d love to hear your thoughts.

If you’re new to the inspector or have a passing knowledge of it, do me a favor and play with it as you read this post. Trying things out are the best ways to learn it! “But Majd, I don’t want to keep creating new files and loading them and editing them to test these things out! I have kids to feed!” I hear you, and I agree with you, that’s where the data: URLscheme comes in! 

Try it out: Open a new tab of Chrome, and paste this into the address bar and hit enter:

data:text/html,<b>ZOMG I AM BOLD!?!!?</b>

This is one of the easiest ways to get some HTML into the page and start inspecting it and playing around/investing ideas. Anything after the comma is interpreted as html and once loaded, you can open up the inspector and start playing with it!

One Inspector to Rule Them All

There isn’t a single WebKit Inspector. In fact, there are 5 at any given time that you can use:

  1. Safari Stable
  2. Chrome Stable
  3. WebKit Nightlies
  4. Chromium
  5. Chrome Canary

I’ve tried to sort them from oldest to newest. Chrome Canary gets updated with new features all the time. After they bake for a while with the early adopters, they make their way slowly to Chromium, WebKit Nightlies, Chrome, then Safari. At any given time, Safari’s Inspector is about a year’s worth of development behind Chrome Canary. That is to say, use Chrome Canary for your development.

Getting Set Up

Awesomesauce. You’ve downloaded Chrome Canary, you have it open, you have your site up, you’ve cracked your knuckles and rolled up your sleeves. Hit CMD+J to open up the Inspector or right click on a specific element and click “Inspect Element”.

Now let’s set up the environment so you’re comfortable. The first thing to do is familiarize yourself with the UI. Take a minute to click on every button you see, hover over it to see the tooltip, and find out what everything does.

Dock to Right

The first thing you’ll want to do is click on the gear icon in the bottom right to bring up the settings. Ignoring the horrendously ugly HUDdisplay, I highly recommend checking the “Dock to Right” setting. What this does is stick the inspector to the right side of your window, but keeps it attached. If you decide to pop it out into its own window, then opening multiple inspectors at the same time can become confusing. If you dock it to the bottom, you get a lot of horizontal space, but vertically you’re very constricted. Docking to the right is the best of both worlds. Here’s what it should look like:

Emulate Touch Events

If you’re working on a mobile application, this setting (in the settings HUD) is essential.

Google, if you’re listening: Default the docked setting to “Dock to Right”.

Keyboard Shortcuts

Another quick tip to help speed up your work with the inspector is to get very familiar with the keyboard shortcuts. Go to the Elements Panel (some of the other panels eat the keystroke), and type “?”. This should bring up another horrendously ugly HUD display that contains a list of keyboard shortcuts. The most helpful shortcuts are the ones to navigate the Scripts panel, which we’ll talk about in a bit.

Google, if you’re listening: Make the keyboard shortcuts accessible from the settings panel. Most people don’t know the secret key. While we’re on the topic, why does the HUD have a different light source than the rest of the UI? Why is the border radius so big? Why is the “X” button not vertically centered in the header? Why are some of the shortcuts so small you can’t see them?

Inspecting an iFrame

Debugging iFrames has long eluded web developers. NO MORE! You can now set which iframe the inspector is inspecting through the popup in the bottom center of the inspector that says “”. This panel is interestingly only visible when you have the console expanded (hit escape from any panel).

Google, if you’re listening: Make the iframe drop down accessible everywhere.

The Console

Sweetums. You’re all set up, you’ve cranked up your music, and you’re hacking your heart away. Now you need to actually do something: Run a command, check the output of a function, check for the existence of a method, or see any logs/errors/warnings. This is where console comes in to help. The console is such a badass, in fact, it not only gets its own panel, it’s also accessible from any other panel by hitting the “>=” icon in the bottom left, or by hitting the Escape key.

It also happens to be one of the more intuitive features: Type something, hit enter, see the output of the expression. Any logs are visible chronologically, click the file name on the right and get taken there in the Scripts panel. What you may not have known though, is that you can type multi-line expressions in the console by hitting “shift + enter”. This is really helpful for writing out long commands that involve anonymous functions or complex statements. You can also type “ctrl + L” to clear the console when the logs get overwhelming.

From a DOM-debugging perspective, one of the cooler features of the console is its integration with the Elements panel (which we’ll discuss in the next section). Any element that’s selected in the Elements panel can be quickly accessed using “$0”. That will reference the element and allow you to interact with it. Inversely, whenever you see a DOM node printed in the console, you can right click on it and click “Reveal in Elements Panel” to quickly find it in the DOM.

Google, if you’re listening: Add syntax highlighting to the console command, it’ll help simple parse errors. It wouldn’t hurt to auto-insert braces and parenthesis and quotes, too.

The Elements Panel

So you got you’re all set up and ready to start building your application. The first step is to get your HTML and your CSS looking right (Or JavaScript, depending on your workflow). That’s where the Elements Panel comes in.

DOM Manipulation

The Elements Panel comes into play whenever you are modifying/debugging CSS or the DOM. The main area of the Elements panel is your live DOM hierarchy. As you make changes through JavaScript, you see them reflected live in the Elements Panel. You can use the arrow keys to navigate the hierarchy, and double click on any attribute to edit either the name or the value. You can also click-drag any node in the DOM to reorder it and change its position.

Because its live, I find myself doing a lot of experimentation in this panel. Drag this node here, does it fix that z-index ordering issue? That div is invisible, is it being hidden by another layer?

At the bottom of the inspector, you’ll find a magnifying glass. When you click [that, you can hover over your application itself and it will highlight the node you have selected. This comes in handy when you need a quick way to go to a deeply-nested element.

While you’re playing around with the Elements panel, try right clicking on one of the nodes and see the options that come up. One of these of note, is the “Break on Subtree Modifications” option. When you enable that, any changes that you make to the DOMhierarchy under that node, it will automatically pause, and let you debug it.

CSS Editing

Moving on to the right, the CSS editor is up-there in the list of most-helpful features of the inspector. Superficially, it allows you to live-edit your CSS. However, it reduces the barrier to experimentation so much, I find myself moving things around and playing around with ideas I normally would’ve dismissed as stupid, which is a good thing, as Bret Victor says.

The first thing in the list you see is the “Computed Style” section. Check the “Show inherited” checkbox, and you will see a list of every single style property and its corresponding value that’s applied to the selected node. Even if you didn’t explicitly set a property, it will show you the inherited default. This helps you not only understand what is making up the styling of the node, but it also helps you find out what properties you can set yourself to modify it. Take a quick look at it and see if there are any CSSproperties you didn’t know about, then try them out and see what they do!

Next in the list is the “Styles” section. This shows you the list of properties, grouped by selector, that have been applied to the node. The first sub-section here says “element.style”. This shows the properties set through the style=”” attribute in the HTML. The next section titled “Matched CSS Rules” shows you the selectors that matched the selected node, their properties, and their values, along with the file name and the line number on the right.

To add a new selector, click the “+” button to the right of the “Styles” header, here you can define the selector, hit tab, then start writing properties and values. You’ll notice Chrome offer auto-complete suggestions (this is another great way to investigate which properties you can set). The version of Canary as of this writing requires you to hit the right arrow key to fill in the autocompletion, then you can hit tab to set the value. Hitting tab again will let you set the next property. If you wanted to set a new property to an existing selector, click once on the closing bracket. Clicking on the button to the right of the “+” new selector button will allow you to specify a pseudo selector. Handy!

Colors behave slightly differently. Clicking once on a color value will toggle through a list of representations (hex, rgb, rgba, etc), and clicking on the little colored square will open up the color picker.

All this is great, but let’s say you’ve just spent 10 minutes editingCSS. Now what? How do you save those changes? To do that, click on the file name of the selector (or go to the file yourself in the Resources panel), then right click on the file (which will be updated to reflect those changes), and you can right click to “Save As” and overwrite your existing files. Personally, I find selecting the text and pasting it into my editor to be faster and less error-prone.

One final node on CSS Editing: If you write a new selector (by hitting the “+” key), it won’t persist into a file because it doesn’t know which CSS file to put the selector in.

Google, if you’re listening: Prompt me which file to put a new selector in when I create one. Also, make “tab” fill in the selected auto-completion. Finally, find a way to make persisting changes inCSS to my code easier. This last one is more of a high-level wish, I don’t really know whether or not it’s possible nor how it would work, I just want the process streamlined :P.

Metrics

Phew, that was a handful! Take a minute to play with all this. When you’re done, let’s move down to the next item in the list: Metrics. If you’re not familiar with the CSS Box Model, take a minute to readthis awesome guide.

The Metrics section basically shows you how the browser is rendering a node from the perspective of content size, padding, border, and margin. Use this tool to debug positioning/dimension problems.

A nice companion tip to the Metrics panel, is that the semi-transparent blue box that overlays the selected node will actually show you the padding and the margin, so you can understand how a box is affecting the flow

Blue is for content, green is for padding, and orange is for margin.

Event Listeners

We’ll skip Properties and DOM Breakpoints for now. I haven’t found a use for the Properties section yet, and DOM Breakpoints shows you any “Break on …” actions you’ve taken by right clicking on a node. The last section we’ll talk about in the Elements panel is the Event Listeners section.

If you’ve attached any event listeners on your node (either using JavaScript or using the attribute in HTML), you’ll find those listeners listed here. This comes in handy when you want to debug whether or not a listener has been properly attached to a node, and what will happen when it gets invoked.

Clicking on the little funnel icon on the right allows you to see either the listeners on the selected node or in the document. This comes in handy if you have listeners attached on things you can’t select in the main list (like window, document, etc).

The Resources Panel

Your HTML and CSS are looking good, and you’ve got a fair bit of JavaScript written to use either the FileSystem API, IndexedDB, LocalStorage, App Cache, or Cookies. The Resources panel is where you go to inspect and debug all these storage resources. Most of them do more or less the the same thing and are pretty self-explanatory: Click a resources, see a list of items, and dig through to navigate your data.

Of note is the first item in the list called “Frames”. It includes a sub-item for every frame in your application, and groups resources such as Images, Scripts, and Stylesheets. Really the only reasons I’ve found to dig through this list is to find a Stylesheet file I edited so I can copy its content and paste it into my editor to save.

The Network Panel

The Network Panel comes in handy when you’re debugging, well, network issues. Is your image asset not updating? The network panel will tell you whether or not it’s being served from a cache. Is your XHR not responding? The network panel will tell you if it’s stuck or error-ing out.

Clicking the “Record” button (the black circle) will maintain a Network session across reloads, handy if you want to see how a change in your codebase affects the network performance.

If you find yourself debugging performance issues, the Network Panel is also very helpful. On the right, you see a “cascading waterfall” of your network requests. If your page is taking a really long time to load, your first step in debugging it would be to look at the waterfall. The blue and red vertical lines show you when the DOMContentLoaded event fired, which means that before then, your use is sitting around waiting for something to happen. You want to reduce that time as much as you can.

The Waterfall

Why do I keep calling it a waterfall, you ask? Well, it looks like one, but more importantly, the reason it looks like a waterfall is because every network interaction takes time both in network latency, and in download time, and the browser can parallelize only so many of them. If your waterfall is wide, you need to go out of your way to cut HTTP requests.

By the way, you can click on the “Timeline” header and you get a drop down (!) to change the sort order. Particularly interesting is the “Latency” sorting, which shows you which of your requests took the longest to establish.

The half-transparent left-side of the capsule shows the latency, and the dark part on the right shows the download time.

The Request Details

On the bottom of the Network panel, click “XHR” to filter the network connections just to XMLHttpRequests. Then click one of them. You see that the right side now changes to show details of that specific request. The first tab shows you all the HTTP Headers sent with the request, and those of the response. This helps when debugging server bugs or CORS bugs.

Preview is a pretty-formatted version of Response. If you’re getting back a lot of JSON, the Preview tab will format it into a collapsable list for you, whereas the Response tab will show it in plain text.

Cookies show you the cookies that were sent as part of the request, and Timing shows more details regarding the time profile of the request. Again, helpful if you have requests taking a long time.

The Scripts Panel

I’m a full-time JavaScript developer, which implies that I spend most of my day in the Scripts Panel. It has also seen some of the biggest changes recently.

Looking around, two buttons worth mentioning are the “Pretty Print” button (looks like a pair of curly braces), which will properly format a minified file. This comes in handy if you get a bug in a third-party minified package and you want to have an even remote chance of figuring out what is going on.

The other button worth mentioning is the “Break on Exception” button (Looks like a pause button). When gray, it’s disabled. Clicking it once will cause your script to pause if it hits any thrown exception. Clicking it again puts it in the “Break on Uncaught Exception” mode, which only pauses your script if you (or something else you use), throw an exception that doesn’t get caught. This is indispensable when you want to track an exception that’s being thrown, since it preserves the call stack and the current state of the application.

File navigation

The addition of tabs in the main workspace and a full file browser, scoped by origin has dramatically improved the efficiency of moving around your project.

To open the file browser, click the weird icon in the top left (it looks like two folders with a right angle between them). By default, the file browser will “float” on top of your workspace, so click the weird icon on the top right of the browser (it looks like a half-white, half-black rectangle) to dock it. Try typing while you’re in the file inspector, it will do a fuzzy-match of the files in your project!

While we’re on the topic of moving around your project, try hitting “CMD+O”, this will open up a TextMate-style “Go-to-File” popover that lets you quickly jump to a file. “CMD + Shift+ O” will open up a “Go-to-Symbol” popover that lets you quickly jump to a symbol in the current file, and “CMD + L” will let you jump to a specific line.

Google, if you’re listening: Add the path to the file in the Go-to-File popover, in case there are duplicates.

Breakpoints

Clicking on a line number in the gutter will insert a breakpoint. If your application hits that line during execution, it’ll pause, bring up the Scripts panel, and highlight that line. Then you can inspect the call stack, the scope variables, and inspect/modify your objects. This is the main workflow when debugging issues with your JavaScript.

Occasionally, you’ll want to debug a problem in hot code (code that gets run over and over). Putting a breakpoint here becomes tedious, since you’d have to hit “Continue” over and over. What I usually do in that situation is wrap the function call I want to debug with “window.foo = true” and “window.foo = false”, then right click on the breakpoint, click on “Edit Breakpoint”, then in the textfield I type “window.foo”. What this tells the inspector is that unless window.foo evaluates to true, don’t stop.

So, you’ve added a breakpoint, you refreshed the page, and now your script is paused. Now, the fun begins.

The first thing of interest in the sidebar is “Watched Expressions”. If you care about the value of some expression (Say “MyApp.someController.property === ‘some value’”), then adding that as a watch expression will let you keep an eye on it without having to type it over and over in the console.

Below that, the “Call Stack” section shows you every function call that the system went through to end up where it did. You can navigate this list using “CTRL + .” to go down and “CTRL + ,” to go up in the stack. I usually navigate this list when I care about how a variable came to have its value and how it traveled through the system.

Next, “Scope Variables” lists the local variables and their variables. If you’re using closures to close over variables, then those will be grouped together. The “Global” group shows you every variable on the “window” object (a huge list). As you move through a function, this list gets updated automatically.

Now that you’ve inspected the state of the app on a breakpoint, you’ll probably want to move around. “Continue”, “Step Over”, “Step Into”, and “Step Out” are your friends here. In fact, you’ll be using them so frequently, it’s worth bringing up the keyboard shortcut list again and learning the shortcuts for them. It’s much more efficient to navigate through the list with the keyboard than the mouse. If you’ve used a debugger before, these terms are already familiar to you. For the web developer though, these are new concepts that we didn’t have before.

Continue resumes the execution of the program. If execution hits the same breakpoint again, it’ll pause again. Step over will skip function invocations and stay within the current function. Step into will enter the new function if it’s being called. If you’re calling multiple functions in the same line, you can step into, and out of each one in order. Step Out will leave the current function and go back up one level in the call stack.

These tools are essential in walking through your code and pin-pointing a bug, or finding out which path through your codebase is being followed.

Another handy tool lives under the “XHR Breakpoints” section. As the name suggests, it sets up breakpoints related to XMLHttpRequest objects. The way you specify the breakpoint, is by typing in a substring of the URL you want to inspect. Handy!

By the way, in the “Scope Variables” section, you can right click on a function and choose “Jump to Definition” to jump to the part of the file that defines that function.

The Timeline Panel

Next in the list is the Timeline Panel. As you might have observed, each panel is designed to help debug a certain class of problems: Elements Panel for DOM and CSS, Resources for local storage and assets, Network for HTTP requests, Scripts for Javascript, and Timeline is for browser performance.

What do I mean by “browser performance”? I’m referring to things that are generally out of your control, but which affect the performance of your application. Understanding what’s happening under the hood is essential to supporting the growing complexity of an application.

Timelines

The first section of interest is the Timelines section. To activate it, hit the Record button (the black circle in the bottom left of the panel). When it’s glowing red, perform a task in your application you like to inspect. If you’re wondering why your scrolling performance is slow, you would try a short scroll. If you’re wondering why loading a modal panel is slow, you would do that. Don’t worry about doing too much and getting overloaded by data in the panel, there are tools to help!

So, you’ve managed to get a nice little timeline of what’s happening, but you’re only interested in a little section of the data. To “Zoom in”, you can click and drag on the timeline graph. You’ll see a couple of draggable thumbs so you can adjust the visible section. Moving down into the waterfall graph, you’ll notice little arrows next to some of the orange capsules. Expand those, and what you’ll see is the function invocation that triggered the browser to do work. In the example below, we can see that a scroll event had fired, invoked a handler, which caused a “Recalculate Style” to fire. If you hover over the item in the sidebar, you see even more detail.

You may be wondering at this point “What are these purple events that are taking up time? Repaint, Recalculate Style, and Layout?”. These are browser-events that are usually invoked by in response to visual changes. For example, If your resize or scroll, the browser needs to do a bunch of work to make sure everything looks as you’d expect it to. You could also invoke these events yourself, so it’s worth understanding what the inspector is telling you and not taking DOM changes for granted.

Recalculate Style

This occurs when you modify CSS properties. In the above screenshot, you see I’m running the same command twice, but seeing different results. The first time I run it, the browser has to Recalculate Style, Layout, and Paint. The next time, it just has to Recalculate style. What’s happening?

Because this is on a fresh page load with nothing visible, giving an unstyle div a height causes its contents to change layout (Layout), causes the visual display to change (Paint), and invalidates the styles (Recalculate Style). The next time I run the same command with the same value, it gets to skip the Paint and the Layout, since they didn’t change. Notice the order: Recalculate Style informs the later processes whether or not they need to get triggered.

Repaint

Back to our empty page, let’s give our div a width, height, and background color so it actually changes visibly on the screen:

Now, it has to repaint both times, but it only needs to calculate layout once. That’s because the Recalculate Style step found that the positioning/dimensions haven’t changed, but the background has, so it skipped that step. Anything that cause a visual change, causes a repaint.

Layout

Often referred to as “Reflows”, a Layout event causes the browser to recalculate the position of elements. For example, say you have a picture that’s floated, so the text wraps around it. If you remove the float, the browser has to “re-flow” the text around it. Paul Irish has a great video where he describes reflows and how to avoid them.

Google, if you’re listening: Please fix the resize behavior. On small Macbook Air screen, it’s common to hit multiple UI bugs when you arrange the inspector/application side by side.

For more detail on how this works under the hood, refer to this blog post.

Memory

Now we’ve looked at the timeline, optimized it, but the application is still crashing every now and then after you use it for a while, sometimes it slows down, and it stutters a lot. You’ve seen a few “GC” (Stands for Garbage Collection, which runs every now and then to clean up unused objects) events in your timeline, the Memory tool helps you debug those issues.

Tony Gentilcore has a great writeup on finding and fixing memory leaks, you should definitely give it a read. I’ll give you a quick overview here.

Click on Memory in the sidebar, then click record. Perform a task in your app, and observe the memory profile. Here’s the memory profile for an app that simply creates an object and throws it away every mousemove event:

A typical javascript memory graph looks like a sawtooth function: You keep accumulating memory until the garbage collector runs and cleans up unused memory. A few cycles through GC runs, and your memory profile should be flat. If it’s constantly going up in between GC cycles, then you have a memory leak. As your application gobbles up memory, the app will slow down, and certain browsers (MobileSafari) will actually kill it.

Below the graph you’ll see some more useful metrics to track the number of DOM nodes, and event listeners, they’re pretty self-explanatory.

Finally, let’s say you deployed your app in production, you found a bug in production, located it in the inspector. How do you tell your coworker/developer? Well, instead of taking a static screenshot, you can actually right click on “Timelines” and “Memory”, and save your session so that you can share the actual debug data! Handy when you’re working as part of a team.

The Profiles Panel

So, you’re now at a point in your application’s development where it looks the way you want it to look, HTTP requests are minimized, and you’re causing the browser to do more work than it needs to. Something’s not right though. Everything seems to be snappy, except for one small part. You’ve tried debugging it with the Timeline panel, but it doesn’t give you enough depth and detail. It’s not the browser that’s slow, it’s your own code.

That’s where the Profiles panel comes in.

JavaScript CPU Profiler

The first type of profiling you can do is JS CPU profile. The description outlines at a high level what it measures: What functions your app spends the most time in.

Select it, then click “Start”. Every action you take now, will be logged until you hit the glowing red “Record” button to stop recording (Or click on the “Stop” button). Once stopped, the profiler will show you an ordered list of all the functions that had executed, and the time it spent in each. You’ll probably see something like “(program)” at the top of your list. That’s webkit taking time to do stuff. You can’t inspect it, and you can’t do much about it (but the Timelines tab should help locate some of those bugs!). Apart from that, here’s what a typical profile looks like:

This is the profile for my blog when I open the photo portfolio and open/close a photo a few times. Looks like the most expensive part of that interaction is setting the curtain’s opacity and retrieving the bounding client rect. Just the info I needed to optimize that part of my app.

Google, if you’re listening: There’s a lot of work you can do here to surface useful information and hide useless information. I often get stuck in infinitely-deep lists, or 99.99% of my time spent in (Program), distorting everything else.

CSS Selector Profiler

CSS doesn’t come for free. Complex stylesheets take time to parse, calculate, and apply. The CSS Selector profiler shows you how many times each selector was matched to a DOM node, and how long the browser spends applying those selectors. In a complex application with many divs of the same type, applying styles to them might take a substantial amount of your app’s startup time.

Heap Snapshot

This is one of the most obtuse views in the inspector. So much so, I haven’t actually found it useful. Take this for example:

The amount of useful information there as far as I can discern is zero. I’ll defer once more to Tony Gentilcore’s writeup, may he light your way.

The Audits Panel

We’re almost there! The last panel is the Audits Panel, and it’s basically the last sanity-check of performance you do before going to production. Essentially, it will inspect the resources and the HTTP requests and suggests improvements based on current industry best practices. For example, while writing this, running the Audits panel told me that I should specify the image dimensions in the HTML to make layout faster. Good to know!

All the tips here are well-documented, and you should at least take a quick look through them.

Conclusion

I hope you’ve found at least some of this information useful. I’ve been writing complex web applications on the desktop and mobile for 2 years now, and I’ve had to use each of these panels to solve a different class of problems.

If I’ve mis-interpreted something, missed something, or made any errors, please let me know.

Further Reading

How Browsers Work – A Fantastic, and in-depth look at the processes and plumbing that we build on.

The Mozilla Developer Network Documentation – The most authoritative and up-to-date reference and guided documentation HTMLCSS, and JavaScript. Ignore w3schools.

Perfect

I’ve been having a recurring thought recently.

The first time was while I was watching A Clockwork Orange when this panning shot came up:

The music, visuals, the characters and storyline came together so well, and everything in the storyline was working together so well, it gave me goosebumps.

The next time that happened was while watching 2001: A Space Odyssey. This shot captured the same feeling:

More recently, a string quartet was playing in the lobby at work. Four musicians moving in perfect synchronicity playing the same thing. It was beautiful.

Above the individual performance though, whether it was a piece of art, a movie, or a musical performance, I realized that what I was admiring wasn’t the piece itself, but everything that must have gone on behind the scenes to bring it all together. Everything complementing everything else, and everything working together. Nothing is superfluous, and everything is there to serve a purpose.

It’s beautiful, and it’s what I try to do with my work.

It’s not easy though, it takes a ton of hard work and practice. It takes patience and perseverance and a self-critical eye to judge your work as you would just other people’s work. To those who have achieved that kind of refinement in their work, I applaud you, and hope to meet you there at some point.