Setting a Default Media Player in Linux

Setting a default media player in Linux in a general way is surprisingly difficult to do. The XDG specification for default applications is located here. Default applications are configured in ~/.config/mimeapps.list which is an ini configuration file. The [Default Applications] entry of this file controls the default applications for the user for the given mime type in the form $MIME=$APPLICATION where the application is one of the desktop entries in /usr/share/applications. A desktop entry should be installed there by your media player package.

I’ve made a script to make this a bit easier.

wget https://gist.githubusercontent.com/acrisci/b264c4b8e7f93a21c13065d9282dfa4a/raw/8c2b2a57ac74c2fd7c26d02d57203cc746e7d3cd/default-media-player.sh

Run default-media-player.sh -l to list all the candidate media player desktop files on your system. Then pick one and set it as the default by passing it as the first argument. For example: default-media-player.sh mpv.desktop.

The script can be found here. Let me know if this is useful for you in the comments.

2009 -2011 Was the Pinnacle of Music

The music of 2009-2011 has an aesthetic that’s stuck with me. It had the pallete and timbre of the 80’s mixed with the daring to be weird of the 90’s. It had a relentless positivity despite clear undertones of sadness and despair. It was an era of mixed feelings. Our faith in the American economic system was being questioned by the Great Recession. We were beginning to accept the reality of endless war in the Middle East. At the same time, the optimism of the beginning of the Obama administration was still going strong. Smart phones had just been invented and they were amazing to us. The internet had just come into maturity and for the first time in history, the world was connected. It was the beginning of the modern era.

At this time, I was living in an apartment in Athens, Georgia studying economics at UGA. It was a challenging time to come into adulthood. The recession delayed my independence quite a bit because the job market was completely dead. The realization that the system can come crashing down gave me a complex that’s shared by many people my age. We have a strong desire to commit to and be part of the world, but something holds us back. The result was a lot of awkard sounding dance music.

Here are some tracks that to me define the spirit of 2009-2011:

Ariel Pink – Round and Round

Pick up the phone!

The Yeah Yeah Yeahs – Zero

Was it the cure? Hope not.

Arcade Fire – Sprawl II

On the surface the city lights shine. They’re screaming at us we don’t need your kind.

Fever Ray – When I Grow Up

Staring at the seashell waiting for it to embrace me.

Twin Sister – All Around and Away We Go

I’m smiling for two.

Cults – Go Outside

I know what’s good exactly cause I have been there before.

Beach House – Walk in the Park

In a matter of time, it would slip from my mind. In and out of my life, you would slip from my mind.

PJ Harvey – The Last Living Rose

Let me walk through the stinking alleys to the music of drunken beatings.

Washed Out – Eyes Be Closed

Feel the wave form now, ride the foam. See the world clearly now.

Miami Horror – I Look to You

The future we’ve found to stay here on high ground.

Rules for Intellectual Roughhousing

When I was a kid, me and my friends played really rough with each other. Wrestling was one of our favorite things to do when we got together after school. It was a fun way to get out our aggression and resolve disputes with each other. If someone had a problem with someone else, they would just go at it for awhile and after fifteen minutes of that, we’d be too exhausted to remember what we were fighting over and everyone would be friends again. The point of our wrestling matches wasn’t to hurt each other and there was an unstated rule that it was not allowed to be too rough. As we matured, we developed more sophisticated ways to resolve our conflicts. Our wrestling matches were gradually replaced by civilized discussions. Although I haven’t wrestled with anyone in a very long time, I believe that roughhousing is the same kind of activity as an intellectual discussion and the same sort of rules apply.

Intellectual discussions have been compared to wrestling since ancient times. Plato was a champion wrestler and used this as a metaphor for the Socratic method. Some of his Socratic dialogues are set in wrestling gyms. In the book of Genesis, there is a story of Jacob wrestling with an angel that’s used as a metaphor for the struggle of faith. After that wrestling match, he was renamed Israel which means contends-with-God. The history of the Great Debate of ideas is filled with rough intellectual sparring matches between interlocutors. Just like in wrestling, the goal is not to destroy the opponent, but to demonstrate skill, and in the case of discussion, to find the truth or the best possible course of action.

In my lifetime, I’ve had the privilege of knowing people who are extraordinarily skilled at engaging in intellectual discussion, especially my good friend Daniel Henry. We can have heated debates over topics we disagree on like politics, religion, and technology and afterward, we’ve both learned something and we are still good friends. I’ve also had friendships break up primarily over ideas and values that were hard on me emotionally. Over time, I started to think about the rules of having good discussions because it’s an important part of my job and I’d like to have more of them with friends. Here’s five rules I can think of that are important for being a good partner in discussion.

Play to Play Again

Wrestling may appear violent, but it is actually a game played between cooperating opponents with a strict set of rules like chess. There is an unstated assumption that sportsmanlike conduct is more important than the contest itself. In a good wrestling match, both contestants come out as better people regardless of the outcome of the game. Developing good character from practicing good sportsmanship is more important than winning or losing. The same is true in intellectual discussions. A discussion is not an isolated event that decides the issue once and for all. Discussion is a game that is played over and over forever. Arguments have to be digested and tested through action for them to be believed. The world is always changing so arguments need to be constantly updated to stay relevant. If you practice good sportsmanship in discussions, people will be more likely to engage you in debate which will cause your arguments to become stronger and you will become more influential by reaching more people.

Let People Be Wrong

“The purpose of thinking is to let the ideas die instead of us dying.” – Alfred North Whitehead

A big reason why discussions become unhealthy today is that people simply aren’t allowed to be wrong. People sense that a wrong opinion about something can get them kicked out of their social circle or fired from their job. However, being wrong is an essential first step to finding out what’s right. Thomas Edison had to come up with thousands of designs for filaments before he made a working light bulb. It may seem wasteful, but the ideas that don’t work are necessary intermediate steps towards figuring things out. They are like the scaffolding of a building that’s discarded after it’s constructed. While the scaffolding won’t be included in the final product, you can’t build a skyscraper without it.

When the stakes for thinking are high, people will turn their brains off and just agree with whoever they think is in charge. This does a great disservice both to themselves and to the people in charge. Competent people surround themselves with others who are thinking through difficult problems and communicating honestly about their best understanding of the situation. Giving people the freedom to be wrong will open them up to the possibility of argument for play. There can be a lot of joy in taking a wild position on an issue just for fun and watching it crash to the ground and blow up in a spectacular manner.

Having a wrong opinion on something does not make you a bad person. Let people be wrong and they will be honest with you. People can only make connections with each other when they have permission to be honest.

Hold Onto Your Point of View

Some people are naturally very agreeable people and aren’t comfortable with confrontation. If I see someone is an agreeable person, I won’t try to argue with them and I’ll be more considerate of their feelings so they don’t have to be as assertive with me. However if you want to have good intellectual discussions with people, you have to be a bit disagreeable.

When I’m arguing against a position someone has taken, I want to argue against the strongest possible version of that position that we can possibly formulate. You should speak confidently and make bold and assertive statements, even if you think you might be wrong, as long as that is your honest point of view. Someone who is confident is not someone who believes he is one hundred percent correct, but rather someone who is sure he can correct himself quickly when he is incorrect.

A good discussion has a “ping pong” quality to it. When I hit the ball to you, I want you to hit the ball back to me so we can keep playing. If you take a position, defend it the best you can for as long as the conversation is productive. I want you to defend yourself and maintain your position of power. I think it’s a tremendous sign of respect when someone disagrees with something I’ve said because it shows they have listened to me, they trust me enough to share their honest opinion, and they think I’m reasonable enough to accept criticism of my views.

Don’t Do It Over Text

It takes a lot of emotional intelligence to engage with someone like this. It’s easy to go too far into a sensitive topic and hurt someone’s feelings or get too far into the details and bore them to tears. It’s important to take emotional cues from people so you can steer the conversation in a good direction. The best way to know if someone is interested in what you are discussing is their nonverbal communication. This is completely lacking over text.

I don’t think I’ve ever had a satisfying intellectual conversation over text. Irony doesn’t come through very well and sometimes I’ve accidentally made people mad when I was just kidding around. It’s easy for conflict to escalate in text because you can’t feel how your words affect the other person. There is an emotional numbness to text messaging that is just as dangerous as physical numbness. You can put your hand on the stove without even realizing it.

I think in general we should all stop having important conversations over text. It should just be for business purposes.

Let the Conversation Affect You

Arguments are soldiers. Once you know which side you’re on, you must support all arguments of that side, and attack all arguments that appear to favor the enemy side; otherwise it’s like stabbing your soldiers in the back – providing aid and comfort to the enemy. People who would be level-headed about evenhandedly weighing all sides of an issue in their professional life as scientists, can suddenly turn into slogan-chanting zombies when there’s a Blue or Green position on an issue. – Eliezer Yudkowsky

When I was a kid we used to play imaginary war games. One time I took out a mime gun and shot my friend and it didn’t affect him. “Tink! I have bullet proof armor.” So I got out increasingly bigger weapons and shot him with those. “Tink! It’s bazooka proof armor too.” Finally I set off a nuclear bomb at his feet. To my horror, he emerged from the mushroom cloud in my imagination completely unscathed and laughed at me. This kid was clearly invincible. The city was destroyed by radioactive fallout and the game was over. This kid was not very fun to play with.

To put this another way, it’s a terrible strategy to pretend like you have all the answers and nothing the person will ever say can change your mind. You will never influence anyone like that. It’s one of the great counter-intuitive truths of human nature that to be influential you must be vulnerable. To make a connection with someone you must be willing to be affected by what they say. Even when you’re in front of a crowd, you should be focused on their reaction and let that guide your tone and content. Without that connection, you are like a college professor giving a lecture for the third time of the day. People will engage with you like they would a YouTube video so you can’t blame them when they want to change the channel.

When someone makes a point, don’t just wave your hands and tell the person what they said is not important. Every time you do that the person will disengage a bit more because it gives them the sense you are not listening to them. They’ll put in less effort to their responses when they sense there is a low chance for a payoff. Listen to the other person, take in what they have to say, assess your true reaction, and then respond accordingly. Don’t be that annoying invincible kid on the playground.

Headspace: Why Small Distractions Matter

I remember a few years ago I was renting a room from an older gentleman after moving to the city. I rented rooms in this time in my life partly because my work location was moving around a lot, but also as a social experiment to see if living with someone else would improve me personally. Living close to someone requires the kind of compromise, tact, and patience, I’ve always been notorious with the people who know me well to lack. And I tried so hard to let that experience affect me, but there was surprisingly one thing that drove a wedge into our relationship that I just couldn’t seem to get past.

At the time, I was doing the most intense work I’ll probably ever do in my life implementing core Wayland interfaces for the wlroots project. It’s the kind of work that requires your full, undivided attention for hours at a time to make any progress with. Now this old man happened to also be a collector of antique grandfather clocks and there was one in particular in the center of the house that would loudly chime the tune of big ben for about thirty seconds once an hour. This very deeply annoyed me. Every hour, whatever I was thinking about just drained out of my head and I had to start over on whatever thought I had built when it was over. I even started to instinctual planning the deeper parts of my work around the chime by starting my important thinking at the beginning of the hour.

When I brought this complaint to him, he seemed to be confused why someone could get emotional about something small like this, and I understand his point of view. I’m kind of an unusual person with some unusual requirements for concentration. None the less, I demanded that he get rid of the clock. He asked me to leave. Now I live alone. My social experiment may have been a failure, but at least I don’t have to live with that damn clock anymore.

I know you probably think I’m weird after reading that story, but I don’t care. I’m doubling down on this. Here’s why small distractions matter if your productivity in life is at all important to you.

Headspace and Intelligence

The idea of headspace is a great word that metaphorically describes what’s going on here. There’s only so much space for thoughts to fit in your head at any one time. The technical term for this in cognitive psychology is called working memory. People are limited in the amount of information they can use for processing at any given time. This is why multiplying large numbers in your head is nearly impossible. You have to occasionally write down some intermediate result on paper so you can forget about it and process it later. When I’m designing a complicated system, I have to think about how a lot of different things work together at the same time and my head fills up quickly. The number of things I can reasonably think about at any given second is only maybe about seven to ten, and that’s really pushing it.

All this sounds very scientific, but you can’t ignore the human factor either. My experience is that using working memory is a very painful process. I think this is the core reason why the general population doesn’t like math. You have to really enjoy the end result of mathematical understanding to offset the violence you have to do to yourself to understand it, and most people get more enjoyment from normal people things like walking their dog or something. To each his own.

Since it’s painful to use working memory, there is only so much time in the day we can actually think deeply about things. The ability to concentrate seems to fatigue when you strain it like a muscle. In my experience, I can only be at peak mental performance for maybe four hours a day. I get most of my work done in short bursts of concentration and use the rest of my time to recharge. I’ve heard people describe this as their good hours. Losing my good hours for a day on an unproductive task may mean I have an unproductive day.

Studies have shown that working memory is highly correlated with fluid intelligence. This sort of intelligence is the ability to reason abstractly about things and solve novel problems. This seems to me to describe the raw ability of someone who works with systems like engineers. There is unfortunately no known way to increase fluid intelligence. But we can improve the efficiency of how we use working memory by making changes in our environment to eliminate distractions. And it follows that if we do that, we should be able to focus more of our capacity for fluid intelligence towards a single goal.

The consequence of working memory being so small and the time of day we can use it effectively being so limited is that small distractions take up a proportionally large amount of space in our head. If you can only think about seven things at a time and one of your seven things is being used up by a small distraction, you can become fourteen percent smarter by eliminating that one distraction. You can get large productivity gains by increasing your focus by just a little bit and this is why engineers tend to be very guarded about what they allow themselves to think about during their good hours.

Consequences

The ability to pay attention and use all of our intelligence towards a single goal is the fundamental skill of an engineer. Taking steps to identify and ignore distractions is an essential part of the work we do on a daily basis. In fact, concentration sometimes feels more like an exercise of shutting things out than letting things in. Distractions are everywhere.

For instance, a study shows that even just having your cell phone on your desk can impair learning ability. The anticipation of a notification on your phone in the back of your mind takes up a measurable amount of your attention. When I really need to concentrate, I put my phone in another room and forget about it. I end up missing some calls and people might think I’m being aloof, but for me it’s a sacrifice I’m willing to make. The things in front of me are more important.

This is also a reason why I don’t like open office plans which are show to decrease productivity. There are a ton of small distractions in an open office happening all the time. Even just someone walking past me can break my concentration for long enough for me to lose my train of thought. The effect of being around that all the time is I’m always operating at about eighty percent of what I could be and my work suffers.

I’m not saying that you have to shut yourself in and work all the time without distraction. My philosophy is to do whatever I’m doing fully. If I’m working, I need to pay complete attention to what I’m doing during my best hours to be productive. But the reverse is true as well. If I’m relaxing socially, I should put all my attention on that situation and not think about work. And of course leave some time for softening up your focus by daydreaming or meditation so you can reflect on whether you are doing the right thing with your concentrated hours to begin with.

Why I Like Improv Comedy

For about the past year, I’ve been going to a lot of shows at a local improv theater called Village Theatre in the city of Atlanta. If you don’t know, improv comedy is a form of theater where all the scenes are improvised. Sort of like that show Who’s Line is it Anyway. I really enjoy going to shows and hanging out there so I wrote a little bit about why I like it so much.

It’s Spontaneus

The most important aspect of improv is that it’s all made up on the spot. A show starts out with a suggestion from the audience, usually a word or phrase from a question from the improvisers. The suggestion serves as a kind of random seed that gets the performers thinking about the same thing. The show starts off with someone telling a story or starting a scene based on a free association of the suggestion. The spontaneus nature of an improv show is what makes it unique.

There’s just something cool about watching people do things live. You are watching unplanned events unfold before your eyes. There is a sense of danger and a feeling that anything can happen. Each new scene may succeed or fail spectacularly, and you get to see the raw unedited events as they unfold. This makes being part of the audience a social experience. When everyone is sharing the same moment, it connects everyone together. This is the reason why sports are broadcast live. Watching a rebroadcast of the Superbowl is just not the same experience.

Improv comedy takes this experience to the limit. Normal theater is something like a “rebroadcast” of an initial inspiration. The success of the production depends on recreating the moment that inspired the piece. Doing this takes an enormous amount of effort and skill for the performers and nobody can do it perfectly. The greatest actors in the world cannot reliably recreate the kind of spontaneous behavior we are all capable of in our everyday lives. You can always tell the difference between a speech given extemporaneously and read verbatim. When you make something up on the spot, you have perfect delivery almost by definition. You did it exactly how you would do it, and that’s indistinguishable from perfect acting.

This affects the content of the shows too. The fact that everything is made up on stage does limit the complexity of the content that can be performed to whatever the group can store in its head during the performance. You won’t see a perfect three act play with a twisting plot and deeply written characters. But interestingly, I’ve found there is just as much variety in improv as there is in normal theater and maybe more. Without an editing process, ideas can be explored that would normally be cut off early. An off-the-cuff remark may become a full blown bit or recurring gag. Shows are unique because they only exist in that moment. The shows are sort of like what friends do when they joke around, which has an infinite possibility for entertainment.

When you watch an improv show, it’s more than just theater. You are watching something truthful actually happen on stage. You may not get to see a complex plot, costumes, or special effects but those things aren’t really the point of the experience anyway.

Audience Participation

When you think of audience participation, you might think of the performers inviting some people on stage to do a dance or sit in a chair or something. That sort of thing happens in improv too. One improviser named Mark Kendal is pretty famous for this. One time he led the whole audience out of the auditorium to go interrupt another show just for fun. But there’s a deeper level of audience participation that is achieved during these shows.

Improv is an extremely simple artform. There aren’t any sets, costumes or props. The simpler an artform is, the more of yourself you are required to bring to it as an audience member. In the audience, you have to bring all of these things to life with your imagination during the performance. This is a really cool thing because it allows for lots of creativity. If the scene takes place in a police station, everyone in the audience will have something different in mind. When scenes get crazy, it’s a lot of fun to puzzle over the insanity of the circumstances.

When worlds can be created and destroyed in the imagination of the audience so quickly, a level of abstraction can be achieved that’s very difficult for other dramatic arts to get to. Scenes can take place in dreams or fantasy settings where the audience is given very little to go on. The performers rely on physical comedy and clowning techniques to create a funny “stage picture” to explore. In one show I went to, a performer announced that the stage was now “the dice world” and the rest of them rolled around the stage like dice. In another scene, the performers formed two lines that spoke to each other like they were two people in a serious conversation which gave it a feeling of generality, but the concept had just enough of the element of the ridiculous to be comedic. These ideas were very successful with the audience, but if these concepts were fleshed out and put in a film production, it would completely fail. This sort of theater is only possible when it is within the imagination of the audience.

It’s Local

Another great thing about improv comedy is that the people who are in the shows are just people from your community. They aren’t big shot millionaires who live in California. They’re just the local theater people and they’re hanging out in the lobby and you can have a drink with them after the show. When I first started going to improv theaters, this was really shocking to me because I was so used to having a lot of distance between myself and the people on TV. Knowing something about the performers in a show makes me appreciate the performance a lot more because I can relate to it on a more personal level. And the theater is also just a really fun place to hang out. The people I’ve met in the improv community are some of the nicest and most supportive people I’ve encountered in my life, and I like to think some of that energy is rubbing off on me by spending time there.

What’s more is that the audience is local. The performers and the audience have so many shared experiences living in the city of Atlanta that a lot of things become accessible that would be impossible to do in a national act. When I go to the improv theater, I get to see scenes about my own local culture and the things that affect the people of the city I live in.

Improv theater just feels like a bunch of people from the neighborhood getting together, expressing themselves, and working through their issues. This is the proper role of art in society and something that’s completely lost in other media like film and television. There’s just something about the whole thing that’s really magical to me.

The Limits of Standardization

Without standards we would all die. Without a standard kind of air to breathe, there would be mass suffocation. If there was no standard song to sing at birthdays, these events would be pure chaos. Nobody wants to live in a world without a standard keyboard layout so I can type on your keyboard. So stop setting your layout to Dvorak, Ed. That’s really annoying and even you say it doesn’t make you type faster. Standards improve our lives by allowing us to make assumptions about how to accomplish certain things and ultimately form the basis of our work culture. However it’s important to realize that standards are not free and should be evaluated in terms of their costs and benefits.

Incentives to Standardize

Standards are not always proposed with the best interest of users in mind. Standards are created by people with their own goals and interests that might not perfectly align with those of the user and a greater political context has to be taken into account when evaluating a standard. Some companies create standards to sell or license for profit. These standards are designed to be profitable first, and may consequently be useful, but the profit motive may lead to design decisions that might not be good for the user. When a company creates a set of standards that are mutually interoperable but not compatible with the wider ecosystem of related standards, we call that a walled garden. Creating walled gardens can be very profitable because once you buy in, it can be very hard to get out.

The most prominent walled garden for consumers today is the Apple ecosystem. Instead of using the standard USB charger, Apple has created their own charger standard that can only be used with iPhones. This is a great business move for the company for several reasons. For one, instead of paying for licensing of the existing standard, creating their own allows them to license the standard to other manufacturers at a large premium over the existing one. Another thing is that if the iPhone user has bought into Apple hardware, it will be more expensive for them to switch to a phone that uses competing standards because they already own a lot of accessories that don’t work with any other type of phone. They are essentially locked in to Apple now and the locks can be expensive to break. These sorts of lock-ins are bad for consumers and ultimately for markets because they reduce consumer choice and stifle innovation by entrenching the owners of the walled garden in their market position. This is the price we pay as a society to give the company incentive to create a standard in the first place.

At their worst, standards seem to be made intentionally difficult to implement, although I believe this effect is really a natural consequence of there being no incentive to make the standard easy to follow. For instance, the Microsoft Word document format is a standard that can theoretically be implemented legally by other word processing applications. However, alternative word processors like LibreOffice have a very difficult time actually creating an implementation because the standard is not well suited for public use. There’s no incentive for Microsoft to expend the effort to make their document standard accessible to competitors. It would be more efficient to have a common open standard we can all use, especially considering that Word documents are used in the course of some civic functions.

Using a standard controlled by another entity gives them a lot of power over your project. You should only choose standards where you trust that the incentives of the creators of the standard align with the interests of your business.

The Reduction of Minds

Aside from enabling interoperability, another important way standards work is to reduce the number of minds that are thinking about solving a problem. Standards provide readymade abstractions like TCP packets or HTTP headers so you don’t have to think about these things if you just want to run a website for your dog grooming service or whatever. The core internet standards are mostly considered a solved problem and nobody even thinks about any other way that could be done. That’s a great thing when the standard you’ve come up with is good enough and the problem is fairly static like data transfer. But when the problem is dynamic and the future is unclear, and especially when the process is social, premature standardization can lead to a whole host of problems.

Standardization is essentially a controlled automation of thought. When thought it automated, it reduces the amount of consciousness being put on a problem. Since changing standards are difficult, it raises the bar for the benefit required for some improvement to be proposed for the standard. With premature standardization, you lose the ability for many people to come up with competing incremental improvements so it puts a lot of pressure on the creator of the standards to get it right on the first shot. And most often this is an impossible task to complete. When incremental improvements are delayed, technical debt builds and can ultimately lead to a breaking point where a different standard is needed. An then you have yet another competing standard.

Sometimes it’s better to have a period at the beginning of the project where there are no standards at all and just let everyone figure out the problem for themselves. An explicit lack of standardization in some areas is a defining characteristic of the Federal system of the United States government. Certain powers of the government are delegated to the states to allow for experimentation with the rules to find out what is the best way to do things. When processes are decentralized, we can have disagreements in theory and try out a lot of different ways of doing things and let the outcome of the experiments be our guide to good policy. Many times having all those extra minds thinking about a problem is really not wasteful, but the best thing they can be doing to improve the situation.

The best standards arise organically from a diverse group of organizations each with their own experience solving the problem in their own way. Standards that are created by a committee at a single organization sometimes lack the flexibility to be used outside their original context.

Application to the Workplace

As a manager, you are probably a conscientous and orderly person who likes everything to fit into nice little boxes and it makes you uncomfortable when things get messy. So to make the world a bit more understandable, you begin to make standards. There’s a standard web framework everyone should use, a standard http server library, a standard number of approvals for code changes, and a standard code coverage target. At the end of the day you have a big pile of standards and you feel like you’ve accomplished a lot of work.

The problem is that most of the time, the decision process for coming up with these standards is simply the intuition of a few people and sometimes these people get things very wrong. It’s easy to implement a standard on a whim in a meeting when none exists, but to change the standard requires justification which can be very difficult to provide when the original standard was imposed without much justification at all. Sometimes it’s just a matter of one person’s intuition against anothers and the person with the original thought may not even work for the company anymore. Team standards are like any other knowledge asset in that they need continuous maintenance to justify their existence. Rules accumulate and become technical debt like code. Before you know it, you have a ton of crufty old rules that people are blindly following and nobody is getting any work done. This is the number one job complaint I hear from my developer friends.

While it might seem counter intuitive, sometimes chaos is not a problem to be solved, but should be embraced as a normal part of the creative process. Sometimes the best thing you can do is to just sit back and let everyone fight it out and see what comes out of it. The results may surprise you. In the process you’ll be gaining knowledge of all the things that don’t work which can be just as useful to know as the things that do. Never forget that you have the great advantage of real human beings solving your problems for you. And while the human way of solving problems in groups can be a very messy, this should not be treated as an engineering problem, but simply a natural limitation of the human experience.

Some Thoughts on Testing

The main problem with testing is that nobody can think of a procedure to decide how to test. And maybe that’s not even possible. What’s worse is that the feedback cycle from bad tests lasts a long time. It might take a year or more before you discover that an important code path has bad tests when a use case changes and subtle bugs appear or large swaths of the test suite needs to be rewritten. Every developer will have a different set of experiences with tests that will shape their attitudes on the matter simply by random chance. It’s easy to see how opposite extremist viewpoints arise under these conditions. A developer who is bitten early in his career by a bad test suite will naturally be opposed to testing efforts. He will test less which will reinforce the belief since he will have less opportunity to be exposed to well-written tests. And if you think about it, that’s a perfectly rational way to react to those experiences since maintaining a bad test suite can definitely be worse than having no tests at all.

I was very fortunate to have been exposed to an excellent test suite on the first major project I worked on as a new developer in open source. The maintainers always insisted on a test for bug fixes and features and I saw for myself how this practice benefited the project.

What is a Test?

A test is a model that is used to approximate user behavior. When the model fits well, we can conclude from a passing test that the user will experience the result defined by the test assertions under the conditions of the test setup. In this way, tests become a precise definition of the intended application behavior bridging the gap between how the application actually runs and how the application ought to run. The setup shows an ideal for usage and the assertions show value judgments the user can use to set their expectations of defined application behavior.

In the broader picture of the engineering process, you can imagine downward flow of work from requirements, to design, to documentation, to testing, to implementation. Each lower level serves the higher level by adding precision at the expense of the ability to judge value. Tests use the documentation as their source of truth and serve its purpose to define application behavior but at a level of specificity that cannot be attained by plain English. However, this specificity comes at the cost of the ability to make more general value judgments since only specific inputs can be tested.

Tests sit only above the implementation which is by definition completely specific and objective. Implementation code simply runs how it runs. Correct behavior can only be determined in the context of the levels above. It is easier to determine whether application code is correct in the context of tests than documentation since tests are written in the same language domain as the implementation.

The Benefits of Testing

Since there is no procedure to decide how to write tests, it’s important for anyone who writes or reviews tests to understand their purpose. If the answer is “because my boss said every pull request must have tests” then in my experience, this nearly always leads to a low quality test suite. Testing may be a legitimate business requirement, and it’s a reasonable ask, but to meaningfully deliver this as a feature, your technical lead must be conscious of the testing strategy and must be able to articulate good practices to less experienced developers. Only include tests that you can reasonably understand brings value to the project, even if this understanding is only intuitive.

There are two different groups of people who are benefited by tests and tests must benefit both of these groups simultaneously.

Benefits to Developers

Most often it is your developers who will be writing their own tests so it’s important to get them invested in the process. Testing is unusual in that it is seen as a low class technical activity, but at the same time it requires an enormous amount of skill to do correctly. If a developer is resentful about needing to write tests, they will always write bad tests with this mindset. To make things easier for them, it’s a good idea to come up with a testing strategy while you determine the approach to implementation. All things equal, you should always prefer an approach that is more testable. Lack of testability is a valid reason to reject an approach.

The main benefit to the writer of the test is that it codifies their intent into the repository. Writing a test sends a clear message to other developers who may modify this code what it’s supposed to do so the writer may be confident others won’t break a feature he is relying on for future work. This is especially important in open source projects where lots of people are making one-off changes and might not recognize an edge case you are relying on for your feature. This sort of communication with others is done much more efficiently with tests than comments.

If your team has a culture where testing is a responsibility the benefits are much clearer. When a developer can expect others to write tests for the features they need, they gain the ability to freely modify the code without being as nervous about breaking another developer’s feature. This frees up mental energy for code quality improvements like large-scale refactoring that simply wouldn’t be possible without feedback to guard against unintended side effects. Ideally, any sensible implementation at all that passes the test suite should be acceptable which has the effect of reducing the actual code base to just details. It’s much more fun to commit to a code base where there are less consequences for mistakes, and much easier to review as well.

Without this expectation, when a regression occurs, the only possible solution is to “be more careful” which is not nearly as actionable as “write a regression test”.

Benefits to Users

As an user, the test suite is a good way to evaluate your use of the application. The test suite contains examples of usage you can compare to your own usage to understand whether you are on the common path. If your usage is different than the tests, you’ll know you are doing something novel and need to exercise some caution with your implementation. Whenever I see some odd behavior with a library I’m using, the first place I look for an explanation is the test suite. If my path is tested and my results are different, then it narrows down the possible reasons for the discrepancy to the environment. Knowing this is helpful when reporting bugs on the project. If the path is not tested, I know I’m doing something with the library the authors may not have intended and I’m on my own to make sure it works. In that case, I know I need to do some work in the library and then add a test for my use case to make sure it remains supported in the future.

You can use the test suite as documentation for the project. In some ways, it’s better than the actual documentation because you know if the tests pass you are looking at working code, while the documentation may be out of date. Not nearly enough people know to use the test suites in the projects they use this way.

The Costs of Testing

Writing tests is a lot of work, but when done correctly, it’s a force multiplier for developer and user productivity by clearly showing design intent and increasing stability of the code base. The problem is the stability you gain is forced and it takes additional effort to relax assumptions when a use case changes.

Just like with any other code, most of your testing effort will go into maintaining an existing test suite and this should be considered the primary driver of cost. Maintenance costs vary inversely with the stability of the interface. The more stable an interface is, the less it costs to test it which makes it a better target for tests. It doesn’t make any sense to test scaffold or POC code because you’ll end up paying the cost of removing the tests later.

General Testing Principles

So in conclusion, here are some basic principles to decide how to design your test suite.

  • Only include a test if you can justify its value.
  • Limit your tests to code under your control.
  • Write application code with testability in mind.
  • Write tests to augment the documentation.
  • Do not test undefined application behavior.
  • Write the minimum amount of tests you need.
  • Write tests whose failure has a meaningful business reason.

The Great Node Mpris Project

I think one of the things that makes me different from other people is that it really bothers me when things don’t work correctly. I feel a compulsion to fix things when I see that they’re broken. As I’ve written about in the past, it’s not glamorous work to be a bug fixer. You don’t get the same credit as the original author. But it’s still important work to do and I find it oddly satisfying to put things back into their intended order.

The Bug

This project started with a bug on my issue tracker for Playerctl that was submitted two years ago. Media players implement a standard protocol on the Linux Desktop called MPRIS which is used for desktop integration. This allows things like the media keys to work, and the desktop to have widgets that allow you to see what song is playing, adjust the volume, and things like that. Playerctl is a utility people use to make their own desktop media player integrations.

When I built the media players affected by the bug and tested them, I found that the bug was in their code and there was nothing I could do on my side to make this work. This makes things a lot more complicated for me. It’s a lot more difficult to understand the inner workings of code that you didn’t write. And since these are established projects, I would have to communicate clearly what needed to be done and make the fixes in the least intrusive way possible so people would accept the fix. There is a whole established etiquite for this within the open source community that needs to be followed in situations like these.

The Broken Library

What the broken media players have in common is that they all have a dependency on a library called mpris-service. I was really lucky here because the owner of the library is someone who I have worked with a lot in the past, Simon (emersion), who is an amazingly talented and responsive open source developer. We met in person about a year ago at a hackathon for Sway.

On his issue tracker, I found all the same issues. Only the very basic features of MPRIS were working and everything else was broken. I was surprised that in the state it was in that the library had gotten such wide adoption. Three major media players were using it despite all the bugs and no progress had been made on the issue for years. I decided to make this my responsibility to help out a friend with a buggy library he didn’t have time to fix (because he’s busy doing other amazing work), for the users of Playerctl, and to improve the Linux Desktop environment.

The Next Broken Library

But it turned out that the bug wasn’t in Simon’s library either. He was using a library for the underlying protocol of MPRIS (called DBus) which simply wasn’t working correctly. It didn’t have support for the data types that are used in MPRIS. And further, both the implementation and the user interface were very bad because it uses platform-specific code written in C++ which makes it less portable across systems. This introduced some build errors in the media players they got around in various hacky ways with their own fork of the library. This definitely needed to be fixed.

The problem though was the DBus library was just not written in such a way that it could ever support MPRIS. Also, the owner seems to have abandoned the project and is no longer taking submissions for fixes. It was then I realized why this hasn’t been fixed. This was going to take a lot of work.

There was some discussion about using an alternative DBus library called dbus-native which had gotten some support by the library users. This path seemed promising because this library was much cleaner than the other DBus library and didn’t require compiling platform-specific C++ code. So I set out to make mpris-service work with this new library.

This didn’t work either. While dbus-native has great internal features, the user interface for creating DBus services did not support some very basic features I needed to implement an MPRIS service, and adding them would require a very extensive rewrite of the top layer of the library.

My Very Own DBus Library

Since I knew this was the only way to get this bug fixed, I did this rewrite and submitted a pull request on the dbus-native project. This pull request remained open for a few months before I realized that it would probably not be merged. This is totally understandable because lots of old code depends on this library that could break with my changes, and reviewing the code is a lot of effort that I couldn’t expect someone to do just to help fix my silly Playerctl bug.

So I decided to fork the library with all my changes and release it as a new library called dbus-next. I also fixed a lot of other bugs and added an integration test suite for all the new functionality that has very good coverage. So now NodeJS finally has a working DBus library. Great.

After that work was done, I then rewrote mpris-service to use my new library and everything worked great.

Media player implementations

Now that the mpris-service library works, people are starting on implementations of MPRIS on media players written in NodeJS and I’m doing my best to help out.

Now it’s possible for all these media players to support Linux Desktop integration. And when that work is done, I can finally close that Playerctl bug on my issue tracker.

Impressions of AlphaStar

Recently I heard that DeepMind has turned its attention towards making a StarCraft II bot in a similar way it made AlphaGo, the bot that recently proved to be capable of playing the game of Go on a very high level. The SC2 bot turned out to be really good as well. It beat two excellent pro players in decisive victories in a series of five games. SC2 is a game that is very dear to me. I first picked up the game in the late 90s when it came out and have at some times played at a fairly high level. A lot has been said about the games and I’d like to add my perspective about the performance of AlphaStar.

How does AlphaStar work?

I’m not an expert in machine learning, and the details are quite dense, so if you want an actual technical explanation, check out their whitepaper if you’re up for it. Otherwise, enjoy my very naive attempt at understanding how this works.

The bot plays programmatically through a headless interface that’s pretty much like a human would use. The domain of possible actions is pretty daunting considering how many places on the screen there are to click. However, it probably simplifies a lot at higher levels of reasoning. If the idea is “move the Stalker away from the Marines”, the exact angle at which that happens is probably not very important, and you really only have maybe like three or four sensible actions in that case. But still it seems like a pretty difficult technical challenge to overcome.

For the higher level gameplay, they broke the game into a few simple challenges.

  • Mine as many minerals as you can in a certain time
  • Build as many units as you can in a certain time
  • Win a battle against enemy units
  • Find things on the map to kill

These things are essentially what you do while you play the game. They created “agents” that do these things with complicated neural networks with a lot of different parameters to tweak and selected the best ones through a process of training. Then I think they glued these things together and ran them all at the same time and basically got something that plays StarCraft. The mining part mines minerals, the building part builds units, the finding part finds enemies, and the winning part wins the battles. Repeat until you win or lose.

This is a really fascinating way to think about the game. It seems so obvious, but in reality humans are thinking about things in a completely different way. Humans start with very high level plans and then think about execution afterwards sort of like a basketball play. I am going to open with this build order, then try to do a heavy Immortal push, and if I see X then I’ll do Y, etc. How does a person come up with a crazy idea like this? Who knows. Machines can’t seem to think this way though.

Whatever high level plans you think the machine is thinking of just seems to emerge out of the details. It’s sort of like when you see a V formation of birds in the sky. They don’t all get together and decide to fly in that formation. It’s just the easiest thing to do because flying like that cuts down on wind resistance, and any bird who doesn’t do it won’t be able to keep up. The machine looks at the details of the situation, and then estimates the probabilities of certain actions (actually to the end of the game) and then picks the action with the best chance of winning. You can really see this at work in the bot’s play style.

How does AlphaStar play?

With such a different approach to the game, AlphaStar naturally has come up with some completely new strategies for playing. A lot has been made in particular about two of its behaviors.

For one, AlphaStar will almost always overbuild workers in the beginning part of the game. It builds about 20 to a human’s 16. This is definitely the most practical result I’ve seen come out of the project because it’s something that a human being can easily copy and test to see if it works. This actually makes a lot of sense because it’s an easy way to counter all the early harass that Protoss has that usually picks off about two to four probes anyway. I expect this to become a new standard on ladder. It would be interesting if we still saw the behavior in matchups with less early worker harass pressure.

Another strange thing AlphaStar is doing is not building a wall at the base entrance, which is considered to be a best practice among human players. It’s difficult interpret this however. The purpose of the wall partially is to address the very human problem of a slow reaction to an Adept harass, but also to block an Adept shade from getting into the base to begin with by building a Pylon for a full block. It would be understandable to think that the Pylon block strategy would not emerge quickly because it takes quite a bit of high level thinking. So I think people will continue doing this. The machine is after all not perfect.

There are some other strategies that AlphaStar notably does not use. For instance, it does not use Sentries to block ramps and it doesn’t drop. These might also be a bit too complicated to emerge from the limited time they trained the agents.

AlphaStar does however have a very entertaining play style. It micromanages its units perfectly in every situation, sometimes even at multiple locations at once. At one point, it executed a perfect three-pronged Stalker ambush in the middle of the map. Each group of Stalkers almost seemed to be controlled by separate players. Much of human play optimizes for the limited attention of the person, but a machine has no such restrictions. Each Stalker can move out of the way of fire at exactly the right moment to avoid destruction. Seeing the game played perfectly was truly amazing.

This point however did however receive some criticism. If AlphaStar is trying to teach us how StarCraft should properly be played and the answer is “just have perfect mechanics”, then that is not very interesting. Sort of like how it’s pretty trivial to create a chess AI that can beat a human opponent with only 500ms on the clock. On every tick, AlphaStar has the human equivalent of hours of pondering for each small move.

While AlphaStar did put on a very impressive show, I still found the play style to be very cold and mechanical. I didn’t feel what was described by people who watched the AlphaGo games who thought that agent played in a human-like way. AlphaStar did do some really insane stuff. But it seemed to almost completely ignore the unit composition of its opponent and most of its decisions seemed to be predicated entirely on the assumption of perfect control. For instance, the game against TLO where it massed Disruptors is a strategy you could not possibly use without perfect control. It’s almost as if it is playing a completely different game than we are. There’s an entirely different set of constraints that the game is simply not balanced for. The same isn’t true in a game like Go which does not reward reaction time.

In fact, a lot of StarCraft II mechanics are specifically designed for the fact that humans do have a limited number of things they can focus on. For instance, Queens do not auto-inject Hatcheries precisely because that would make Zerg imbalanced in the early game. Human-scale focus is baked into many of the mechanics of the game.

What can we learn from this?

My primary takeaway is that machines like this just do random dumb shit until they find something that works. I really like what this company is doing though because I think overall these sorts of things can have a positive impact on our culture. They sort of remind me of Boston Dynamics, a company that seems to be in the business of making random cool things for YouTube videos.

I hope this project can influence game designers to make better competitive games. It puts into focus what machines do well versus what humans do well. I think game designers should take a cue from this to maximize game design for human skills by rewarding high-level thinking and creative problem solving over mechanical mastery. Now that computers are better than us at StarCraft II, the challenge should be to create a game that humans will always be better at. There must be some kind of game like that, right? I’m not sure anymore actually.

At least we know if the Zerg are real and they ever invade Earth, we should have a chance to defeat them now.

References

Write Drunk Edit Sober

The famous quote write drunk, edit sober is often attributed to Ernest Hemmingway. When I first heard this, I thought of how I could incorporate this idea into my own creative process and came to the conclusion it is a terrible idea. As a creative professional, I need to come up with creative ideas every day. If I needed to rely on alcohol for my creative process, I would very quickly destroy my health. But something about this idea still rings true to me so I think it’s worth some time to analyze to see if there’s anything we can learn from it not just for writing, but for any creative activity.

Write Drunk

“I hate to advocate drugs, alcohol, violence, or insanity to anyone, but they’ve always worked for me.” – Hunter S. Thompson

The first part is write drunk. The first thing I think about when I hear this is one of my favorite authors, Hunter S. Thompson and the book Fear and Loathing in Las Vegas. Thompson’s inspiration for writing often comes from altered states of consiousness from the use of drugs and alcohol. Obviously you don’t need to go this far to be a creative person. But there is certainly something about the creative process that makes it feel like a different state of mind than normal waking consciousness. Creativity seems to flourish not by direct effort, but by the suppression of some more rational part of our personality that is responsible for inhibition.

The key insight is that the creative state of mind is sort of like being drunk. If we change this to write as if you were drunk the advice becomes much more practical. Someone who is drunk tends to be bursting with ideas. Most of the ideas are really bad, but there’s a lot to choose from. The drunk person has so many ideas precisely because he doesn’t care whether they’re bad or not. The alcohol suppresses the critical faculty responsible for their immediate evaluation.

We can mimick the creative part of the drunken state by slowing the feedback loop between idea generation and evaluation. An idea that seems bad may actually lead to some valuable path that we may have never discovered if we cut off the line of reasoning too early. For instance in chess, a common tactic is to make a move that intentionally loses a piece, sometimes even an important one like the queen, to gain a positional advantage that will win the game. If we consider the move and then immediately evaluate it, it might seem insane to intentionally lose our queen and the opportunity to win will be lost.

Edit Sober

Another great insight in this quote is that the creative process happens in two distinct stages. There is the drunk stage where you freely come up with ideas without judgement and then there is the sober stage where you pick one of the ideas and start to flesh it out. These two stages are completely different contexts, and switching between them incurs some overhead cost. Knowing when to switch is an important part of being creative.

With this process, the skill of creativity is to recognize a good idea through a process of selection. You become sort of like a music critic rummaging through recently released albums trying to find something to recommend to your readers. Sometimes a great piece of music won’t just jump out at you. Some of my favorite albums required multiple listenings for me to appreciate them. Many good ideas will challenge you to find their value. These tend to be the best ideas though, because if it were obvious, then everybody would be doing it already.

This selection process must be done sober. One of the problems with actually getting drunk is that drunk people make really bad decisions when it comes to selecting something to act on. I think we’ve all had that experience.

Applications to Programming

Since my craft is computer programming, I’ve thought about this quote in the context of what I do. Write drunk edit sober works for writing code too. When you first start on a project, none of the rules for best practices are practical. They just get in the way and slow you down. I make big ugly monoliths, write giant functions, hardcode everything, copy and paste big swaths of code around, and all the other stuff they teach you not to do the first day on the job. I can write code really quickly and efficiently this way because I’m self-taught and this is exactly what I did for the first few years and nobody told me any differently. I made some really beautiful disasters like this.

These days, nobody ever sees my code in this state because after I’ve gotten something basically working, only then do I clean it up and make into something pretty. After it works and all the details are in place, cleaning things up becomes really easy. The abstractions are neat and pretty because they were made at the last minute by necessity, not up front because of a guess. None of the cruft survives the editing process. Anything I show to anyone has probably been rewritten three or four times just by drunkenly iterating through bad ideas and then polishing up whatever is left.

I really wish language designers would take my workflow into account by providing me with tools to support both stages of work. I think we can split up programming languages (and frameworks) into those that are drunk and those that are sober.

Drunk Languages

  • JavaScript
  • Python
  • C
  • Scala

Sober Languages

  • Rust
  • Java
  • Go

The problem with this dichotomy is that it is very hard to write sober code in a drunk language and it’s very hard to write drunk code in a sober language. This is my main problem with Rust how it is right now. It’s extremely hard to drunkenly iterate with Rust code because it forces you to deal with a bunch of details you aren’t prepared to think about. In Rust, your code won’t even compile unless it’s guaranteed to be thread safe, has no memory leaks, and a lot of other things. Once you actually get your code to compile, it tends to be extremely reliable and safe. But your abstractions are going to be weird because it’s so painful to try new things without slogging through a bunch of details first.

A language like JavaScript has the opposite problem. Writing drunk code is really easy because there aren’t many rules. But cleaning it up after is very hard because your code doesn’t have a lot of enforcable structure to it. Anything can be anything at any time, which is very liberating in the first stage because it gives you a lot of flexibility, but becomes infuriating when you realize it’s nearly impossible to finish a big project cleanly. I’ve heard a lot of people complain about this when their Node projects ultimately become unmanagable when the structure becomes difficult to reason about.

I really wish someone would make a language that did both of these things well.

So I think the things we can learn from this quote are 1) don’t judge your ideas too early and 2) design your APIs for both stages of the development process.

Happy coding and please drink responsibly.