Archive

Unpub 8 First Thoughts

A week ago, I was excited—but terrified—to attend Unpub 8, my first gaming convention as a game designer. Now, a goal I thought might be unreachable has become Plan B, and a goal I never would have considered is directly within reach.

While in the midst of 31.5 hours (😱) of travel out to Baltimore, I ran out of the patience required to listen to Yet Another Podcast, switched to music, and tried my best to let my brain rest in the middle of all that stress and anxiety. Now traveling westward again, I fired up the interrupted podcast, a sermon from Chris Eltrich of Lettered Streets Covenant Church where Chris shared the following:

Isn't that often the way things are in your life? Jesus comes to us by surprise. We think we know so well what our life is going to be like, what it should be like, and then out of the blue something beyond our control surprises us; forces us to respond to new information, to new circumstances, to new reality.

I'm overwhelmed with how timely and relevant that statement has become. I'll share more specifics as time moves on, but I'll leave you with this: God is good.

(Here is the rest of that sermon recording, in case you're interested.)

Learning Rust

I have this niggling feeling like I still haven't really "learned" Rust. I realized today that this feeling is wrong—I know enough Rust to build whatever I want, which should be the rubric anyone uses to decide they "know" something or not.

I know enough about cooking to prepare any dish I could imagine wanting to prepare—is that enough, or have I still not "learned" how to cook? (After about 10 years of persistent study, I finally feel comfortable saying "I can cook".)

It's so easy to get sucked into the games played by elitists who try to decide who's a "real" programmer and who's not. Who's a "real" Rust programmer? Ruby programmer? JavaScript programmer? CSS programmer? Does it matter?

I've decided I don't want to "learn" something for the label. I know enough. I know Rust.

A note specific to Rust

What's made this transition (from "learning" to "learned") harder with Rust, I think, is that Rust has an intense learning curve up front, and then almost completely gets out of your way. Once you've learned how to tell the language your plan, it quickly gets out of the way, exposing nothing but the problem you're trying to solve. Because I'm using Rust to solve problems I've never solved before, part of my hesitation in saying that I know Rust is that I haven't completely finished those projects. I haven't finished those projects because I haven't solved those problems, not because I'm unfamiliar with the tools I'm using.

Most languages conflate the two, and I appreciate those that have designed Rust otherwise.

Science (Education) is Cool

Science is cool.

No, I don't mean that space is cool, though it is.

No, I don't mean that eclipses are cool, though they are.

No, what I mean is that when everyone else is losing their minds and staring at the sun until their eyes bleed, Googling "diy eclipse glasses", you can recall your "scientific knowledge" that pinhole cameras exist, and go build one in your backyard.

A picture of a hastily made pinhole camera out of a pizza box and some recycling bins.

Science (education) is cool because I've been trained to look at the world around me and realize that the tree in my backyard is really hundreds of pinhole cameras all at once, and that I can see the eclipse hundreds of times, simultaneously.

A picture of the image a tree's shadow made during the eclipse: many tiny images of the eclipsed sun.

The gift of science and the gift of science educators is wonderful because it allows me, not a "scientist", to sit in my science-riddled backyard and enjoy my science-riddled coffee while I experience something uniquely science-riddled and once-in-a-lifetime like a solar eclipse.

Thank you, science teachers.

A picture of the image I got from my pinhole camera of the eclipse.

Creation & Consumption

Kiddo,

Every philosophical discussion with my father includes the following tenet: the subject at hand is really on a pendulum, with each generation destined to rebel and choose the opposite of their parents. Any hope of progressiveness, therefore, is nothing more than rebellion rationalized.

This is not about that tenet or my issues with it. I will, however, borrow it for a moment.

Creation and consumption delimit a similar pendulum—albeit one that swings a bit faster. On one hand, productivity and sharing one's voice. On the other, information and connecting to others'. On the whole, binge-and-bust cycles throw this pendulum back and forth as creators burn out and consumers burn with regret. As with most such pendulums, I can't help but feel like balance must exist somewhere in the middle.

Both creation and consumption are tempting forces easy to rationalize: both "productivity" and "knowledge" (not to mention those seen as "productive" or "knowledgeable") have become worshipped as Gods of the Secular World. Listicles abound of the best ways and places to accomplish or learn more, from the shiniest new tools to the sexiest new podcast. If we just keep adding more weight to the pendulum, surely our cycles of regret, jealousy, and fatigue will be assuaged.

For how many of us is that true? How many of us have found peace and balance by adding more, whether to our to-do list or our inbox?

If we prune away those forms of creation and consumption that are not edifying, not life-giving, we give more space to those that remain to flourish. Each book not read gives the next book more room to grow in our mind. Each project not started leaves the next project more time to be nourished and to nourish us. With enough intention and attention, this pruning will alleviate enough pressure from the pendulum that, though it may swing from time to time, the violence of the swinging will be eased, and the nausea of our hearts likewise.

If we cannot see the sources of creation and consumption in our life, how do we know where to prune? Though it may seem strange at first, we need to take stock of these hidden (or neglected) drains on our time and energy.

This is a far-from-comprehensive list:

  • Friendship — Friendships take time and energy. When each individual provides that time and energy, friendships are inimitable gifts. For how many of your relationships are you always the instigator, or always the follower? Though it may be hard to admit, what does that say about your relationship? Do you actually care about this person? Do they actually care about you?

  • Chores — We all have to eat and dirty clothes do not, with today's technology, clean themselves. It is tempting, however, to so strongly desire food and to loathe laundry that we spend time and energy improving these chores: their process or their product. Do you enjoy trying to shave seconds off of a daily chore routine? Will you still be this excited about kombucha a year from now?

  • Fashion — Fashion is a source of both creation and consumption in our lives, tempting us with dual heads and salacious messages of false beauty and false connection. Feeling confident in your own skin (or second skin) is important, but felling self-important about what brand your wearing (that someone else owns) or how "in" your clothes are (by someone else's definition) is toxic. Would you rather toe the Fifth Avenue line, or build your own persona around a single piece of clothing? Should your "image" change every week, or never?

  • Children — Children take a unique place on this list, in that they shift around on this scale. Newborns make poor conversationalists, requiring you to provide both sides of any discussion you intend to have with them. As kids grow older, however (whether they're yours or not), they transition from sinks of time and energy to well-springs of curiosity.

    Children (and mentees, and younger peers, and …) are also unique among this list in that you may not practically have a choice in whether they require you to invest your time or energy. What would you prune away to enjoy the time you spend with your kids? Would you stop out-delivering your co-workers if it meant you could compassionately mentor those that need it?

  • Meditation — Whether you think of it as your subconscious, the Holy Spirit, or an amorphous, anonymous power pervading the Universe, meditation (or prayer) is an often-deprived form of intense and intentional consumption. Intuition and introspection are powerful, quiet forces the abusers in our lives (ourselves often included) work to drown out. Would you stop reading poetry if it meant better connecting to your own sense of self? Would you start reading poetry if it meant discovering yourself anew?

  • Little imagination is required to continue this list ad nauseum: video games, substances, open source software, home renovations, email, music recommendations, adult kickball leagues, and so forth.

There are no right answers to these questions, but we wrong ourselves by never asking them in the first place. What would you create if you consumed less? What would you learn if you built less? What would you experience if you did less?

P.S. A note about social media

I know it's "hip" to be dropping Twitter these days, (for Mastodon, I guess?) but I will miss Twitter while I'm away. I may still post (a superficial form of creation), but I won't be following my normal routine of reading.

What hurts most about this scenario is knowing that I'm effectively leaving behind a group of people I only see through this form of consumption. Whether I've "met" them or not (for anyone's definition), I've become fond of people like Rami Ismail, Tim Keller, and Gary Bernhardt to whom Twitter is my primary connection. Though it may be a superficial connection, similar have led to my meeting, helping, and bringing into community others before.

Maybe, just maybe, by the time I come back it won't be so thoroughly filled with dangerously inept politicians and eggs.

On-Air: Better Coworking at Home

TL;DR: I made a thing! When my Mac camera is on (presumably because I'm in a meeting), an "On Air" light turns on. This should make co-working at home (between a software engineer and a domestic engineer) much easier.

My home "office" is current co-located with our bedroom. On multiple occasions this week alone, my wife poked her head in during a video call, sheepishly closing the door after discovering me in my mid-morning standup.

This week was different: rather than continuing to chuckle each time it happens, I decided to make use of the growing pile of microcontrollers on my desk and make an Internet-connected "on-air" light.

The microcontroller I chose is the Electric Imp (specifically the imp001). I first considered a custom build with an April board, but decided to use the Hannah instead and build a custom case instead (the unused knob is a bit of an eyesore, but it's significantly easier this way). One cardboard box, a pair of scissors, and some masking tape later, and I had my case. I made a little window in the box for the RGB LED to shine through, covering up the window with a small piece of paper with "ON AIR" written on it.

Since I used an Imp, I took advantage of their excellent community and grabbed some code for the I2C and IO Extender from GitHub, and the rest of the Agent/Device code was incredibly simple. In the end, I had a single URL I could hit to turn the LED on and off: agent.electricimp.com/DEVICE_ID?led=$STATE. This was my original goal: to be able to turn the light on and off from my desk.

Fortunately, that evening was the monthly Bellingham Codes meetup. Talking about my little project with the group, another attendee had a great idea: even if writing plugins for each video conferencing platform would be overly complicated, I could write a script to detect if the camera is in use, and trigger the light entirely based on that.

My first instinct to check camera state was Objective-C, and I spent a few hours to that effect. As it turns out, using a generalized search engine to find sample Obj-C code for detecting the camera state was impossible. Browsing StackOverflow directly, less so. However, I discovered something even better: other solutions to the same problem. While browsing the osx tag, I found this post discussing Chrome's use of the camera. It turns out the camera device shows up via lsof, so I had my hook.

I published the resulting code on GitHub, though it is certainly Mac-only. Let me know what you think!

Keep Schoon Bearded: Recap

In short, "Keep Schoon Bearded" was wonderfully successful. We raised $300 for local missions, forcing me to keep a loofah permanently fixed to my face until Christmas morning—including the initial No-Shave November period, that makes 54 days of Bearded Schoon.

While thinking through the results, I'm led to consider whether I would do this again. Should I do it next year? Should I do this every year? Are there better ways to raise money like this?

If I grow a beard for charity again, I imagine I'd take the same tack as Movember, and make it a group effort. I'm sure I'm not the only developer who loathes both facial hair and the "joke" that we look homeless once it threatens to take over our visage.

I'm considering other charitable ventures, such as a private, catered dinner. While I'm not a professional chef by any means, I have a heart for hospitality, and would be overjoyed to fill my backyard with hungry guests in the stunning Bellingham summer weather, a steady stream of culinary delights pouring out of the house. The margins aren't as good as "do nothing, and let your body do what it wants", so I would only pursue this if the overall revenue would be more significant.

For now, however, I'm content with the success. I set out to raise a little money, and have a little fun at my own expense. With checks cut—and cheeks shaved—that's good enough for now.

Keep Schoon Bearded

TL;DR: Donate here to keep me bearded.

If you need positive motivation, donations help alleviate homelessness in my community. If you need negative motivation, this beard is really itchy.

The RND Stack

Last week, ZEIT released a new framework for Universal React applications: Next.js. Unlike previous attempts, Next provides a complete solution for rendering and routing React applications in a single dependency (transitive dependencies notwitstanding, of course). No amount of configuration is required for Webpack, or Babel, or React itself. Furthermore, no convention is imposed on React beyond the way Next.js handles routing. It's an incredibly elegant solution.

On its first day of release, developers piled onto Guillermo, one of the creators of Next.js, to add custom server-side logic. While this will no doubt be a useful feature, I think it continues to miss the point: this is an opportunity to cleanly separate concerns between services, with technologies to match. The advantage of "Universal JavaScript" is not the opportunity to run our UI rendering alongside our business logic. Instead, it is the opportunity for UI Engineering to take complete advantage of the server independent of the business logic.

In short, Next.js is the ideal "front layer" (also referred to as the "presentation layer") solution. [For more discussion of what that entails, see here and here.]

What should we use for business logic and communicating with the database, then? Rails.

Where the front layer can benefit from "just enough" flexibility as provided by Next.js, API tiers are best served by convention. Where the front layer can take risks and dodge the rigor of test coverage (though React and Redux benefit from their rich testing story), the API tier is the primary line of defense against data corruption, leakage, and loss. Rails remains a mature solution in this domain; I know no comprehensive argument that it's done anything but continue to prove this to be true.

Not to leave out some of the nuanced practicalities of these suggestions, I propose the name "RND Stack" for two reasons:

  • This is a stack to start with. The best stack for your application is the one that's already providing value, but the zero-to-sixty story of both Next and Rails is more than sufficient for an expedient start to any project. Where better to do R'n'D than on the RND Stack?
  • The D: Docker. The biggest operational risk to splitting resources across Rails and Node is the deployment environment, whether local or remote. On one hand, maintaining two complete environments (runtimes, OS dependencies, etc.) is a nightmare. On the other, Docker (or any imaging solution) provides a better byte-for-byte identity guarantee than either Gemfile.lock or npm-shrinkwrap.json. On a foot, Docker brings with it a rich suite of tooling for orchestration and management: Terraform, Triton, Kubernetes, etc.

Interested? Let me know. Next up, assuming there's interest? Demo.

Living a Limited Life

Kiddo,

Life has limits. You will try to break them, as I have, but they will catch up with you.

Life has limits. Even though God may be limitless, we are called to live within those limits and be Sabbath people.

Life has limits. I pray that will learn this lesson quicker than I have, as I have wasted more time than I care to recount trying to deny these limits, rather than embracing them and living a full life.

Life has limits. Those limits are, indeed, life-giving: God gave us those limits so that we would prune away those things in our lives that spoil and cultivate those things that edify.

Mental Health First

In Why I Follow Who I Follow, I gave a list I try to follow when building my Twitter Timeline:

  • Challenge my assumptions
  • Broaden my perspective
  • Check my privilege
  • Help my growth
  • Brighten my day
  • Empower my faith
  • Improve my profession

While this has been true for quite some time, I need to add an addendum: I will follow as much of that list as I can as long as I have the mental headroom to internalize and do something with that information.

At times, that means culling below that bar.

I can be hard on myself, but my mental health needs to come first. From that comes my physical health, the health of my marriage, the health of my family, the health of my career, you name it. It's hard for me, but some times I have to slow down.

Maybe I need to look at my list of projects, too...

JSON API in 5 Minutes

This is a Resource (from http://jsonapi.org/examples/):

{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!",
      "body": "The shortest article. Ever.",
      "created": "2015-05-22T14:56:29.000Z",
      "updated": "2015-05-22T14:56:28.000Z"
    },
    "relationships": {
      "author": {
        "data": {"id": "42", "type": "people"}
      }
    }
  }],
  "included": [
    {
      "type": "people",
      "id": "42",
      "attributes": {
        "name": "John",
        "age": 80,
        "gender": "male"
      }
    }
  ]
}

HTTP entities that contain a Resource do so with two top-level fields:

  • data - Contains the Resource itself (or an Array of such Resources)
  • included - Contains an Array of other Resources. In the above example, the included data is requested. Additionally, the server may include any unrequested Resources it wants.

Resources themselves have four top-level fields:

  • type - A namespace of sorts for all similar Resources, represented as a String. Example: "widgets"
  • id - An identifier unique to its namespace, represented as a String. Example: "42"
  • attributes - Any properties specific to this Resource, represented as an Object. Example: { "name": "Best Widget Ever" }
  • relationships - Links from this Resource to all related Resources, represented as an Object. Each of these values should be a Resource Identifier, an Array of Resource Identifiers, or null. Example: { "brand": { "type": "companies", "id": "Initech" } }.

Resource Identifiers are, as their name implies, only the identifying properties of a Resource: type and id.

Routes

  • You can fetch a resource with a GET request, which will return the complete Resource as described above. Example: GET /widgets
  • You can create a resource with a POST request, which should include the complete Resource being created in the request body. Example: POST /widgets
  • You can update a resource with a PATCH request, which should include only the attributes and relationships that should be updated, using the structure described above for HTTP entities containing Resources. Example: PATCH /widgets/42
  • You can remove a resource with a DELETE request. Example: DELETE /widgets/42
  • You can replace a relationship with a PATCH request, which should include the entire relationship being replaced (e.g. a Resource Identifier, an Array of Resource Identifiers, or null) under a data field. Example: PATCH /widgets/42/brand
  • You can append to a one-to-many relationship with a POST request, which should include the relationship(s) being appended (e.g. a Resource Identifier or an Array of Resource Identifiers) under a data field. Example: POST /widgets/42/parts
  • You can remove from a one-to-many relationship with a DELETE request, which should include the relationship(s) being removed (e.g. a Resource Identifier or an Array of Resource Identifiers) under a data field. Example: DELETE /widgets/42/parts

Further Reading

Obviously this just skims the surface of what JSON API is, even going so far as to assume you already know why JSON API is a good idea, or how you would go about making that judgement for yourself.

While I understand that the official documentation contains very precise, technical writing, I cannot overstate how valuable that documentation is for understanding the standard.

As for the "why" of things, I'll echo their supposition that JSON API is a valueable anti-bikeshedding tool; this standard is what most teams work toward when they roll their own API design, and few teams ever make it. Starting from a worked standard like JSON API foregoes this process, enabling teams to develop the model and business logic without worrying about PUT vs PATCH, where to put metadata on a route that returns a POJO, etc.

TL;DR: Go read the official spec.

Speaking Up

As I've tried to explain before, institutionalized patriarchy and institutionalized white supremacy provide men like Drumpf with a considerable deal of privilege (there's that word again).

On the surface, using "Drumpf" follows the same logic, albeit against the person granted power by those institutions, rather than against those persons marginalized by them. When you refer to a trans person by their deadname, you are deciding to refuse them the fullness of their personhood and their ability to self-identify. Since the deck is stacked in your favor to begin with, the institution agrees with your choice and they're marginalized even further.

On the flip side, referring to a liar, megalomaniac, and terrorist by the name they've chosen to leave behind (for a word that means "in a class above all others", no less) is a similar attempt to pull the same wind out of their own sails. Since the institution favors them in this matter, however, it has little effect: at its worst, this negative feedback loop normalizes the effects of the institution at large, providing equitability of discourse in the general.

James calls out this exact imbalance in chapter 2, verse 6 of his letter: "But you have dishonored the poor man. Are not the rich the ones who oppress you, and the ones who drag you into court?" (ESV, context: esv.to/jas2:6) The word here is "katadunasteuo", which Strong defines as "to exercise harsh control over one, to use one's power against one, or to oppress one". What power (even "riches") we as cis, white men yield today!

While this is more of my own heart than I typically share over social media, silence is no longer an option. Too many of our marginalized brothers and sisters are being threatened, attacked, and even killed here and abroad because those given privilege by institutions refuse to speak up on their behalf. It's often hard to speak out, but society at large is on our side and will hear us out just as it ignores those beneath its feet.

Whether you agree with me or my methods (or my faith), I implore you to at least meditate on and consider how you and I might "correct oppression" (Is 1:17 ESV, esv.to/is1:17) and bring a little more shalom to this world.

God bless you.

Growing Up Gamer

Today's my birthday.

Without a doubt I'll wind up spending it, for the most part, like any other day: working, having lunch with people I love, occasionally flipping through Twitter to see what awful thing is going on for the rest of the world today. And, like any other day, those awful things include the harassment of anyone not simultaneously white, male, and cisgendered for simply existing and having an opinion. This is even worse in the industry I miss to this day being involved in, as female employees of Nintendo in specific and game development in general become the target of harassment for bringing diversity into this "sacred", white-boy-serving medium.

This got me thinking about the following dynamic:

  1. I grew up a gamer.
  2. My parents thought I'd "grow out of it", but that never happened.
  3. I grew up.
  4. I got a job, and can afford, for the most part, to buy any game I want whenever I want—one of many privileges I've been afforded, I guess.
  5. I have less time and patience for games, so I buy fewer of them, not more.
  6. I start to choose game purchases because of the people responsible for them as much as for the content of the game itself.
  7. I had two children.
  8. I only buy games I want to be proud of playing today, prouder still to someday share with my kids.

And that leads me back to the present day:

  1. I don't buy games that objectify anyone, especially those already oppressed due to their gender, race, ethnicity, etc. (It's not satire, it's not art, it's active oppression.)
  2. I don't buy games from Nintendo.
  3. I don't buy games.

I'm 100% sure GamerGate and its ilk don't care. Good.

I'm 100% sure Nintendo doesn't care. Fine.

I'm 100% sure nobody cares about this but me, but I'm 100% sure I'm not alone in my conclusions.

As such, game companies need to adjust if they want our money: more and more gamers are growing up, and we just don't have the time or the patience to deal with their childish, insecure shenanigans anymore. You stand up for what's right, or I spend this money on the other million-and-one things demanding my time and attention. I lose no sleep over missing out on the latest over-sexualized garbage from You-Name-It Studios. On the contrary, not wasting my time with the latest oppressive tire fire means I get specifically to spend more time in bed with my wife instead of on the couch, controller in hand.

So if you'll excuse me, I'll be in the yard chasing my kids. Call me if the industry grows up, too.


P.S. This is purposefully hyperbolic, but less than you'd want or imagine. That said, I know that against all odds, those who don't look like the cast of Indie Game: The Movie have managed to bring to market wonderful, diverse, important art and I love and appreciate every one of them for it more than they'll ever know.

Standards Wanted: Yelp

Earlier today I received another link through another concerned individual to another person fired from Yelp for being human and having human needs. The corporate culture at Yelp clearly values departmental and tribal performance over individual well-being, and it shows in the ways its middle management treats their staff: you're "putting them in a tough spot" when you decide on priorities higher than the tasks they put before you.

We can and should hold companies to higher standards.

Yelp has what's known as a "two-sided market". As a startup, this would have even been referred to as their "two-sided market problem": they need users to get businesses on board, and they need relevant data from businesses to get and "retain" users. The only way they make money is by selling those users to their true customers: those same businesses.

Today, Yelp has "solved" this problem. They're a pervasive influence in the restaurant industry: a pied piper for all the "foodies" (read: would-be food critics that scathe anything outside of their limited worldview) nationwide. They're now publicly traded on the NYSE, and as of right now they seem to be rising slowly to around $20.50 a share (though their cash flow seems to be in the red – big surprise there).

As we all should know by now, this is by no means a permanent position.

As it turns out, individual users have a lot of power over these same platforms in how they choose to spend their time and share their personal information. Every piece of information you share on Facebook and Twitter further strengthens their position, entrenching them in the overall sphere of "social media". So it goes with Yelp and the industry of gleaning values from those that spend countless hours contributing to their database of reviews and ratings. The inverse is true as well: enough users discontinuing use of Yelp in lieu of the growing list of alternatives (even for other monopolies like Apple and Google) is the strongest motivating force for such a lifeless juggernaut.

That's a good enough argument for me. I'm not sure I'll miss the foodies anyway.

Wat's Going On?

A quick, 5-minute video explaining the JavaScript portions of Gary Bernhardt's infamous "Wat" talk.

Why I Follow Who I Follow (on Twitter)

TL;DR: If I follow you on Twitter, I find what you say important for me to hear. If I don't follow you on Twitter, that means almost nothing, and you should not take that personally. For all you know, I may consider you one of my closest friends.

For all intents and purposes, I use Twitter incorrectly: I read every post, often scrutinizing the nuances involved and the ways in which this post might challenge one of my assumptions. Because of this method I might invest more of my time on Twitter considering a single idea than most people seem to spend on a single visit. Twitter is more than a social network: it has become a tool of my profession, and it remains a part of my daily work to invest in that network.

Currently, however, I am drowning under waves of rich debate.

Rich debate? On Twitter? Yes. It's there, if you're willing to follow the right people. Consider a conversation between Michael Jackson and Marco Rogers: Marco called Michael out publicly for posing a naïve question from a position of relative privilege, and the two struggled with the situation for the better part of a day. While I hope both men grew from the encounter, I know I did, and I'm sure other third parties did, too. (For posterity, here is the "offending" post and Marco's considered response.)

Unless I want to spend all of my time reading thoughts and conversations like these and no time contributing my own ideas, I need to be a little ruthless, culling my list of follows down dramatically. I've thought about going "write-only" (only posting, never reading), and I know that works for some, but the growth begotten by that nuance and debate remains important to me. As a result, I need to ensure I follow a group of people that, together:

  • Challenge my assumptions
  • Broaden my perspective
  • Check my privilege
  • Help my growth
  • Brighten my day
  • Empower my faith
  • Improve my profession

These are co-dependent needs, and I hope to discover a group of people that can (whether they know this or not) meet these needs with me while reducing the cognitive burden of keeping up with all the nuance and debate Twitter users present on a daily basis.

Addendum: The "Do you know them?" Challenge

My wife once asked me that question, and I challenged myself to be able to answer "yes" by meeting everyone on my Twitter follows in the real world. While I still look forward to seeking out a few more people I've "met" through Twitter, I expect I'll wind up following far fewer people on that list, from celebrities like Wil Wheaton, Chris Kluwe, and Kenji Lopez-Alt to "normal folk" like Fabian Giesen, Caitie McCaffrey, and Kelly Sommers.

That said, far more unfollows will be people I do know and have already met, and that's hard.

SSH-Agent and Windows

During my day job I use a Windows laptop to make working with a number of .NET projects easier. That said, I've not completely abandoned Node as a platform, nor do I wish to leave Bash behind. Ergo, I wind up using msysgit to emulate a Bash-like environment for Windows. To make things even easier, I use ConEmu to provide a tabbed interface around msysgit. The final piece of the problem is that I have multiple git accounts with their own SSH key (one GitHub for Enterprise, and one Github), and each of these keys has a passphrase.

The naive approach is to just add eval $(ssh-agent -s) to the top of my .bashrc file. The Problem is that this requires a separate ssh-add call for every tab, requiring me to enter my passphrase in every tab. This pretty-well defeats any ease-of-use I was originally looking for.

Screenshake on Tweet

A fun little bookmarklet I made for @tha_rami and @legobutts. It applies screenshake to Twitter every time you press the Tweet button.

Geographical Closure

Kiddo,

It was a strange feeling to return to the world I grew up in. After several episodes of completely leaving my world and moving to a new one, taking such a large step backward was anathema to such an extreme defense mechanism. I know I left these places behind to try and bury some version of myself along with it, so exhuming any portion of that past self seemed disagreeable at best.

Nevertheless, Carlisle is the place Jess fell in love with, and I can't argue with that.

Perfectly Imperfect Bash

A quick and dirty nerdy reflection on some Perfectly Imperfect Bash I just wrote while exploring the skip-worktree flag in Git:

git ls-files -v | grep 'S ' | xargs -n 1 git update-index --no-skip-worktree

To the uninitiated:

Motivation: "The Gap"

In a moment of Fantastic Inspiration, I was presented with an elegant solution to a problem so many makers have: motivation.

More specifically, a co-bootstrapper and friend was concerned that he felt unmotivated to come home after a day of programming and continue programming on our product. Coincidentally, I've been having motivational problems with my day job. In a random moment of inspiration, I decided to see if the motivational issues were the same, coining the issue itself "The Gap".

The Best Password Database: Your Mind

In the wake of Heartbleed, one particularly interesting side effect kept surfacing: users of Lastpass were encouraged to regenerate all "important" (read: All) passwords. 1Password, on the other hand, announced that they weren't affected. I think it's great that these password security options are promoting good practices. That said, OpenSSL's bug today is Agile's bug tomorrow. It's still software, and it's inevitable for it to become vulnerable someday.

My "Annual" Snowman, 2014 Edition

This is my "annual" snowman for 2014. He's about 7 feet tall; I'm slightly in front of him. His arms are a bit hard to see, but one goes out to his walking stick, and the other is raised to his left, waving to the passing cars.

Wipe that snow off your shoulder, Mr. Snowman.

Anatomy of a Schoon TODO

In its original Dutch, my nickname, Schoon, means "clean". Doubly-appropriate, perhaps, that my method of TODO comments be called a "Schoon TODO" by former colleagues. It's the cleanest I've seen.

Quick disclaimer, perhaps: I don't know this style to be unique, but I don't know it not to be unique. I've never verified either way, so I won't assert either to be true. Just take this as "the way I do things, and maybe that's helpful."

Overwhelming Uncertainty

Kiddo,

On a completely different track from my thoughts on Insufficient Uncertainty, today I'm fighting off Overwhelming Uncertainty. Michael Lopp, a.k.a. Rands, introduced me to the concept of "entropy surfing" through his Trickle Theory post. The post is worth a full read, but here's the ending from this well-written analysis of software development:

Remote Meeting Courtesies

With an increasing prevalence of meetings done over Skype, Hangouts, and similar, I feel that everyone (especially remote workers, but this isn't specific to folks who primarily work remotely) should know a few basic courtesies involved with this young form of interaction.

In decreasing order of importance:

  1. Mute yourself unless you are speaking. - I know you're being silent while on the call, and that's fantastic. The problem is that your computer is picking up the faintest sounds, amplifying them, and sending them to the server anyway. Unless you're actually trying to speak to the group, use the mute feature of the software. This always reduces the background noise of the call, even if you're not making any.

Insufficient Uncertainty

I've started working on a game with simultaneously-executed turns. It's meant to be as simple as possible: the first version only allowed for two decisions per turn with only four choices per decision.

Any time you iterate on a concept, you need to know where to iterate and why you're iterating there. Do it scientifically: build a theory, make a related change, make a measurement, and check your theory. This game wasn't fun at first (just reading the sentence above might make that obvious), so I needed to iterate. Time for that theory.

Unit Testing over SMB in Visual Studio

Situation

Though I've recently upgraded computers, my old Drobo is still attached to the old machine, shared through Windows (SMB) with the new machine. I've been working on getting CS-RESP wrapped up in support of a Unity project, and wanted to start testing it.

Problem

After reading all the MSDN documentation I could on using the Test Explorer, I could not get the tests load for the life of me. I tried writing the test classes by hand, deleting them and generating a second time, restarting, you name it. Though common error cases were diligently called out on MSDN, my problem was not. Test Explorer remained empty, and I had no way of running my tests. Even Assert.AreEqual(1, 2); was passing...

Silicon Valley's "Meritocracy"

Kiddo,

I can't find the Tweet anymore, but I know someone from my network (I think it was @raganwald) posted something to the effect of:

Silicon Valley is a meritocracy for sufficiently cronyistic values of "meritocracy".

That phrase has stuck with me since, mostly because it explains one of several issues I had with Silicon Valley. Silicon Valley's barrier of entry rivals that of AAA game development, and every AAA game development job on the planet is either a dead end or it requires a shipped title. Good luck jumping that one.

Cross-Country Road Trip

Kiddo,

Growing up in an era when flying is cheaper, safer, and easier than alternative transportation methods, I've never before had the occasion or opportunity to partake in a cross-country road trip. This means that at less than a year old you've joined in something I've missed out on for twenty-seven years.

It's been epic:

Old Friends, New Places

Kiddo,

An Old Friend is such a wonderful, rare sight in my life. Not that I'm opposed to making friends with the elderly, but I assume that you can assume that I'm not referring to the old and wise; rather, I'm referring to those friends I haven't seen "in a while".

Thoughts on Git

A few thoughts on Git workflows:

  • I tend to prefer simple, low-friction workflows in general, but this is amplified greatly for Git. In my experience, complex wastes time, whether in the form of continual education to newcomers (who can't self-educate due to its complexity) or fixing problems that arise (due to the almost certain fragility that joins complexity in the fun). For this reason I've regularly attempted (and usually succeeded) to instill a workflow closer to GitHub than git-flow. Check out those links to see the differences for yourself. One simple difference is that git-flow all but requires its own tooling to manage the complexity. GitHub's simpler flow is just branching.

Deploying Wordpress to Openshift

Even though I have moved to Jekyll for this blog, Wordpress remains an extremely powerful and user-friendly blogging engine. If it weren't for its PHP nature, I'd probably still be using it. But I digress. While most of my in-development Node apps run on Heroku, for my latest Wordpress project I decided to give OpenShift a try. (My decision may have been influenced by working with ex-Makara and ex-RedHat folks at [StrongLoop][ls], but they didn't solicit this post.)

OpenShift provides an example Wordpress project this method relies heavily on, but I wanted to diverge from this method by managing the Wordpress code as a separate Git repository. That is, the OpenShift app server is the only remote for any OpenShift-specific code, and GitHub provides the remote for everything else: Wordpress core, plugins, themes, etc.

Commentary on a Pull Request

Open source projects thrive on the existence of active contributors. The best contributors, typically leading to the best projects, are those using the software in question to solve real, interesting problems with the software while running into either insufficiencies in its feature set or bugs with the existing features. The process follows that these same good programmers, rather than simply complain about the issue they face, dig into the source code they've been freely given in an effort to solve these issues themselves. Since these are grateful, effective programmers, they decide to give back to the community at large, submitting a pull request (or similar); should the matriarchs and patriarchs of the microcosm around the open source project agree with the solution presented, it becomes law, folded into the rest of the software, ready to be distributed to its users lest they face the same issue.

Sublime & GitHub

TL;DR

My Sublime Text User settings are now on GitHub. View the README for further instruction.

Why?

Why Sublime? Because it makes my day (which is spent predominantly reading and editing code) so much easier. Why store my personal settings on GitHub? Much better question:

Getting Started with ZeroMQ

A surprisingly frequent topic of discussion with me is ZeroMQ, especially regarding how to get started using ZeroMQ. Along with that usually comes some desire for starting into distributed systems architecture, programming, or the like.

I cannot recommend The Guide enough. It's well-written, topical, and (most importantly) enjoyable.

"Welcome to Jekyll!"

UPDATE: I'm not longer using Jekyll, but static site generation remains my jam.

Why thank you, Jekyll. I certainly feel welcome.

After using both Wordpress and home-rolled solutions, I've decided to switch to Jekyll, a "blog-aware" static site generator. With Nodepaper, I decided to move away from a db-based CMS to one based on flat Markdown files. I agree with the makers of Jekyll that it's backward, and I, too, have lost a lot of content from bad hosts.

So it's on to Jekyll and Github Pages, and I'm enjoying the process so far. The idea that a new theme or theme inspiration is just a fork away is exciting. That a correction or comment can be made by Issue (or even a Pull Request) seems ideal and forward-thinking.

Jekyll is not for everyone; it's for makers.

Field notes

  • Jekyll could use a jekyll add command (or similar) to start a new blog post. Not that it's hard to run subl `date "+%Y-%m-%d"`-some-title.md, but I prefer not to make choices (like what key to press) when the answers are obvious (See: game design). I'll update if I can learn enough Ruby to submit a pull request.
  • jekyll serve --watch doesn't provide a lot of information about formatting errors, which is ironic as it's intended to be used during development. While you don't want a big, fat stack trace every time you save if you save as often as I do, it is inconvenient (if minorly so) to have to restart the server to get the stack traces you do want.
  • Maruku is the default Markdown processor. I'm not a Ruby programmer, but I understand RDiscount to be better. It should probably be the default, as it produces far better output based on the kind of Markdown I write.

The Pebble & I

My phone and I have had a touch-and-go relationship ever since we met. I hated when it would interrupt my life, so I would leave it on my desk or otherwise out of sight; I'm away from my desk enough that those trying to reach me had difficulty doing so, and I would hate that, too. There seemed to be no middle ground:

  • If the phone is ringing, it needs to be loud to be consistently heard, making it innevitably interrupting.
  • If the phone is on silent, I'll never hear it, making me unacceptably unreachable.
  • If the phone is on vibrate and in my pocket, it's close, but unreliable. But maybe that's something.

Enter Pebble

The Pebble is a smartwatch that connects to my Galaxy Nexus via Bluetooth, and my phone can send it notifications and receive basic input for everything from Phone and Messaging to Spotify and Calendar. I'd found my middle ground.

How I make the most of it

To really capitalize on this, my phone is set to Silent permanently, and I configured the Pebble to receive all available notification types. Aside from the occasional loss of connection1:

  1. Notifications are extremely reliable. I know people can reach me.
  2. I never have to check my phone. See #1.
  3. If I can hear the notification sound, it's not my phone. (For instance, when I'm at home I know it's for my wife, not me. With three Nexus devices, that got confusing.) See #2.
  4. The vibrate is subtle enough that most people don't seem to notice or care. A quick glance to my watch and I can tell if it's urgent.

1 I guarantee this will improve. Pebble isn't even done shipping pre-orders, and the only bug in the connection has to do with the Android client app not tearing down the Bluetooth connection completely when it loses it. It's a really quick fix - just twiddle the Bluetooth on your phone Off-On, and the connection will be reestablished immediately. The process should take 5 seconds tops on a 4.x Android phone, as the Bluetooth settings are available via the shortcut in the Notification Tray.