<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blog on Justin Abrahms</title><link>https://justin.abrah.ms/blog/</link><description>Recent content in Blog on Justin Abrahms</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Mon, 09 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://justin.abrah.ms/blog/rss.xml" rel="self" type="application/rss+xml"/><item><title>Scaling at the mediumest company: half-measures save the day</title><link>https://justin.abrah.ms/blog/2026-03-09-scaling-at-the-mediumest-company-half-measures-save-the-day.html</link><pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-03-09-scaling-at-the-mediumest-company-half-measures-save-the-day.html</guid><description>&lt;p&gt;I&amp;rsquo;ve worked for globocorps like Amazon, eBay, Walmart and Google. I&amp;rsquo;ve worked for startups you&amp;rsquo;ve certainly never heard of.. but nothing in between. Thrive Market, an online grocer, is the mediumest company I&amp;rsquo;ve ever worked for. This company was my very first experience with &amp;ldquo;medium company problems&amp;rdquo;. At a startup, efficiency numbers largely don&amp;rsquo;t matter. At massive companies, all of the low hanging fruit has been picked. Medium company problems are when you&amp;rsquo;ve got enough scale for it to hurt, but not enough investment for anyone to have looked.&lt;/p&gt;</description></item><item><title>On MCPs vs CLIs</title><link>https://justin.abrah.ms/blog/2026-03-07-on-mcps-vs-clis.html</link><pubDate>Sat, 07 Mar 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-03-07-on-mcps-vs-clis.html</guid><description>&lt;p&gt;MCPs (Model Context Protocol servers) are services that expose tools for LLMs to use. CLIs (Command Line Interfaces) are shell utilities that programmers use to interact with a tool without using something like a website. Both of these tools are available to many agentic LLMs like Claude Code. Which should you pick?&lt;/p&gt;
&lt;p&gt;My take on this is that you should nearly always prefer a CLI.&lt;/p&gt;
&lt;h2 id="mcp" class="heading-anchor"&gt;MCP&lt;a href="#mcp" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;There are three benefits to using an MCP: auth, updates, and preconfiguration.&lt;/p&gt;</description></item><item><title>CI Theater: we deleted our flaky tests and nothing broke</title><link>https://justin.abrah.ms/blog/2026-02-26-ci-theater-we-deleted-our-flaky-tests-and-nothing-broke.html</link><pubDate>Thu, 26 Feb 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-02-26-ci-theater-we-deleted-our-flaky-tests-and-nothing-broke.html</guid><description>&lt;h1 id="the-problem" class="heading-anchor"&gt;The problem&lt;a href="#the-problem" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;At Thrive Market in 2024, we had ~150 flaky tests and a 76% deploy success rate. This meant that one in four deploys failed. Not because the code was wrong, but because the pipeline couldn&amp;rsquo;t be trusted.&lt;/p&gt;
&lt;p&gt;A one line code review took two days to land. Engineers were watching CI fail over and over and retrying ad nauseam. Ephemeral PR environments took 30 minutes to spin up, sometimes requiring 4 retries before they were green. This applied to both the frontend and backend and folks were anguished. When asked &amp;ldquo;When was the last time these e2e tests caught an actual bug?&amp;rdquo; 80% of people answered &amp;ldquo;I know it&amp;rsquo;s happened, but I don&amp;rsquo;t remember when&amp;rdquo;.&lt;/p&gt;</description></item><item><title>Claws don't need to be complicated</title><link>https://justin.abrah.ms/blog/2026-02-21-claws-don-t-need-to-be-complicated.html</link><pubDate>Sat, 21 Feb 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-02-21-claws-don-t-need-to-be-complicated.html</guid><description>&lt;p&gt;Last weekend, I spent time setting up &lt;a href="https://github.com/openclaw/openclaw"&gt;OpenClaw&lt;/a&gt;. Within 4 hours, I had hit $20 in usage (thank you, spend caps!). It was clear that if I wanted to experiment with this type of software, my clanker would need to run within the bounds of subscription pricing.&lt;/p&gt;
&lt;p&gt;For the purpose of this post, I&amp;rsquo;ll refer to the software repo I&amp;rsquo;m using (&lt;code&gt;epiphyte&lt;/code&gt;) as &lt;a href="https://x.com/karpathy/status/2024987174077432126"&gt;my &amp;ldquo;claw&amp;rdquo;&lt;/a&gt; and the instance of that software with a set of memory/skills/identity as &lt;a href="https://x.com/steipete/status/2018012302730305573?s=20"&gt;my &amp;ldquo;clanker&amp;rdquo;&lt;/a&gt; (&lt;code&gt;briar&lt;/code&gt;).&lt;/p&gt;</description></item><item><title>How to diff a book against your mind</title><link>https://justin.abrah.ms/blog/2026-02-18-how-to-diff-a-book-against-your-mind.html</link><pubDate>Wed, 18 Feb 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-02-18-how-to-diff-a-book-against-your-mind.html</guid><description>&lt;p&gt;I was looking into &lt;a href="https://justin.abrah.ms/notes/Embeddings"&gt;embeddings&lt;/a&gt; recently and realized you can embed your personal knowledge base and a book’s sections/chapters/pages, then use &lt;a href="https://justin.abrah.ms/notes/Cosine-Similarity"&gt;cosine similarity&lt;/a&gt; to estimate what you’re likely to learn. &lt;code&gt;mindblown.gif&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The result is the ability to &lt;code&gt;diff&lt;/code&gt; a book against your current knowledge base. This lets you glance at a technical book and see whether you’ll learn something new, deepen your understanding of a topic, or if it’s simply review.&lt;/p&gt;
&lt;p&gt;It works like this: The book text is extracted page by page and chunked into 100–800 word segments, then labeled with the nearest table of contents entry so an unread book is still easy to contextualize. Personal notes under 500 words embed as a single chunk while larger ones are split on headings. Embeddings run locally via &lt;code&gt;sentence-transformers&lt;/code&gt;, and the tool compares each book chunk to my notes to classify it as novel, a depth gap, or review.&lt;/p&gt;</description></item><item><title>Announcing FRM, a CLI based CRM... 15 years in the making</title><link>https://justin.abrah.ms/blog/2026-02-17-frm-a-cli-based-crm-15-years-in-the-making.html</link><pubDate>Tue, 17 Feb 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-02-17-frm-a-cli-based-crm-15-years-in-the-making.html</guid><description>&lt;p&gt;When I lived in NYC, I frequented &lt;a href="https://hackandtell.org/"&gt;hack &amp;amp;&amp;amp; tell&lt;/a&gt;, a hackers&amp;rsquo; meetup where folks showed off side projects and generally were nerds with one another. During that time, I was trying to better understand how to show up for my friends and community. I came up with what some might call a technical solution to a social problem, but, after 15 years of reflection, I&amp;rsquo;d say it&amp;rsquo;s a bit closer to a cognitive prosthetic: &lt;strong&gt;FRM, the CRM for Friends&lt;/strong&gt;.&lt;/p&gt;</description></item><item><title>How to generate demo videos with playwright</title><link>https://justin.abrah.ms/blog/2026-02-12-generating-demo-videos-with-playwright.html</link><pubDate>Thu, 12 Feb 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-02-12-generating-demo-videos-with-playwright.html</guid><description>&lt;p&gt;I came across &lt;a href="https://x.com/oliverhenry/status/2022011925903667547"&gt;this post&lt;/a&gt; on social media about how a user was using OpenClaw to generate tiktok content for their iOS app automatically. This made me realize that we could be using LLMs to generate product demo videos of the features we work on.&lt;/p&gt;
&lt;p&gt;I worked with Claude in order to generate on for a &lt;a href="https://flagd.dev"&gt;flagd&lt;/a&gt; UI I was playing with, slapped some royalty free music on it and here was the result.&lt;/p&gt;</description></item><item><title>Recommended reviewers to build your council</title><link>https://justin.abrah.ms/blog/2026-02-06-recommended-reviewers-to-build-your-council.html</link><pubDate>Fri, 06 Feb 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-02-06-recommended-reviewers-to-build-your-council.html</guid><description>&lt;p&gt;There&amp;rsquo;s a common pattern of building up a council of reviewers and have them
debate a topic. The first ones of these I saw was the &lt;a href="https://deepwiki.com/OmarTheGrey/Council-Of-HAL"&gt;Council of
HAL&lt;/a&gt;. Following that, I&amp;rsquo;ve
seen similar things like with
&lt;a href="https://github.com/spencermarx/open-code-review"&gt;open-code-review&lt;/a&gt;, which will
bring up a panel of experts and have them debate, then synthesize the feedback
and write it into a PR.&lt;/p&gt;
&lt;p&gt;In doing some design doc review, I stumbled on a pattern I think is really
interesting: asking the robot for a recommendation of other colleagues who
might have good insights.&lt;/p&gt;</description></item><item><title>AI Doesn't Work Without Good Inputs (And Neither Do Humans)</title><link>https://justin.abrah.ms/blog/2026-01-27-ai-doesn-t-work-without-good-inputs-and-neither-do-humans.html</link><pubDate>Tue, 27 Jan 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-01-27-ai-doesn-t-work-without-good-inputs-and-neither-do-humans.html</guid><description>&lt;p&gt;AI skeptics complain about code which is verbose, overwrought, unmaintainable,
and misguided. In many specific instances, I&amp;rsquo;ve found that to be correct. The
problem to be solved isn&amp;rsquo;t higher ownership, more diligent human review or the
perfect &lt;code&gt;CLAUDE.md&lt;/code&gt; file. We need better control over the inputs if we want to
tighten the band of acceptable outputs.&lt;/p&gt;
&lt;p&gt;The core problem with LLMs going off the rails is ambiguity and complexity. LLMs
have better luck solving small, well defined problems when they have adequate
context. A lot of working with LLMs today is about scoping down those problems
or providing them that corrected context. These are not uniquely LLM
problems. Humans also do much better with well defined problems, clear outcomes
and good context, and I think that&amp;rsquo;s a much more useful frame.&lt;/p&gt;</description></item><item><title>agent-chat: a way to monitor multi-agent orchestration</title><link>https://justin.abrah.ms/blog/2026-01-24-agent-chat-a-way-to-monitor-multi-agent-orchestration.html</link><pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-01-24-agent-chat-a-way-to-monitor-multi-agent-orchestration.html</guid><description>&lt;p&gt;When running multi-agent orchestration like
&lt;a href="https://github.com/steveyegge/gastown"&gt;gastown&lt;/a&gt; or
&lt;a href="https://github.com/dlorenc/multiclaude"&gt;multiclaude&lt;/a&gt;, there&amp;rsquo;s a
lot of moving pieces. It can be noisy to determine what&amp;rsquo;s really going on,
especially as it&amp;rsquo;s happening across several tmux sessions. To address this,
I&amp;rsquo;ve released &lt;a href="https://github.com/justinabrahms/agent-chat"&gt;agent-chat&lt;/a&gt;. It shows communication between the agents as though
you were in a chat room with them. One chat-room per repository-equivalent.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://justin.abrah.ms/images/agent-chat.png" alt="agent-chat screenshot showing a Slack-like interface with multiple workspaces and agent messages"&gt;&lt;/p&gt;
&lt;p&gt;In the screenshot, you can see a supervisor coordinating workers to process a PR. When the spec requirement failed, it spawned a new worker to fix the issue - all visible in real-time.&lt;/p&gt;</description></item><item><title>multiclaude, a different take on llm orchestration</title><link>https://justin.abrah.ms/blog/2026-01-20-multiclaude-a-different-take-on-llm-orchestration.html</link><pubDate>Tue, 20 Jan 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-01-20-multiclaude-a-different-take-on-llm-orchestration.html</guid><description>&lt;p&gt;Dan Lorenc recently started talking about his LLM orchestration experiment
dubbed &lt;a href="https://github.com/dlorenc/multiclaude"&gt;multiclaude&lt;/a&gt; . I&amp;rsquo;ve used it a
bit and thought others who were looking at it might want to know how it&amp;rsquo;s
different.&lt;/p&gt;
&lt;h2 id="how-it-feels" class="heading-anchor"&gt;How it feels&lt;a href="#how-it-feels" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Multiclaude is similar to &lt;a href="https://github.com/steveyegge/gastown/"&gt;Gastown&lt;/a&gt; in
that it&amp;rsquo;s a distributed go binary that will help you launch and manage a pile of
claude code sessions in tmux. Its vibes are much more &amp;ldquo;unix tool&amp;rdquo; and not &amp;ldquo;I&amp;rsquo;m a
mad mage peering through my orb&amp;rdquo;.&lt;/p&gt;</description></item><item><title>A Tuesday in 2027: What orchestrated LLMs might look like</title><link>https://justin.abrah.ms/blog/2026-01-09-a-tuesday-in-2027-what-orchestrated-llms-might-look-like.html</link><pubDate>Fri, 09 Jan 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-01-09-a-tuesday-in-2027-what-orchestrated-llms-might-look-like.html</guid><description>&lt;p&gt;What follows is from an LLM session w/ Claude Code, where I was discussing some
of the tensions in the current world. This accurately represents where I think
things are heading. Is this a perfect analogy? Absolutely not. But it&amp;rsquo;s
directionally interesting and indicative of the levels of change I think we&amp;rsquo;re
looking at in the next 1-3 years.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A Tuesday in 2027&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You open your morning dashboard. Not a PR queue - an outcomes
board. Overnight, 47 changes shipped across three services. You don&amp;rsquo;t see
diffs; you see deltas in error rates and latency percentiles. Two anomalies
flagged. You don&amp;rsquo;t ask &amp;ldquo;what changed&amp;rdquo; - you ask &amp;ldquo;does it matter?&amp;rdquo;&lt;/p&gt;</description></item><item><title>Yegge's Developer-Agent Evolution Model</title><link>https://justin.abrah.ms/blog/2026-01-08-yegge-s-developer-agent-evolution-model.html</link><pubDate>Thu, 08 Jan 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-01-08-yegge-s-developer-agent-evolution-model.html</guid><description>&lt;p&gt;In
&lt;a href="https://steve-yegge.medium.com/welcome-to-gas-town-4f25ee16dd04"&gt;Welcome to Gas Town&lt;/a&gt;
, Steve Yegge generated a list of the 8 stages of agentic workflow evolution. I
find myself wanting to deep link to it, so I&amp;rsquo;m replicating it here.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://justin.abrah.ms/images/yegge-agent-evolution.webp" alt="Yegge&amp;rsquo;s Developer-Agent Evolution Model"&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Stage 1: Zero or Near-Zero AI: maybe code completions, sometimes ask Chat
questions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Stage 2: Coding agent in IDE, permissions turned on. A narrow coding agent in
a sidebar asks your permission to run tools.&lt;/p&gt;</description></item><item><title>Wrapping my head around Gas Town</title><link>https://justin.abrah.ms/blog/2026-01-05-wrapping-my-head-around-gas-town.html</link><pubDate>Mon, 05 Jan 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-01-05-wrapping-my-head-around-gas-town.html</guid><description>&lt;p&gt;I read &lt;a href="https://steve-yegge.medium.com/welcome-to-gas-town-4f25ee16dd04"&gt;Steve Yegge&amp;rsquo;s post announcing Gas
Town&lt;/a&gt;, an LLM
orchestrator which allows you to manage dozens of Claude Code instances at once
while they make independent progress towards some stated goals. It was a wild
ride, but I believe I see the promise.&lt;/p&gt;
&lt;h2 id="context" class="heading-anchor"&gt;Context&lt;a href="#context" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Two pieces of context seem useful before diving in. First, I worked with Steve
briefly at Google. I remember him working on &amp;ldquo;stone tools&amp;rdquo;, which was bringing
the features of an IDE to old editors like Emacs and Vim. This was 3 years
before &lt;a href="https://en.wikipedia.org/wiki/Language_Server_Protocol"&gt;LSPs&lt;/a&gt;
happened. This is to say, I think that Steve has some degree of future sight. I
think that&amp;rsquo;s in play here. His Kool-aid is good. I&amp;rsquo;ve drunk it before
and likely will again.&lt;/p&gt;</description></item><item><title>LLM Session Sharer: Easily share a claude code session without clutter</title><link>https://justin.abrah.ms/blog/2026-01-04-easily-share-a-claude-code-session-without-clutter.html</link><pubDate>Sun, 04 Jan 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-01-04-easily-share-a-claude-code-session-without-clutter.html</guid><description>&lt;p&gt;Trying to learn how to use LLMs is a pain. So many of the day-to-day invocations
are hard to pick up. Pairing with people isn&amp;rsquo;t very scalable. To that end, I saw
a slack message by &lt;a href="https://davidedmiston.com/"&gt;David Edmiston&lt;/a&gt; about a tool he
wrote:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Trivial, but in OpenCode, just one-shotted (and then tweaked the result a bit) a single page utility that can take a Claude conversation (JSON file exported from the web version via the browser dev tools) via drag-and-drop or file picker dialog and generate a nice HTML view of it, with an option to export the conversation as a markdown file (suitable for github gists) or copy to clipboard as markdown for import into obsidian (the real reason I wanted it, i sometimes rubberduck things with claude and wanted to capture it to chew over later)&lt;/p&gt;</description></item><item><title>Using your (Backstage) service catalog for compliance</title><link>https://justin.abrah.ms/blog/2026-01-01-using-your-service-catalog-for-compliance.html</link><pubDate>Thu, 01 Jan 2026 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2026-01-01-using-your-service-catalog-for-compliance.html</guid><description>&lt;p&gt;At work, I rolled out backstage as a service catalog offering in 2025 across a
few hundred git repos. It provided a pathway to get rid of a spreadsheet
hand-maintained by a developer about what each repo or service was, who owned
it, what it depended on, etc. When our regular compliance reviews came around,
it made me think: Can this help us here too? It turns out it could.&lt;/p&gt;</description></item><item><title>Consul leader election issues</title><link>https://justin.abrah.ms/blog/2023-07-20-consul-leader-election-issues.html</link><pubDate>Thu, 20 Jul 2023 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2023-07-20-consul-leader-election-issues.html</guid><description>&lt;p&gt;Problem: The cluster is in a broken state because consul can&amp;rsquo;t seem to gather a
quorum w/ it&amp;rsquo;s raft implementation.&lt;/p&gt;
&lt;p&gt;In my case, there was a raft peer that was bogus. I accidentally had it
advertising it&amp;rsquo;s IP as &lt;code&gt;127.0.0.1&lt;/code&gt; , but there was no process who had that
node-id at that address.&lt;/p&gt;
&lt;p&gt;There are two possible paths out that I know of. You can put a &lt;code&gt;peers.json&lt;/code&gt; file
in the consul data directory. Or you can manually bring up the consul process
with the &lt;code&gt;-bootstrap&lt;/code&gt; flag, to allow it to self-elect into a leader. The
&lt;code&gt;peers.json&lt;/code&gt; file approach worked for me.&lt;/p&gt;</description></item><item><title>A risk-based approach to open source strategy</title><link>https://justin.abrah.ms/blog/2023-04-19-a-risk-based-approach-to-open-source-strategy.html</link><pubDate>Wed, 19 Apr 2023 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2023-04-19-a-risk-based-approach-to-open-source-strategy.html</guid><description>&lt;p&gt;On it&amp;rsquo;s face, using open source code is an inherently risky endeavor. We are
trusting external developers to write code that we&amp;rsquo;ll eventually deliver to our
users, and we have no recourse if the code is buggy or malicious in some way. In
practice, people are generally good and the forces that govern popularity of
open source projects help reduce this risk to the point where nearly all folks
in the industry are prolific consumers of open source code.&lt;/p&gt;</description></item><item><title>SREcon 2023 trip report</title><link>https://justin.abrah.ms/blog/2023-03-27-srecon-trip-report.html</link><pubDate>Mon, 27 Mar 2023 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2023-03-27-srecon-trip-report.html</guid><description>&lt;p&gt;Last week, I attended SREcon 2023. I was invited to attend the &amp;ldquo;next-gen
delivery&amp;rdquo; working group meetings, due to my involvement within the Continuous
Delivery Foundation (CDF). I used the opportunity to attend the rest of the
conference as well. While I&amp;rsquo;ve never been an SRE by title, I&amp;rsquo;ve toed the line
between operations and software development for many years.&lt;/p&gt;
&lt;h2 id="conference-makeup" class="heading-anchor"&gt;Conference makeup&lt;a href="#conference-makeup" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Surprisingly, the makeup of the conference attendees were different than I
expected. It appeared that many of the folks were managerial. Talking with an
organizer, they believed this was due to the budget cuts happening across our
industry. They believed managers were attending to determine if it was a
high-value conference to send their reports to. For similar budgetary reasons,
large tech companies were underrepresented. The only participants from many
(Google, Dropbox, etc) were those speaking. Ultimately, this made the conference
feel less mature than I suspect previous years might have felt. Instead of these
companies, financial services and healthcare were well represented.&lt;/p&gt;</description></item><item><title>Feature Flags, Dynamic Config and Experimentation (oh my!)</title><link>https://justin.abrah.ms/blog/2022-11-15-feature-flags-dynamic-config-and-experimentation.html</link><pubDate>Tue, 15 Nov 2022 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2022-11-15-feature-flags-dynamic-config-and-experimentation.html</guid><description>&lt;p&gt;As part of the &lt;a href="https://openfeature.dev/"&gt;OpenFeature&lt;/a&gt; project, I&amp;rsquo;ve been
thinking a bunch about feature flags. There&amp;rsquo;s been ambiguity about how feature
flags differ from dynamic config and if that&amp;rsquo;s the same thing as experimentation
(e.g. A * B testing).&lt;/p&gt;
&lt;p&gt;At their core, feature flags are really fancy if statements. Those if statements
control the behavior we want to manage for our application.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// example OpenFeature java code&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBoolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;should-show-redesign&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cm"&gt;/* default */&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That may be backed by a file or it may be backed by some giant distributed
system. That&amp;rsquo;s a serialization concern that&amp;rsquo;s separate from the use of &amp;ldquo;gimmie
this config value&amp;rdquo;. This brings up the question about how this relates to config
in general. Should we use something like to fetch environment variables? system
properties?&lt;/p&gt;</description></item><item><title>Understanding Etsy's search service migration</title><link>https://justin.abrah.ms/blog/2022-11-15-understanding-etsys-search-service-migration.html</link><pubDate>Tue, 15 Nov 2022 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2022-11-15-understanding-etsys-search-service-migration.html</guid><description>&lt;p&gt;Etsy
&lt;a href="https://www.etsy.com/codeascraft/deep-learning-for-search-ranking-at-etsy"&gt;published a recent article&lt;/a&gt;
which documented how they migrated from their old search service to one which
was based on deep learning. The majority of that article made little sense to
me, so I wanted to take a moment to document what the heck that actually meant.&lt;/p&gt;
&lt;p&gt;Originally, Etsy&amp;rsquo;s search service was based on a gradient-boosted decision tree
model, which drove personalized search. They had to manually engineer the
features of the tree model and their relevancy gains began to plateau. Deep
learning models offered several exciting potential improvements, especially
because they could embed features directly, incorporate multi-modal data and
alter the network architecture itself. The search team ran two passes of ranking
and their work was primarily targeted at the second layer.&lt;/p&gt;</description></item><item><title>Git pre-receive hooks for deployment</title><link>https://justin.abrah.ms/blog/2022-11-09-git-pre-receive-hooks-for-deployment.html</link><pubDate>Wed, 09 Nov 2022 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2022-11-09-git-pre-receive-hooks-for-deployment.html</guid><description>&lt;p&gt;I host this blog on a git repo that lives on the same box as the webserver. When
I push to it, I want to ensure that deploys happen. Previously, it involved
SSHing and doing a bit of a dance. Today, I setup a deploy-on-push script
through git&amp;rsquo;s pre-receive hooks. It was surprisingly difficult to find a good
example of this pattern, so I wanted to publish my result.&lt;/p&gt;
&lt;p&gt;When the pre-receive hook is invoked, it&amp;rsquo;s given a line on stdin for each ref
that was pushed. If the branch is master, then invoke the &lt;code&gt;make publish&lt;/code&gt; command
in the repo.&lt;/p&gt;</description></item><item><title>re: Zettelkasten concerns</title><link>https://justin.abrah.ms/blog/2022-09-12-re-zettelkasten-concerns.html</link><pubDate>Mon, 12 Sep 2022 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2022-09-12-re-zettelkasten-concerns.html</guid><description>&lt;p&gt;I recently read the article
&lt;a href="https://karl-voit.at/2020/06/14/Zettelkasten-concerns/"&gt;Zettelkasten/Org-roam/Org-brain Is Crap&lt;/a&gt;
. After sending this response to the author, they asked for a place to link it.&lt;/p&gt;
&lt;p&gt;There were a few misconceptions to clear up and a few tips I thought I&amp;rsquo;d share.
For context, I went from a very large &lt;code&gt;eng-log.org&lt;/code&gt; file to multiple files
(~210) managed through org-roam at the end of 2021. I probably don&amp;rsquo;t follow zk
precisely, but something in that vein. My work is not based in research, but as
an architect at a large company.&lt;/p&gt;</description></item><item><title>An attempt at defining an ideal pipeline</title><link>https://justin.abrah.ms/blog/2022-08-16-an-attempt-at-an-ideal-pipeline.html</link><pubDate>Tue, 16 Aug 2022 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2022-08-16-an-attempt-at-an-ideal-pipeline.html</guid><description>&lt;p&gt;The &lt;a href="https://cd.foundation/"&gt;Continuous Delivery Foundation&lt;/a&gt; is currently
looking to build out a reference architecture, which I think is a fantastic
idea. While there are a bunch of social things that need to be figured out to
really &amp;ldquo;get&amp;rdquo; CI/CD, the
[[&lt;a href="https://bestpractices.cd.foundation/"&gt;https://bestpractices.cd.foundation/&lt;/a&gt;][Best Practices SIG]] is working to get
those well documented. I thought it might be helpful for me to document what
&lt;em&gt;my&lt;/em&gt; ideal pipeline is.&lt;/p&gt;
&lt;p&gt;When a developer submits their pull request, automatic validation begins. We
validate:&lt;/p&gt;</description></item><item><title>My thoughts on crypto: 2022</title><link>https://justin.abrah.ms/blog/2022-01-27-my-thoughts-on-crypto.html</link><pubDate>Thu, 27 Jan 2022 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2022-01-27-my-thoughts-on-crypto.html</guid><description>&lt;p&gt;It&amp;rsquo;s 2022. 1 bitcoin is about $35.5k USD. An ethereum is $2.3kUSD. I hold
0.2ETH, which I bought because I really like Gary Vaynerchuk, and I was
interested in his NFT project &lt;a href="https://veefriends.com/"&gt;VeeFriends&lt;/a&gt;. Ultimately, those NFTs were too
expensive for me to feel comfortable participating, primarily around gas fees.&lt;/p&gt;
&lt;p&gt;I first heard about bitcoin in late 2010 or early 2011 at
&lt;a href="https://hackandtell.org/"&gt;hack&amp;amp;&amp;amp;tell&lt;/a&gt; . A finance person was telling me about
it and it didn&amp;rsquo;t make a lot of sense to me. A BTC was worth about $6, but he
wouldn&amp;rsquo;t sell me his.&lt;/p&gt;</description></item><item><title>the function '..' is not known to be defined</title><link>https://justin.abrah.ms/blog/2021-08-13-the-function-is-not-known-to-be-defined.html</link><pubDate>Fri, 13 Aug 2021 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2021-08-13-the-function-is-not-known-to-be-defined.html</guid><description>&lt;p&gt;I was working on ox-gemini, a gemini exporter for org-mode documents. In the
latest versions of emacs, &lt;code&gt;string-replace&lt;/code&gt; is a function which replaces a word
in a string. It doesn&amp;rsquo;t exist in emacs 27.2 and earlier, so I added a simple
shim.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; backport for older emacs verisons&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;not&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fboundp&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;string-replace&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;string-replace&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt; &lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;replace-regexp-in-string&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;regexp-quote&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt; &lt;span class="nv"&gt;in&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;literal&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The shim says &amp;ldquo;If you don&amp;rsquo;t see a string-replace function, use this one).
Unfortunately, this left me with this compilation error:&lt;/p&gt;</description></item><item><title>Governance versus Stewardship</title><link>https://justin.abrah.ms/blog/2021-08-09-governance-versus-stewardship.html</link><pubDate>Mon, 09 Aug 2021 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2021-08-09-governance-versus-stewardship.html</guid><description>&lt;p&gt;In the enterprises I&amp;rsquo;ve recently been a part of, there&amp;rsquo;s been lots of discussion
about &amp;ldquo;governance&amp;rdquo;. Governance is a process where you ask other people for
permission to do things. The governing body serves to enforce consistency in
things like API design or to ensure adequate testing on deploys to production.&lt;/p&gt;
&lt;p&gt;One of the biggest problems with governance is that the beaurecratic process can
be quite slow. Relying on an outside authority to manually approve your deploys
to production introduces latency which is likely to cause your deploys to
accumulate. The subsequent deploys are larger, which means that both their blast
radius is bigger and, when things do go wrong, it&amp;rsquo;s difficult to isolate which
change in the batch caused the issue. In this paradigm, introducing this
strong-handed governance is actually counter to their own goals.&lt;/p&gt;</description></item><item><title>Federated GraphQL Ops with Apollo Studio</title><link>https://justin.abrah.ms/blog/2021-07-28-federated-graphql-ops-with-apollo-studio.html</link><pubDate>Wed, 28 Jul 2021 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2021-07-28-federated-graphql-ops-with-apollo-studio.html</guid><description>&lt;p&gt;There are several differences between the traditional REST API model and how
federated GraphQL operates, which can cause some friction when discussing the
tech with your SRE/ops organization. This is a list of issues that I&amp;rsquo;ve come
across in my work and the mitigations we&amp;rsquo;ve either considered or adopted. This
list assumes that you either have access to Apollo Studio or have replicated the
relevant functionality to your custom solution.&lt;/p&gt;</description></item><item><title>Learning from Production Incidents</title><link>https://justin.abrah.ms/blog/2020-12-15-learning-from-production-incidents.html</link><pubDate>Tue, 15 Dec 2020 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2020-12-15-learning-from-production-incidents.html</guid><description>&lt;p&gt;&lt;em&gt;Note: This was originally posted internally at Walmart, and has since been sanitized for public consumption.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The postmortem process is a tool that we use to better understand failures
within our systems. There are two ways to view failures within complex systems:
&amp;ldquo;That failure cost us $250,000&amp;rdquo; or &amp;ldquo;The company spent $ 250,000 to learn this
lesson&amp;rdquo;. Taking the second approach, this document aims to outline a process
which wrings as much value from that lesson as possible.&lt;/p&gt;</description></item><item><title>First and Second order metrics</title><link>https://justin.abrah.ms/blog/2020-10-31-first-and-second-order-metrics.html</link><pubDate>Sat, 31 Oct 2020 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2020-10-31-first-and-second-order-metrics.html</guid><description>&lt;p&gt;As part of our efforts of continual improvement, we have been diving
deep on the metrics that we want to track at an organizational
level. This has been happening at all levels of the organization,
which has resulted in multiple contemporary conversations around which
metrics we should track. In these discussions with engineers and
leaders, we’ve lacked some wording to classify the metrics we were
discussing. I believe that thinking about metrics as either
first-order metrics or second-order metrics is a useful distinction.&lt;/p&gt;</description></item><item><title>Biogas Digestion system.</title><link>https://justin.abrah.ms/blog/2020-06-04-biogas-digestion-system.html</link><pubDate>Thu, 04 Jun 2020 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2020-06-04-biogas-digestion-system.html</guid><description>&lt;p&gt;A biogas digestion system is a way to convert biological waste (like
kitchen scraps, grass clippings, and manure) into usable biproducts of
methane and both liquid and solid fertilizers.&lt;/p&gt;
&lt;p&gt;Biogas digestion works by creating an anerobic chamber (i.e. a place
without oxygen) which breaks down the organic matter you put in
it. There are two types of bacteria at play here. One type takes food
and converts it into acid. These are called acidogenic bacteria (aka
acetogens). Methanogenic bacteria (methanogens) convert the acid from
the first system into methane gas.&lt;/p&gt;</description></item><item><title>Is web scraping ethical?</title><link>https://justin.abrah.ms/blog/2020-06-04-is-webscraping-ethical.html</link><pubDate>Thu, 04 Jun 2020 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2020-06-04-is-webscraping-ethical.html</guid><description>&lt;p&gt;Someone recently asked: &amp;ldquo;Is web scraping an ethical concept?&amp;rdquo; I
believe that web scraping is absolutely an ethical concept. Web
scraping (or screen scraping) is a mechanism to have a computer read a
website. There is absolutely no technical difference between an
automated computer viewing a website and a human-driven computer
viewing a website. Furthermore, if done correctly, scraping can
provide many benefits to all involved.&lt;/p&gt;
&lt;p&gt;There are a bunch of great uses for web scraping. First, services like
Instapaper, which allow saving content for reading on the go, use
screen scraping to save a copy of the website to your phone. Second,
services like Mint.com, an app which tells you where and how you are
spending your money, uses screen scraping to access your bank&amp;rsquo;s
website (all with your permission). This is useful because banks do
not provide many ways for programmers to access your financial data,
even if you want them to. By getting access to your data, programmers
can provide really interesting visualizations and insight into your
spending habits, which can help you save money.&lt;/p&gt;</description></item><item><title>How to make a font on Ubuntu with PPAs</title><link>https://justin.abrah.ms/blog/2019-09-19-how-to-make-a-font-on-ubuntu-ppa.html</link><pubDate>Thu, 19 Sep 2019 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2019-09-19-how-to-make-a-font-on-ubuntu-ppa.html</guid><description>&lt;p&gt;Microsoft released a new font called Cascadia Code. I&amp;rsquo;d prefer if I
could install this with the debian package manager, so I went to
figure out how to put that on Ubuntu&amp;rsquo;s PPAs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Install dependencies for the ppa creation process&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install -y dh-make bzr-builddeb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Tell bzr who I am&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bzr whoami &lt;span class="s2"&gt;&amp;#34;Justin Abrahms &amp;lt;justin@abrah.ms&amp;gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Download the font&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget https://github.com/microsoft/cascadia-code/releases/download/v1909.16/Cascadia.ttf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Create a tarball&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tar cf cascadia.tar ./Cascadia.ttf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Try to build the actual package&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bzr dh-make ttf-cascadia-code 1909.16 cascadia.tar 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From here, we have a &lt;code&gt;debian/&lt;/code&gt; folder that contains lots of files we
need to configure. I deleted the two README files that were generated
and filled out the &lt;code&gt;copyright&lt;/code&gt; and &lt;code&gt;control&lt;/code&gt; files. It&amp;rsquo;s important
that the name-email combination you put for yourselve in these matches
the name-email combination used in your GPG key.&lt;/p&gt;</description></item><item><title>Whiteboard photo snapper</title><link>https://justin.abrah.ms/blog/2019-02-10-automatic-whiteboard-snapper.html</link><pubDate>Sun, 10 Feb 2019 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2019-02-10-automatic-whiteboard-snapper.html</guid><description>&lt;p&gt;Six people live in my house. We don&amp;rsquo;t have strong technology overlap
(some folks in the house only use simple phones and others aren&amp;rsquo;t keen
on things like slack or similar). We&amp;rsquo;ve addressed this by centralizing
around a large whiteboard in our kitchen space. This holds things like
grocery lists, house announcements, and similar. I often do grocery
shopping on my way home, but rarely remember to snap a photo of the
list before leaving for work.&lt;/p&gt;</description></item><item><title>Serene Lake</title><link>https://justin.abrah.ms/blog/2018-04-17-serene-lake.html</link><pubDate>Tue, 17 Apr 2018 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2018-04-17-serene-lake.html</guid><description>&lt;p&gt;Serene lake is a backpacking trip that I&amp;rsquo;ve done a few times. It
features wonderful Oregon moss-y forests, a variety mushrooms,
huckleberries, and some wonderful lakes. If you&amp;rsquo;re lucky, you can also
catch some mountain views from ontop of the hike&amp;rsquo;s one ridgeline.&lt;/p&gt;
&lt;p&gt;The hike is lollipop shaped from the entrance and clocks in at around
14 miles. It starts at Shell Rock lake. There are often car campers
here, given it&amp;rsquo;s proximity to the parking lot (about a mile or
less). From there, you take the trail onward to a fork in the
road. The first year, we went right, which is the direction I&amp;rsquo;d
suggest. It takes you to Frazier Turnaround, which is accessible by
car some parts of the year. Commenters saying that it&amp;rsquo;s blocked by
boulders and such has been enough to add the extra 2-3 mile hike for
the Shell Rock start.&lt;/p&gt;</description></item><item><title>Software engineering vs other engineering</title><link>https://justin.abrah.ms/blog/2018-04-17-software-engineering-vs-other-engineering.html</link><pubDate>Tue, 17 Apr 2018 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2018-04-17-software-engineering-vs-other-engineering.html</guid><description>&lt;p&gt;Quality Assurance (or QA) is a mechanism by which teams confirm that
they’re hitting the requirements they’ve said they’d hit. One example
is ensuring you’re validating your contractual obligations from a
consulting standpoint. Another is making sure you meet the end user’s
expectations.&lt;/p&gt;
&lt;p&gt;A friend who does QA in the nuclear industry recently had some issues
with an outside software vendor. They caused some political strife
between the government and a native tribe because they didn’t follow
the contractual processes. He wrote asking me if there were any
similar standards to the “American Society of Mechanical Engineers QA
Requirements for Nuclear Facilities Applications”, which outlines how
teams build software in his industry. I didn’t have good news for him.&lt;/p&gt;</description></item><item><title>Stub Stewart Bike Ride</title><link>https://justin.abrah.ms/blog/2018-04-17-stub-stewart.html</link><pubDate>Tue, 17 Apr 2018 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2018-04-17-stub-stewart.html</guid><description>&lt;p&gt;I do a yearly bike ride out to LL Stub Stewart State Park, between
Banks, OR and Venonia, OR. It&amp;rsquo;s a fantastic intro to bike camping trip
that&amp;rsquo;s a known quantity. The full ride is around 48 miles and requires
minimal meal preparation given it&amp;rsquo;s access to food and grocery stores.&lt;/p&gt;
&lt;p&gt;The guidance I give to my friends is: &amp;ldquo;If you bicycle around town to
get around, you can do the trip no problem. If you aren&amp;rsquo;t much of a
cycler but are in reasonable shape, you can do it, but your saddle
will be sore. If you&amp;rsquo;re not in shape and don&amp;rsquo;t bicycle, you should
strongly consider whether this is where you start cycling. You&amp;rsquo;ll
probably fall behind and be tired. While the group won&amp;rsquo;t leave you,
people tend to feel bad to be the last one in the line.&amp;rdquo;&lt;/p&gt;</description></item><item><title>Understanding the formal definition of Big-O</title><link>https://justin.abrah.ms/blog/2018-04-17-understanding-big-o-formal-definition.html</link><pubDate>Tue, 17 Apr 2018 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2018-04-17-understanding-big-o-formal-definition.html</guid><description>&lt;p&gt;This is the third in a three post series. The first post
&lt;a href="https://justin.abrah.ms/blog/2013-07-23-big-o-notation-explained.html"&gt;explains Big-O from a self-taught programmer&amp;rsquo;s perspective&lt;/a&gt;
. The second post talks about
&lt;a href="https://justin.abrah.ms/blog/2013-10-14-how-to-calculate-big-o.html"&gt;how to calculate Big-O&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;In my &lt;a href="https://justin.abrah.ms/blog/2013-07-23-big-o-notation-explained.html"&gt;original Big-O piece&lt;/a&gt;, I’ve made a bunch of simplifying
assumptions and told you a bunch of half truths. It might seem a bit
disingenuous, but really.. these half-truths are helpful because
(unless you’re going after a formal CS degree) they don’t really
matter.&lt;/p&gt;</description></item><item><title>What is an algorithm?</title><link>https://justin.abrah.ms/blog/2018-04-17-what-is-an-algorithm.html</link><pubDate>Tue, 17 Apr 2018 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2018-04-17-what-is-an-algorithm.html</guid><description>&lt;p&gt;One of the early classes in computer science curriculum is “data
structures and algorithms”. When you read computer science text books,
you’ll see these words paired together. This makes the word sound more
fancy and important than it should. An algorithm, while important, is
not particularly fancy.&lt;/p&gt;
&lt;p&gt;Algorithms, simply put, are how you go about doing something.&lt;/p&gt;
&lt;p&gt;When paired with data structures, “algorithm” means how you do
something using a particular data structure. One example of this is
how do you put an item into a list? Well, that depends a bit on what
the underlying data structure to the list is. Maybe you’re moving some
pointers around. Maybe you’re doing a big shuffle of blocks of
memory. The exact machinations of this are your “algorithm”.&lt;/p&gt;</description></item><item><title>Will binary always be the lowest level way to program?</title><link>https://justin.abrah.ms/blog/2018-04-17-will-binary-always-be-the-lowest-level.html</link><pubDate>Tue, 17 Apr 2018 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2018-04-17-will-binary-always-be-the-lowest-level.html</guid><description>&lt;center&gt;
&lt;blockquote class="twitter-tweet" data-lang="en"&gt;&lt;p lang="en" dir="ltr"&gt;&lt;a href="https://twitter.com/justinabrahms"&gt;@justinabrahms&lt;/a&gt; serious question: will binary always be the lowest level computer language? Is there (conceivably) a different model?&lt;/p&gt;&amp;mdash; Justin Jackson (@mijustin) &lt;a href="https://twitter.com/mijustin/status/676640625995845632"&gt;December 15, 2015&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="//platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;/center&gt;
&lt;p&gt;Justin Jackson asked if binary will always be the lowest level
language, or if that might ever change. To answer that, let’s talk
about what low level means.&lt;/p&gt;
&lt;p&gt;Binary isn’t exactly the lowest level programming language
though. Binary isn’t actually a programming language at all. Binary is
simply a way to convey information. In some cases, this information is
the layout of logic circuits. In others, it might be media like a
YouTube video or git checkout streaming to your disk.&lt;/p&gt;</description></item><item><title>An overview of Guice</title><link>https://justin.abrah.ms/blog/2016-08-23-an-overview-of-guice-java-dependency-injection.html</link><pubDate>Tue, 23 Aug 2016 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2016-08-23-an-overview-of-guice-java-dependency-injection.html</guid><description>&lt;p&gt;Google&amp;rsquo;s Guice is a Java-based dependency injection framework, which
means approximately nothing to people who aren&amp;rsquo;t familiar with it.&lt;/p&gt;
&lt;p&gt;Google&amp;rsquo;s Guice is a way to build a graph of dependencies so you can
instantiate complex objects made of simpler parts.&lt;/p&gt;
&lt;p&gt;Google&amp;rsquo;s Guice is a replacement for the &lt;code&gt;new&lt;/code&gt; keyword for many of your
objects. Bizzarre, right?&lt;/p&gt;
&lt;p&gt;In a more tangible sense, Guice is a tool that&amp;rsquo;s used in a lot of Java
development. Beyond that, it positively impacts your code resulting in
a reduction of boilerplate and an increase in testability.&lt;/p&gt;</description></item><item><title>Literate API Testing with Dredd</title><link>https://justin.abrah.ms/blog/2015-11-12-literate-api-testing-with-dredd.html</link><pubDate>Thu, 12 Nov 2015 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2015-11-12-literate-api-testing-with-dredd.html</guid><description>&lt;p&gt;I&amp;rsquo;ve just started &lt;a href="https://github.com/mitodl/ccxcon"&gt;my latest project&lt;/a&gt; at MIT, and I&amp;rsquo;m quite excited
about a new piece of technology that the team uses: apiary.io.&lt;/p&gt;
&lt;p&gt;With Apiary, we generate a simple blueprint file (&lt;a href="https://github.com/mitodl/ccxcon/blob/master/apiary.apib"&gt;source&lt;/a&gt;, &lt;a href="http://docs.ccxcon.apiary.io/#"&gt;output&lt;/a&gt;)
which is a full description of your API. This shows off requests and
responses with a bit of prose. It&amp;rsquo;s all in markdown file and is very
simple to get started. There is a tool called &lt;a href="https://github.com/apiaryio/protagonist"&gt;Protagonist&lt;/a&gt; which will
parse this into a big JSON blob.&lt;/p&gt;</description></item><item><title>Altruism in the job hunt</title><link>https://justin.abrah.ms/blog/altruism-in-the-job-hunt.html</link><pubDate>Wed, 11 Nov 2015 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/altruism-in-the-job-hunt.html</guid><description>&lt;p&gt;I&amp;rsquo;ve recently accepted a job at MIT&amp;rsquo;s Office of Digital Learning which
I&amp;rsquo;m quite excited about. The bulk of the work is done in open source
on GitHub. We&amp;rsquo;re working on a stack I&amp;rsquo;m familiar with (Python/Django)
but are also actively using newer technology I&amp;rsquo;m interested in
(React/Docker).&lt;/p&gt;
&lt;p&gt;Technology choice wasn&amp;rsquo;t the actual reason I chose this job though. I&amp;rsquo;ve been
gaining a bunch of experience over the past few years in product and
engineering. First at Google, where I first started to understand what product
was about, then later at Sprint.ly where I got to see first-hand how it&amp;rsquo;s done
by &lt;a href="http://stu.mp/"&gt;Joe Stump&lt;/a&gt; . The next stop on my career path would have
naturally been somewhere leading an engineering team at a venture-backed
startup. I certainly have enough industry connections to make that a reality
(and I&amp;rsquo;m thankful for that!).&lt;/p&gt;</description></item><item><title>MicroConf 2015 Recap</title><link>https://justin.abrah.ms/blog/2015-04-20-microconf-2015-recap.html</link><pubDate>Mon, 20 Apr 2015 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2015-04-20-microconf-2015-recap.html</guid><description>&lt;p&gt;I&amp;rsquo;ve just returned from MicroConf 2015. &lt;a href="http://microconf.com/"&gt;MicroConf&lt;/a&gt;, if you&amp;rsquo;re
unfamiliar, is a conference for self-backed startup entrepeneurs. Most
of the talks center around how to grow out a small business. The
audience is split roughly evenly between consultants and product.&lt;/p&gt;
&lt;p&gt;There were two stand-out talks for me this year. One by Patrick
McKenzie and the other by Steli Efti.&lt;/p&gt;
&lt;p&gt;The first talk of the conference was by &lt;a href="http://www.kalzumeus.com/blog/"&gt;Patrick McKenzie&lt;/a&gt; (or patio11
as he&amp;rsquo;s known around the internet). He talked about his original
product, Bingo Card Creator (which does exactly what it sounds like),
and how it&amp;rsquo;s audience was different than his next product, Appointment
Reminder (which calls people to remind them of their appointment). He
wasn&amp;rsquo;t able to leverage his existing audience of teachers. In terms
that I use, he wasn&amp;rsquo;t able to use the assets he had (a wide network of
teachers) as a superpower in his latest endeavor. Patrick also had my
favorite quote of the conference.&lt;/p&gt;</description></item><item><title>Real-time code coverage analysis</title><link>https://justin.abrah.ms/blog/2015-04-09-real-time-code-coverage-analysis.html</link><pubDate>Thu, 09 Apr 2015 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2015-04-09-real-time-code-coverage-analysis.html</guid><description>&lt;p&gt;I recently sat down to write a node service and happened upon a very
helpful workflow when trying to write tests that I wanted to share.&lt;/p&gt;
&lt;p&gt;When writing tests, one of the biggest jobs is to ensure you have a
reasonable degree of coverage on the various branches in your
code. This means that if you have an if statement, you want to check
the case where the if is true and the case where the if is false. This
gets a little more complicated if you have multiple statements in your
if statement like &lt;code&gt;if (foo || bar) {&lt;/code&gt;, but the idea is similar.&lt;/p&gt;</description></item><item><title>Imhotep helps you enforce your styleguide during code review</title><link>https://justin.abrah.ms/blog/2014-08-23-imhotep-code-review-assistance.html</link><pubDate>Sat, 23 Aug 2014 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2014-08-23-imhotep-code-review-assistance.html</guid><description>&lt;p&gt;Over the holiday break, I got a &lt;a href="https://github.com/justinabrahms/imhotep"&gt;long-standing side project&lt;/a&gt; into a
working state. Imhotep is a tool that will enforce coding standards on
pull requests and commits. It accomplishes this by running code
linters and commenting on your GitHub pull requests with any violations.&lt;/p&gt;
&lt;p&gt;The main motivation for imhotep is based on a trend I saw at
Google. We did pre-merge code reviews and I was on a team of
approximately 12 people. It became apparent that different folks gave
different sorts of code reviews. There were some people who would
validate syntax, code style enforcement and rubber stamp your
change. These were the tactical reviewers. There were others who would
identify problematic aspects of your overall design and, as a result,
would teach you a great deal about how to build robust software. These
were the strategic reviewers.&lt;/p&gt;</description></item><item><title>Inheritence versus Composition</title><link>https://justin.abrah.ms/blog/2014-08-23-inheritence-vs-composition.html</link><pubDate>Sat, 23 Aug 2014 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2014-08-23-inheritence-vs-composition.html</guid><description>&lt;p&gt;Part of a healthy engineering culture is having a good code review process.
There are many things that contribute to a
[[&lt;a href="https://github.com/sprintly/sprint.ly-culture/blob/master/Coding.mkd#code-review-as-knowledge-sharing-and-buy-in"&gt;https://github.com/sprintly/sprint.ly-culture/blob/master/Coding.mkd#code-review-as-knowledge-sharing-and-buy-in&lt;/a&gt;][good code review process]]
, but one of those is thinking through why something should be the way it
should. I recently did more writing than is usual which I&amp;rsquo;ve adapted to use as
this post.&lt;/p&gt;
&lt;h3 id="the-code-under-review" class="heading-anchor"&gt;The code under review&lt;a href="#the-code-under-review" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;We start with some code used to render columns of tickets in
&lt;a href="https://sprint.ly/"&gt;Sprint.ly&lt;/a&gt;&amp;rsquo;s UI. Depending on where they are in the UI, these columns
are sortable, you can drag &amp;amp; drop between them, or you can adjust
which properties they are ordered by. The code looked something like
this:&lt;/p&gt;</description></item><item><title>Meaning of Community</title><link>https://justin.abrah.ms/blog/2014-08-23-meaning-of-community.html</link><pubDate>Sat, 23 Aug 2014 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2014-08-23-meaning-of-community.html</guid><description>&lt;dl&gt;
&lt;dt&gt;My wife attended Cascadia JS 2013 and I tagged along to join the&lt;/dt&gt;
&lt;dt&gt;significant other track, which was really just an excuse to visit&lt;/dt&gt;
&lt;dt&gt;Vancouver for a weekend. I had a great deal of fun getting there on&lt;/dt&gt;
&lt;dt&gt;the Hacker Train, which was a merry band of JavaScripters who rented&lt;/dt&gt;
&lt;dt&gt;out a train car. Along the way, I had many conversations that went&lt;/dt&gt;
&lt;dt&gt;something like this.&lt;/dt&gt;
&lt;dd&gt;
&lt;p&gt;js: &amp;ldquo;Are you excited for the conference?&amp;rdquo;&lt;/p&gt;</description></item><item><title>Setuptools Entrypoints Explained</title><link>https://justin.abrah.ms/blog/2014-08-23-setuptools-entrypoints-explained.html</link><pubDate>Sat, 23 Aug 2014 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2014-08-23-setuptools-entrypoints-explained.html</guid><description>&lt;p&gt;Python&amp;rsquo;s setuptools has a rather interesting feature called
&amp;ldquo;entry points&amp;rdquo; which facilitates plugin discovery. I&amp;rsquo;m using this in
&lt;a href="https://github.com/justinabrahms/imhotep"&gt;imhotep&lt;/a&gt; to allow linters to live as separate packages.&lt;/p&gt;
&lt;h3 id="so-how-does-it-work" class="heading-anchor"&gt;So how does it work?&lt;a href="#so-how-does-it-work" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;In your &lt;code&gt;setup.py&lt;/code&gt;, you defined a property called
&lt;code&gt;entry_points&lt;/code&gt; which is a dictionary mapping the entry point key to a
list of values. The values take the form of &lt;del&gt;.py =
imhotep_pylint.plugin:PyLint&lt;/del&gt;. This is another mapping in string form
from a user-defined string to a dotted module name (and optionally, as
here, an object to import).&lt;/p&gt;</description></item><item><title>Thinking like a programmer: Inputs &amp; outputs</title><link>https://justin.abrah.ms/blog/2014-08-23-thinking-like-a-programmer--inputs-and-outputs.html</link><pubDate>Sat, 23 Aug 2014 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2014-08-23-thinking-like-a-programmer--inputs-and-outputs.html</guid><description>&lt;p&gt;One of the difficulties in learning to program is not the specific
syntax it takes to accomplish a goal, but the thinking that went
behind it. As a coworker of mine once said, &amp;ldquo;I understand what you
did, but I wouldn&amp;rsquo;t have thought of doing it that way.&amp;rdquo; One method of
thinking about a problem is by considering the inputs and outputs of a
program or function.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s talk about inputs and outputs from a function. Functions are a
good example, but it could apply to modules or distributed system
components too.&lt;/p&gt;</description></item><item><title>Why a community might want a Python Software Foundation</title><link>https://justin.abrah.ms/blog/2014-08-23-the-whys-of-the-python-software-foundation.html</link><pubDate>Sat, 23 Aug 2014 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2014-08-23-the-whys-of-the-python-software-foundation.html</guid><description>&lt;p&gt;There have been a few discussions around the node.js community around
why someone might want a foundation similar to the ones created by the
&lt;a href="http://www.python.org/psf/"&gt;Python&lt;/a&gt; or &lt;a href="https://www.djangoproject.com/foundation/"&gt;Django&lt;/a&gt; communities.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll start by noting that the bulk of my involvement with these
entities has been indirect at best. I am a member of the Python
community, but haven&amp;rsquo;t had many direct involvements with these
organizations. That said, I&amp;rsquo;ve seen the benefits of their hard work.&lt;/p&gt;</description></item><item><title>NodeConf 2014: A story of aspiration and community</title><link>https://justin.abrah.ms/blog/2014-06-04-nodeconf-2014-story-of-aspiration-and-community.html</link><pubDate>Wed, 04 Jun 2014 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2014-06-04-nodeconf-2014-story-of-aspiration-and-community.html</guid><description>&lt;p&gt;This year, I helped mentor &lt;a href="https://nodeconf.com"&gt;NodeConf 2014&lt;/a&gt;, which was an amazing
experience. For those not familiar, NodeConf is a much different
format than the average industry conference. First, instead of a
standard conference center, the venue for NodeConf is an idyllic
middle schooler’s summer camp in sunny California. There’s a museum of
taxidermied animals, foxes and deer wandering about, and a pond for
swimming adventures. Evening activities ranged from heated games of 4
square (or absurd variants like 25 square) to s’mores, from LED
firework displays to late night hacking.&lt;/p&gt;</description></item><item><title>Pull request templates make code review easier</title><link>https://justin.abrah.ms/blog/2014-06-04-pull-request-templates-make-code-review-easier.html</link><pubDate>Wed, 04 Jun 2014 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2014-06-04-pull-request-templates-make-code-review-easier.html</guid><description>&lt;p&gt;We do a bunch of code reviews at &lt;a href="http://sprint.ly/"&gt;Sprint.ly&lt;/a&gt;. One of the things we&amp;rsquo;ve
done to make that process a little easier is institute a code review
template. This template is a free-form list of questions that every
person filling out a pull request uses.&lt;/p&gt;
&lt;p&gt;Our pull request template looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;#### What&amp;#39;s this PR do?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;#### Where should the reviewer start?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;#### How should this be manually tested?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;#### Any background context you want to provide?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;#### What are the relevant tickets?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;#### Screenshots (if appropriate)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;#### Questions:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Is there a blog post?
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Does the knowledge base need an update?
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;-&lt;/span&gt; Does this add new (Python) dependencies which need to be added to chef?
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some sections get a &amp;ldquo;n/a&amp;rdquo;, such as the screenshot section for API only
changes. In general though, this has proven to make reviewing a much
easier process. Curious what it looks like in practice? Here&amp;rsquo;s an
example from a recent pull request.&lt;/p&gt;</description></item><item><title>PyCon 2014 was awesome</title><link>https://justin.abrah.ms/blog/2014-06-04-pycon-2014-was-awesome.html</link><pubDate>Wed, 04 Jun 2014 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2014-06-04-pycon-2014-was-awesome.html</guid><description>&lt;p&gt;PyCon was a ton of fun this year. Always the highlight of my
conference season, 2014 was no exception.&lt;/p&gt;
&lt;p&gt;I gave a talk this year on Big-O notation. I told the story about how
not knowing it led to a few costly mistakes and then explained it so
that (hopefully) no one will make the same mistake again. You can
watch the video below. Thanks to everyone who came up to me after my
presentation to talk about it!&lt;/p&gt;</description></item><item><title>Node Knockout: A chance to play &amp; experiment</title><link>https://justin.abrah.ms/blog/2013-11-10-node-knockout-play-and-experiment.html</link><pubDate>Sun, 10 Nov 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-11-10-node-knockout-play-and-experiment.html</guid><description>&lt;p&gt;This weekend, I competed in Node Knockout, a 48-hour coding
competition designed around Node.js. For my idea, I chose to write a
visualization of an AST querying language called cssauron. The entry
has since been taken offline.&lt;/p&gt;
&lt;h3 id="overview" class="heading-anchor"&gt;Overview&lt;a href="#overview" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://npmjs.org/package/cssauron"&gt;cssauron&lt;/a&gt; is a tool which maps the ideas of querying for DOM elements
through CSS selectors (eg how jQuery operates), and mapping that to
source code. &lt;code&gt;cssauron&lt;/code&gt; itself is AST agnostic and there are plugins
for a few options that map the concept of selectors to the relevant
AST nodes. The implementation I used was &lt;a href="https://npmjs.org/package/cssauron-falafel"&gt;cssauron-falafel&lt;/a&gt; which
binds with the &lt;a href="https://npmjs.org/package/falafel"&gt;falafel&lt;/a&gt; library for querying javascript source.&lt;/p&gt;</description></item><item><title>Obseletion through Programming</title><link>https://justin.abrah.ms/blog/2013-11-10-obsoletion-through-programming.html</link><pubDate>Sun, 10 Nov 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-11-10-obsoletion-through-programming.html</guid><description>&lt;p&gt;Working in tech, programmers are often brought in to apply automation
to processes as a means to increase productivity. This ranges from
automating the creation of manufactured goods or speedily compiling
reports based on Excel spreadsheets. As a younger programmer, I found
myself wondering what the person who used to do this work would do
with their new found time. Simply put, is my hard work getting someone
else fired? Within the context of knowledge workers, I think the
answer is no.&lt;/p&gt;</description></item><item><title>Book Review: Backbone.js Testing by Ryan Roemer</title><link>https://justin.abrah.ms/blog/2013-11-03-book-review-backbonejs-testing.html</link><pubDate>Sun, 03 Nov 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-11-03-book-review-backbonejs-testing.html</guid><description>&lt;p&gt;Ryan Roemer, the author of &lt;a href="http://www.amazon.com/gp/product/178216524X/ref%3Das_li_qf_sp_asin_tl?ie%3DUTF8&amp;amp;camp%3D1789&amp;amp;creative%3D9325&amp;amp;creativeASIN%3D178216524X&amp;amp;linkCode%3Das2&amp;amp;tag%3Djusabrblo-20"&gt;Backbone.js Testing&lt;/a&gt;, wrote a post to the
Seattle-area JavaScript developer&amp;rsquo;s mailing list to ask if anyone was
interested in reviewing his book. As I have been diving into front-end
testing at Sprint.ly, I agreed to review it. I was interested in how
our setup compared to the setup he was advocating.&lt;/p&gt;
&lt;h3 id="the-book" class="heading-anchor"&gt;The book&lt;a href="#the-book" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The book itself talks a bit about the generalities of testing: how to
test, what to test, and what makes a good test. It introduces a simple
app which is centered around taking notes in markdown and rendering
them as HTML. It is similar to the &lt;a href="http://todomvc.com/"&gt;TodoMVC&lt;/a&gt; app, but is a bit simpler
and more focused.&lt;/p&gt;</description></item><item><title>Selenium's Page Object Pattern: The Key to Maintainable Tests</title><link>https://justin.abrah.ms/blog/2013-11-03-selenium-page-object-pattern--the-key-to-maintainable-tests.html</link><pubDate>Sun, 03 Nov 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-11-03-selenium-page-object-pattern--the-key-to-maintainable-tests.html</guid><description>&lt;p&gt;At &lt;a href="https://sprint.ly/"&gt;Sprint.ly&lt;/a&gt;, we&amp;rsquo;ve been investing in the longer term health of our
code base. Part of our strategy for handling this involves selenium
testing.&lt;/p&gt;
&lt;p&gt;For those who may be unfamiliar, selenium tests operate by instructing
a browser to click on things or type in text boxes in an order you
specify. The biggest upside to this is it&amp;rsquo;s the most accurate
simulation of an actual user&amp;rsquo;s experience. One of the biggest
obstacles of these sorts of tests is they are brittle. To combat
this, we&amp;rsquo;re using a concept called the page object pattern.&lt;/p&gt;</description></item><item><title>Javascript Refactoring without an IDE</title><link>https://justin.abrah.ms/blog/2013-10-16-javascript-reafactoring-without-ides.html</link><pubDate>Wed, 16 Oct 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-10-16-javascript-reafactoring-without-ides.html</guid><description>&lt;p&gt;There are a lot of questions that pop up when you&amp;rsquo;re changing an entry
in your style guide. If you&amp;rsquo;re editing a file which hasn&amp;rsquo;t been
updated, is this pull request the one to update it in? Is that a
separate PR? Should I just keep with the old style for now, but use it
for new files? Without a clear cross-over point, you may end up with
multiple competing standards, all of which are a snapshot of what the
styleguide looked like when the code was written.&lt;/p&gt;</description></item><item><title>A list of scary topics.</title><link>https://justin.abrah.ms/blog/2013-10-14-a-list-of-scary-topics.html</link><pubDate>Mon, 14 Oct 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-10-14-a-list-of-scary-topics.html</guid><description>&lt;h3 id="computer-science--engineering" class="heading-anchor"&gt;Computer Science / Engineering&lt;a href="#computer-science--engineering" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Binary Protocols&lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Sockets &lt;em&gt;Packets&lt;/em&gt; low-level networking&lt;/li&gt;
&lt;li&gt;Systems Coding (aka linux syscall apis)&lt;/li&gt;
&lt;li&gt;Compilers&lt;/li&gt;
&lt;li&gt;Assembly&lt;/li&gt;
&lt;li&gt;3D Graphics Programming&lt;/li&gt;
&lt;li&gt;Animation&lt;/li&gt;
&lt;li&gt;Binary Compatibility&lt;/li&gt;
&lt;li&gt;File systems&lt;/li&gt;
&lt;li&gt;Writing a virus&lt;/li&gt;
&lt;li&gt;C++&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="mathematics" class="heading-anchor"&gt;Mathematics&lt;a href="#mathematics" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;All of it past arithmetic.&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Big-O is easy to calculate, if you know how</title><link>https://justin.abrah.ms/blog/2013-10-14-how-to-calculate-big-o.html</link><pubDate>Mon, 14 Oct 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-10-14-how-to-calculate-big-o.html</guid><description>&lt;h2 id="calculating-big-o" class="heading-anchor"&gt;Calculating Big-O&lt;a href="#calculating-big-o" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;This is the second in a three post series. The first post
&lt;a href="https://justin.abrah.ms/blog/2013-07-23-big-o-notation-explained.html"&gt;explains Big-O from a self-taught programmer&amp;rsquo;s perspective&lt;/a&gt;
. The third article talks about
&lt;a href="https://justin.abrah.ms/blog/2018-04-17-understanding-big-o-formal-definition.html"&gt;understanding the formal definition of Big-O&lt;/a&gt;
.&lt;/p&gt;
&lt;p&gt;So now that we &lt;a href="https://justin.abrah.ms/blog/2013-07-23-big-o-notation-explained.html"&gt;know what Big-O is&lt;/a&gt;, how do we calculate the Big-O
classification of a given function? It&amp;rsquo;s just as easy as following along with
your code and counting along the way.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_ones&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;a_list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above code is a classic example of an &lt;code&gt;O(n)&lt;/code&gt; function. This is
because we have to loop over every element that we get in order to
complete our calculation. We can trace this by following along the
code and counting. We&amp;rsquo;re doing a few calculations here.&lt;/p&gt;</description></item><item><title>Pricing books as a function of risk</title><link>https://justin.abrah.ms/blog/2013-10-14-book_price_based_on_risk.html</link><pubDate>Mon, 14 Oct 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-10-14-book_price_based_on_risk.html</guid><description>&lt;p&gt;I&amp;rsquo;ve started the motions for &lt;a href="https://leanpub.com/computer-science-for-self-taught-programmers"&gt;a book&lt;/a&gt; that teaches computer science
information to people who didn&amp;rsquo;t go through a university program. This
is pretty common in the field of programmers. It&amp;rsquo;s one of the few
knowledge-based fields where practical experience still competes
against university degrees.&lt;/p&gt;
&lt;h3 id="where-do-you-publish-a-book-like-this" class="heading-anchor"&gt;Where do you publish a book like this?&lt;a href="#where-do-you-publish-a-book-like-this" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;I came across &lt;a href="https://leanpub.com/"&gt;leanpub&lt;/a&gt;, which is a really interesting ebook publisher
and marketplace. You link your Dropbox account to their service and
edit Markdown files in a folder they share with you. They take this
and build a book for you in multiple formats.&lt;/p&gt;</description></item><item><title>The State of GitHub's Code Review</title><link>https://justin.abrah.ms/blog/2013-10-14-state_of_githubs_code_review.html</link><pubDate>Mon, 14 Oct 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-10-14-state_of_githubs_code_review.html</guid><description>&lt;h2 id="in-a-word-stagnant" class="heading-anchor"&gt;In a word: Stagnant&lt;a href="#in-a-word-stagnant" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Code review is an essential part of a team&amp;rsquo;s shipping process. It
helps disseminate knowledge across teams, catches bugs (or more likely
poor architectural decisions) before they bite you, and provide
opportunities to educate junior engineers. GitHub, the current de
facto standard for this, is letting us down.&lt;/p&gt;
&lt;p&gt;Perhaps they&amp;rsquo;ve hit some sort of local maximum for this activity, or
maybe they&amp;rsquo;re focused on providing GitHub functionality for verticals
like GIS or 3D modelers, but not much has changed in the world of
reviewing code in many years. Herein is my 5 item wish list for code
review.&lt;/p&gt;</description></item><item><title>Thinking of Databases as an Excel file</title><link>https://justin.abrah.ms/blog/2013-10-14-databases-as-an-excel-file.html</link><pubDate>Mon, 14 Oct 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-10-14-databases-as-an-excel-file.html</guid><description>&lt;p&gt;I was having a conversation recently around the value of databases as
opposed to flat files and the question &amp;ldquo;What is the essence of a
database?&amp;rdquo; came up. I explained it as it relates to Excel files, which
I think is surprisingly apt.&lt;/p&gt;
&lt;p&gt;Excel files are logically constructed around a few principles. First,
there is the file itself. This lives on a hard drive somewhere, it has
a name, and there is a program that can open it. When you open it up,
things are organized on multiple sheets. These sheets contain columns
and rows which contain data.&lt;/p&gt;</description></item><item><title>Big-O notation explained by a self-taught programmer</title><link>https://justin.abrah.ms/blog/2013-07-23-big-o-notation-explained.html</link><pubDate>Tue, 23 Jul 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-07-23-big-o-notation-explained.html</guid><description>&lt;p&gt;This is the first in a three post series. The second post talks about
&lt;a href="https://justin.abrah.ms/blog/2013-10-14-how-to-calculate-big-o.html"&gt;how to calculate Big-O&lt;/a&gt; . The third article
talks about
&lt;a href="https://justin.abrah.ms/blog/2018-04-17-understanding-big-o-formal-definition.html"&gt;understanding the formal definition of Big-O&lt;/a&gt;
.&lt;/p&gt;
&lt;p&gt;Big-O notation used to be a really scary concept for me. I thought
this is how &amp;ldquo;real&amp;rdquo; programmers talked about their code. It was all the
more scary because the academic descriptions (such as &lt;a href="https://en.wikipedia.org/wiki/Big_O_notation"&gt;Wikipedia&lt;/a&gt;) made
very little sense to me. This is frustrating because the underlying
concepts aren&amp;rsquo;t actually that hard.&lt;/p&gt;</description></item><item><title>Finding Unused files with Require.js imports</title><link>https://justin.abrah.ms/blog/2013-07-17-finding_unused_requirejs_imports.html</link><pubDate>Wed, 17 Jul 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-07-17-finding_unused_requirejs_imports.html</guid><description>&lt;p&gt;In an effort to clean up some code, I wanted to find a list of files
not imported by my app. I didn&amp;rsquo;t see anything in a brief search, so I
wrote this little script. Hopefully its helpful. It finds all
javascript files in directories you specify as parameters to the
script, greps your git repository for references to those files and
echos those that should be removed.&lt;/p&gt;
&lt;p&gt;This script does have the possibility for false negatives (ie: things
that aren&amp;rsquo;t used that we don&amp;rsquo;t mention) because we use
basenames. Examples might be a &lt;code&gt;foo/utils.js&lt;/code&gt; which is used hiding the
&lt;code&gt;bar/utils.js&lt;/code&gt; which isn&amp;rsquo;t used. You may need to run this multiple
times as deleting some files will uncover new unused files.&lt;/p&gt;</description></item><item><title>PyATOM for static site syndication</title><link>https://justin.abrah.ms/blog/2013-07-17-pyatom_as_static_site_rss.html</link><pubDate>Wed, 17 Jul 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-07-17-pyatom_as_static_site_rss.html</guid><description>&lt;p&gt;Bitten by the bug to write more and for others, I&amp;rsquo;ve brought back
syndication (via Atom rather than RSS) to the blog. I found a few
hundred subscribers still checking in on me, so thanks to you all for
sticking around. As I run a &lt;a href="https://justin.abrah.ms/blog/2011-07-14-orgmode_static_site_generator.html"&gt;static site&lt;/a&gt;, generating RSS can be a bit
of a pain.&lt;/p&gt;
&lt;p&gt;After a brief search of not finding anything for generating RSS or
Atom for static blogs, I started writing something in Go which would
take a YAML file and dump it into an ATOM format. A bit demoralized
with the state of YAML parsers (nothing seemingly working), I swapped
over to python. I was about to write a naive Atom dumper with a small
templating language, when I came across PyAtom. Thanks to Python&amp;rsquo;s
readable syntax, it makes for a fantastic feed writing format. As an
example, this is the atom feed of this blog with the last entry
populated.&lt;/p&gt;</description></item><item><title>PyATOM for static site syndication</title><link>https://justin.abrah.ms/blog/2013-07-17-pyatom_as_static_site_syndication.html</link><pubDate>Wed, 17 Jul 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-07-17-pyatom_as_static_site_syndication.html</guid><description>&lt;p&gt;Bitten by the bug to write more and for others, I&amp;rsquo;ve brought back
syndication (via Atom rather than RSS) to the blog. I found a few
hundred subscribers still checking in on me, so thanks to you all for
sticking around. As I run a &lt;a href="https://justin.abrah.ms/blog/2011-07-14-orgmode_static_site_generator.html"&gt;static site&lt;/a&gt;, generating RSS can be a bit
of a pain.&lt;/p&gt;
&lt;p&gt;After a brief search of not finding anything for generating RSS or
Atom for static blogs, I started writing something in Go which would
take a YAML file and dump it into an ATOM format. A bit demoralized
with the state of YAML parsers (nothing seemingly working), I swapped
over to python. I was about to write a naive Atom dumper with a small
templating language, when I came across PyAtom. Thanks to Python&amp;rsquo;s
readable syntax, it makes for a fantastic feed writing format. As an
example, this is the atom feed of this blog with the last entry
populated.&lt;/p&gt;</description></item><item><title>setup.py, distutils and testing.</title><link>https://justin.abrah.ms/blog/2013-07-17-setuppy_distutils_testing.html</link><pubDate>Wed, 17 Jul 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-07-17-setuppy_distutils_testing.html</guid><description>&lt;p&gt;In releasing the &lt;a href="https://github.com/justinabrahms/pisces/"&gt;web framework&lt;/a&gt; I&amp;rsquo;ve been working on, I went about
providing the things any upstanding python project does: a CI
configuration file, a setup.py and some tests.&lt;/p&gt;
&lt;p&gt;The setup.py file was simple enough. &lt;a href="https://www.jetbrains.com/pycharm/"&gt;PyCharm&lt;/a&gt; wrote one
automatically. I was surprised to learn that when using
distutils &lt;em&gt;defining dependencies in your setup.py doesn&amp;rsquo;t install them
with easy_install or pip&lt;/em&gt;. Its just a bit of metadata that is sent
upstream.&lt;/p&gt;
&lt;p&gt;The other gotcha is that I wanted single-command access to running my
tests. The easier tests are to run and write, the more likely they are
to be run and written. From setuptools land, a simple &lt;del&gt;python setup.py
test&lt;code&gt;and a&lt;/code&gt;setup.py&lt;/del&gt; entry was all it took to get
started. Unfortuantely, there is no specific information about setting
this up in either the distutils2 documentation or in the packaging
guide for Python. When attempting to cargo-cult my setup.py together,
I stumbled upon simplejson&amp;rsquo;s setup.py and came across a custom test
runner. You add a &lt;code&gt;cmdclass&lt;/code&gt; keyword argument to your setup.py with a
dict value mapping the command to the correct &lt;code&gt;distutils.core.Command&lt;/code&gt;
object to run.&lt;/p&gt;</description></item><item><title>Why Pisces?</title><link>https://justin.abrah.ms/blog/2013-07-17-why_pisces.html</link><pubDate>Wed, 17 Jul 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-07-17-why_pisces.html</guid><description>&lt;p&gt;&lt;a href="https://github.com/justinabrahms/pisces/"&gt;Pisces&lt;/a&gt; is a Python web framework that was written with testing in
mind. It was birthed as a reaction to the typical workflow in a Django
project, which I&amp;rsquo;ve come to dislike as it encourages you to make your
code tightly coupled and less testable.&lt;/p&gt;
&lt;h3 id="whats-wrong-with-django" class="heading-anchor"&gt;What&amp;rsquo;s wrong with Django?&lt;a href="#whats-wrong-with-django" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;The majority of my issues with Django can be summed up with one code
block pulled from the &lt;a href="https://sprint.ly/"&gt;Sprint.ly&lt;/a&gt; code base which is indicative of how
I&amp;rsquo;ve seen things work elsewhere.&lt;/p&gt;</description></item><item><title>Securing your email</title><link>https://justin.abrah.ms/blog/2013-07-03-securing-your-email.html</link><pubDate>Wed, 03 Jul 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-07-03-securing-your-email.html</guid><description>&lt;p&gt;With the recent news surrounding privacy implications here in the US, I’ve taken
it as an opportunity to encrypt and sign more emails that I send.&lt;/p&gt;
&lt;h2 id="motivations" class="heading-anchor"&gt;Motivations&lt;a href="#motivations" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The motivations I have behind sending encrypted email aren’t to hide secrets, as
I don’t really have anything to hide from the government. That said, I dislike
the act of surveillence without cause in itself. I believe the simple act of
passively recording all information is an inherintly immoral one and is easily
corruptable. Couple this with recent statements like:&lt;/p&gt;</description></item><item><title>Meaning is not zero-sum</title><link>https://justin.abrah.ms/blog/2013-05-30-meaning-is-not-zero-sum.html</link><pubDate>Thu, 30 May 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-05-30-meaning-is-not-zero-sum.html</guid><description>&lt;p&gt;Rick Turoczy
&lt;a href="http://futureofwork.glider.com/work-life-balance-is-a-myth/"&gt;wrote an article&lt;/a&gt;
about the role of meaning in the Work-Life balance equation. Rick suggests that
finding meaning in your life (in his words “an occupation that fulfills you”) is
a substitute for a work-life balance. I happen to fundamentally disagree with
his point. Unenjoyable activites lead to a poor life&lt;/p&gt;
&lt;p&gt;From &lt;a href="http://futureofwork.glider.com/work-life-balance-is-a-myth/"&gt;the post&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;It’s not a problem of how much time you spend &lt;strong&gt;with&lt;/strong&gt; meaning, it’s about how
much time you spend &lt;strong&gt;without&lt;/strong&gt; meaning.&lt;/p&gt;</description></item><item><title>Converting from MySQL to Postgres</title><link>https://justin.abrah.ms/blog/2013-05-21-converting_from_mysql_to_postgres.html</link><pubDate>Tue, 21 May 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-05-21-converting_from_mysql_to_postgres.html</guid><description>&lt;p&gt;In playing with &lt;a href="http://gitstreams.com"&gt;GitStreams&lt;/a&gt;, I&amp;rsquo;ve made the switch from MySQL to
Postgres. The reason for the switch was mostly shaming from [[&lt;a href="http://about.me/jdunck"&gt;http://about.me/jdunck&lt;/a&gt;][Jeremy
Dunck]], &lt;a href="http://www.chesnok.com/daily/"&gt;Selena Deckelmann&lt;/a&gt; and a few others. The results, however were
quite surprising.&lt;/p&gt;
&lt;h2 id="storage-efficiency" class="heading-anchor"&gt;Storage Efficiency&lt;a href="#storage-efficiency" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Operating on a budget $20/month
&lt;a href="http://www.linode.com/?r%3D1b2588fc92dac7ecb8bb76e85bf2fe730db4dc0c"&gt;Linode&lt;/a&gt;
server (affiliate link), disk space is precious to me. In using MySQL, my data
files were hovering just under 8GB for a couple of million rows of mostly-JSON
data. After the migration, my size-on-disk dropped to 3GB. This is quite
exciting for me as I&amp;rsquo;ve 2x&amp;rsquo;d the lifetime of this server. You can see the
[[&lt;a href="https://github.com/justinabrahms/go-gitstreams/blob/fc41957fd03224953a85cfdfec736e4cf3e62b3c/schema.sql"&gt;https://github.com/justinabrahms/go-gitstreams/blob/fc41957fd03224953a85cfdfec736e4cf3e62b3c/schema.sql&lt;/a&gt;][MySQL schema]]
and the
&lt;a href="https://github.com/justinabrahms/go-gitstreams/blob/29fe8ac0ce93e57f643552581d5e99c72240d3e3/schema.sql"&gt;Postgres schema&lt;/a&gt;
for comparison purposes. The main table is &lt;code&gt;streamer_activity&lt;/code&gt; .&lt;/p&gt;</description></item><item><title>Ignore Django, write testable code</title><link>https://justin.abrah.ms/blog/2013-05-21-ignore_django_write_tests.html</link><pubDate>Tue, 21 May 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-05-21-ignore_django_write_tests.html</guid><description>&lt;p&gt;One of the best talks at PyCon 2013 was Gary Barnhardt&amp;rsquo;s &lt;a href="http://pyvideo.org/video/1670/boundaries"&gt;Boundaries&lt;/a&gt;
talk. One aspect of the talk was avoiding mocking by making the data
interchange format based around value types. This is distinctly
separate from entity types (where the identity of the object is more
than the value). The canonical example value types is money. A $5 bill
is a value type because it can be evenly exchanged with any other $5
bill. Entity types on the other hand are closely correlated with their
identity. Even if a user has all the same preferences as another user,
it&amp;rsquo;s profile is distinct.&lt;/p&gt;</description></item><item><title>Project Structure for Advanced Beginners</title><link>https://justin.abrah.ms/blog/2013-03-12-projects-for-advanced-beginners.html</link><pubDate>Tue, 12 Mar 2013 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2013-03-12-projects-for-advanced-beginners.html</guid><description>&lt;p&gt;I&amp;rsquo;ve recently volunteered to help out &lt;a href="http://codescouts.org/"&gt;Code Scouts&lt;/a&gt;, a non-profit
organization tasked with helping people learn programming and increase
diversity in the field. One of the other mentors, &lt;a href="https://twitter.com/psbanka"&gt;Peter Banka&lt;/a&gt;, had a
very interesting take on project-based work.&lt;/p&gt;
&lt;h2 id="programming-projects-as-an-mmorpg" class="heading-anchor"&gt;Programming projects as an MMORPG&lt;a href="#programming-projects-as-an-mmorpg" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Peter&amp;rsquo;s idea was simple. Instead of requiring everyone to know
everything, let them specialize. The way he explained it was in terms
of looking for a quest group in an MMORPG. It takes a fighter and a
wizard and a few more to complete quests. That doesn&amp;rsquo;t mean one person
needs to know all things (at first, especially). The smaller the
surface area of things people need to learn before they&amp;rsquo;re
meaningfully contributing, the more engaged people are. I&amp;rsquo;d suspect
this positively correlates to fewer people churning out of the program
or generally being frustrated.&lt;/p&gt;</description></item><item><title>Why I changed my name</title><link>https://justin.abrah.ms/blog/2012-11-01-why-i-changed-my-name.html</link><pubDate>Thu, 01 Nov 2012 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2012-11-01-why-i-changed-my-name.html</guid><description>&lt;h2 id="justin-lillyabrahms" class="heading-anchor"&gt;Justin {Lilly,Abrahms}&lt;a href="#justin-lillyabrahms" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I got married, my wife and I chose to change our names. My new
name is Justin Abrahms. As I expect there will be several people
who have questions mostly around the question of &amp;ldquo;Why?&amp;rdquo;. So..&lt;/p&gt;
&lt;h3 id="why" class="heading-anchor"&gt;Why?&lt;a href="#why" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve been sort of interested in changing my name conceptually. I have
a fascination with weird polish names like Poliskiewicz
(Po-lis-ko-witz), Kowalski (Ko-wal-ski), or my good friend &lt;a href="http://apgwoz.com/"&gt;Andrew&amp;rsquo;s&lt;/a&gt;
last name. I&amp;rsquo;ve joked with &lt;a href="http://hackygolucky.com/"&gt;Tracy&lt;/a&gt; for years that we would change our
names when we eventually got married. When the time came, we started
really exploring the name thing. She asked &amp;ldquo;Well, what about my name,
Hinds?&amp;rdquo;. Pffft. I just couldn&amp;rsquo;t even entertain the idea. Then it hit
me: If I find it preposterous to take my wife&amp;rsquo;s name, why would I ask
her to take my name?&lt;/p&gt;</description></item><item><title>Cellphone Plans for Geeks</title><link>https://justin.abrah.ms/blog/2012-09-23-cellphone-plan-for-geeks.html</link><pubDate>Sun, 23 Sep 2012 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2012-09-23-cellphone-plan-for-geeks.html</guid><description>&lt;h2 id="same-stuff-less-money" class="heading-anchor"&gt;Same stuff, less money&lt;a href="#same-stuff-less-money" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;In an effort to be more frugal, I&amp;rsquo;ve recently altered my cellphone
plan to one in which I get unlimited data and text messages for
$30/mo. When I say frugal, I don&amp;rsquo;t mean cheap. The goal here isn&amp;rsquo;t to
spend as close to 0 dollars as possible, but rather to minimize the
expense things to the point feasible, given your values. I value
having a smartphone with maps (specifically with bicycling directions)
quite a lot, so I&amp;rsquo;m willing to spend money for it. &lt;a href="http://ericholscher.com/"&gt;Eric Holscher&lt;/a&gt; (the
only person I know with a feature phone) values knowing how to get
around the city without needing a phone, so his calculation is
different than mine. This is the essence of frugality. Now its just a
matter of minimizing the expense such that I can still get my maps any
time I want them.&lt;/p&gt;</description></item><item><title>Gittip: New, Interesting, Important</title><link>https://justin.abrah.ms/blog/2012-09-23-gittip.html</link><pubDate>Sun, 23 Sep 2012 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2012-09-23-gittip.html</guid><description>&lt;h2 id="great-possibilities-solid-direction" class="heading-anchor"&gt;Great possibilities, solid direction&lt;a href="#great-possibilities-solid-direction" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://gittip.com/"&gt;Gittip&lt;/a&gt; is a service for donating money to people (initially, open
source developers, but could be for anyone) with no strings
attached. Just keep being awesome. It&amp;rsquo;s being lead by [[&lt;a href="http://whit537.org/"&gt;http://whit537.org/&lt;/a&gt;][Chad
Whitacre]]. While the service is still a few months old, folks seem to
be using it and deriving benefit. All successful markers for the
system.&lt;/p&gt;
&lt;h3 id="how-it-works" class="heading-anchor"&gt;How it works&lt;a href="#how-it-works" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Donations made through gittip are anonymous in that recipients don&amp;rsquo;t
know who is giving them the money. This is meant to facilitate the
idea that the money isn&amp;rsquo;t for any particular work. This isn&amp;rsquo;t &amp;ldquo;because
you fixed that bug I had&amp;rdquo; or &amp;ldquo;so you &lt;em&gt;WILL&lt;/em&gt; fix that bug I have&amp;rdquo;. It&amp;rsquo;s
meant as ongoing encouragement for doing good things. The ongoing
portion of this is rather important. This isn&amp;rsquo;t a tip in the sense
that it is a one-time payment. You allocate some amount of money (1,
3, 6, 12, or 24 USD) to be paid out weekly to a person.&lt;/p&gt;</description></item><item><title>Personal Philosophy</title><link>https://justin.abrah.ms/blog/2012-09-15-personal_philosophy.html</link><pubDate>Sat, 15 Sep 2012 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2012-09-15-personal_philosophy.html</guid><description>&lt;h2 id="beliefs-in-action" class="heading-anchor"&gt;Beliefs in action&lt;a href="#beliefs-in-action" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been doing a bit of thinking lately about my own personal values
and how they drive my decisions on a day-to-day basis. I think, to
some degree, this is normal when going through a big move and starting
at a new job. You&amp;rsquo;re faced with people who don&amp;rsquo;t know much about
you. It also draws into focus some of the differences between you and
others. As such, I thought I would list a few things that I personally
believe both in hopes that you might learn something of me and I might
learn something of myself.&lt;/p&gt;</description></item><item><title>Literate programming with org-babel</title><link>https://justin.abrah.ms/blog/2012-01-15-literate_programming.html</link><pubDate>Sun, 15 Jan 2012 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2012-01-15-literate_programming.html</guid><description>&lt;p&gt;As part of my &lt;a href="https://justin.abrah.ms/blog/2011-07-14-orgmode_static_site_generator.html"&gt;ongoing love affair&lt;/a&gt; with emacs, I&amp;rsquo;ve started annotating
my dotfiles with &lt;a href="http://orgmode.org/worg/org-contrib/babel/"&gt;org-babel&lt;/a&gt;. This may on the surface sound syncing
these things would be a tedious task, but thanks to [[&lt;a href="http://en.wikipedia.org/wiki/literate_programming"&gt;http://en.wikipedia.org/wiki/literate_programming&lt;/a&gt;][literate
programming]], its not too bad.&lt;/p&gt;
&lt;h2 id="literate-programming" class="heading-anchor"&gt;Literate programming?&lt;a href="#literate-programming" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Literate programming is a concept in which you write prose and embed
in it source code. You can see examples of it in &lt;a href="https://justin.abrah.ms/blog/configs/git.html"&gt;my article on git&lt;/a&gt;. It
has the benefit of being written for humans in the first place. I
haven&amp;rsquo;t spent enough time with it to know if this is true, but I
suspect it also makes updating the documentation with a given change a
little easier as well.&lt;/p&gt;</description></item><item><title>EasyMock for mere mortals</title><link>https://justin.abrah.ms/blog/2011-08-04-easymock_for_mortals.html</link><pubDate>Thu, 04 Aug 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-08-04-easymock_for_mortals.html</guid><description>&lt;p&gt;I&amp;rsquo;ve found, during my brief experience with EasyMock, that trudging
through the documentation makes it terribly difficult to get things
done. From my reading, I wrote a handful of tests which use the
&lt;code&gt;reset()&lt;/code&gt;, &lt;code&gt;replay()&lt;/code&gt;, &lt;code&gt;verify()&lt;/code&gt; dance. When I changed trivial things
in my implementation, all of my tests broke. &amp;ldquo;We expected you to call
&lt;code&gt;uselessMethod()&lt;/code&gt; but you didn&amp;rsquo;t!&amp;rdquo;&lt;/p&gt;
&lt;h2 id="simply-fulfilling-an-interface" class="heading-anchor"&gt;Simply fulfilling an interface&lt;a href="#simply-fulfilling-an-interface" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Simply put, &lt;code&gt;verify()&lt;/code&gt; is overrated. It turns out that the majority of
what I want out of easymock is for it to override all of the
interface&amp;rsquo;s methods with &lt;code&gt;OperationNotSupported&lt;/code&gt; exceptions, except
for a few precious methods, which I can provide a bit of
implementation. This is done by just simply not calling &lt;code&gt;verify()&lt;/code&gt; at
the end of the method. While you don&amp;rsquo;t assert that X method was called
Y times, chances are, you really don&amp;rsquo;t want to do that anyway. It ties
you terribly close to your implementation, making your tests brittle.&lt;/p&gt;</description></item><item><title>Django at 30,000ft: A Manager's View</title><link>https://justin.abrah.ms/blog/2011-07-25-django_at_30000ft.html</link><pubDate>Mon, 25 Jul 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-07-25-django_at_30000ft.html</guid><description>&lt;p&gt;/Note: This article was originally published in the September 2008
edition of Python Magazine. It is published here edited only for formatting./&lt;/p&gt;
&lt;p&gt;&lt;a href="http://djangoproject.com/"&gt;Django&lt;/a&gt; is a full-stack web framework based in Python that allows you
to achieve fast turnaround times. &amp;ldquo;Full-stack web framework&amp;rdquo; basically
means it comes with tools necessary to access information in your
database(s), report that information back to the user and many of the
other functions you need on an everyday basis when dealing with web
applications.&lt;/p&gt;</description></item><item><title>Vim &amp; Python: Making yourself at home</title><link>https://justin.abrah.ms/blog/2011-07-25-vim_and_python.html</link><pubDate>Mon, 25 Jul 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-07-25-vim_and_python.html</guid><description>&lt;p&gt;You might look at Python code every day, but what is the lens through
which you view code? It&amp;rsquo;s your text editor. This article was written
for Python Magazine and was first in a series on Python development
environments. Here, we look at how Vim users can boost their
productivity by having Vim tell you as much as possible about your
program, while you&amp;rsquo;re writing it.&lt;/p&gt;
&lt;p&gt;As developers, we spend a majority of our productive day interacting
with code. How we interact with this code is often the last thing on
our mind. Taking a step back and looking at our daily habits can often
yield surprising results in productivity, and is a healthy thing to do
once in a while.&lt;/p&gt;</description></item><item><title>Writing a static site generator using org-mode.</title><link>https://justin.abrah.ms/blog/2011-07-14-orgmode_static_site_generator.html</link><pubDate>Thu, 14 Jul 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-07-14-orgmode_static_site_generator.html</guid><description>&lt;p&gt;This site is now generated through &lt;a href="http://orgmode.org/"&gt;org-mode&lt;/a&gt;, an emacs library which
is used for outlining. The generation of the HTML lies in the export
functionality of outlines. The benefits of this system is that its
easy, uses a tool that I&amp;rsquo;m already familiar with, and extensible.&lt;/p&gt;
&lt;h2 id="motivations" class="heading-anchor"&gt;Motivations&lt;a href="#motivations" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;My old site was written in Django and was consuming a fair amount of
system resources. This has little to do with Django itself, but more
with my hosting setup. In an effort to simplify, I&amp;rsquo;ve changed hosting
and, with this, changed what generates my website. Part of this change
is removing many of the &amp;ldquo;expensive&amp;rdquo; operations in a server, such as
python interpreters that run per site. Now, while sustaining 150
requests per second, the hosting setup only consumes 4% of my 64mb of
ram allotment.&lt;/p&gt;</description></item><item><title>6 things I learned about setuptools</title><link>https://justin.abrah.ms/blog/2011-06-17-setuptools_lessons.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-setuptools_lessons.html</guid><description>&lt;p&gt;While building &lt;a href="http://pypi.python.org/pypi/pyvcs/"&gt;pyvcs&lt;/a&gt; and
&lt;a href="http://pypi.python.org/pypi/django-vcs"&gt;django-vcs&lt;/a&gt; over 4th of July weekend
with Alex Gaynor [fn:0] , there were a few interesting lessons learned, mostly
revolving around how setuptools works. As Jacob mentions in his
[[&lt;a href="http://jacobian.org/writing/django-apps-with-buildout/"&gt;http://jacobian.org/writing/django-apps-with-buildout/&lt;/a&gt;][post on buildout]] ,
you mostly have to cobble together the usage of setuptools from other setups.
This works well at about 90% of the case. There are a few gotchas, however.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;find_packages(&amp;lsquo;directory&amp;rsquo;) will look under directory for a list of python
modules to install. For our applications, we actually just wanted
find_packages()&lt;/li&gt;
&lt;li&gt;You can&amp;rsquo;t easily specify multiple authors for a project. We settled on
author = &amp;ldquo;First Author, Second Author&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Its a good idea to version target your requirements. Don&amp;rsquo;t require &amp;ldquo;pyvcs&amp;rdquo;,
require &amp;ldquo;pyvcs&amp;gt;=0.1&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;If your project contains django templates, set the zip_safe property to
False.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;register&lt;/code&gt; or &lt;code&gt;sdist upload&lt;/code&gt; setup.py commands actually check that your
project installs. For that, its likely better to use a virtualenv and test
the installation.&lt;/li&gt;
&lt;li&gt;package_data is used to includes docs (or in our case, templates) with the
project.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;[fn:0] You can find the announcement &lt;a href="http://lazypython.blogspot.com/2009/07/announcing-pyvcs-django-vcs-and-piano.html"&gt;here.&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Bash: Your forgotten friend (part 1)</title><link>https://justin.abrah.ms/blog/2011-06-17-forgotten_friend_1.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-forgotten_friend_1.html</guid><description>&lt;p&gt;In the name of meta-productivity, or improving productivity by
improving process, I&amp;rsquo;ve come to learn and love Bash. For those who
aren&amp;rsquo;t familiar, Bash is the &amp;ldquo;scary&amp;rdquo; black terminal in Mac and
Linux. Its often recognized as the home of true geeks a la
Wargames. From here out, I&amp;rsquo;ll assume a basic knowledge of bash (what
&amp;ldquo;export&amp;rdquo; and similar commands do). In an effort to spread some of the
joy of Bash, I&amp;rsquo;ve included a few handy features and tricks that help
me out day to day.&lt;/p&gt;</description></item><item><title>Bash: Your forgotten friend (part 2)</title><link>https://justin.abrah.ms/blog/2011-06-17-forgotten_friend_2.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-forgotten_friend_2.html</guid><description>&lt;p&gt;Aliases are one of the core portions of Bash that will help you become
more productive almost immediately. To define an alias, the command is
simply:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;short&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;long command goes here&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Super simple! To save aliases, however, you&amp;rsquo;ll need to put them in
your .bash_profile so they load automatically. To see a list of
currently defined aliases, type &lt;code&gt;alias&lt;/code&gt;. Here are my aliases, chunk by
chunk, and a brief bit about what they do.&lt;/p&gt;</description></item><item><title>Bash: Your forgotten friend (part 3)</title><link>https://justin.abrah.ms/blog/2011-06-17-forgotten_friend_3.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-forgotten_friend_3.html</guid><description>&lt;p&gt;For the final installment of Bash: Your forgotten friend (see:
&lt;a href="https://justin.abrah.ms/blog/2011-06-17-forgotten_friend_1.html"&gt;part one&lt;/a&gt; and
&lt;a href="https://justin.abrah.ms/blog/2011-06-17-forgotten_friend_2.html"&gt;part two&lt;/a&gt; ), I&amp;rsquo;ll be going over the functions I
use to make life easy. For those unfamiliar, functions aren&amp;rsquo;t as scary as they
sound. They&amp;rsquo;re basically things that are too complex for simple aliases but
aren&amp;rsquo;t worth writing an entire bash script to do. This doesn&amp;rsquo;t, however, mean
that they aren&amp;rsquo;t powerful. You can pack a lot of functionality into these small
functions.&lt;/p&gt;</description></item><item><title>Customizing Django Forms Multiwidgets</title><link>https://justin.abrah.ms/blog/2011-06-17-django_multiwidget.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-django_multiwidget.html</guid><description>&lt;p&gt;This once contained slides to a talk I gave to django-nyc. While I
don&amp;rsquo;t know where those are anymore, you can find the resulting code
demonstration on &lt;a href="https://github.com/justinabrahms/django_multiwidget_demo/tree"&gt;github&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Developing a Personal Brand</title><link>https://justin.abrah.ms/blog/2011-06-17-developing_a_personal_brand.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-developing_a_personal_brand.html</guid><description>&lt;p&gt;I&amp;rsquo;ve spent the last year in classes at &lt;a href="http://aionline.edu"&gt;AiO&lt;/a&gt;, and they have really
brought me a better understanding on the importance of things like
branding. It provides a consistent feeling across your site and other
products, such as business cards, resumes, and invoices. It offers
people who interact with you assurance that they&amp;rsquo;re dealing with the
same person as before through the use of visual touchstones. A lot of
people get the concept of branding wrong, though. Branding isn&amp;rsquo;t about
putting your logo on everything you own. That&amp;rsquo;s called making
something garish. Branding is just using a consistent style across
everything: the same font, the same colors, even something as
intangible as the same sense of humor in your writing. It all plays a
part in your brand.&lt;/p&gt;</description></item><item><title>Django Portfolio Application</title><link>https://justin.abrah.ms/blog/2011-06-17-django_portfolio.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-django_portfolio.html</guid><description>&lt;p&gt;As I near the end of my run with &lt;a href="http://aionline.edu/"&gt;AiO&lt;/a&gt;, I&amp;rsquo;ve been asked to come up
with a portfolio. This has been pretty time consuming as there have
been several rounds of critiques as I went through the process. The
last stage of this journey, at least as far as the school is
concerned, is the creation of an interactive portfolio. While the
class will be doing theirs in Dreamweaver (&lt;em&gt;eew&lt;/em&gt;), I&amp;rsquo;ve elected to
create a reusable application for django to handle this. This is
basically a mind dump of what it should include in hopes someone will
spot something I&amp;rsquo;ve missed.&lt;/p&gt;</description></item><item><title>django-voting: A brief tutorial</title><link>https://justin.abrah.ms/blog/2011-06-17-django_voting.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-django_voting.html</guid><description>&lt;p&gt;django-voting is a reusable application which gives you reddit-style
voting capabilities on generic objects. The application, itself, is a
very well documented piece of software. Then again, that&amp;rsquo;s not saying
a lot considering its from Jonathan Buchannan. All of his projects are
famously documented.&lt;/p&gt;
&lt;h2 id="installation" class="heading-anchor"&gt;Installation&lt;a href="#installation" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;The installation of this application was standard fare for a google code
app. SVN Checkout the application to a point on your python path and
that&amp;rsquo;s about it. For me, the command was: ::&lt;/p&gt;</description></item><item><title>Django, PyISAPIe and IIS</title><link>https://justin.abrah.ms/blog/2011-06-17-django_and_pyisapie.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-django_and_pyisapie.html</guid><description>&lt;p&gt;For those poor souls who are forced to deploy Django on IIS, I feel
your pain. I spent the better part of my morning fixing a broken
PyISAPIe. To shortcut your trek, here&amp;rsquo;s what I&amp;rsquo;ve found.&lt;/p&gt;
&lt;p&gt;Signals have changed since the last release. To fix this, I altered
the call to signals to directly call the signals instead of importing
the signals module. I then updated the signal calls themselves to
reflect the new style.&lt;/p&gt;</description></item><item><title>Domain Sniffing Middleware</title><link>https://justin.abrah.ms/blog/2011-06-17-domain_sniffing_middleware.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-domain_sniffing_middleware.html</guid><description>&lt;p&gt;My first project for the new job has been creating an
internationalized version of the website. I think it also serves as a
good test run for how django works with the infrastructure that&amp;rsquo;s in
place. Instead of having two separate django installations, each with
mirrored files (save settings.LANGUAGE_CODE), I wrote a quick
middleware which will add a session key for django_language, which is
used by the locale middleware to determine which version of the site
to show you, based on the domain you&amp;rsquo;re accessing.&lt;/p&gt;</description></item><item><title>Emacs and Transmit: Remote edit Fix</title><link>https://justin.abrah.ms/blog/2011-06-17-emacs_and_transmit.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-emacs_and_transmit.html</guid><description>&lt;p&gt;So I&amp;rsquo;m a huge fan of Panic&amp;rsquo;s &lt;a href="http://www.panic.com/transmit/"&gt;Transmit&lt;/a&gt; application, as referenced by my
&lt;a href="https://justin.abrah.ms/blog/2011-06-17-most_used_programs_index.html"&gt;favorites post&lt;/a&gt;. Its ease of use makes editing remote files not
suck. One very cool feature of Transmit is its ability to edit remote
files with any sort of editor. This works famously with both Textmate
and Vim, but didn&amp;rsquo;t quite work for me in emacs. After sending an email
to the fellows at Panic, I got the fix in about 20 minutes. Those guys
completely rock (go buy their software!).&lt;/p&gt;</description></item><item><title>Emacs: Being Productive</title><link>https://justin.abrah.ms/blog/2011-06-17-being_productive.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-being_productive.html</guid><description>&lt;p&gt;As not to give false ideas of what this post is about, let&amp;rsquo;s lay it
out up front. I&amp;rsquo;m going to show you how to be able to get work done in
emacs. You&amp;rsquo;re not going to be an emacs guru after reading this. You&amp;rsquo;re
not even going to be all that productive. That being said, you will be
able to accomplish some work.&lt;/p&gt;
&lt;h2 id="configuration-for-an-effective-session" class="heading-anchor"&gt;Configuration for an Effective Session&lt;a href="#configuration-for-an-effective-session" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Following Steve Yegge&amp;rsquo;s &lt;a href="https://sites.google.com/site/steveyegge2/effective-emacs"&gt;epic post&lt;/a&gt;, there are a few things in there
that you might question. I know I did. He suggests swapping the places
of capslock and control. At first this just seemed pointless. I
ignored his suggestion and after 2 days, I got a case of emacs pinkie
which is pain from over use. Taking his suggestion, however, has
proven to be quite helpful. It keeps my fingers on the home row a
majority of the time which allows for speedier typing. Another change
he suggested, C-w as kill-word, seemed to be another one of those
small gains that wasn&amp;rsquo;t worth doing. Turns out, I still
don&amp;rsquo;t. Kill-word itself is quite useful, but remapping C-w makes using
other&amp;rsquo;s emacsen painful. I&amp;rsquo;ve tried to stop customizing the built-in
shortcuts for portability. The only one I can&amp;rsquo;t live without is
C-M-hjkl for navigation between buffers.&lt;/p&gt;</description></item><item><title>Emacs: Introduction &amp; Installation</title><link>https://justin.abrah.ms/blog/2011-06-17-introduction_installation.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-introduction_installation.html</guid><description>&lt;h2 id="a-very-brief-background" class="heading-anchor"&gt;A (very) Brief Background&lt;a href="#a-very-brief-background" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;So emacs is one of those programs that never dies.. it just looks that
way. Development for emacs began in the 70&amp;rsquo;s and is still active,
making it somewhat of a big deal in terms of computer history. Emacs
stands for Editor MACroS and was originally designed for some archaic
system I&amp;rsquo;ve never heard of. If you&amp;rsquo;re really that interested, check
out the &lt;a href="http://en.wikipedia.org/wiki/GNU_Emacs#History"&gt;wikipedia entry&lt;/a&gt;. The plural form of emacs is emacsen. There is
a very popular fork of emacs called Xemacs, which forked in 1991
apparently due to emacs&amp;rsquo;s glacial release cycle. Over time, they&amp;rsquo;ve
converged on features (I think), and mostly serve as a headache to
people wanting to support both. Enough about that.. On to the
important stuff.&lt;/p&gt;</description></item><item><title>Emacs: The Mindset, A contextual shift</title><link>https://justin.abrah.ms/blog/2011-06-17-mindset_contextual_shift.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-mindset_contextual_shift.html</guid><description>&lt;p&gt;There were a few insights I got when I switched from vim to
emacs. Hopefully they&amp;rsquo;ll help you get a leg up.&lt;/p&gt;
&lt;h2 id="meta-vs-ctrl" class="heading-anchor"&gt;Meta vs. Ctrl&lt;a href="#meta-vs-ctrl" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Learning the difference between meta and ctrl was my first aha moment
when I started using emacs. There is a definite difference in the
general functions of the control key and the meta key in reference for
navigation and text manipulation.&lt;/p&gt;</description></item><item><title>Fixing your models subdirectory</title><link>https://justin.abrah.ms/blog/2011-06-17-fitures_model_subdir.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-fitures_model_subdir.html</guid><description>&lt;p&gt;For those of you who keep your models in a subdirectory, you may have
noticed that you can&amp;rsquo;t properly load fixtures. This is because Django
checks for the location of your models file to determine your app
directory. To fix this, move your models directory to something like
modeldir and create a models.py which imports the models from inside.&lt;/p&gt;
&lt;p&gt;Before:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myapp
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;|__ views.py
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;|__ __init__.py
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;|__ models/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;|____ __init__.py
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;|____ mymodel1.py
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;|____ mymodel2.py
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After:&lt;/p&gt;</description></item><item><title>Google account suspended: A post mortem</title><link>https://justin.abrah.ms/blog/2011-06-17-google_account_suspended.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-google_account_suspended.html</guid><description>&lt;p&gt;A few weeks back, I had my Google account disabled. If you&amp;rsquo;re anything
like me, your first reaction is a lackadaisical, &amp;ldquo;That sucks.&amp;rdquo; Then
the realization of what that really means starts to creep in to your
gut, making you nauseous. No more email. No more iGoogle homepage. No
more feed reader. Next year&amp;rsquo;s vacation spots you had mapped out in a
comparison chart on Google Docs? Yep, those are gone too. More Nausea.&lt;/p&gt;</description></item><item><title>Importance of Documentation</title><link>https://justin.abrah.ms/blog/2011-06-17-importance_of_documentation.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-importance_of_documentation.html</guid><description>&lt;p&gt;I think there is a bit of a pain point for me currently with regards
to open source software: documentation. I&amp;rsquo;ve been in a position where
I need to create a GUI application for HTML generation with a bit of
database interaction. Nothing too serious, but a bit of help wouldn&amp;rsquo;t
be a bad thing.&lt;/p&gt;
&lt;p&gt;The first result google brought to me was &lt;a href="http://dabodev.com/"&gt;dabo&lt;/a&gt;, a gui application
framework based on &lt;a href="http://wxpython.org/"&gt;wxPython&lt;/a&gt;. Cross platform GUI apps with the ease of
development provided by a framework? Sign me up! Then came my
impasse. No download link. I traversed their wiki for a solid 15-20
minutes trying to find a way to download this awesome application. No
results, it would seem.&lt;/p&gt;</description></item><item><title>Javascript unit tests with JS Test Driver</title><link>https://justin.abrah.ms/blog/2011-06-17-javascript_unit_tests.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-javascript_unit_tests.html</guid><description>&lt;p&gt;The general idea for &lt;a href="http://code.google.com/p/js-test-driver/"&gt;JS Test Driver&lt;/a&gt; is that it allows you to run
javascript unit tests. While this is nothing new, there are some
interesting bits. JSTD provides XML output of tests running, which can
be used for CI integration and test coverage. It can also run your
tests across multiple browsers.&lt;/p&gt;
&lt;h2 id="js-test-driver-installation" class="heading-anchor"&gt;JS Test Driver Installation&lt;a href="#js-test-driver-installation" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;JSTD&amp;rsquo;s only dependencies are java and a browser, which makes it very
easy to get it setup. I&amp;rsquo;m assuming you are on an Ubuntu machine, if
you aren&amp;rsquo;t, you&amp;rsquo;re on your own.&lt;/p&gt;</description></item><item><title>Macports and PYTHONPATH</title><link>https://justin.abrah.ms/blog/2011-06-17-macports_and_pythonpath.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-macports_and_pythonpath.html</guid><description>&lt;p&gt;Setting up my new macbook, I&amp;rsquo;ve had to go through the joy and pleasure
that is &lt;a href="http://www.macports.org/"&gt;macports&lt;/a&gt;. Overall, it wasn&amp;rsquo;t so bad. A few missing packages
here or there. Everything was going fine until I tried to install
&lt;a href="http://fabfile.org/"&gt;Fabric&lt;/a&gt;. Its dependency on pycrypto kept failing. I had installed
pycrypto via macports and no luck. Turns out there are two paths under
opt which need to be added to the python path in order to get it to
work.&lt;/p&gt;</description></item><item><title>Most Used Programs: An Index</title><link>https://justin.abrah.ms/blog/2011-06-17-most_used_programs_index.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-most_used_programs_index.html</guid><description>&lt;p&gt;/Note: This represents a snapshot in time. I may or may not still be
using these pieces of software./&lt;/p&gt;
&lt;p&gt;Attempting to index those programs you use every day is, in my
opinion, a worthwhile task, if only in hopes of getting suggestions
for X program being better than Y.&lt;/p&gt;
&lt;h2 id="browser" class="heading-anchor"&gt;Browser&lt;a href="#browser" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m a &lt;a href="http://firefox.com"&gt;firefox&lt;/a&gt; junkie. There are few times when I&amp;rsquo;ve had to turn to
other browsers outside cross-browser testing. &lt;a href="http://www.webkit.org/"&gt;Webkit&lt;/a&gt; offers some
nice speed increases (especially where javascript is concerned), but
&lt;a href="http://getfirebug.com"&gt;firebug&lt;/a&gt;, &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/delicious-bookmarks/"&gt;delicious&lt;/a&gt; plugin and &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/"&gt;greasemonkey&lt;/a&gt; really make this
the browser for me.&lt;/p&gt;</description></item><item><title>NameError: global name 'log' is not defined</title><link>https://justin.abrah.ms/blog/2011-06-17-nameerror_log_undefined.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-nameerror_log_undefined.html</guid><description>&lt;p&gt;I&amp;rsquo;ve spent a portion of this evening trying to get caught up with the
crazy amounts of development that have been going on with the &lt;a href="https://github.com/brosner/oebfare/network/"&gt;oebfare&lt;/a&gt;
blogging engine over the past few weeks. I have a nice little Ubuntu
VM setup that works really nicely, but when gathering the requirements
for the projects, I hit a snag. I apparently had a borked setuptools
(installed via apt) which resulted in the error::&lt;/p&gt;</description></item><item><title>Piping to stdout when using BuildBot</title><link>https://justin.abrah.ms/blog/2011-06-17-stdout_with_buildbot.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-stdout_with_buildbot.html</guid><description>&lt;p&gt;Just a quick tidbit for anyone googling like I have been all morning:&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re attempting to pipe a command in a buildbot script, you need
to issue it as a single string, not a list of strings. By using a
single string, buildbot uses a shell, otherwise it doesn&amp;rsquo;t. The &amp;gt;
necessary for output redirection is a shell thing, which will only
work in this method.&lt;/p&gt;
&lt;p&gt;To recap:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;f1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addStep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ShellCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/home/www/bin/django&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;build_solr_schema&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/etc/solr/conf/schema.xml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;building&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;schema&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;descriptionDone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;schema&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;built&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;becomes:&lt;/p&gt;</description></item><item><title>psycopg2 Internal Error</title><link>https://justin.abrah.ms/blog/2011-06-17-psycopg2_internal_error.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-psycopg2_internal_error.html</guid><description>&lt;p&gt;For those who&amp;rsquo;ve hit the following complaint with django (like I just
did):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;psycopg2.InternalError: current transaction is aborted, commands ignored until end of transaction block
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You need to set up PostGIS and ensure that the table you&amp;rsquo;re looking at
has been created from the template_postgis template. Just a warning,
check your database logs for more info.&lt;/p&gt;</description></item><item><title>Speedy Google Code Checkouts</title><link>https://justin.abrah.ms/blog/2011-06-17-google_code_checkout.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-google_code_checkout.html</guid><description>&lt;p&gt;Here&amp;rsquo;s a handy bash shortcut for automatically checking out a google-code
project.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SVN ALIASES&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;GOOGLE_CODE_CHECKOUTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Code/trunks&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gcco &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; svn checkout http://&lt;span class="nv"&gt;$@&lt;/span&gt;.googlecode.com/svn/trunk/ &lt;span class="nv"&gt;$GOOGLE_CODE_CHECKOUTS&lt;/span&gt;/&lt;span class="nv"&gt;$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Top 5 Bookmarklets</title><link>https://justin.abrah.ms/blog/2011-06-17-top_5_bookmarklets.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-top_5_bookmarklets.html</guid><description>&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="http://simonwillison.net/2007/Aug/15/jquery/"&gt;Insert jQuery&lt;/a&gt; : This
bookmarklet is amazing if you&amp;rsquo;re a &lt;a href="http://getfirebug.com/"&gt;firebug&lt;/a&gt; user. It
allows you to use jquery in firebug, even when the site doesn&amp;rsquo;t support it. I
use it for things ranging from checking a bunch of checkboxes or checking the
number of uses for a particular css class. You don&amp;rsquo;t know that you&amp;rsquo;re missing
it until you don&amp;rsquo;t have jQuery at your fingertips. (The bookmarklet is
towards the middle)&lt;/p&gt;</description></item><item><title>Using Database views with Django</title><link>https://justin.abrah.ms/blog/2011-06-17-database_views_django.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-database_views_django.html</guid><description>&lt;p&gt;Database views will make their appearance in the upcoming Django 1.1
release. Having used them for my latest project, there are a few
gotchas when it comes to using them.&lt;/p&gt;
&lt;p&gt;In our project, we were using &lt;a href="http://south.aeracode.org/"&gt;South&lt;/a&gt; for our database migrations. To
ensure our database views were created, we added them to a south
migration using &lt;code&gt;db.execute&lt;/code&gt;. This worked very well for 90% of our
use case. The biggest hurdle for this ended up being testing. When
syncdb runs, your unmanaged models (ie: database views) aren&amp;rsquo;t
generated. There were a few options available to us at this point.&lt;/p&gt;</description></item><item><title>Using test generators to save time</title><link>https://justin.abrah.ms/blog/2011-06-17-test_generators.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-test_generators.html</guid><description>&lt;p&gt;Test generators are an amazing tool when you are testing small
variations in the same code path. It uses generators[fn:0] which yield
callables[fn:1] that are called as the test suite runs. For example,
imagine you&amp;rsquo;re testing a rounding library.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestRound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_check_rounding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_rounding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_check_rounding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# VERSUS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestRound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_rounding_same&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_rounding_one_dot_nine_to_two&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.9&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While these two examples look mostly similar for 2 cases, imagine what
ten cases would look like, or 50. For a much more real-world example,
imagine a test generator which will crawl your webapp&amp;rsquo;s url routing
setup and assert that each of them return a 200 status code.&lt;/p&gt;</description></item><item><title>Versioning Production Settings</title><link>https://justin.abrah.ms/blog/2011-06-17-versioning_production_settings.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-versioning_production_settings.html</guid><description>&lt;p&gt;In deploying my latest side project, I came across a conundrum. How do
you manage production specific settings files (complete with
passwords, API keys and other secrets), while still publishing the
source code?&lt;/p&gt;
&lt;p&gt;Until now, I&amp;rsquo;ve had unversioned production settings sitting around the
file system. While this hasn&amp;rsquo;t failed me yet, its only a matter of
time. Sensing an opportunity to derail a perfectly good deployment for
another half hour, I&amp;rsquo;ve come up with what I think is a seemingly solid
way to keep those production settings around: git submodules.&lt;/p&gt;</description></item><item><title>Vim Screencast: % Operator</title><link>https://justin.abrah.ms/blog/2011-06-17-screencast_percent_operator.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-screencast_percent_operator.html</guid><description>&lt;p&gt;Here&amp;rsquo;s another in my series of vim screencasts. This one talks about
the various uses of the % operator. You can find the video at
&lt;a href="http://showmedo.com/videotutorials/video?name%3D3160020"&gt;http://showmedo.com/videotutorials/video?name%3D3160020&lt;/a&gt; (likely dead)&lt;/p&gt;
&lt;p&gt;In non-editing mode, the % operator swaps between (), [] or {} style
braces. This is super helpful for PHP style syntax that wraps large
portions of code in these. The real power of the % operator comes in
Ex mode, however.&lt;/p&gt;
&lt;p&gt;Ex mode is the mode that is triggered by the colon ( : ). It prefaces
such commands as :w[rite] or :q[uit]. In this mode, the % sign
represents your current working file. You can use it to great effect
with the ! operator which escapes to the shell temporarily. This
allows commands such as::&lt;/p&gt;</description></item><item><title>Vim Screencast: An Introduction</title><link>https://justin.abrah.ms/blog/2011-06-17-screencast_an_introduction.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-screencast_an_introduction.html</guid><description>&lt;p&gt;In my latest screencast, I&amp;rsquo;ve gone a bit longer than normal (about 7
minutes) in order to cover an introduction to vim. In this screencast,
I give a brief overview of modal editing and what that means. I then
go over how to move around in vim, how to enter editing mode in
various and interesting ways. After that, how to cut / copy and paste
were next on the list. Finally, I showed how to save and exit a vim
file. You can find the video at
&lt;a href="http://showmedo.com/videotutorials/video?name%3D3160030%3BfromSeriesID%3D316"&gt;http://showmedo.com/videotutorials/video?name%3D3160030%3BfromSeriesID%3D316&lt;/a&gt;
(Unfortunately dead since original publishing).&lt;/p&gt;</description></item><item><title>Vim Screencast: Macros</title><link>https://justin.abrah.ms/blog/2011-06-17-screencast_macros.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-screencast_macros.html</guid><description>&lt;p&gt;Having tried for literally days to get a legible screencast uploaded
and online to any of a number of video services, I&amp;rsquo;ve decided to link
to the actual file itself. This is a very quick and simple screencast
of how to use macros in Vim. You can find the video at
&lt;code&gt;showmedo.com/videotutorials/video?name=3160000&amp;amp;fromSeriesID=316&lt;/code&gt;
(likely dead).&lt;/p&gt;</description></item><item><title>Vim Screencast: Selections</title><link>https://justin.abrah.ms/blog/2011-06-17-screencast_selections.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-screencast_selections.html</guid><description>&lt;p&gt;This is a relatively short screencast on a few different ways to
select text in Vim. Vim&amp;rsquo;s visual mode is a very powerful feature of
the editor which allows you to select data in different, yet
meaningful, ways.&lt;/p&gt;
&lt;p&gt;The screencast goes over normal visual mode, visual block mode, and
text object selection. The relevant helpfiles are::&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;:h visual-mode
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;:h v_b_i
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;:h text-objects
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As a developer, its as important to know your editor as well as a
carpenter knows his hammer. You can find this video at
&lt;a href="http://showmedo.com/videotutorials/video?name%3D3160010"&gt;http://showmedo.com/videotutorials/video?name%3D3160010&lt;/a&gt; (likely dead).&lt;/p&gt;</description></item><item><title>Vim: My new IDE</title><link>https://justin.abrah.ms/blog/2011-06-17-my_new_ide.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-my_new_ide.html</guid><description>&lt;p&gt;On &lt;a href="http://michaeltrier.com/"&gt;Michael Trier&lt;/a&gt;&amp;rsquo;s suggestion, I&amp;rsquo;ve decided to make Vim my primary
editor once again. Having recently switched from Textmate, there were
a few things that I needed to get up and running to stay
productive. Here they are in no particular order.&lt;/p&gt;
&lt;h2 id="nerdtree" class="heading-anchor"&gt;NERDtree&lt;a href="#nerdtree" class="anchor-link" aria-label="Link to this section"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://justin.abrah.ms/images/nerdtree.png" alt="NERDtree screenshot"&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://www.vim.org/scripts/script.php?script_id=1658"&gt;NERDtree&lt;/a&gt; plugin functions much the same way that TM&amp;rsquo;s project
drawer works. It allows a hierarchal view of a folder structure. From
this view, you can open files in new tabs, in the opposite window,
even in split views. The only downside I&amp;rsquo;ve come across yet is the
inability to perform file operations from within NERDtree. That being
said, TM&amp;rsquo;s implementation of this was always felt a bit wonky to me as
well.&lt;/p&gt;</description></item><item><title>Virtualenv Wrapper Helper</title><link>https://justin.abrah.ms/blog/2011-06-17-virtualenv_wrapper_helper.html</link><pubDate>Fri, 17 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-17-virtualenv_wrapper_helper.html</guid><description>&lt;p&gt;A bit inspired by all the awesome stuff happening at PyCon, I&amp;rsquo;ve done
a bit of hacking on my shell to improve the use of
virtualenvwrapper. Remembering to checkout the correct virtualenv is a
bit of a pain, especially when you move around your filesystem as much
as I do. To fix this, I&amp;rsquo;ve written a &lt;a href="../dotfiles/zsh.html#sec-2-7"&gt;bit of code&lt;/a&gt; for my bash prompt to
ease the pain. It works by looking for the existence of a .venv file
every time you cd into a directory. If it exists, it will attempt to
&lt;code&gt;workon&lt;/code&gt; the contents of the file, which should be the project
name. For instance, for my oebfare project, the file contains the name
of my virtualenv. Due to this, the following is possible:&lt;/p&gt;</description></item><item><title>My motivations for choosing emacs</title><link>https://justin.abrah.ms/blog/2011-06-15-emacs_motivations.html</link><pubDate>Wed, 15 Jun 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-06-15-emacs_motivations.html</guid><description>&lt;p&gt;The &lt;a href="http://wiki.python.org/moin/EmacsVsVi"&gt;EmacsVsVi&lt;/a&gt; wiki page on the PythonInfo wiki describes emacs as&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Among technically inclined UNIX*Linux users vi*vim tends to be
preferred more by sysadmins while emacs/xemacs tends to be favored
by programmers.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In an effort to &amp;ldquo;know your enemy&amp;rdquo; and whatnot, I figured I would give
emacs a shot. I&amp;rsquo;ve tried the tutorial a few times before and typically
got about 1/2 way through before giving up on the control and alt
craziness. This time, however, I actually managed to get through the
tutorial.&lt;/p&gt;</description></item><item><title>GTD Excel File</title><link>https://justin.abrah.ms/blog/2011-03-04-index.html</link><pubDate>Fri, 04 Mar 2011 00:00:00 +0000</pubDate><guid>https://justin.abrah.ms/blog/2011-03-04-index.html</guid><description>&lt;p&gt;Hi. I&amp;rsquo;m guessing you&amp;rsquo;re looking for the GTD excel file. Unfortunately,
this file is no longer available.&lt;/p&gt;</description></item></channel></rss>