The emotional tax of bad recommendations

tl; dr: I find some web 2.0 content so draining it undermines the experience of entire platforms

I think we can all relate to those moments in life when you feel overwhelmed — beset on all sides by obligations or problems. In such times I try to turn to humor, distractions, and escape.

For over a year now I’ve known that certain social-media platforms I was trying to “escape” to were actually promoting stress-inducing content that was having an entirely inverse effect. “This is my problem,” I told myself, “I’m the one choosing to open these sites.”

I never even touched Twitter. Facebook was the first to go almost a decade now. Then some news sites. Then linkedIn, nextdoor. The last stragglers are reddit, youtube, and news.ycombinator.

Reddit is the simplest illustration of this phenomenon. I have an exhausting meeting coming up, I need a 10 minute breather to clear my head, I turn on reddit for cat pictures and boom suddenly I’m witnessing a cop battering a protestor. My body has an immediate visceral response. So caught up am I in righteous indignation, that I have completely forgotten in the moment about how my goal was to relax. “I need to care about this!” screams my body.

I pruned my reddit feed, and now I’m down to “r/madeMeSmile” and “r/HighQualityGifs.” Unfortunately, if I ever log out of the site I get this default feed, which is about 25% outrage-bait (e.g. a video of a group of people confronting a car driving on the sidewalk) (e.g. “Controversial law allows police to seize and sell cars of non-lawbreakers, keeping the proceeds”).

The math here is working against me. One cute picture of a cat does not negate one horrifying video of somebody slipping on the stairs and hurting themselves. Or in the case of HN, one intense rant s not negated by one thoughtful comment.

Youtube though is the platform I’d miss the most. I seem to have no control over my youtube feed, but ideally it’d be this “Nothing political, nothing with the words ‘destroyed’/’owned’/’idiot’. Nothing about millennials/boomers. Nothing where the thumbnail is a face-palm. Nothing with the phrase ‘You wont believe'”.

I go to youtube for things like lockpicking videos, gameboy repair, primitive survival. Unfortunately, somehow I seem to get recommended a ton of Joe Rogan clips, unwanted fringe political videos, and a mix of other neutral content. And the comments are the worst.

Unfortunately what youtube’s algorithm doesn’t understand is linking one single inflammatory bad video recommendation (even if I don’t click it) may make my entire youtube experience negative. Most topics have an emotional impact on people, and web 2.0 needs to start regulating for this, or I suspect others will eventually find themselves booting platforms wholesale too.

If this were a youtube video, this is the point where I’d be telling you that all humanity will dieeeee if you don’t freak out about what I’ve just told you. But honestly it’s not really an urgent problem. I think there’s an opportunity for us as individuals to become increasingly aware of when we’re being baited/provoked and avoid platforms. I also think there’s an opportunity for new platforms or algorithms to form that prioritize giving the user the emotional experience that they are seeking.

The internet doesn’t need parrots

This is going to be a long one, so buckle in.

Let’s start with a hypothetical. Suppose I were to ask the average person if it was safe to apply a homemade cream everyday that had the chemical “homosalate” in it, their reaction would be “no.” Upon googling, they’d learn that the chemical homosalate has the potential to disrupt hormones. Their reaction would fall under the “common sense” aka “You’re dumb for even asking this” type of response.

At the same time, if I were to ask the average person whether it’s safer to use sunscreen or not use sunscreen, they would say “use it.” Upon googling, they might encounter an official-looking webpage from the American Academy of Dermatology saying “everyone” should use sunscreen “every day if you will be outside.”

I imagine you know what I’m going to say next: that sunscreen has homosalate in it. And it’s not just homosalate, “FDA has put the entire sunscreen industry on alert by proposing that in just two instances do we have enough safety information about ingredients to determine whether they’re safe and effective: zinc oxide and titanium dioxide.” [2] There are concerns about multiple suncreen chemicals disruption hormones.

How can it be obviously unsafe to use be exposed to homosalate, but obviously unsafe not to use sunscreen? Clearly, if you just go by google’s top result, we’re at an impasse.

This article isn’t about sunscreen. No, we’re getting all philosophical. This article is about “common sense.”

This article is about how we have a propensity to follow and repeat “common sense.” This articles about when two pieces of “common sense” contradict, like described above, we “parrot” them both anyways. But now that we have the internet, I hypothesize that parroting is no longer necessary, and is actively destructive.

A web of factoids

Humor me, while I describe one way to look at society. Very abstractly, let’s try to model the messy tangle of how distinct opinions and experiences slowly accrue to a rough social consensus about what’s true. What they are coming to a consensus about, and how long it takes them, varies (social norms, usefulness of email, modern ideologies).

I propose that most of us in society are like little machines, executing code all the time via our behaviors (you might find the word habits more palatable). Much of the code we execute is hardcoded (breathing), some of it we choose ourselves. But most of it we download from those around us, without even realizing we’re doing it.

We’re constantly watching and copying the behaviors of those around us (“norms”) following them, and then spreading them on to others. This isn’t necessarily good or bad in the abstract. Many of the things we copy are very useful (how to talk, social edicate, modern hygiene, how to use a doorknob). Many of the things we copy are necessary to fit in (grooming and attire). Many of the things we copy are completely arbitrary and vary between cultures (should I eat at a table rather than sitting on the floor?). Some of the things we copy are bad (e.g. for a while people liked to smoke, mainly because other people smoked).

(Here me out, I am aware this is reductionistic to the point of humorous, but I think some things are so complicated they are hard to see, whereas other things are so simple they are hard to see)

I want to emphasize this is copying and not a conscious, calculated choice. It feels good to believe that we’re fully conscious and autonomous in our behaviors, which is why I want to be extra clear: it’s not so. It’s not that people drew out a chart of “pros” and “cons” and said, “Yep, smoking does make sense for me, for the next 3 years, but eating at tables is essential.”

But of course, at some point, slowly, perhaps too slowly, smoking stopped being cool. Bit by bit over multiple generations small changes added up to have a drastic effect on the system. How is that?

So the model I’m proposing is that all information dissemination can be viewed as 3 behaviors

  • Creating: Generating new information (e.g. “I invented a new type of concrete”)
  • Parroting: Relaying information blindly (e.g. “I just heard Joe invented a new type of concrete”)
  • Filtering: Selectively relaying information (e.g. keeping your mouth shut because you have no idea if Joe has any clue what he’s talking about)

Finally after all this time, we back to our thesis: parroting. Parroting is basically another word for the copying I’ve just described. And (in addition to raw behaviors being copied) it’s how most knowledge is passed along.

Half what I “know,” I don’t actually know. For example, I knew there were 9 planets in the solar system back in 5th grade, despite having never seen any of them with my own eyes except Earth. There could have been 3, or 15, I was repeating what I was told. Later, it was decided that there are actually 8, and Pluto doesn’t count.

Most of the time this “parroting” seems practical, even indespensible. It would be pretty absurd if teachers weren’t allowed to teach how many planets there are unless they had personally verified them all. So it would seem there is a very healthy reason for us to “parrot” this information about planets (that is to say – to take it verbatim, pass it along without questioning or verifying it).

But books exist, and they do exactly that (parrot). And because they are printed permanently, you know nothing was lost along the way. However, compared to word-of-mouth, books are slow to print, expensive, and difficult to update (say, when a planet is demoted). So it would seem parroting is still useful.

But now the internet exists. And it makes parroting by word-of-mouth obsolete. We can have a widely-distributed article on exactly what planets there are, why they are planets, how we know this, photos, up-to-date information on their positions, how to verify it for yourself, and it can be updated in seconds. This is almost what wikipedia is. The value of “caching” (parroted) facts in our brains has gone down drastically now that a more reliable source can always parrot them to us through our phone.

The Parrot’s-eye view

A parrot would reject this point entirely. A parrot would say “Well there are actual agreed-upon experts out there, and there’s nothing wrong with being a relay.” And there are fields where this is fairly true.

For example, there are experts in aviation, and the fact that we can generally trust planes not to crash midflight objectively validates that those experts and systems.

But there are also fields, like economics, where the track-records of experts predicting things is scarcely better than chance, and there’s little consensus on anything, and when there is consensus it’s sometimes wrong anyways (e.g. The Big Short).

The question of which experts are actually experts, is so confusing we almost would want an expert on the topic. What makes somebody an expert? Being on the TV box? Being in political office? Using big words? An expensive degree? A lot of followers? Having ceremonial attire? Published journal articles?

My perspective

So then what? We can’t have authorities?

No. We can’t. You can’t get the title “authority” and then get to say whatever you want free of second-guessing. Think of it like the ideal of academia — there is no “president of science;” there are peers and slowly-earned trust. Nobody is above criticism, everybody is a peer.

We’re inevitable already heading in this direction — everybody gets an opinion, and the attention you receive is proportional to the argument you make. And when you have a good track-record, your signal gets amplified more (by people “subscribing” to you). This technique powers scientific community this is the basic premise of decentralization and “web 2.0” replacing gatekeepers.

Twitter, to some extent, is a system to replace parrots, and allow the informed to reach the uninformed without human-telephone. Though I can’t say the execution is perfect.

What should change?

I think our scientific community has long since abandoned hierarchy, and particularly this chain-of-command mentality. There is no need to parrot, rather you cite a source.

What I notice though, during covid, is how ineffective our chain-of-command government has been. I think many individuals have been weeks ahead of the government by using simply internet sources to correctly challenge a lot of “official” information around ventilators, curve-flattening, efficacy of masks, distribution of bailout money, and I expect more examples to follow.

When we become conscious of this change in truth-seeking, it will be come clear our political process will have to change with it. I believe mistakes like Vietnam would become increasingly improbably in our modern hyper-connected society.

We’ll know this succeeds when, before starting a quarantine, our elected officials publicly share risk models with the wider community, solicit input, and update decisions as on-the-ground information changes.

But if that seems like wishful thinking, let the simplest takeaway be this, that there is now a word, a derogatory one, for every time somebody plays the expert on a topic they haven’t researched by simply reiterating a buzzword. Perhaps the WHO claims masks don’t help, but you’re a parrot, you wouldn’t know (you’ve done no research), and you wouldn’t know if the WHO would know (you haven’t validated any of their “experts”).

A different github design

Earlier today HN reviewed a proposed github redesign and largely didn’t favor it.

I figured I’d take a stab at it

See the proposed before-and-after pictures above.
Here are some principles that seem intuitive to me, and maybe designers might consider them too.

  1. The visibility of an item should be proportional to its usefulness. This includes size, placement, brightness/colorfulness.
  2. There is always a flexible solution which caters to both experts and novices simultaneously.
  3. Hierarchy of UI should reflect conceptual hierarchy.

In practice here are the things I changed in my mockup, based on those 3 rules:

  • Create new file has no business being on the same line as “Clone repo.” It is a branch-specific operation next to a repo-specific operation.
  • The current-branch dropdown/button should connected-to the file-list widget. The file-list widget is showing files of that branch. The two are logically interdependent but visually separated.
  • Wiki and Insights are features I have never used on github and may never use. They should be hidden by default. They can intelligently show for repos that have ever once used those features.
  • The repo description shouldn’t be in the code tab. The repo description is an attribute to the repo itself


Good luck on your design journeys.

My Brainf Quine

A quine is something simple to describe yet surprisingly challenging to implement– a program which outputs exactly its own source-code. It is something of a rite-of-passage for an engineering afficianado. For those that consider ourselves one level beyond afficianado we always are looking to up the ante. I took two years exploratory years off after high school, and remember them fondly. Those were the days I could explore anything I wanted. Time was so abundant and problems were so scarce that I’d take on challenges like quines recreationally.

It’s a magical place to be in, when you any path feels possible and no obligations feels mandatory. It’s a time when one’s world-view is fully open, and interesting opportunities seem everywhere. It’s a time before traditional adulthood, where one can feel exhausted by unending obligations (cable bill, health insurance, change my oil, arrange my 401k, excercise more, sleep more, read more, relax more, setup dentist appointment, pickup groceries, return that item, answer those emails to those family members).

Once we’re in the “real world” it can be a challenge to remember that initial feeling of possibility. Once the lionshare of our time is spoken for, one may switch modes from expanding exploration to reduction. A mode where we filter our world into a functional place of checklists and routines to optimize staying afloat when our time, attention, and concern run short and we must ration them.

Anyways, I reminisce. But back in that era, one thing my friends and I would do is make coding challenges for each other. After a friend introduced me to “brainfuck,” a language with only 6 commands all represented as single characters, I challenged him to write a quine in brainfuck. I can see by googling that many other people like us are out there, who, like us, have been to that place where we are hungry for the next challenge to create for ourselves.

Recently I found my quine from back then it brought back memories.

 

>>>>++>+>>>>>+++>++++++>>>>>++++++>+>
>>>>++++>+>>>>>+>+>>>>>+++>++++++++++
>>>>>++>+>>>>>+++++++>+>>>>>+>+>>>>>+++>++>>>>>+++++>++++
++>>>>>++++++>+>>>>>++++>+>>>>>+++++++>+>>>>>+>++++++>>>>>
++++++>+>>>>>+>++++++>>>>>+++++++>+>>>>>++>+++>>>>>+++
>++++++>>>>>++++++>+>>>>+>+>>>>>+++>++++++++++>>>>>++>
+>>>>>++++>+>>>>>+++++++>+>>>>>+>+>>>>>+++>++>>>>>++>++
>>>>>+++>++++++>>>>>++++++>+>>>>>+>+>>>>>+
++>+++++++>>>>>++>+>>>>>++++>+>>>>>+++++++>+>>>>>+>+
>>>>>+++>+>>>>>++>+++>>>>>++++++>++>>>>>+>+>>>>>+++>+
>>>>>+>+>>>>>+++>+>>>>>++>+
+>>>>>++++>+>>>>>+++++++>+>>>>>+>++>>>>>++++++>+>>>>>++++>
+>>>>>++>++>>>>>+++>+>>>>>+>++>>>>>+++++++>+>>>>>++>+>>>>>++++++>+>>>>>+++
+>+>>>>>+>++>>>>>+++++>+>>>>>++>++>>>>>+++++++>+>>>>>+
>+++>>>>>+++++>+>>>>>++>+++++>>>>>++++++>+>>>>>++++>+>>>>>+>++>>>>>+++>+>>>>>+
+>>>>>+++>+>>>>>++>+++>>>>>+++++++>+>>>>>+>++>>>>>++++++>
+>>>>>++++>+>>>>>++>++>>>>>+++>+>>>>>+>++>>>>>+++++++>+>>>>>+>+>>>>>++++++
+>>>>>+>+>>>>>+++++>+>>>>>++>+>>>>>++++>+>>>>>+++++++>+>>>>>+>++>>>>>
+++++>+++++>>>>>++++++>+>>>>>++++>+>>>>>++>++++++>>>>>+++>+>>>
>+>++++++>>>>>+++++++>+>>>>>++>+>>>>>++++++>+>>>>>++++>+>>>>>++>++++++
>>>>>+++>+>>>>>+>++++++>>>>>+++++++>+>>>>>++>+++++++++>>>>>++
+++++>+>>>>>+>++++++>>>>>++++++>+>>>>>+>++++++>>>>>+++++++>+>>>>>++
>++++++>>>>>++++++>+>>>>>+>++>>>>>+++>++++++>>>>>++++++>+>>>>>++>
+>>>>>+++>++++++++++>>>>>+>+>>>>>++++>+>>>>>+++++++>+>>>>>++>++
>>>>>++++>+>>>>>++++++>+>>>>>++++>+>>>>>+>+>>>>>+++>++>>>>>++>+>>>>>+
+++++>+>>>>>++++>+>>>>>+>+>>>>>+++>+>>>>>+>+>>>>>+++>+++++>>>>>++++++
>+>>>>>++>+>>>>>++++>++++>>>>>+>+>>>>>++++>+>>>>>+++++++>+>>>>>
++>++>>>>>++++++>+>>>>>++++>+>>>>>+>+>>>>>+++>++>>>>>++>+>>>>>++++++>
+>>>>>++++>+>>>>>+>+>>>>>+++>+>>>>>++>+>>>>>++++++>+>>>>>++++>+
>>>>+>++>>>>>+++>+++++>>>>>++++++>+>>>>>++>+>>>>>+++>+++++++++>>>>>+>
+>>>>>++++>+>>>>>+++++++>+>>>>>++>++>>>>>++++++>+>>>>>++++>+>>
>>+>+>>>>>+++>++>>>>>++>+>>>>>+++++++>++++++>>>>>++>+>>>>>++++++>
+>>>>>++++>+>>>>>+>++>>>>>+++++>+>>>>>++>++>>>>>+++++++>+>>>>>++>+
++++>>>>>+++++++>+>>>>>>

++++++[-<++++++++++>]
<++……[-]
<<<<<<[<<<<<<]
>>>++++++
[<++++++++++>-]
<++>>++++++
[<+++++++>-]
<+>>>
[[<+<+>>-]<<
[->>+<<]>[-<<.>>]<<<.>>>>>
[-<<+<+>>>]<<[->>+<<]<[<.>-]
<<…..[->>>>>>+<<<<<<]>
[->>>>>>+<<<<<<]>>>>>>>>>]
<<<<<<[<<<<<<]>>>>>>
[<<++++++
[>++++++++++<-]>>-
[-<++>
[-<+<+++++
[>—-<-]>>
[-<++>
[-<+>
[-<<+++++
[>+++++++++<-]>>
[-<++>]
]
]
]
]
]
>[-<<.>>]
>>>>>
]

Sopping Wet — Today’s Software Ecosystem Isn’t DRY [and nobody seems to understand or care]

Tl; Dr:

  • Everyone seems to understand DRY is good at the program level, but they don’t seem to understand it at the community level.
  • Examples of useless duplication include many programming languages, libraries, package managers, data-stores, tools
  • This community duplication reduces interoperability and slows productivity across the board

Section 1: Some examples

1. Why is there more than one unix/linux package manager? Do we really need a different package manager with the same commands but renamed for each programming language? Do we really need a distinct package manager for each distro? Rhetorical question — No. We don’t.

2. Nobody seems to admit it, but Php, Ruby, Python, and Javascript are the same language, with a little sugar added here or there and different libraries.  I’m okay if not everybody wants to use curly braces but would rather indent for typing, but I’m not okay with every library for every functionality (date parsing, database connectivity, html parsing, regex, etc) being rewritten as a distinct library for every language when those languages have almost no significant differences.

This leads to a scenario where “learning a language” is more about learning the library than anything else (e.g. “How do timezones work again in PHP?”)

3. MongoDB never should have existedMongoDB should be a storage engine. The concept of a datastore that adapts its schema on-the-fly and drops relations for speed is okay, but there’s no reason the entire data-storage technology has to be reinvented to allow this. There’s no reason the entire query syntax has to be reinvented. There’s no reason the security policy has to be reinvented and all the DB drivers. There’s no reason all the tools to get visibility (sql pro) and backup the database need to be reinvented. Plus, if it were just a storage engine, migrating tables to InnoDB would be easier.

The same point holds for cassandra (which is basically mysql with sharding built in), elastic search, and even kafka (basically just WAL of mysql without columns). For example, a kafka topic could be seen as a table with the columns: offset, value. Remember storage engines can process different variations on SQL to handle any special functionality or performance characteristics as-needed.

4. Overly-specialized technologies should not exist (unless built directly around a general technology). You ever see a fancy dinner-set, where for “convenience” people are offered 5 forks and spoons, each one meant to be used slightly differently for a slightly different task? That’s how I feel about overly-specialized technologies. For example, people seem to love job queues. All job queues should be built on top of a SQL backend so that engineers get the normal benefits

  1. engineers know how to diagnose the system if it fails because it’s a common one (e.g. performance issues, permissions)
  2. engineers can always query the system to see what’s happening because it’s using a standardized query language
  3. engineers can modify the system if necessary because it provides visibility into its workings
  4. engineers can use existing backup, replication, and other technologies to store/distribute the queue (giving interoperability)

Section 2: What’s the result of all this?

  • Senior Engineers are all set back years relative to junior ones (which is bad for senior engineers, good for junior engineers)
  • The ecosystem is set back as a whole (all tools, libraries that interact with the old technology are rebuilt for the new one)
  • The company is placed in a precarious position because it now only has junior engineers in the given technology. Did I tell you that time the place I worked accidentally lost most of their customers phone numbers, because their PHP driver for mongo would convert numeric strings to numbers, and phone numbers would overflow the default integer, resulting in no fatal errors but simply negative phone numbers?
  • The company runs the risk of being saddled with a technology that will be dropped (e.g. couchdb, backbone) and will require a rewrite back to a standard technology or be perceived as behind-the-times.
  • Slow-learning / part-time engineers must keep pace with the changing landscape or face irrelevance. Those that can’t learn 10 technologies a year (a storage technology, a build tool, a package manager, a scripting language, data-monitoring tool, 2 infrastructure tools,  5 libraries, etc) will stumble.
  • Fast paced-engineers will lose half of their learning capacity on trivialities and gotchas of each technology’s idiosyncrasies (e.g. why can’t apache configs and nginx configs bare any resemblance to each other?). Once these technologies are phased out, all of that memorization is for naught. It’s a treadmill effect – engineers have to sprint (keep learning new technologies) to move forward at all, walk just to stay in place, and if you can’t keep pace with the treadmill you get thrown off the machine.

 

Section 3: The exceptions

There are a few exceptions I can think of when a complete rebuild from scratch was an improvement. One would be Git. In a few months, one of the most prominent software geniuses of our era invented a source-control system so superior to everything else that it has been adopted universally in a few years, despite the intimidating interface.

The times a rebuild is justified seem to be when many of these criteria apply:

  • You’re a known and well-respected name that people trust so much the community might standardize on what you make (e.g. Linus Torvalds, Google)
  • The existing systems are all awful in fundamental ways, not simple in easily-patchable ways. You’ve got the ability, time [and we’re talking at least a decade of support], money to dedicate yourself to this project (git, aws, gmail, jquery in 2006)
  • You can make your system backward compatible (e.g. C++ allows C, C allows assembler, Scala allows Java, many game systems and storage devices can read previous-generation media) and thus can reuse existing knowledge, libraries, and tools
  • You’re so smart and not-average that your system isn’t going to have the myriad of unanticipated flaws that most software systems you want to replace will. For example, angular, backbone, nosql, are all community fails. I theorize Go, Clojure, Haskell, Ruby, and several other high-buzz languages will evaporate.
  • Your system is already built-in-to or easily-integrated-with existing systems (e.g. JSON being interpretable in all browsers automatically, moving your service to the web where it will work cross-platform and be accessible without installation)

Section 4: What can one do?

  1. Learn the technologies that have stood the test of time: linux cli, c++/java, javascript, sql
  2. Wait years before adopting a technology in professional use for a major use-case– let other companies be the guinea pig
  3. Roll your eyes the next time somebody tells you about a new sexy technology. For whatever reason, it’s culturally “cool” to know about the “next big thing,” but professionals need to rise above such fads
  4. Next time you have a brilliant idea, instead of thinking “How great it would be if the entire dev ecosystem adapted itself to use my invention” think “Is there any open-source project out there that can be minimally adapted to accomplish my goal?”

Our obligation as leadership

The talk of importance of values is one irony of the San Francisco scene, if not human nature. The same values are discussed everywhere; so why then is it that these same values seem to be applied nowhere?

Could it simply be that it’s much easier to see the mistakes of others than our own? Perhaps those of us in positions of power often subjected to less scrutiny? Yes, to both of these. And so it becomes our own greatest personal challenge to remain true to our goals when nobody else is checking.

Let’s consider the value of ownership. What does this mean for us? It’s easy to look at the engineers who report to us and think about the times they didn’t take a personal investment in what they were doing, and how that harmed the company.

But for us to be good at our job, we must challenge ourselves to hold ownership, because it’s rare somebody will tell us when we’re not.

So what does ownership actually mean? Well, if an engineer is taking ownership of a project that to me means that she takes personal and emotional accountability for doing the best feasible job she can at it. If it’s broken on production, she is treating the lost revenue like her own.

But what does ownership look like in a manager? To me ownership is no less of an obligation. In fact we have more obligation because we have more influence. We should hold ourselves personally accountable for accurately assessing the merits of our direct reports. If a great manager screws up, he should lay awake at night until he fixes it, just as a great engineer would wake up to fix a production issue. A great manager won’t “good enough” it and wait until the next review cycle to compensate. Us not admitting to an error to save face is no less excusable than an engineer covering up when he breaks the app (which is to say absolutely inexcusable).

Ownership is about caring about the job getting done correctly, at a core level, above-and-beyond what is immediately asked of you. If you see a problem that nobody else sees, ownership is taking it up and ensuring that it gets resolved, regardless of how it reflects on you. Ownership is helping the company and the customer, even if it costs you your job (be that whistle-blowing, disagreeing with an incorrect authority, refusing to do something immoral/illegal).

If you institute an initiative that is clearly ineffective, then you should admit it and withdraw the initiative. Your self-promotion is not a contribution to the company. If you are a great manager, you won’t make it your direct reports’ job to convince you they are great; you will make it your job, your contribution to ensure everyone beneath you is being used to the best of their ability. And if your manager is great, she won’t expect you bring donuts, wear a tie, show up early, or flatter; because it will be her contribution to the company to accurately evaluate your work (and not how much she loves or hates you).

And if, when you hear this, you find it mildly irritating that anybody would ask so much of you… then don’t be surprised when those you lead act as do and not as you say. Your attitude is the irony of the SF tech scene.

Solving rush-hour

For those who’ve been inspired by last programming challenge, I thought I’d give annotations on a programming exercise I’ve created.

The challenge: code an AI to solve Rush Hour, you can play Rush Hour online if you aren’t familiar with how the game works. If you want to follow along, you can find my solution on github.

The game of Rush Hour
The game of Rush Hour(tm) – The objective is to get the red car to the exit. The above picture illustrates one possible board.

Let me start with the high-level thought process.

How to solve it?

The most naive approach is a brute-force solution, trying every move, filtering out backtracking. Some simple math will let us rule this possibility in or out.

The only state in Rush Hour the positions of the cars. Thus the number of possible game states is equal to the number of possible arrangements of cars. We can approximate an upper bound of the latter by multiplying the number of possible spaces each car could move to (this ignores cars being on top of each other, hence upper-bound). In the above board we see 8 vehicles, and each vehicle can only ever occupy 4 or 5 squares [they can’t turn ever] depending if their size). Some boards have more vehicles, so if we estimate 10 vehicles at 5 positions that’s 5^10 < 10 million.  So yes, brute force is in.

The general solution:

Because “brute force” is such a general mechanism, there really is a lot of reusable code in the solution. In my solution I’ve pulled out the reusable logic into genericSearch.js. The idea is that a whole host of puzzles follow the same form: Given an Initial state try to get to End State.

The docblock below is the interface to genericSearch that is used by the solver, but this same search function could be used by any number of puzzles (triangle peg game, sudoku, etc).

Screenshot_2
Any brute-force can be represented with only these params.

Thus, to write the program (after having written genericSearch.js) all I must do is to make those 5 parameters [and any helpers to go along].

Initial state – Brain Dead Simple

I know a lot of engineers who would be tempted to represent the game of rush hour with at least a half dozen classes (“so we have vehicle base class, which has car or truck subclasses, and we’d need a class for the board and legal moves”).

And that is a valid way to go about it. I went with a minimalist solution– a nested array 36 characters. Brain dead simple.

 

 

 

It seems that perfection is attained, not when there is nothing more to add, but when there is nothing more to take away. — Antoine de Saint Exupéry

Because every car is at least 2 in size, this string notation suffices to convey both the position and bearing of vehicles, everything we need. Since the exit is always in the same spot, that needn’t be represented in state. Adjacent characters of the same value represent the same car.

We have our first parameter, initial state. However, we have skimped in our state, by not defining what a vehicle is or orientation in the state object we’ll have to define that logic later.

Some of the advantages of representing the board state as an array of characters:

  • It’s trivial to serialize. Serialization is key to making sure we don’t backtrack when searching for solutions.
  • It’s very easy to input.
  • It’s very easy to output and debug. At the end to see the solution found I can simply “play” the states and watch the characters move.
  • At any given moment it’s trivial to determine if a space is vacant of any vehicles.
  • Certain impossible board-states are prevented automatically (e.g. a misconfigured initial state could not result in overlapping vehicles).

Some of the disadvantages:

  • We must determine every car on the board and which direction it’s facing. This is non-trivial (let’s call “trivial” something that I code correctly on my first try).
  • Moving a vehicle is kind of “dirty.” By moving vehicles by overwriting the board state it’d be easy make bugs that create weird board states (vehicle with size one).
  • Certain impossible board-states are prevented automatically (e.g. a misconfigured board state could not result in a vehicle with no bearing)
Parameter 2 – Possible moves

Each vehicle may move forward, or backward (assuming its path is unobstructed). To keep things simple, we can say a vehicle can only move 1 square at a time and represent longer travels as multiple moves.

Get all possible moves from this state
Get all possible moves from this state

This definition introduces a few more functions (getVehicles, canGoForward, canGoBackward), which I won’t put into the post. See the full code for that. The reason I exclude them is because I don’t have any particularly elegant solution to those tasks.

Parameter 3 – Apply move

Again I have no magic to work on this one so I won’t show the 15 lines. In fact, it feels like the least dry piece of the code to me, and it makes me want to refactor the most. The number of occurrences of -1 are too numerous (6) and speak to casual coding.

So don’t get me wrong, I don’t want to say anybody should hold this code up as an amazing example of good code. What I hoped to illustrate is how a problem that seems daunting can actually be broken down into 19 functions, the longest being 23 lines.

The Gimmes

I have two functions left. One is how to uniquely represent the state as a string. The other is win condition. The former is easy: JSON.stringify. The latter is easy as well.

Screenshot_6

And we’re done! Now I’ve left our the genericSearch.js, which honestly was perhaps the most fun, but this post is long enough. If your thirst isn’t quenched try playing around with it yourself.

Takeaways
  • Keep the pure & reusable code in a separate file (or separate function) from your 1-time, implementation-dependent code
  • Maybe 2 classes would have come in handy. Despite being small, the code doesn’t seem as friendly as I’d want. If I had kept state as an object of objects I would never have to define string -> state mapping.
  • Unit tests would have been a good way to allow such a refactoring to be less painful.

Don’t be an Architecture Hipster – A guide

One of my more popular HN comments was a teardown of an all-too-common engineering subculture. The article in question sought to teach “Software Architecture,” but ultimately annoyed me and many other HN readers.

Tl; dr:
Software architecture discussions are so polluted by software-hipsters that the majority of software engineers are disinclined to discuss and study architecture at all.

Know-it-all / hipster

  • Probably studied philosophy, english, film-studies, or engineering.
  • Lurks around discussions, hoping to overhear a mistake, any mistake. 
  • Uses an unnecessarily complex vocabulary
  • Has a self-righteous and loud tone of voice, especially when correcting people.
  • Enjoys correcting people, even on minor/irrelevant points.
  • If asked him a question you can be sure of two things:
    1) he will never admit he doesn’t know
    2) he will answer with so many niche terms that you will end up more confused than when you began
  • He may be likened to Dwight Shrute, or the comic-book guy.

Architecture  Hipster

  • Loves UML making diagrams. Gladly presents them without a legend to people who don’t know how to read UML diagrams.
  • Love creating new unintuitive names for very simple ideas (e.g “Broker topology”). Proceeds to use these niche names in discussions and judges other people for not knowing what a “Broker Topology” is.
  • Gets really into programming fads that are hailed as panaceas but later get tossed out for a new panacea (e.g. microservices, Layered Architecture, REST).
  • Gets very emotionally attached to programming decisions, even if they will have no effect on the user.
  • Loves engineering around unlikely “what ifs…”.
  • Prefers creating abstraction through classes instead of functions, even if no state is needed.
  • Is bored by “practical details” like logging, debugging, convenience, fail-safes, and delivering quickly.
  • Maximizes the number and obscurity of patterns used, leading to classes named things like EventLoopListenerFactory.
  • Only cares about performance if obscure (e.g. tail-call optimization)
  • Isn’t actually very capable creating software (hasn’t won any coding competitions, has trouble with git reset, hasn’t written any software that people enjoy using)

Thus:

Know-it-all / hipster
 = Architecture  Hipster 
+ software architecture 

I don’t dislike architecture. Architecture is a beautiful study. However, the complexity of the discipline makes an fertile ground for phonies; a space for phonies to use miscommunication as a tool to create an illusion of their own competence.

The “Hello” World

Have you ever been searching for a song on your favorite music service and scrolled through all the songs that matched your search. All of them?

For example, top of the pop billboards at the time of this writing is Adele’s “Hello.” I scrolled for a while and got to at least 1,962 songs named “Hello,” before I stopped scrolling.

It feels like looking into the grand canyon.

A few things are immediately apparent-

  1. All comes to pass. To illustrate, Madonna too is in the Hello list, but her Hello didn’t last; I can’t see why Adele’s would.
  2. The top dog takes it all. Adele’s variant has 250 million spotify listens. Most of the Hellos have < 2,000 listens. Adele’s Hello very well may have more (spotify) listens than all of the other 2 thousand combined.
  3. It’s  harder than it seems. When all the songs you know of are big hits, it can be hard to realize just how many unpopular songs are out there.
  4. This goes deeper than “Hello.” I just picked the top song on the billboard at the moment, but it could have been any songs. Or any poem, or book, blog, or famous person.

And a few things are less obvious-

  1. Why does the top dog take it all? Why do 99% of songs never reach the radio? Are most of these songs just bad? Is it simply that it’s ten times easier to write a bad song than a good one? Or is it that the music industry builds pop celebrities for profit, and radios buy in? Or is it that audiences don’t want so much choice, that we only like a song the 3rd time we hear it so we focus on a few new ones?
  2. So two thousand people chose the same word for their title. Is unique art only a fantasy? From the pool of a million english words, two thousand artists all picked the same one as the title of their song. I know this because I searched by title. How many of these songs share the same key chords? How many of these songs are about the same thing? Artists, like the rest of us, like to think they are doing the unique, but maybe the pool of possibilities split among all of humanity isn’t big enough to allow us each a distinctly unique idea, song title, or life story.
  3. So where do they all end up? There must be at least 80 hours of “Hello,” on spotify. Which makes me think there must be enough music on spotify that I couldn’t listen to it all if I dedicated the rest of my waking life to it. And people are still writing music. Is it just a never-ending cycle of new genres with a small fraction surviving into each new generation with the vast musical history resting in peace at the bottom of our searches? Or do we someday exhaust the unique musical possibilities?

 

Quote

Readable Code: Name Everything

Consider the following code samples.

// Specimen A 

if ($forceClose !== ' ' && $forceClose !== NULL && $issues['forcedClose'] && $forceClose > 0) 
     { 
     //ONLY SAVE IF 1, NEVER TOGGLE BACK
     $this->saveAttrForUser($user, 'forced_close', $forceClose);
     if ($forceClose == '1') 
         {
         Log::saveWrite("App killed");
         }
    }
// Specimen B
// note the prefix 'b' indicates type Boolean, the prefix 's' indicates type String
$bGotValidMessageFromClient = !($sForceClose !== ' ' && $sForceClose !== NULL);
$bAppPassedExitMessage = $aIssues['forcedClose']; 
$bExitWasForceful = ( (int)$sForceClose > 0);
$bAppWasForceClosed = $bExitWasForceful && $bGotValidMessageFromClient && $bAppPassedExistMessage;

if ($bAppWasForceClosed) 
     { 
     // A comment here that would mean something...
     $this->saveAttrForUser($sUserId, 'forced_close', $sForceClose);
     $bForceCloseWasAKill = ($sForceClose == '1');
     if ($bForceCloseWasAKill) 
         {
         Log::saveWrite("App killed");
         }
    }

These two samples contain the exact same logic. The former is more direct, essentially it inlines all of the variables in the latter. And that is why it is worse. A variable serves as a unit of abstraction, and a well-named variable is a comment; thus having more variables is better. In fact, all if conditions should the form if ($bSomeVariable) {, that is, never put a complex expression within the parentheses of the if. If the logic is particularly complex then use multiple variables, as seen in the sample above.

All if conditions should the form if ($bSomeVariable) {

At first glance, the bottom example is longer and may look intimidating. But it is superior because it exposes its internal logic. Try deciding what the top code does, and what ‘1’ indicates in that code. Then consider the bottom code. The top is an actual code sample.

And while we’re adding in these extra variables, let’s name our variables clearly. Programmers seem to have some unspoken assumption that variable names need to be less than 10 characters and not have prepositions… Maybe this made sense when you had an 80 character wide monochromatic screen with no form of autocomplete, but technology has made that trend obsolete.  I suspect most people would try to turn the variable name $sLinkToUniversalDownloadPage into something like $sUniversalDownloadLink which is inferior because it is ambiguous (is the link universal or the download universal?).

Or, for example, what would a function named “OpenFileLock” do? Is it opening a lock on a file? Is it filing a lock (in some kind of lock registry)? Is it locking an open file? Each of the three words in the title can be read as a multiple parts of speech (i.e. verb, noun, adjective, etc). Or perhaps FileLock is an existing class in this codebase. Prepositions here would make all of the difference.

Name everything; name it well.