Tag: Dive Deep

Show Me The Data

Show Me The Data

For Christmas back in 2020 my daughter got me a daily crossword puzzle calendar. That started a streak of completing a puzzle every day for two years. I tracked data on how fast I was able to complete each one, curious if I would get measurably better over time.

Today I finally sat down, put all the data into Excel, and crunched some numbers. Here’s a couple interesting results (interesting to me, at least):

Normally I aimed to complete a puzzle in about 15 minutes. For the most part my results clustered around that value, though my overall average across 623 puzzles was 15.9 minutes thanks to the occasional outliers in the 30-ish minute range. Fastest solve time was 6 minutes, which I accomplished 7 times.

This graph of rolling average (with a 30 day window) pretty clearly shows I got better over time as I suspected, going from a 20-ish minute average at start all the way down to 13-ish minute average towards the end. I’m happy with those results!

In total, I spent 165 hours working crosswords in 2021 and 2022, and while it’s not exactly the world’s most productive activity, there’s enough mental benefit that I don’t regret it.

Just No

Just No

Can we all agree that “drinking from a fire hose” is a terrible metaphor for the feeling of starting a new job? It’s overused, cliched, and kinda gross.

What I find most funny is that it’s usually stated as a humble brag about the amount of information you can ingest in short order, or to indicate that your new company is some kind of special unicorn doing work so incredibly complex that it overwhelms all who dare join it.

Reality is that the feeling of being overwhelmed in a new role is totally normal, even if the work is banal or the company is pedestrian. Sure, it takes time, but don’t make it sound harder than it is.

Personal Assistant

Personal Assistant

For some reason unbeknownst to me, health insurance in the United States is tied to employment. So one of the joys of starting a new job is being forced to reevaluate a bunch of plans, choose new options, and in some cases, find new doctors. As it turns out, my previous physician retired last year, so in any case I need to find a new one.

This afternoon I called my preferred medical network to ask about doctors accepting new patients, and the agent informed me that due to a shortage of folks, there pretty much isn’t anyone for the next couple of months. Lovely. I asked about waiting lists or notifications I could sign up for; naturally that doesn’t exist either. The best he could suggest was to check the physician search page every couple of days.

Well, I’m lazy, so I reverse engineered the search API behind the website, wrote a Lambda function to query it periodically, and set up an alarm to email me when the search results come back non-empty. Take that, manual process.

In Medias Res

In Medias Res

I appreciate people who open up about difficult emotions they’ve experienced in the past. But I appreciate even more people who are willing to discuss them as they are feeling them in the present.

In that spirit, I must confess that this week I’ve experienced considerable Imposter Syndrome. Starting a new job can be overwhelming; doing so when you’re expected to be in charge, even more so, as I’m learning (this is my first time in the latter situation). There’s so much new information to absorb, new people to meet, new customers to understand, and a new culture to internalize. Literally everyone else I talk to knows more than me, and while there’s certainly a grace period, at some point I’ll be expected to earn my salary and contribute, and it’s hard to see when that will be.

Let this serve as a reminder to us all that feelings of inadequacy are normal, especially at times of transition like a new job or getting laid off (which, if that’s you right now, I’m so sorry). I’m telling myself that I’ve been here before, and it’ll be okay. Though I’ll be happy when onboarding is behind me, for sure.

Craft And Commerce

Craft And Commerce

According to the behind the scenes documentaries, the designers working on The Lord of the Rings trilogy spent countless hours adding details to the various costumes, weapons, and other props used on the film, including details that were on the inside of garments or other places that would never be seen on the screen. They wanted these items to feel real to the actors, but I also imagine there was a simple love of craft that drove them to put their absolute best into their work.

This same attention to detail is applicable to software development. Rarely will an end user ever see the source code that runs her favorite app, but that doesn’t mean it’s not worth making just as beautiful as what ends up in the interface. Beauty inspires quality, and there’s some things worth doing well even if just for yourself.

Of course one must balance this against deadlines and the needs of the customer, but whenever possible, pay attention to the details.

Worth A Million Words

Worth A Million Words

The other day I posted a rundown of my work setup. I thought it’d be fun as a follow-up to give a demo of various microphone options I considered. Besides, you might not often get to see my face, and isn’t it more fun to show than tell?

Shokz OpenRun Pro (headset mic) – It’s mobile, but sounds terrible
Macbook Pro (built-in mic) – Ubiquitous and setup-free, but sounds muffled
Razer Kiyo Pro (webcam mic) – Better, but still a bit of background honkiness
Blue Yeti X (external mic) – Aww yeah, that’s what I’m talkin’ about

What do you think? At what point do you believe there are diminishing returns? Or do you disagree with my quality ordering altogether?

Oh, and for anyone wondering, the quote is from Confucius.

Gut Check

Gut Check

It’s that time again: New Year’s resolutions! Per my meta-resolution, this year’s book reading target is 44, but I wanted to add a twist to it.

Leaders who are right a lot “seek diverse perspectives and work to disconfirm their beliefs.” In 2022, 16 of the 45 books I read in were by authors who were either not male or not white. That’s 36%, a sizable fraction; in line with what I did in 2021 (33%) and 2020 (38%), and much better than my rates in 2019 (18%) and 2018 (15%).

But none of those metrics are anywhere close to reality: about 91% of the world’s population is either not male or not white. That’s a lot of valuable perspectives I’m missing out on.

Given my backlog and some strategic book choices I have lined up, getting all the way to 40 out of 44 isn’t realistic, but I can still do better than my recent history. So in 2023, my plan is to double last year’s fraction to 32 out of 44 (73%). Ambitious but doable. And I can’t wait.

Already finished my first one, in fact: Radical Candor. And I’m a chapter into The Analects, by Confucius. It’s embarrassing that I’ve never read anything by this giant of ancient wisdom. Already found a couple sayings that stand out:

The Master acquires his information by being affable, kind, and respectful, and by showing restraint in his action and a willingness to yield. The way the Master asks for information is different from that of other people.

Do not worry that other people do not know you. But be concerned that you do not know them.

Good stuff!

Adventures With APIs

Adventures With APIs

I’ve written before about the advantages of knowing how to dig around in DevTools to reverse engineer website interfaces. This week I’ve had three further instances of doing this work to good effect.

The Friendly Skies

Firstly, I travel a lot, enough that I now have Executive Platinum status on American Airlines. This means I’m first in line for complimentary upgrades, but only if there are seats available. So I wanted an easy way to go straight to a complete seat map to look at availability without needing to go through a full search on the website. Turns out there’s a magic URL that does just that, and all you need to do is pass it some parameters. So I present to you, a quick and dirty seat map lookup form. Give it a try!

While that’s cool, I wondered if I could make it simpler by leveraging a flight data API like the one from FlightLabs. That was pretty straightforward as well. Though I couldn’t embed it in WordPress, I did script it up in Python for your enjoyment. Just pass it a flight number, and it’ll do the rest. Neat!

Shake It Off

This week Taylor Swift tour tickets went on sale, and needless to say it broke Ticketmaster, despite their best attempts to add friction via pre-registration to enter a lottery to win a code to join a queue to enter a room to maybe get lucky enough to click fast enough to buy tickets. Sadly I was unsuccessful at securing seats despite dozens attempts across several days. But I did learn something about the API Ticketmaster used to check queue status, so all was not lost.

When I first joined the queue, the following was displayed:

Of course I was curious: how many more than 2000 people were there… 5000? 25000? A million? So I opened up DevTools, and took a look at the calls coming back from the server to check status. Lo and behold, there was a wealth of info in an easily digested JSON block:

Wouldn’t it have been helpful to display that information to the user? At least the exact users in line, and the expected service time value. No idea why it wasn’t shown, other than Ticketmaster not being known as a terribly customer obsessed company.

Automating ******** Across ****

The final example can’t speak of publicly other to say my penchant for automation will save my employer a sizable amount of money. In these uncertain economic times, that’s always a good thing.

That Lovin’ Feeling

That Lovin’ Feeling

I’ve done a fair share of production debugging in my career. There’s a heroic Dopamine rush that comes with it, that feeling of diving deep on a problem in a critical situation, finding the solution, and then implementing it to the delight of your customers and teammates (well, either delight or they graciously allow you to live another day).

A similar feeling is experienced any time you build something with your own two hands and see it come to life; that joy is why this blog is named what it is, because I love to build. But as a manager of a technical team, I don’t get the chance to directly build solutions as often as I might like, and when I do, it often represents a failure of some kind. To be successful as a leader, one needs to learn to let the joy of building go, at least the hands-on kind.

Instead, what a manager must cultivate is the joy of watching others succeed, especially those to whom they are charged to mentor as direct reports. Being thrilled when a person shares a difficult problem they solved; rejoicing when a struggling individual responds to your coaching with positive growth. Giving others the spotlight and serving their needs while hidden from view. Learn to get a Dopamine hit from such experiences, and you’ll do well.

And here’s the real kicker: when you achieve it, you’ll have scaled your ability to enjoy your job beyond what was possible before, because you now have a whole team of people whose successes are a source of happiness, versus just your own. Ultimately you’re still building, but now it’s through others.

Expect The Unexpected

Expect The Unexpected

Like many other languages, Python has the notion of default values for function parameters, for example:

def compute_final_price(cost, sales_tax_rate=0.08):
    return cost * (1.0 + sales_tax_rate)

This code behaves as you would expect:

compute_final_price(10.0, 0.07)  # returns 10.7
compute_final_price(10.0)  # returns 10.8

However, interesting things happen in more complex cases, because the default value is evaluated once, at the time the function is defined, and not when it’s executed.

my_rate = 0.05

def compute_final_price(cost, sales_tax_rate=my_rate):
    return cost * (1.0 + sales_tax_rate)

compute_final_price(10.0)  # returns 10.5
my_rate = 0.06
compute_final_price(10.0)  # still returns 10.5

You can prove to yourself the value is evaluated at definition time by running help(compute_final_price), and you’ll notice the default value has already been computed:

Help on function compute_final_price in module __main__:

compute_final_price(cost, sales_tax_rate=0.05)

The above can be pernicious if the default value is an object that’s modified inside the function:

def add_to_list(item, my_list=[]):
    my_list.append(item)
    return my_list

add_to_list(4, [1, 2, 3])  # returns [1, 2, 3, 4]
add_to_list(1)  # returns [1]
add_to_list(1)  # returns [1, 1]

A common workaround for the above is to do the following:

def add_to_list(item, my_list=None):
    if my_list is None:
        my_list = []
    my_list.append(item)
    return my_list

add_to_list(1)  # returns [1]
add_to_list(1)  # returns [1]

I’ve encountered folks that insist one should never use default values except for None and the above pattern, but I’ve found most of the time I’m not mutating such defaults, and the behavior described here is fine. But still, the more you know.