Hi! I'm Feifan.

I've started and stopped many blogging efforts over the year, but it's a medium that constantly draws me back. I like long-form writing as a way to gather, sequence, and sharpen my thoughts — and publicly publishing my pieces nudges me to clarify my ideas and understand their implications beyond my head.

These days, I'll most likely write about uncommonly interesting ideas I come across, frameworks for thinking and seeing the world, and my tinkering into ways to improve the experience of using computers.

  1. Building A New Blog

    I've moved my blog off of Wordpress — in part because of limitations with Wordpress.com's hosted offering — and onto a custom-built site.

    I mainly did this to serve as a proof-of-concept for implementing a blog on the first primitives that come from Tanagram, a project I've been tinkering with over the past few months. Tanagram is, in part, a bunch of simple, transparent data types and functions that operate on those data types and return updated data. This, I hope, will make it much easier to build boring software — and that's a good thing! Most software ideas are essentially variations on cookie-cutter themes, and Tanagram should provide the setup and primitives to make the process of building software like that as quick and easy as, say, writing an essay.

    Continue reading →
  2. The Dream Machine: A Story of Creativity, Tinkering, and Cross-Pollination

    "Creativity is a function of freedom" – George Pake

    The advent of computers and the internet is a story of human creativity and organizations that brought myriad dreams to come to life. From the 1950s through the end of the 1970s, during which a scientific community tinkered with and established fundamental ideas in computing, and up through the explosion of personal computers and early internet in the subsequent decades, the story is rife with characters and environments that allowed creativity to flourish, along with those that undermined it. The Dream Machine tells this story by following the life of J.C.R. Licklider, a central figure and instigator of much of the creative accomplishment by virtue of his personality and career.

    Lick, as he insisted on being called, was perennially playful. He tinkered with computational devices and early predecessor computers in his own time. Upon learning how to program a Librascope LGP-30 in 1958 — a woefully inadequate, unreliable machine — Lick spent hours on end with it, refining his intuition for how humans could interact with computers. The following year, he got his hands on a DEC PDP-1. It was a monumentally better machine, and he ecstatically spent long evenings sketching out ideas in code, interacting with the computer. He was often not doing serious work — a coworker remarked that Lick would not even save his programs after spending all night on them — but he was happily at play.

    Continue reading →
  3. Computers Aren't Fun Anymore

    Throughout The Dream Machine, a history of the early days of computing, tinkering and having fun was a recurring theme throughout the decades. I wasn't around to experience the early days of computers myself, but they seemed to be genuinely exciting and rewarding. In the words of MIT sociologist Sherry Turkle: computers empowered their users, making them feel smart[er], "in control", and "more fully participant in the future".

    Those feel like odd descriptions for the modern computing experience. Using computers today doesn't feel like an empowering experience. Sometimes it's mindless and distracting. Sometimes, when a redesign rolls out, or laptop doesn't wake from sleep mode, it's downright hostile. The experience of using a computer in 2020 is a concoction of data silos, dinging notifications and reinvented wheels, presented in gratuitously bubble-wrapped UIs hyper-optimized by persnickety product managers and soulless A/B tests.

    Continue reading →
  4. No One Cares About Software Quality

    No one cares about software quality anymore. I mean, yes technically that is untrue and there are demonstrably some people who do, but for the most part, quality software has become a niche luxury while the most commonly-used software has become a slow, laborious cesspool.

    I just had the misfortune of using the new Google Groups for the first time and died a little on the inside. The first thing I noticed (besides the egregious amount of pixels wasted on whitespace) was that they broke copy-and-paste. Let me explain:

    Continue reading →
  5. Inadequate Equilibria: A Summarized Remix

    In late 2017, Inadequate Equilibria spread like wildfire across my Twitter feed. Having worked through it, I’d now easily rank this book as one of the most impactful I’ve ever read on the way I see the world and think about my career. It is quite a bit of work though — my first read-through was near-incomprehensibility, alongside fragments of ideas that I found tremendously insightful and hinted at a very different way of interpreting the world than I was used to. That held my interest long enough that I reread this book several times; each time resolving the intent and ideas to a finer degree, like a developing Polaroid. Nevertheless, with each reading, I felt that the abstruse writing made the book hard to understand and share with other people. That’s really unfortunate. So, as a way to pay that forward, I’ve decided to remix it — these are my notes, presented in complete sentences, using friendlier terms and assuming fewer conceptual prerequisites so that it reaches a wider audience. I’m sure I’ll lose some technical precision around the edges, but hopefully I’ve got it mostly right.

    The core thesis in Inadequate Equilibria is a bold perspective for interpreting the world: there are identifiable instances where you shouldn’t have blind trust in the world’s competence at doing something when the underlying systems don’t deserve that trust. The book presents a collection of situations that archetypically identify types of systemic failure; this type of failure is couched in a roughly quantifiable concept named “adequacy”. Under such systems, it’s possible for you to do better than the best option that’s broadly available and you shouldn’t anxiously second-guess yourself when you identify such an opportunity. But this isn’t always the case: in some cases the world is highly competent; in other cases you may be able to do better on a dimension that no one actually cares about; in still other cases there simply isn’t an exercisable mechanism for doing better.

    Continue reading →
  6. Never Waste a Good Crisis

    The past few weeks, indefinitely isolated at home, has given me time to think about the civilizational optimizations and limitations that COVID-19 has revealed and the stunning interconnectedness of it all. We live in world of long supply chains that magnify rather than mollify shocks and minimally-provision capacity where headroom has been optimized away in service of efficiency. Elsewhere, rules and regulations are being loosened, raising the question of why they're necessary in the first place. And the heterogeneity of government effectiveness is on full display.

    This is a post about the long-term-oriented questions we should be asking as we rebuild. I don't have many of the answers, but I think it's existentially important that we address and act on these questions rather than just trying to return to life as we knew it. For example:

    Continue reading →
  7. Remove the Middle Option

    Recently I was talking to a friend who’s thinking about getting a car and wanted to get my thoughts on leasing for 3–5 years vs buying/financing. As it happened, I have also been thinking about getting a car, and I’d already decided that I wanted to lease because for the car I wanted to get, I didn’t want to own it for the long-term.

    (This is a post about decision-making, not personal finances.)

    Continue reading →
  8. An Eighty-Year Career

    When I was a kid living at home, I remember my dad, from time to time, wistfully looking forward to retiring. I would often ask him why, since retirement sounded so boring, but I don't remember ever getting a clear answer. In the years since, as my sense of how big — how interesting! — the world can be, retirement has come to seem like a strange idea. As the default ending for the conventional career narrative, we've canonized deferred living en mass. That seems unfortunate. What's more, retirement appears to discard a career's worth of experience for decades at a time for millions of people. That seems like a lot of collective human potential going to waste.

    I don't ever want to retire. Instead, I want to have an eighty-year career, one where I get to build upon a lifetime of experience and resources to move the needle on some of the messiest problems we face.

    Continue reading →
  9. How To Do My Job

    Recently, I was talking to a future coworker (who didn’t work as a software engineer), and I found myself indelibly curious about what exactly his job was like and what I would need to know if I wanted to competently perform his job. I didn’t get to fully find out at the time, but I later came up with a possible framework for how I’d like to explore the topic. For illustrative purposes, I’ll go first:

    How would I describe what I do to a reasonably intelligent knowledge worker who isn’t a software engineer?

    First, some context: this is from the perspective of a mid–/senior–level software engineer, and only covers the software engineering piece of the job. Real-world roles, especially at smaller companies, will likely require some skills in other functions, including product development, UI design, mentoring/coaching other team members, and building productive work relationships.

    Continue reading →
  10. Documenting Some Thoughts Around Tanagram

    Tanagram is the name of a project idea I’ve been thinking about for a while. I trace the idea’s lineage back to a little prototype I built in late 2013. I didn’t think much of it at the time, but I’ve revisited this idea (or at least something directionally-related) countless times in intervening years.

    With the free time I’ve had lately, I decided to gather my scattered thoughts and define what exactly I want to build, distilling many vague ambitions into specific product features. I treated it as an exercise in articulating my thoughts, as well as a singular place to point people to when I’m asked about the project (it’s rather complex to explain!). The result is a rather long read.

    Continue reading →
  11. Introducing LeetcodeSolutions

    On a Saturday afternoon last fall, I found myself in front of an expansive whiteboard covered in diagrams, tables, and somewhat legible hand-writing. I was there with a new coworker, and we had just finished going through the data models she’d be working with. Along the way, we’d taken a long digression into database design, and I’d explained the differences between SQL databases and Mongo and when it made sense to use one or the other; our codebase worked with both. At the end, she looked up from her notes and exclaimed, “That makes sense! Wow, why didn’t anyone explain it this way?”

    Rewind to eight years ago. I was sitting with a close friend around his kitchen table covered with papers, notebooks, and textbooks. We were both in high school at the time, and I spent that afternoon helping him study for a calculus exam. After working through a particular problem together, he looks at me and told me I was really good at explaining things — better than his teacher; that’s why he had me over in the first place.

    Continue reading →
  12. Next Steps

    Last week was officially my final week with Trustwork, a seed-stage startup where I joined about two years ago as the second engineer. It’s an equitable conclusion to a personal journey that began when I decided to leave three months ago. I’ll be joining the Issuing team at Stripe in a month, a relatively new team with a really audacious charter.

    In the lead-up to making my decision to leave, a couple of factors came together to bring my shields down.

    Continue reading →
  13. Learn Harder Things

    When you take the time to learn something new on your own time, it’s better to learn things that are conceptually harder than, or paradigmatically different from, what you already know, rather than something that’s adjacent. For example, in software engineering, if you already know Ruby, learn a functional language like Elixir, or a lisp like Clojure — doing so will expand your abilities much more than learning, say, Python, which is conceptually very similar. In the gym, if you’ve been training traditional weight lifting, learn functional strength exercises rather than yet another movement with barbells and plates.

    In most cases, the harder or foreign skill expands your understanding of what you already know. The insights get back-ported — functional programming experience leads to better object-oriented code; functional strength leads to a better deadlift.

    Continue reading →
  14. Decisions ≠ Outcomes

    While reflecting on how well I make decisions, I realized that it’s possible, and in fact important, to separate the evaluation of the decision-making from its outcome. In other words, the process of making a decision is not the same thing as the outcome of the decision — it’s possible to have a well-made decision that results in a bad outcome, or to have a poorly-made decision that results in a good outcome.

    This is not an original idea (in fact, Peter Attia’s recent newsletter shares the same idea and prompted this piece), but it’s also not obvious or commonly-held.

    Continue reading →
  15. Apple Watch: Not-a-Review

    There seems to be an inverse correlation between how much I pay for an Apple product and how much I enjoy using it. My Macbook Pro (2016, Touchbar) is functional at best, and unusably glitchy uncomfortably frequently. My iPhone (XS) is wicked fast and a pleasure to use, although my iPad Pro (Pro, 10.5) is more delightful and practical to use because of ProMotion and the larger display. But after living with the Apple Watch (Series 4) for the past month, it’s become my favorite computing device.

    The Review

    It’s responsive. It’s mostly bug-free. It stays perfectly in sync with my phone. Battery life is excellent. The Series 4 screen size looks “right” and makes the previous size look like a toy.

    Continue reading →
  16. On Frustration and Anger

    When I was younger, I used to be easily frustrated when things weren’t going my way. I would feel a surge of emotion wash over me, and I would indulge in that burning warmth while it lasted. The sensation was a strange combination of feeling powerful — a wave of pent-up energy coursing through me, looking for an outlet — as well as a profound powerlessness, the inability to do something which had brought about the frustration in the first place. I knew that it wasn’t healthy or productive to rail against the world in the long term, but each indulgence brought a sense of gilded satisfaction that was hard to forget.

    Over time, I’ve gotten to better know myself and my abilities, and I’ve shifted the way I approach problems and unknown or ambiguous situations. Doing so has illuminated the dark corners of my mind where frustration (and anger, its concomitant cousin) used to dwell. Reliably recognizing these feelings within me has also sharpened my awareness of them in the world around me, both online and in real life. I’ve been trying to better understand it.

    Continue reading →
  17. Aphantasia and the Speed of Thought

    A recent Twitter exchange reminded me that we all perceive the world differently. For me, one of these differences is that I’m not really able to visualize anything in my mind.

    Over the course of a few conversations I’ve had with friends and family, and some light research into this topic, I’ve realized that aphantasia does (or at least could) tie together a bunch of characteristics of how my brain works, especially in ways where I’ve noticed my perception or mental function ostensibly deviating from how I think most other people perceive the world.

    Continue reading →
  18. An Introduction to jscodeshift

    Recently, I had to make a straightforward change over dozens of files spread across our entire frontend codebase. I didn’t like the idea of finding all the files and manually make the change; in the spirit of laziness-driven-development, I decided to figure out a way to script it. I’d discovered jscodeshift a few months ago as an interesting tool to explore and bookmarked it for “later”, and this was a perfect opportunity to actually do that.

    Background

    jscodeshift didn’t include many details on how to get started with the tool and get things done, so I had to figure things out based on source code, other blog posts, and background. Before diving into my task and a solution, some general background will help explain the concepts involved.

    Continue reading →
  19. So-what-ness

    I’ve noticed a sense of so-what-ness that permeates a lot of the conversations I’ve had or observed. It’s a sense of mild cynicism that hangs over a conversation or idea, where it feels like every sentence has to justify its significance against an unspoken “so what?”. It’s skepticism as a default; an indulgence in intellectual incredulity.

    Here’s how it usually goes:

    Continue reading →
  20. Notes on Fasting

    The hardest part of not eating for 120 hours and 11 minutes was the boredom. From the afternoon of May 17th until a late lunch on May 22nd, it was as if I found myself living in a boundless void. Time stretched out forever. I’m not sure if it’s a psychological thing — not having meals to break up the day or look forward to — or if it’s a physiological response, a dilation of time designed to give the primal senses a better chance of finding the next meal. It might be a combination of both.

    My official fasting timer — [Zero](https://medium.com/@kevinrose/introducing-zero-a-new-app-to-help-you-fast-209935e8245d)

    Continue reading →
  21. Thoughts on Personalizing Software

    I’ve been obsessed with productivity software for most of my life. I’ve sampled dozens, from simple personal tools (like Apple Notes) to full-featured productions complete with the kitchen sink (like Phabricator and JIRA). None of them ever felt comfortable — many were too simplistic, some were too prescriptive, and some were overwhelmingly customizable (although not necessarily in the ways that I would’ve liked).

    The fundamental challenge is that software products are more-or-less centrally designed, and even assuming a product is well-designed with many use cases covered, software products are exactly as-is, no more or less. Without the ability to add specific functionality, change certain flows, or remove unnecessary complexity, most software ends up being prescriptive and less-than-ideal for most specific use-cases.

    Continue reading →
  22. Work on Good Ideas

    Despite what some people might want to believe, there is such a thing as bad ideas. In the context of building valuable ventures, bad ideas are typically bad in a few ways:

    Continue reading →
  23. Tech Stacks Are Overrated

    In the process of interviewing dozens of junior and intermediate engineers, the questions candidates ask implicitly say as much about them as the rest of the interview. One question that comes up occasionally is some variation of “what tech stack are you using”? List some of the myriad Javascript libraries-du-jour and I get a murmur of approval; mention something mature and be met with silence or a disappointed “oh”. In fact, many outright say that they want to be working with the latest or “bleeding edge” technologies.

    I get it, the “right” technologies are cool and shiny and have undeniable appeal. You feel invigorated when using them. For me, I’m excited about Elm, Crystal, and GraphQL.

    Continue reading →
  24. Service Objects As Test Fixtures

    In our Rails codebase at work, we often have tests that begin with many lines of setup code — declaring relevant variables, creating and updating models — to setup the database so we actually test what we intend.

    Most of this test's body is setup

    Continue reading →
  25. How I Think About Salary

    Nobody gets rich from a salary.

    Aggressive statement; it warrants some definitions. A salary, broadly speaking, is compensation for your labor — for your input into the machination of a company. The same is true for a hourly wage, except the relationship is more obvious there.

    Continue reading →
  26. Evaluating Work Opportunities

    Recently, I spoke with a friend about job opportunities. I briefly shared with him my framework for deciding between companies, which I developed during my job search last summer. I want to expand on the questions and the thinking behind them — as far as I can tell, this isn’t common knowledge, and perhaps someone else will find it useful.

    The framework centers around three dimensions, two which look at the upside (trajectory and potential), and one to cap the downside (sustained damage).

    Continue reading →
  27. There’s More to Coding than Just Writing Code

    For most of my life I firmly believed that a Computer Science degree wasn’t necessary to work as a software engineer; there exists a massive amount of resources and practice opportunities to learn outside of the context and cost of a university degree. I maintained this perspective even after I ended up getting a CS degree, partly because of the lack of practical skills in a typical CS program.

    I still don’t think a CS degree is a requirement, but more recently I’ve realized that it’s a very good proxy for a baseline of skills and ways of thinking. If nothing else, a CS degree indicates that someone has spent a lot of time understanding software patterns, becoming familiar with a range of patterns, and developing the basic abstractions necessary to understand more complex problems.

    Continue reading →
  28. Behavioral Observations From Taking Over SXSW

    I just got back from taking over SXSW with Trustwork. We ran a scavenger hunt with multiple stations giving out free stuff in exchange for user signups. This post is the second of two posts on learnings and observations from that week. Part 1 is here.

    My intent is to present some personal observations. It is not to disparage anyone or any usage pattern. I’m also not saying that Trustwork had a perfect signup flow — for example, we definitely could’ve had more performant code, and we had a contentious Confirm Password field.

    Continue reading →
  29. Personal Lessons From Taking Over SXSW

    I just got back from taking over SXSW with Trustwork. It was an exhausting eight-day marathon, complete with an air mattress in the office, questionable food, and hundreds of rejections a day. I wouldn’t want to do it again. Despite all that, it was a fantastic experience, and I’m really glad it happened.

    For reference — Trustwork is essentially a jobs marketplace, backed by professional profiles for each user. It’s like the marketplace of Craigslist plus the reputation of LinkedIn plus the on-demand aspect of Uber. For the past week, our team of 20 stood on various street corners in downtown Austin giving out a variety of free stuff in exchange for user signups, one at a time. Most days were 10+ hours across a day shift and night shift; at our best we were sustaining over 200 signups an hour.

    Continue reading →
  30. Mind-mapping

    For many years, I dogmatically resisted using mind maps to take notes or organize my thoughts. I was always afraid I’d get “stuck” if I used pen and paper — that my map would end up too cramped (or too sparse, which seemed wasteful), and the software always seemed too expensive and a bit clunky. I would always fall back to verbose, linear notes (written out top-to-bottom, left-to-right), often ending up with walls of text that I would then have to decipher.

    Recently, I had a long-form writing project, and somewhat arbitrarily decided to build my outline in a mindmap. I dowloaded Mindnode — the app is ergonomic and a delight to use on both Mac and iPad, and syncs flawlessly through iCloud. Mindnode’s keyboard shortcuts made it feel like taking linear notes, and got me close to operating at the speed of thought.

    Continue reading →
  31. ROI: In-Unit Laundry

    I walked past a fancy laundromat + café place today. As a business, I think it’s a great idea (although somewhat indulgent as well), but it got me thinking (as one does) about the economics of laundry, especially in apartments that have laundry on-site. My current apartment has a washer and dryer in every unit. It’s an amazing amenity, and makes doing laundry tolerable. My previous apartment had a laundry room on each floor. Turns out, based on some rough numbers, the former is a better setup for everyone. Here’s how it breaks down (at least in the San Francisco rental market):

    • Rent in my neighborhood is between $6–$7 per square foot, per month. Let’s call it $6.
    Continue reading →
  32. Viewing iMessage History on a Computer

    I occasionally want to go back and browse conversations I’ve had, either to lookup some detail or to revisit a discussion (many of which might become future blog posts 🙃). Aside from work Slack, the vast majority of my conversations are through iMessages, but Apple’s apps don’t make it easy to scroll through history. I figured it would be fun to write my own. The first version is the equivalent of one day’s work, and everything is available on Github.

    The rest of this post will walk through the code and my thought process as I went along. When I was learning to program, I would come often across projects where I didn’t know enough to begin to understand how I might build something similar, and I wished that the author would have explained the thoughts that took them from A–Z. This is the sort of guide I would’ve wanted to read.

    Continue reading →
  33. Falcon Heavy

    I didn’t expect to get chills racing down my spine, but I did. Even now, after the initial excitement has worn off, I still think the Falcon Heavy launch and booster landing is one of the coolest things I’ve ever seen.

    Peter Diamandis explains the idea of super-credibility — an event or confluence of associations that bypasses the default skepticism in our minds and instantly makes an idea seem attainable. It becomes a question of when, not if.

    Continue reading →
  34. Deleting Facebook

    A week ago I deactivated my Facebook. It’s tempting to indulge in hyperbole and say that it’s the best thing I’ve done for my life, but I don’t feel any different. And I think that’s the point.

    After college, I moved across the country, and my mindshare shifted dramatically to figuring out how to be a functioning adult. My Facebook feed started to feel quaint, irrelevant, sometimes inane. At one point, I moved and had to wait a few weeks to get internet setup at my new apartment; not having internet made it easy to not come back to Big Blue.

    Continue reading →
  35. Breakfast: Eggs

    I didn’t know how to make eggs for a very long time. That’s mostly because I was squeamish about touching raw eggs. It might’ve also been related to my inability to crack an egg without making a mess or shattering the shell and making a different sort of hopeless mess (I’m still just barely adequate at cracking eggs).

    Fast-forward to now, and I get three chances to practice egg-cracking every morning. That comes after dicing garlic and bacon (uncured, thick-cut). Plain eggs are boring.

    Continue reading →
  36. Start With Why

    This is my blog. There are many like it, but this one is mine.

    For the past year or so, I’ve flirted with the idea of having a blog — a place where I can think out loud, share cool tools/tips/books, and explore ideas at length. I kept coming back to this idea while planning my 2018 (a topic for a future post), and knew I had to give it a shot. Currently, this blog is a year-long experiment for myself; I’m committing to writing 50 longish-form pieces this year (although, since I’m making up the rules, this count can include posts on my company’s blog).

    The outcomes and hypotheses I want to explore:

    Continue reading →