<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>Hacker News Personal Blogs 2013 | Top 100 Blogs</title><link>https://hn-blogs.kronis.dev/feed-top100.xml</link><description>A collection of blog posts from users of Hacker News, based on RSS feeds.</description><language>en-US</language><lastBuildDate>Sat, 13 Jun 2026 04:03:20 GMT</lastBuildDate><generator>rfeed v1.1.1</generator><docs>https://github.com/svpino/rfeed/blob/master/README.md</docs><item><title>2013 Year in Review</title><link>https://benovermyer.com/blog/2013/12/2013-year-in-review/</link><description>&lt;p&gt;A great deal happened in 2013 for me and my family. Sadly, though, I missed the mark on all six of my goals for the year. Despite that, I think 2013 can be counted a success in general.&lt;/p&gt;
&lt;h1 id="my-goals-for-2013"&gt;My Goals for 2013&lt;/h1&gt;
&lt;p&gt;My first goal for 2013 was to release a computer game. For a variety of reasons, this never came close to completion. I overestimated my free time and, to be honest, my motivation. I ended up spending far more time developing tabletop games. I'll get into that in a second. My second goal was to join a local developer group. Technically, I succeeded at this, since I started going to MNPHP meetups for awhile. However, because I didn't sustain my attendance, I'm counting this one failed. There is promise here, though. My third goal was ambitious - take a vacation to Hawaii. Saving up the money to do so, especially amidst changing jobs, proved too difficult for me. My fourth goal, lead a yoga class, failed for more than just inability to do so. Most yoga schools these days seem to focus solely on the physical side of yoga, with no thought for the spiritual side. I had a moment of clarity when I realized that I couldn't get to the level of proficiency in just a year to be qualified to teach both the physical and spiritual sides. I may revisit this goal some year in the future, but not in the near tense. My fifth goal was well on its way to success when I sabotaged it by re-incorporating Dicejockey into my main site. Though I wanted to reach 1,000 visitors per month for at least one month in 2013, my desire to pull in everything to one destination representing me was greater than my desire to continue a blog dedicated solely to MMORPGs and tabletop RPGs. My sixth and final goal for 2013, to collaborate on a project with my sister Tasha, went fairly well for the first half of the year. Unfortunately, I think I was too ambitious in the project we chose to work on, because my contribution would have been a large number of artworks that my skill level and free time did not allow for. Still, this goal was inspiring, and I'll do something along these lines in 2014.&lt;/p&gt;
&lt;h1 id="major-happenings-of-2013"&gt;Major Happenings of 2013&lt;/h1&gt;
&lt;p&gt;I changed jobs twice this past year. The first time, I left Group 3 Marketing because I felt I was stagnating as a developer. I joined a startup called Sportsdigita and worked heavily on Symfony2 projects. While I certainly grew as a developer at Sportsdigita, the culture was damaging everything else about my life. In August, then, I left that company to work for the Minneapolis Star Tribune, the largest newspaper in Minnesota (and, possibly, the Midwest). The Star Tribune has proved to be a wonderful balance between interesting projects and good culture, and it doesn't hurt that it pays well, too. My contributions to Silver Gryphon Games grew this year. My efforts on the web side increased, and my interest in this side of the business is definitely heating up. I released the first web tool for Ingenium, and it's proved very useful - internally, anyway. I did more writing this year in previous years, releasing no less than three adventures for Ingenium. Two of those I did all the writing for, and the third I contributed a third of the final word count to. This also marked the first year where I managed a convention on my own, using the newly-minted “Booth 2.” All in all, 2013 was a successful year for me. I got back into tabletop gaming in a big way this year. I started what has become my longest-running D&amp;amp;D campaign ever. I started playing Warhammer 40k and Warmachine on a weekly basis with some good friends. I did a lot of miniature painting, and produced some works that I'm actually proud of, which hasn't happened before. I also began writing the rules for my own war game, and that could bode well for Silver Gryphon Games, based on early playtest feedback. I met several new friends and strengthened relationships with others. I've been more social-minded this year than the past couple years. I've definitely gone to more conventions this year than in past years, also.&lt;/p&gt;
&lt;h1 id="closing-thoughts"&gt;Closing Thoughts&lt;/h1&gt;
&lt;p&gt;Many positive things happened this year, but I'm disappointed that I wasn't able to follow through with a single one of my goals. I grew as a developer, a gamer, and a person in general in 2013. Overall, despite the lack of goal completion, I think 2013 was a win for me. Here's to an even better 2014!&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sun, 29 Dec 2013 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/12/2013-year-in-review/</guid></item><item><title>Using Beyond Compare 4 Mac Beta with Git</title><link>https://donatstudios.com/Beyond-Compare-Mac-Beta-with-Git-in-OSX</link><description>&lt;p&gt;A little over a year ago I wrote a post about using &lt;a href="https://donatstudios.com/Beyond-Compare-with-Git-in-OSX"&gt;Beyond Compare on Mac&lt;/a&gt; via Wine.  A native version is now in beta and open to everyone! If you haven't tried Beyond Compare, I suggest you do. If you have you already know how awesome it is.&lt;/p&gt;
&lt;p&gt;I've been testing the Alpha for many months now and thought I'd throw together some instructions for getting it going with git.&lt;/p&gt;
&lt;p&gt;You can download the beta here: &lt;a href="https://www.scootersoftware.com/beta.php?zz=beta4_dl"&gt;http://www.scootersoftware.com/beta.php&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After you have the App installed, the next step is to install the command line tools. All other steps require this.&lt;/p&gt;
&lt;p&gt;From the App, go to the &amp;quot;Beyond Compare&amp;quot; drop down menu and choose &amp;quot;Install Command Line Tools...&amp;quot;. It will then prompt you for your password. After this, you &lt;code&gt;bcomp file1.txt file2.txt&lt;/code&gt; &lt;/p&gt;
&lt;h2&gt;Using with Git CLI&lt;/h2&gt;
&lt;p&gt;The next step is to set it up as a git diff tool and merge tool. Git already has native support for it built in thanks to the Linux client having existed for years now.&lt;/p&gt;
&lt;p&gt;This can be achieved simply by running the following commands.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ git config --global diff.tool bc3
$ git config --global difftool.prompt false
$ git config --global merge.tool bc3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This simple setup will leave &lt;code&gt;git diff&lt;/code&gt; and &lt;code&gt;git merge&lt;/code&gt; functioning as usual, as well as allowing you to use Beyond Compare for the task by doing &lt;code&gt;git difftool&lt;/code&gt; and &lt;code&gt;git mergetool&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;I &lt;strong&gt;highly&lt;/strong&gt; recommend giving Beyond Compare a go as a &lt;strong&gt;merge tool&lt;/strong&gt; next time you need to do a merge as it makes it wonderfully simple (when you understand whats going on with the 4 sections anyway).&lt;/p&gt;
&lt;h2&gt;Using with Tower 1.x&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Tower 2.0.6+ include built in support for Beyond Compare which the following instructions will interfere with.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Quit Tower&lt;/li&gt;
&lt;li&gt;Navigate to &lt;code&gt;~/Library/Application\ Support/Tower&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;CompareScripts&lt;/code&gt; folder if one does not already exist.&lt;/li&gt;
&lt;li&gt;Download &lt;a href="https://jdon.at/3tWV"&gt;bcomp.sh&lt;/a&gt; and place it in the new &lt;code&gt;CompareScripts&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;Make it executable via &lt;code&gt;chmod +x bcomp.sh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Download &lt;a href="https://jdon.at/J4cR"&gt;CompareTools.plist&lt;/a&gt; and place it in the &lt;code&gt;~/Library/Application\ Support/Tower&lt;/code&gt; directory. Rename / move any old version that might exist.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Using with SourceTree&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Open SourceTree&lt;/li&gt;
&lt;li&gt;Open &amp;quot;Preferences&amp;quot;  from the SourceTree menu&lt;/li&gt;
&lt;li&gt;Along the top bar, choose the &amp;quot;Diff&amp;quot; tab.&lt;/li&gt;
&lt;li&gt;Under External Diff / Merge
&lt;ol&gt;
&lt;li&gt;for Visual Diff Tool choose &lt;code&gt;Other&lt;/code&gt; then in the Diff Command enter &lt;code&gt;/usr/local/bin/bcomp&lt;/code&gt; and for Arguments enter &lt;code&gt;$LOCAL $REMOTE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;For Merge Tool choose &lt;code&gt;Other&lt;/code&gt; and in Merge Command enter &lt;code&gt;/usr/local/bin/bcomp&lt;/code&gt; and for Arguments enter &lt;code&gt;$LOCAL $REMOTE $BASE $MERGED&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;/ol&gt;</description><author>Donat Studios</author><pubDate>Fri, 27 Dec 2013 01:29:40 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/Beyond-Compare-Mac-Beta-with-Git-in-OSX</guid></item><item><title>On GitHub</title><link>https://captnemo.in/blog/2013/12/25/on-github/</link><description>&lt;p&gt;I am an Internet addict. And the website I’m most addicted to is called GitHub. GitHub is a social code hosting website that is totally awesome. Not your general run-of-the-mill awesome, but rather ass-kicking best-thing-in-the-world awesome. If GitHub was a ninja, it would be Po, defeating the evil clutches of SourceForge.&lt;/p&gt;

&lt;p&gt;When Linux was released a couple of decades ago, it was hosted on a university FTP server. Today, the days of FTP are way past, and unless your code is hosted on a code-sharing website like GitHub, it is as good as dead. The last decade has seen an explosive grown in software and the open source movement. Things like GitHub, Linux, Android, Facebook have been made possible due to the combine efforts of millions across the globe following the Unix philosophy of doing one thing well.&lt;/p&gt;

&lt;p&gt;Ahh, I digress. The point I’m trying to make is that it is very hard to explain to a layman how important GitHub  has been to the software community. It has been used as a collaboration platform for writers, law makers, governments, programmers, and even musicians. People have used its issue tracking feature to even plan weddings. And above all, people adore GitHub. It is one of the few startups that have been accorded God status in the community.&lt;/p&gt;

&lt;p&gt;The question here is what makes GitHub tick? As the largest hosting site for code, it obviously makes a huge impact just by virtue of being there. But its tide of features and innovative progression had made it a darling of all. For instance, their 1 click to fork feature has allowed people to contribute to any project so much easier.&lt;/p&gt;

&lt;p&gt;GitHub has an amazing User Experience, making sure it works  perfectly on all devices large or small. Their amazing support makes sure all of its users are happy as possible. Their regular meetups makes sure that GitHub is invested in the software community themselves. And their GitHub Store lets people invest back in GitHub by romoting them via Tees, stickers and  even laptop sleeves.&lt;/p&gt;

&lt;p&gt;My personal experience with GitHub has been overwhelmingly positive. People have stood beside GitHub even as they faced major issues, and for me that is indicative of a trust in GitHub that no money can buy. The GitHub API (which I’ve used more than once) lets developers create their own apps on top of GitHub which others can use to create even more awesome things.&lt;/p&gt;

&lt;p&gt;For me GitHub is more than just a coding website. It is a testament to creativity and the Hacker Way, reminding me every day that anything is possible.&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Wed, 25 Dec 2013 02:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2013/12/25/on-github/</guid></item><item><title>Testing a NAS hard drive over FTP</title><link>https://anisse.astier.eu/testing-a-nas-hard-drive-over-ftp.html</link><description>&lt;p&gt;So I have this NAS made by my ISP, that does a lot of things; but recently, I
started having issues with its behavior. Recorded TV shows had lag/jitter while replaying, and the
same happened with other types of videos I put on it. I narrowed it down to …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Fri, 20 Dec 2013 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/testing-a-nas-hard-drive-over-ftp.html</guid></item><item><title>Digging in with Foreign Tables</title><link>/2013/12/19/Digging-in-with-Foreign-Tables/</link><description>&lt;p&gt;I wrote a couple months back about exploring FDWs. Its become quite clear to me, despite still having ample room for improvement, they&amp;rsquo;re not getting enough attention. Foreign data wrappers are perhaps better thought of as a foreign table, or even better yet as a view into some remote data source. They don&amp;rsquo;t take care of auto-updating or syncing data, thats all up to you, but it gives you a straight forward mapping to work with remote data easier.&lt;/p&gt;
&lt;p&gt;The first step in working with FDWs is getting them setup. I wrote an earlier post on how to do this manually. And if you&amp;rsquo;re on Heroku theres an even easier solution if you want to setup a mapping entirely from one DB to another. The &lt;a href=""&gt;pg-extras CLI plugin&lt;/a&gt; has a command &lt;code&gt;fdwsql&lt;/code&gt; which will generate the SQL to map all the tables for you. To run it simply specify the prefix app and database:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;heroku pg:fdwsql yourprefix APP::DATABASE_URL
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will generate a lot of SQL. From here you&amp;rsquo;ll want to connect to the database where you want those foreign tables to be visible. Then run all the SQL. This will create all the foreign tables, this will mostly look just like another view or table to you in &lt;code&gt;\d&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="tips-on-working-with-them"&gt;
&lt;div&gt;
Tips on working with them
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;For the most part you can work with your foreign tables just like any other view or table. You can insert into them, read from them, join against them. Though currently foreign tables have some performance limitations, such as when joining it may return a lot more data than you expect then join. To make your performance a bit more ideal you can follow a few basic principles.&lt;/p&gt;
&lt;p&gt;Lets look at some example tables to highlight this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; \d
users
todos
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case users is local and the todos are a foreign table. Looking at each of the schemas we have something like you might expect:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; \d users
Table &amp;quot;public.users&amp;quot;
Column | Type | Modifiers
-------------+-----------------------------+-----------
id | integer | not null
email | text |
created_at | timestamp without time zone |
Indexes:
&amp;quot;users_pkey&amp;quot; PRIMARY KEY, btree (id)
&amp;quot;users_created&amp;quot; btree (created_at)
&amp;gt; \d todo
Foreign Table &amp;quot;public.todo&amp;quot;
Column | Type | Modifiers
-------------+-----------------------------+-----------
id | integer | not null
user_id | integer |
desc | text |
created_at | timestamp without time zone |
status | boolean |
Indexes:
&amp;quot;users_pkey&amp;quot; PRIMARY KEY, btree (id)
&amp;quot;todo_created&amp;quot; btree (created_at)
&lt;/code&gt;&lt;/pre&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 19 Dec 2013 22:55:56 GMT</pubDate><guid isPermaLink="true">/2013/12/19/Digging-in-with-Foreign-Tables/</guid></item><item><title>Quora answer about writing a search engine</title><link>https://boyter.org/2013/12/quora-answer-writing-search-engine/</link><description>&lt;p&gt;The following I posted on Quora in response to the question &lt;a href="http://www.quora.com/Search-Engines/I-am-planning-to-make-a-small-scale-search-engine-on-my-local-system-but-I-dont-know-from-where-to-start"&gt;&amp;ldquo;I am planning to make a small scale search engine on my local system, but I don&amp;rsquo;t know from where to start?&amp;rdquo;&lt;/a&gt;. It&amp;rsquo;s a reasonable answer so like my &lt;a href="http://www.boyter.org/2009/01/athlon-64-pc-512-ram-hold-home-server/"&gt;Mahalo&lt;/a&gt; one I thought I would make a copy for myself.&lt;/p&gt;
&lt;p&gt;I agree with Wolf Garbe and that you are better off in your case starting with existing technologies, have a look at &lt;!-- raw HTML omitted --&gt;&lt;a href="http://yacy.net/"&gt;http://yacy.net/&lt;/a&gt;&lt;!-- raw HTML omitted --&gt; and SphinxSearch as well. However if you are doing this to learn and not just deliver a product I can provide a few links for you.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Fri, 06 Dec 2013 03:31:30 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/12/quora-answer-writing-search-engine/</guid></item><item><title>Go Binary Sizes Are Growing out of Control</title><link>https://donatstudios.com/Golang-Binary-Sizes</link><description>&lt;p&gt;&lt;strong&gt;Update 2019-07-17:&lt;/strong&gt; I have released a follow up post &lt;a href="https://donatstudios.com/Golang-Binary-Sizes-Part-2"&gt;Go Binary Sizes Are Relatively Stable&lt;/a&gt; which speaks on what's happened in the time since this was published.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is not intended as a &amp;quot;Go Sucks&amp;quot; post. I &lt;strong&gt;&lt;em&gt;love&lt;/em&gt;&lt;/strong&gt; Go. I &lt;strong&gt;am not&lt;/strong&gt; saying the developers are &lt;em&gt;lazy&lt;/em&gt; or &lt;em&gt;dumb&lt;/em&gt; or any of the things Reddit has implied. I am not implying I could build a better compiler. Rob Pike and the Go team are geniuses whom I look up to. The tone of this was intended to be a light &amp;quot;man I wish binaries were smaller&amp;quot; but that is not how Reddit seemed to take it.  Also, the title is &lt;a href="https://en.wikipedia.org/wiki/Hyperbole"&gt;hyperbole&lt;/a&gt; and not meant to literally mean no one has control over it.&lt;/p&gt;
&lt;p&gt;I started toying with Go about two years ago before the 1.0 release. I love the language, it meets me in a comfortable place between C and a scripting languages like PHP. I find it fun to write and an easy way to bust out performant code quickly. The binaries for a simple &lt;code&gt;Hello, 世界&lt;/code&gt; were large  though, around 55KB.  I figured this was something the Go team would work out later; it is a lot of space just to send a string to standard out.&lt;/p&gt;
&lt;p&gt;With the release of Go 1.0 though, I noticed the binary size had grown slightly to 242KB. Discouraging but livable. I was quite hopeful with the 1.1 release, but it had actually nearly doubled in size coming out to a whopping 405KB. Then this morning I compiled it again in the newly release 1.2 and to my horror the ever simple program came out to 557KB.&lt;/p&gt;
&lt;p&gt;What on earth is going on in that binary? I am no expert on compilers but I would imagine the vast majority of what is in there is completely unnecessary and could be optimized out.  Changing the script to &amp;quot;Hello, World&amp;quot; rather than Go's flaunted unicode version has zero effect on binary size, as one would expect but I was hopeful.&lt;/p&gt;
&lt;p&gt;For reference the complete source of my &lt;code&gt;Hello, 世界&lt;/code&gt; follows. Using &lt;code&gt;fmt&lt;/code&gt; comes out even larger.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main

func main() {
    println("Hello, 世界")
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here is a collection of binaries compiled in different versions of Go.  Notice how imgavg grows from 1.9MB to 3.7MB. My applications are all small tools.  I can only imagine the effect this has an already large application.&lt;/p&gt;
&lt;img alt="Golang binary sizes grow with each release" src="https://donatstudios.com/assets/48/golangBinarySizes.png" style="display: block; margin: 0 auto; border: 1px solid #aaa;" /&gt;
&lt;p&gt;I really hope something is done about this. I would love to see tiny (&amp;lt;32KB) binaries from Go but right now that doesn't seem to be a priority for them. The fact that &lt;code&gt;Hello, 世界&lt;/code&gt; fills half a floppy means the language is not be useful for lighter or embedded environments.&lt;/p&gt;
&lt;p&gt;As noted in the header there is an addendum to this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://donatstudios.com/Golang-Binary-Sizes-Part-2"&gt;Go Binary Sizes Are Relatively Stable&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Donat Studios</author><pubDate>Tue, 03 Dec 2013 01:25:43 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/Golang-Binary-Sizes</guid></item><item><title>Making HackerTray</title><link>https://captnemo.in/blog/2013/11/28/making-hackertray/</link><description>&lt;p&gt;A few days back, I found the excellent &lt;a href="http://hackerbarapp.com/"&gt;HackerBarApp&lt;/a&gt; via Hacker News. Hacker News,
for those of you who don’t know, is  tech news website run by &lt;a href="http://ycombinator.com"&gt;YCombinator&lt;/a&gt;.
Hacker Bar was the simplest way of accessing HN stories that I’d ever seen. Unfortunately,
it was only for Mac (made using &lt;a href="http://www.rubymotion.com/"&gt;rubymotion&lt;/a&gt;) and even though the source was available,
it was of no use to me as a Linux User.&lt;/p&gt;

&lt;p&gt;I decided to make a clone of Hacker Bar that would work on Linux. My first choice of the
stack was &lt;a href="https://github.com/rogerwang/node-webkit"&gt;node-webkit&lt;/a&gt;, an application framework that allows you to build cross-platform
applications using HTML, CSS, JS, and modules from the node.js ecosystem. After reading a lot
about node-webkit, I figured out that building this application in node-webkit (as it stands)
would not be possible. Or rather, it would not work under Ubuntu and its derivatives because
of lacking appindicator support in &lt;a href="https://github.com/rogerwang/node-webkit/issues/1087"&gt;node-webkit&lt;/a&gt;. More details &lt;a href="https://groups.google.com/d/topic/node-webkit/FeX7YYwK8jI/discussion"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The next obvious language and stack of choice was Python + Gtk. I’d already played a little bit
with Gtk and Python some time back, so I knew the basics. But I’d never build a real application
with PyGtk, just toys and small scripts. I found a &lt;a href="http://www.eurion.net/python-snippets/snippet/Create%20an%20Application%20Indicator.html"&gt;basic skeleton app&lt;/a&gt;
that was written for AppIndicator and modified it somewhat to form the base of HackerTray.&lt;/p&gt;

&lt;p&gt;The next challenge I faced was keeping the check boxes always checked despite of any number
of clicks after the first. That is, we don’t want any menu item to be “un-checked” at
any moment. A basic idea is to do this (partial code):&lt;/p&gt;

&lt;figure class="highlight"&gt;&lt;pre&gt;&lt;code class="language-python"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
	&lt;span class="nf"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_active&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
		&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_active&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
	&lt;span class="n"&gt;webbrowser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
	&lt;span class="c1"&gt;#create a new CheckMenuItem (i)
&lt;/span&gt;	&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;activate&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;However, this does not work as expected, because the &lt;code class="language-plaintext highlighter-rouge"&gt;widget.set_active()&lt;/code&gt; call also results
in the &lt;code class="language-plaintext highlighter-rouge"&gt;activate&lt;/code&gt; event being fired, which ultimately calls &lt;code class="language-plaintext highlighter-rouge"&gt;open&lt;/code&gt;. This means on a click to
an unchecked menuItem, the open function is called twice. This results in the browser opening
the link twice.&lt;/p&gt;

&lt;p&gt;As a workaround, I disabled the event handler in case it is a checked menuItem:&lt;/p&gt;

&lt;figure class="highlight"&gt;&lt;pre&gt;&lt;code class="language-python"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
	&lt;span class="nf"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_active&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
		&lt;span class="n"&gt;wiget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
		&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_active&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
		&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;activate&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;webbrowser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
	&lt;span class="c1"&gt;#create a new CheckMenuItem (i)
&lt;/span&gt;	&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;activate&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
	&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signal_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;activate&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The next thing I worked on was a persistent memory for the app. In a nutshell, I needed to
make sure that the tick on an item remained there, even if the app was restarted. This meant
writing a list of all the “viewed” items into a file. After looking at &lt;a href="http://docs.python.org/lib/module-shelve.html"&gt;shelve&lt;/a&gt; for a
bit, I just &lt;a href="https://github.com/captn3m0/hackertray/commit/167397e51f665847400617935653027ebba0b396"&gt;rolled my own implementation&lt;/a&gt;
, based on storing the data into &lt;code class="language-plaintext highlighter-rouge"&gt;~/.hackertray.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;After that I worked on packaging the app into a python package, so that it could be easily installed.
The &lt;a href="https://python-packaging.readthedocs.io/en/latest/"&gt;python packaging tutorial&lt;/a&gt; was an easy to use guide
that let me &lt;a href="https://github.com/captn3m0/hackertray/commit/6ca735ea089d9189f152612ed016d31d72f9c36b"&gt;create the package&lt;/a&gt;
easily and push it to the &lt;a href="https://pypi.python.org/pypi/hackertray/"&gt;Python Package Index&lt;/a&gt;. A few issues in the package
were found, and were fixed quickly thanks to &lt;a href="https://github.com/captn3m0/hackertray/pull/7"&gt;the pull request&lt;/a&gt; by &lt;a href="https://github.com/brunal"&gt;@brunal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After improving the README a bit, I posted about it on Hacker News, where it failed to get any traction. I re-tried with a link
to the HackerTray website, and that fell flat as well. It was on the next day, when I &lt;a href="https://news.ycombinator.com/item?id=6819042"&gt;posted it to HN&lt;/a&gt;
for the third time, that it took off. After 50 or so upvotes, I found that my instance refused to run because it had
hit the API Rate Limit on the excellent &lt;a href="https://node-hnapi.herokuapp.com/"&gt;node-hnapi&lt;/a&gt;. I quickly &lt;a href="https://github.com/captn3m0/hackertray/commit/8f0b08137b6c4b05ebe63a33029a36c068cfbc05"&gt;pushed a fix&lt;/a&gt;
that used a list of servers to hit as fallback in case it crossed the Rate Limits.&lt;/p&gt;

&lt;p&gt;After a lot of feedback from HN, I started work on a &lt;code class="language-plaintext highlighter-rouge"&gt;node-webkit&lt;/code&gt; based clone of hackertray for Windows. I should be able to release
it in a few more days, if nothing else crops up. Keep watching this space for info. If you have any queries, just &lt;a href="https://github.com/captn3m0/hackertray/issues/new"&gt;file an issue on GitHub&lt;/a&gt;
or &lt;a href="mailto:capt.n3m0@gmail.com"&gt;contact me&lt;/a&gt;.&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Thu, 28 Nov 2013 02:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2013/11/28/making-hackertray/</guid></item><item><title>University Presentation</title><link>https://tomforb.es/blog/university-presentation/</link><description>So I did a presentation on Information Security at University today. I think it went rather well, however I couldn’t show a couple of the demonstrations due to some SkyDrive files only being available online. That sucked because those were my best demonstrations, but overall I was happy. A few peopl...</description><author>Tom Forbes</author><pubDate>Wed, 27 Nov 2013 20:19:28 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/university-presentation/</guid></item><item><title>PostgreSQL - It's kind've a nifty database</title><link>https://www.brightball.com/articles/postgresql-its-kindve-a-nifty-database</link><description>This is a presentation I recently gave to provide an overview of PostgreSQL and some of it's excellent features, including full-text search, multiple built in datatypes, data compression and extensions.  Also, Morgan Freeman is narrating. You're welcome.</description><author>Brightball Articles</author><pubDate>Wed, 27 Nov 2013 11:42:00 GMT</pubDate><guid isPermaLink="true">https://www.brightball.com/articles/postgresql-its-kindve-a-nifty-database</guid></item><item><title>My Dimension in Rift</title><link>https://benovermyer.com/blog/2013/11/my-dimension-in-rift/</link><description>&lt;p&gt;I started playing Rift again, after trying out Everquest 2 and Guild Wars 2 also. Until Everquest Next Landmark comes out, Rift may be my fantasy MMO of choice. We'll see.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Wed, 27 Nov 2013 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/11/my-dimension-in-rift/</guid></item><item><title>Hack things, acquire clothing.</title><link>https://tomforb.es/blog/hack-things-acquire-clothing/</link><description>I discovered an XSS flaw in a website a month ago and reported it to the owners. As a thank you they sent me a hat, a rather large american sized t-shirt and a pair of “DeFeet” socks (guaranteed to stay cooler and drier than any other brand). I didn’t expect them to ship something like that overseas...</description><author>Tom Forbes</author><pubDate>Fri, 22 Nov 2013 18:59:42 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/hack-things-acquire-clothing/</guid></item><item><title>Books I read in 2013</title><link>https://nindalf.com/posts/books-in-2013/</link><description>A list of books read in 2013, including fantasy, historical fiction, and science fiction.</description><author>Krishna's blog</author><pubDate>Tue, 19 Nov 2013 02:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/books-in-2013/</guid></item><item><title>The best Postgres feature you're not using – CTEs aka WITH clauses</title><link>/2013/11/18/best-postgres-feature-youre-not-using/</link><description>&lt;p&gt;SQL by default isn&amp;rsquo;t typically friendly to dive into, and especially so if you&amp;rsquo;re reading someone else&amp;rsquo;s already created queries. For some reason most people throw out principles we follow in other languages &lt;a href="http://www.craigkerstiens.com/2013/07/29/documenting-your-postgres-database/"&gt;such as commenting&lt;/a&gt; and composability just for SQL. I was recently reminded of a key feature in Postgres that most don&amp;rsquo;t use by &lt;a href="http://www.twitter.com/timonk"&gt;@timonk&lt;/a&gt; highlighting it in his AWS Re:Invent Redshift talk. The simple feature actually makes SQL both readable and composable, and even for my own queries capable of coming back to them months later and understanding them, where previously they would not be.&lt;/p&gt;
&lt;p&gt;The feature itself is known as CTEs or common table expressions, you may also here it referred to as &lt;code&gt;WITH&lt;/code&gt; clauses. The general idea is that it allows you to create something somewhat equivilant to a view that only exists during that transaction. You can create multiple of these which then allow for clear building blocks and make it simple to follow what you&amp;rsquo;re doing.&lt;/p&gt;
&lt;p&gt;Lets take a look at a nice simple one:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;WITH users_tasks AS (
SELECT
users.email,
array_agg(tasks.name) as task_list,
projects.title
FROM
users,
tasks,
project
WHERE
users.id = tasks.user_id
projects.title = tasks.project_id
GROUP BY
users.email,
projects.title
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using this I could now just append some basic other query on to the end that references this CTE &lt;code&gt;users_tasks&lt;/code&gt;. Something akin to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT *
FROM users_tasks;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But where it becomes more interesting is chaining these together. So while I have all tasks assigned to each user here, perhaps I want to then find which users are responsible for more than 50% of the tasks on a given project, thus being the bottleneck. To oversimplify this we could do it a couple of ways, total up the tasks for each project, and then total up the tasks for each user per project:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;total_tasks_per_project AS (
SELECT
project_id,
count(*) as task_count
FROM tasks
GROUP BY project_id
),
tasks_per_project_per_user AS (
SELECT
user_id,
project_id,
count(*) as task_count
FROM tasks
GROUP BY user_id, project_id
),
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we would want to combine and find the users that are now over that 50%:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;overloaded_users AS (
SELECT tasks_per_project_per_user.user_id,
FROM tasks_per_project_per_user,
total_tasks_per_project
WHERE tasks_per_project_per_user.task_count &amp;gt; (total_tasks_per_project / 2)
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now as a final goal I&amp;rsquo;d want to get a comma separated list of tasks of the overloaded users. So we&amp;rsquo;re simply giong to join against that &lt;code&gt;overloaded_users&lt;/code&gt; and our initial list of &lt;code&gt;users_tasks&lt;/code&gt;. Putting it all together it looks somewhat long, but becomes much more readable. And as a bonus I layered in some comments.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;--- Created by Craig Kerstiens 11/18/2013
--- Query highlights users that have over 50% of tasks on a given project
--- Gives comma separated list of their tasks and the project
--- Initial query to grab project title and tasks per user
WITH users_tasks AS (
SELECT
users.id as user_id,
users.email,
array_agg(tasks.name) as task_list,
projects.title
FROM
users,
tasks,
project
WHERE
users.id = tasks.user_id
projects.title = tasks.project_id
GROUP BY
users.email,
projects.title
),
--- Calculates the total tasks per each project
total_tasks_per_project AS (
SELECT
project_id,
count(*) as task_count
FROM tasks
GROUP BY project_id
),
--- Calculates the projects per each user
tasks_per_project_per_user AS (
SELECT
user_id,
project_id,
count(*) as task_count
FROM tasks
GROUP BY user_id, project_id
),
--- Gets user ids that have over 50% of tasks assigned
overloaded_users AS (
SELECT tasks_per_project_per_user.user_id,
FROM tasks_per_project_per_user,
total_tasks_per_project
WHERE tasks_per_project_per_user.task_count &amp;gt; (total_tasks_per_project / 2)
)
SELECT
email,
task_list,
title
FROM
users_tasks,
overloaded_users
WHERE
users_tasks.user_id = overloaded_users.user_id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;CTEs won&amp;rsquo;t always be quite as performant as optimizing your SQL to be as concise as possible. In most cases I have seen performance differences smaller than a 2X difference, this tradeoff for readability is a nobrainer as far as I&amp;rsquo;m concerned. And with time the Postgres optimizer should continue to get better about such performance.&lt;/p&gt;
&lt;p&gt;As for the verbosity, yes I could have done this query in probably 10-15 lines of very concise SQL. Yet, most may not be able to understand it quickly if at all. Readability is huge when it comes to SQL to ensure its doing the right thing. SQL will almost always tell you an answer, it just may not be to the question you think you&amp;rsquo;re asking. Ensuring your queries can be reasoned about is critical to ensuring accuracy and CTEs are one great way of accomplishing that.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re looking for a deeper resource on Postgres I recommend the book &lt;a href="https://theartofpostgresql.com/?affiliate=cek"&gt;The Art of PostgreSQL&lt;/a&gt;. It is by a personal friend that has aimed to create the definitive guide to Postgres, from a developer perspective. If you use code CRAIG15 you&amp;rsquo;ll receive 15% off as well.&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Mon, 18 Nov 2013 22:55:56 GMT</pubDate><guid isPermaLink="true">/2013/11/18/best-postgres-feature-youre-not-using/</guid></item><item><title>Restricting Thrift clients to specific IP addresses with Twisted</title><link>https://tomforb.es/blog/restricting-thrift-clients-to-specific-ip-addresses-with-twisted/</link><description>Apache Thrift is pretty awesome - you can build Twisted bindings for your Thrift interface file that work fantastically. There is one thing that took me a while to figure out: I want to restrict clients connecting to the service to a specific set of IP addresses stored in a database. There were thre...</description><author>Tom Forbes</author><pubDate>Mon, 11 Nov 2013 19:17:11 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/restricting-thrift-clients-to-specific-ip-addresses-with-twisted/</guid></item><item><title>Load a Github Gist with Composer</title><link>https://donatstudios.com/Load-Gist-With-Composer</link><description>&lt;p&gt;Composer is amazing for pulling in packages, but what if you find a Gist that isn't Composer aware? Fear not, as Composer has the magical ability to pull in repositories not explicitly set up in Packagist by defining them in the &amp;quot;repositories&amp;quot; section. &lt;/p&gt;
&lt;p&gt;But what if you wanted to load a single class from a git gist? &lt;/p&gt;
&lt;p&gt;You can add the following &lt;code&gt;repositories&lt;/code&gt; section to your &lt;code&gt;composer.json&lt;/code&gt; file, adjusting &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;url&lt;/code&gt; as necessary. The &lt;code&gt;name&lt;/code&gt; should be a &lt;code&gt;vendor/package&lt;/code&gt; (all lower) style name you make up for it, and &lt;code&gt;url&lt;/code&gt; will be from the &lt;em&gt;Clone this gist&lt;/em&gt; box on GitHub. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;"repositories": [
    {
        "type":"package",
        "package": {
            "name": "turin86/wssoapclient",
            "version": "master",
            "source": {
                "url": "https://gist.github.com/5569152.git",
                "type": "git",
                "reference":"master"
            },
            "autoload": {
                "classmap": ["."]
            }
        }
    }
]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in your require section, add your selected &lt;code&gt;name&lt;/code&gt; as follows.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;"require": {
    "turin86/wssoapclient": "dev-master"
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the name of the class doesn't match the filename in a friendly autoload-able manner, you'll have to replace &lt;code&gt;"classmap": ["."]&lt;/code&gt; with &lt;code&gt;"files": ["ClassToAutoload.php"]&lt;/code&gt; replacing &lt;code&gt;ClassToAutoload.php&lt;/code&gt; with the filename. More info on autoloading can be found &lt;a href="https://getcomposer.org/doc/04-schema.md#autoload"&gt;here&lt;/a&gt;. Note that if you are experimenting with autoload settings you may need to remove your vendor directory and &lt;code&gt;composer install&lt;/code&gt;, as updates to the autoload were not reflected for me after a &lt;code&gt;composer update&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After this, just run &lt;code&gt;composer update&lt;/code&gt; and voilà, you are loading a gist with Composer.&lt;/p&gt;</description><author>Donat Studios</author><pubDate>Thu, 07 Nov 2013 04:36:45 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/Load-Gist-With-Composer</guid></item><item><title>Embedded Linux Conference Europe 2013 notes</title><link>https://anisse.astier.eu/embedded-linux-conference-europe-2013-notes.html</link><description>&lt;p&gt;So I was in Edinburgh this year, and I took notes as I usually do. These are intended for personal consumption (do no expect LWN-style reports), but as more people were asking me to share them, I thought why not do it in public ?&lt;/p&gt;
&lt;h1&gt;Embedded Linux timeline&lt;/h1&gt;
&lt;p&gt;by Chris Simmonds …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Wed, 30 Oct 2013 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/embedded-linux-conference-europe-2013-notes.html</guid></item><item><title>Installing the PHP "memcached" Extension</title><link>https://donatstudios.com/OS-X-Mavericks-Memcached-PHP-Extension-Installation</link><description>&lt;h3&gt;Please Note&lt;/h3&gt;
&lt;p&gt;This tutorial only covers the &lt;strong&gt;default PHP installation&lt;/strong&gt; that ships with Mac OS X / macOS. If you have installed a new installation this does not cover you. &lt;/p&gt;
&lt;p&gt;For those using brew, you can simply &lt;code&gt;brew install&lt;/code&gt; the &lt;a href="https://github.com/Homebrew/homebrew-php/blob/49cb525f2dd836ac1fe79905d9f094931d7b02ba/Formula/php55-memcached.rb"&gt;appropriate brew formula&lt;/a&gt; for the extension.&lt;/p&gt;
&lt;p&gt;These directions are verified to work with Mac OS X 10.9 Mavericks through macOS 10.14 Mojave.&lt;/p&gt;
&lt;fieldset&gt;&lt;legend&gt;System Integrity Protection&lt;/legend&gt;

&lt;p&gt;If you are running OS X El Capitan or &lt;strong&gt;newer&lt;/strong&gt; you will need to disable System Integrity Protection to modify system files and directories.&lt;/p&gt;
&lt;p&gt;To disable System Integrity Protection, boot into recovery mode by restarting and then holding &lt;code&gt;⌘R&lt;/code&gt; as you hear the startup chime. Then start the Terminal from the Utilities menu.&lt;/p&gt;
&lt;p&gt;Run the following command&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ csrutil disable&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then reboot. You are good to go.&lt;/p&gt;
&lt;p&gt;If you wish to turn it back on, follow the instructions above but instead use:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ csrutil enable&lt;/code&gt;&lt;/pre&gt;

Click &lt;a href="https://donatstudios.com/Disable-macOS-System-Integrity-Protection"&gt;here&lt;/a&gt; for a full post on the topic.

&lt;/fieldset&gt;
&lt;p&gt;The first step is to install the latest version of Xcode. On modern versions of MacOS this can be done from the App Store.&lt;/p&gt;
&lt;p&gt;After this, install the Xcode developer tools. &lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ xcode-select --install&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Special note to Mojave users&lt;/strong&gt; if the following steps fail, you may need to reinstall your Xcode header files. Instructions for that can be found &lt;a href="https://donatstudios.com/MojaveMissingHeaderFiles"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next we will need to install the required dependencies before we can build the extension. If you are not already using &lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt; you should be. &lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ brew install wget autoconf pkg-config libmemcached&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You will also want to make sure you have PEAR installed; full instructions can be found &lt;a href="https://pear.php.net/manual/en/installation.getting.php"&gt;here&lt;/a&gt; but can be summarized as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ wget http://pear.php.net/go-pear.phar
$ php go-pear.phar&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in the &lt;code&gt;/tmp&lt;/code&gt; directory we will create a folder we can work in.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ cd /tmp
$ mkdir memcached-work
$ cd memcached-work&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we will use pecl, part of pear, to fetch the current version of the extension.  &lt;/p&gt;
&lt;p&gt;The version of the memcached extension will vary so you will need to update the paths accordingly.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ pecl download memcached
$ open memcached-{{version}}.tgz
$ cd memcached-{{version}}/memcached-{{version}}
$ phpize
$ ./configure
$ make
$ sudo make install&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally you will need to add the following line to your php.ini&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;extension = memcached.so&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can verify your installation with the following:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ php --info | grep memcached\\.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Depending on your setup now you may want to restart apache. &lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ sudo apachectl restart&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should be all set to go!&lt;/p&gt;</description><author>Donat Studios</author><pubDate>Wed, 23 Oct 2013 13:42:40 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/OS-X-Mavericks-Memcached-PHP-Extension-Installation</guid></item><item><title>How to: Disable macOS System Integrity Protection</title><link>https://donatstudios.com/Disable-macOS-System-Integrity-Protection</link><description>&lt;p&gt;If you are running OS X El Capitan or &lt;strong&gt;newer&lt;/strong&gt; you will need to disable System Integrity Protection to modify system files and directories.&lt;/p&gt;
&lt;p&gt;To disable System Integrity Protection, boot into recovery mode by restarting and then holding &lt;code&gt;⌘R&lt;/code&gt; as you hear the startup chime. Then start the Terminal from the Utilities menu.&lt;/p&gt;
&lt;p&gt;Run the following command&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ csrutil disable&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then reboot. You are good to go.&lt;/p&gt;
&lt;p&gt;If you wish to turn it back on, follow the instructions above but instead use:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ csrutil enable&lt;/code&gt;&lt;/pre&gt;</description><author>Donat Studios</author><pubDate>Wed, 23 Oct 2013 13:42:40 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/Disable-macOS-System-Integrity-Protection</guid></item><item><title>My wishlist for a Star Wars Galaxies 2</title><link>https://benovermyer.com/blog/2013/10/my-wishlist-for-a-star-wars-galaxies-2/</link><description>&lt;p&gt;Star Wars Galaxies 2 will most likely never happen, owing to the fact that SOE has publicly stated that it will never work on an MMO based on an external IP again. Whether that's true or not, if somehow this project were to be conceived, here are the changes from the original that I'd personally want to see in a sequel.&lt;/p&gt;
&lt;h1 id="modern-graphics-engine"&gt;Modern Graphics Engine&lt;/h1&gt;
&lt;p&gt;This is the most obvious one. My personal choice for SWG2's engine would be Unreal Engine 4, owing to its extremely impressive technology. The “Infiltrator” demo video for UE4 shows that it would be perfect for the realistic art style of the Star Wars: Galaxies franchise, as compared to the more stylized art direction of Star Wars: The Old Republic.&lt;/p&gt;
&lt;h1 id="a-return-to-skill-based-character-progression"&gt;A Return to Skill-Based Character Progression&lt;/h1&gt;
&lt;p&gt;Like most SWG veterans, I lamented the loss of the skill tree progression system when the New Game Experience took over. With SWG2, I'd want to see it return with a vengeance. Particularly, I'd like to see the depth and breadth of trees expand, allowing for greater freedom than even the original. Several aspects of the Star Wars universe were never fully explored in the first game, or were only given light treatment, such as slicing or smuggling.&lt;/p&gt;
&lt;h1 id="more-player-races"&gt;More Player Races&lt;/h1&gt;
&lt;p&gt;The selection of available races in the original was good, allowing for most of the popular choices. I would like to see the Togruta, Chiss, and Devaronian races make a core appearance in SWG2. I'd also like to see droids as a player race, though that might be too complicated to balance against other races' gameplay.&lt;/p&gt;
&lt;h1 id="bigger-worlds"&gt;Bigger Worlds&lt;/h1&gt;
&lt;p&gt;The original SWG planets were pretty big, but they frequently felt empty. The expansion worlds had stronger design, but felt smaller. I'd want to see planets in SWG2 be more expansive than the original SWG planets, but have more points of interest throughout each. For example, the planets in the first SWG felt a lot like the same planet given a different skin each time. While I don't want quests to provide a meta plot, I would like to see localized content that gives each world its own character.&lt;/p&gt;
&lt;h1 id="greater-freedom-of-movement"&gt;Greater Freedom of Movement&lt;/h1&gt;
&lt;p&gt;Let's face it, movement was pretty horrible in the original SWG. You couldn't jump or fly over obstacles, and it was completely possible to walk straight up a sheer cliff face. While we don't necessarily need the full parkour aspects of EverQuest Next, I do want the ability to jump over things, be prevented from walking up impossible surfaces, and be able to climb, swim, and otherwise move as a person should be able to move.&lt;/p&gt;
&lt;h1 id="atmospheric-vehicles"&gt;Atmospheric Vehicles&lt;/h1&gt;
&lt;p&gt;I know these were added to the original SWG, but it came only in the last few months of the game's life. Given how important they are to the Star Wars universe in general, it would be a crime not to include these from the beginning in SWG2. I want to be able to bullseye womp rats in a T-16, over take a cruise over the highlands of Corellia in my own YT-1300. I also want shuttle transports to actually have real transit time, and not be a wait-and-teleport affair like they were in the original.&lt;/p&gt;
&lt;h1 id="player-factions"&gt;Player Factions&lt;/h1&gt;
&lt;p&gt;While it was great to have Imperial and Rebel affiliations in the original, to really ramp up the sandboxy nature of Star Wars Galaxies, the sequel would need to have player factions. This is particularly important if the game is set in a time period after the fall of the Empire, where a billion new factions would be vying for power. I see player factions being akin to massive alliances of Player Associations, rather than just an enormous PA. They'd also have to be able to influence planetary politics, like how Imperial and Rebel players were able to influence things towards the end of the original SWG.&lt;/p&gt;
&lt;h1 id="a-player-exchange"&gt;A Player Exchange&lt;/h1&gt;
&lt;p&gt;Unlike the auction house format of current MMORPGs, I'd like to see something closer to the original vendor system in SWG. You'd be able to search available items on a local, planetary, or galactic level, as well as purchase them, but you'd need to physically travel to the vendor in order to pick up the item or items. This is important for two reasons: to encourage exploration and travel, and to support the possibility of player deliverymen - “FedEx” quests that actually matter. I want to have to travel to Tosche station to pick up some power converters.&lt;/p&gt;
&lt;h1 id="greater-visual-customization-of-crafted-items"&gt;Greater Visual Customization of Crafted Items&lt;/h1&gt;
&lt;p&gt;I liked that crafters could dye armor in SWG, but a sequel would need to take it to a new level. Item appearance should be further separated from item game mechanics than in the original. There is a vast variety of armor appearances in Star Wars, for example, and that should be reflected in SWG2. I don't want just a dozen different kinds of armor in different colors. I want several dozen, if not more. If World of Warcraft can do it, so can SWG2. Involving the Player Studio could help defray the cost of developing new models and textures for components of items.&lt;/p&gt;
&lt;h1 id="vehicular-combat"&gt;Vehicular Combat&lt;/h1&gt;
&lt;p&gt;If we can fly in the atmosphere, we should be able to fight in it also. I'd want to see hover tanks finally make an appearance, among other things. If PlanetSide 2 can balance heavy armor against infantry, Star Wars Galaxies can do it too. This list could be even longer, but the above are my biggest wishes for a Star Wars Galaxies 2. How about yours? What would you want to see in a sequel?&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sun, 20 Oct 2013 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/10/my-wishlist-for-a-star-wars-galaxies-2/</guid></item><item><title>Hello, World!</title><link>https://anisse.astier.eu/hello-world.html</link><description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Update&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;: I updated the information below with the &lt;a href="blog-update.html"&gt;2020 tech&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So I finally did it. You're reading it right now. My personnal website/blog.&lt;/p&gt;
&lt;p&gt;I should be posting here about things that cross my mind as well as various projects I've been working on. And maybe even new projets I …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Sun, 20 Oct 2013 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/hello-world.html</guid></item><item><title>First post</title><link>https://nindalf.com/posts/first-post/</link><description>A personal blog about mundane observations on reading, programming, and gaming, with occasional updates and vain attempts to drive traffic to the blog.</description><author>Krishna's blog</author><pubDate>Sat, 19 Oct 2013 03:00:00 GMT</pubDate><guid isPermaLink="true">https://nindalf.com/posts/first-post/</guid></item><item><title>Adding tail-call optimization to Python</title><link>https://tomforb.es/blog/adding-tail-call-optimization-to-python/</link><description>Tail-call optimization is a trick many languages and compilers use to avoid creating excess stack frames when dealing with recursive code like this:...</description><author>Tom Forbes</author><pubDate>Tue, 15 Oct 2013 22:04:05 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/adding-tail-call-optimization-to-python/</guid></item><item><title>Tooling for Simple but Informative Emails</title><link>/2013/10/13/Tooling-for-Simple-but-Informative-Emails/</link><description>&lt;p&gt;Emails are one of my favorite methods of communicating with users. Its works as a quick test for product validation. It works well at one-&amp;gt;some-&amp;gt;many-&amp;gt; all. Its still highly effective even as much noise as we receive in our inboxes. Over the years I&amp;rsquo;ve tried a lot of email tools from custom built solutions, to newer entrants that help around drip actions (&lt;a href="http://www.intercom.io"&gt;intercom.io&lt;/a&gt; and &lt;a href="http://www.customer.io"&gt;customer.io&lt;/a&gt;), to more &amp;ldquo;enterprise&amp;rdquo; tools such as Marketo. While I have varying opinions on all of those, I still find myself coming back to a simple one off script setup to deliver clear concise emails.&lt;/p&gt;
&lt;h3 id="getting-the-data"&gt;
&lt;div&gt;
Getting the Data
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;The first step of any email is deciding what you want to do, but hopefully you know that already. The part that is usually a bit more effort is actually getting the list to send it to and formatting it appropriately. I usually opt for SQL. While the specifics of the query of course always vary it common follows a general structure:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;WITH initial_data AS (
SELECT
email,
app_name,
information_about_app
FROM
users,
apps
WHERE users.id = apps.user_id
AND some_filter_to_limit_data
),
candidates_for_email AS ... --- likely to have additional CTEs
--- Finally I build up the list
SELECT email,
array_to_string(array_agg(data_for_email), '
') --- an important note is to add a newline or not here depending on how you wish to format it
FROM candidates_for_email
GROUP BY email;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The query structure you&amp;rsquo;ll want is first column email, second column whatever data you want to include in your email.&lt;/p&gt;
&lt;p&gt;From here I usually create a dataclip of it. This makes it easy to allow my data to change over time. If I&amp;rsquo;m testing an email for data over the last 7 days I just come back in 7 days and I have new data. It also lets me easily share and iterate on the data. The nice part is there&amp;rsquo;s an easy way to click a button and get the data as a CSV which is what you want for sending.&lt;/p&gt;
&lt;p&gt;Once you download the CSV you&amp;rsquo;ll want to remove the header line as its not needed for the script.&lt;/p&gt;
&lt;h3 id="sending-the-mail"&gt;
&lt;div&gt;
Sending the Mail
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;To actually send the email you&amp;rsquo;ll need this script, which is largely credited to &lt;a href="http://www.twitter.com/leinweber"&gt;@leinweber&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require 'mail'
require 'csv'
FILE = ARGV[0]
Mail.defaults do
delivery_method :smtp, {
address: 'smtp address',
port: 587,
domain: 'gmail.com',
user_name: 'craig.kerstiens@gmail.com',
password: ENV.fetch('EMAIL_PASSWORD'),
authentication: :plain,
enable_starttls_auto: true
}
end
def send_email(address, app)
mail = Mail.new do
to address
from 'Craig Kerstiens &amp;lt;craig.kerstiens@gmail.com&amp;gt;'
subject &amp;quot;Your email subject in here&amp;quot;
body generate_body(app)
end
end
def generate_body(app)
%Q(
Hi,
Your list of apps:
#{app}
Various email content in here...
)
end
CSV.parse(File.read(FILE)).each do |line|
address = line[0]
app = line[1]
m = send_email(address, app)
puts m.to_s
p m.deliver!
puts
puts
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;You&amp;rsquo;ll want to make sure to export the PW of your email provider with EXPORT EMAIL_PASSWORD=pw_here&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You can easily download this script from off of &lt;a href="https://gist.github.com/craigkerstiens/6922897"&gt;Github&amp;rsquo;s Gist&lt;/a&gt;. I&amp;rsquo;d recommend using an email service provider other than Gmail in sending your emails such as &lt;a href="http://www.mailgun.com"&gt;mailgun&lt;/a&gt; as they&amp;rsquo;re built to handle sending a large amount of emails. Finally send your emails:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ruby email.rb nameofyourfile.csv
&lt;/code&gt;&lt;/pre&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Sun, 13 Oct 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/10/13/Tooling-for-Simple-but-Informative-Emails/</guid></item><item><title>My Uni's timetable system sucks, so I built a better one.</title><link>https://tomforb.es/blog/my-uni-s-timetable-system-sucks-so-i-built-a-better-one-1/</link><description>tl;dr The timetable system sucks, so I made one that works Getting your timetable sorted at Uni has never been fun. In years 1 and 2 of my study the department posted a timetable for each year showing all modules and students were expected to remove the classes they did not take, which while not the...</description><author>Tom Forbes</author><pubDate>Sat, 12 Oct 2013 02:05:09 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/my-uni-s-timetable-system-sucks-so-i-built-a-better-one-1/</guid></item><item><title>Objective-C</title><link>https://3059274a.danpalmer-me.pages.dev/2013-10-12-objective-c/</link><description>&lt;p&gt;If I mentioned that I like C, C++ or Python to other students on my course, or colleagues, there would be no reaction. There are things you can criticise about each one, but they are all very safe bets. When I tell people that I enjoy writing Objective-C however, they are confused and often quite hostile towards the language.&lt;/p&gt;
&lt;p&gt;I am by no means an Objective-C expert, but I&amp;rsquo;ve been thinking through the reasons &lt;em&gt;why&lt;/em&gt; I like it, so this is a random collection of reasons why I enjoy using the language.&lt;/p&gt;</description><author>Dan Palmer</author><pubDate>Sat, 12 Oct 2013 02:00:00 GMT</pubDate><guid isPermaLink="true">https://3059274a.danpalmer-me.pages.dev/2013-10-12-objective-c/</guid></item><item><title>Purchasing a £30,000 numberplate for the price of a bus ticket</title><link>https://tomforb.es/blog/purchasing-a-30000-numberplate-for-the-price-of-a-bus-ticket/</link><description>Regtransfers.co.uk is a website that allows you to purchase customized numberplates for your car or motorbike. They boast a large number of famous clients and short numberplates are often on sale for upwards of £20,000 (the plate ABC 4 is up for £30,000). While playing with their site I discovered a...</description><author>Tom Forbes</author><pubDate>Mon, 07 Oct 2013 04:40:33 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/purchasing-a-30000-numberplate-for-the-price-of-a-bus-ticket/</guid></item><item><title>Breaking out of secured Python environments</title><link>https://tomforb.es/blog/breaking-out-of-secured-python-environments/</link><description>A week or so ago I was browsing /r/Python and I saw a link to a website called rise4fun.com , which is a Microsoft Research project that contains a lot of cool demos and tools that you can run in your browser. The demo I was linked to was a restricted Python shell that could be used to experiment wi...</description><author>Tom Forbes</author><pubDate>Wed, 25 Sep 2013 23:02:33 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/breaking-out-of-secured-python-environments/</guid></item><item><title>Aboard the Nautilus</title><link>https://captnemo.in/blog/2013/09/21/aboard-the-nautilus/</link><description>&lt;p&gt;I’d done a &lt;a href="http://captnemo.in/blog/2009/12/04/nautilus-behind-the-curtains/"&gt;post&lt;/a&gt; on this a long time back (2009), detailing
what all softwares I use on a daily basis. This
is an update to that post.&lt;/p&gt;

&lt;p&gt;Since the last post, I’ve moved on to using Linux, using
Elementary OS as my primary OS. Over the time period this post was written,
I’ve shifted from using Cinnamon to Openbox and finally
to elementaryOS’s pantheon as my Desktop Manager. I’m thinking of switching
to Arch Linux, just to get a faster experience. I use 
Synapse as my application launcher, because its much faster
than anything else out there.&lt;/p&gt;

&lt;p&gt;For most of my web browsing needs, I rely on Google Chrome Stable
and a daily build of Chromium (v31 as of now) for most of my work.
 I switch between them all the time. I use Firefox (stable) only to
test out my projects from time to time.&lt;/p&gt;

&lt;p&gt;The current editor I use is Sublime Text. It is
everything you need, and much more. I’m still to
get started using its build system, and its
plethora of packages; but its still an excellent
choice for a daily use editor. On the command line, I use
Vim, git (with &lt;a href="https://github.com/ndbroadbent/scm_breeze" title="Faster Git Shortcuts"&gt;SCM Breeze&lt;/a&gt;), &lt;a href="https://github.com/clvv/fasd" title="Command Line Booster"&gt;fasd&lt;/a&gt; and &lt;a href="https://github.com/jonas/tig" title="Excellent Git CLI"&gt;tig&lt;/a&gt;, 
which is an excellent git interface on the command line.&lt;/p&gt;

&lt;p&gt;I listen to music on my own browser-based music
player, called &lt;a href="https://sdslabs.co.in/muzi" title="Link works only inside IITR"&gt;Muzi&lt;/a&gt;, YouTube and GrooveShark.&lt;/p&gt;

&lt;p&gt;For my terminal needs, I use Gnome-Terminal. I use
&lt;a href="http://byobu.co/"&gt;Byobu&lt;/a&gt; to manage my session, and often
connect to it from other computers as well. Its an
excellent multiplexer that fits in my workflow
really well.&lt;/p&gt;

&lt;p&gt;I use &lt;a href="http://imo.im/"&gt;Imo.im&lt;/a&gt; on both the
Desktop and my tablet to chat. I occasionally use &lt;a href="http://sourceforge.net/projects/retext/"&gt;ReText&lt;/a&gt;
for editing markdown files. I use &lt;a href="http://jonls.dk/redshift/"&gt;RedShift&lt;/a&gt; on my laptop and &lt;a href="http://justgetflux.com/"&gt;f.lux&lt;/a&gt;
on my iPad to help me sleep better. I recommend it to everyone who is
suffering from eye-strain or wants to sleep better.&lt;/p&gt;

&lt;p&gt;On the browser, my most visited sites would be
&lt;a href="https://news.ycombinator.com/"&gt;Hacker News&lt;/a&gt; (via hckrnews.com), &lt;a href="http://workflowy.com/"&gt;WorkFlowy&lt;/a&gt; for managing
my to-do list and GitHub on a daily basis for most of my projects.&lt;/p&gt;

&lt;h2 id="hardware"&gt;Hardware&lt;/h2&gt;
&lt;p&gt;I own a old Nokia X3-02, and will be upgrading to a &lt;a href="https://www.mozilla.org/en-US/firefox/os/"&gt;Firefox OS Phone&lt;/a&gt; soon enough. I use a Dell Inspiron 1545 as my personal machine. I also use an iPad 2 (with 3G) on a daily basis (mostly for reading). I also own a Dayan Zhanchi 3x3 and a 5x5 shengshou 
speed cube.&lt;/p&gt;

&lt;h2 id="ipad-apps"&gt;iPad Apps&lt;/h2&gt;
&lt;p&gt;The must have iPad apps for me are Chrome, &lt;a href="https://imo.im/iphone/"&gt;imo&lt;/a&gt;,  and iBooks. I have installed &lt;a href="http://www.mailboxapp.com/"&gt;Mailbox&lt;/a&gt; alongside GMail, and haven’t used GMail since
I installed it. I sometimes write stuff using &lt;a href="http://www.hogbaysoftware.com/products/plaintext/"&gt;Plaintext&lt;/a&gt;, and sketch using &lt;a href="http://www.fiftythree.com/paper"&gt;Paper&lt;/a&gt;. I read my RSS feeds using Newsify and Feedly.&lt;/p&gt;

&lt;h2 id="extensions"&gt;Extensions&lt;/h2&gt;
&lt;p&gt;Chrome Extensions that I use on a daily basis include &lt;a href="http://chimeapp.com/"&gt;Chime&lt;/a&gt; for 
wonderful notifications (highly recommended), &lt;a href="http://www.ghostery.com"&gt;Ghostery&lt;/a&gt; for getting a tracker-free internet
, &lt;a href="https://www.eff.org/https-everywhere"&gt;HTTPS Everywhere&lt;/a&gt; to keep me secure, &lt;a href="http://lastpass.com/"&gt;LastPass&lt;/a&gt; to manage passwords and &lt;a href="https://chrome.google.com/webstore/detail/stylish/fjnbnpbmkenffdnngjfgmeleoegfcffe"&gt;Stylish&lt;/a&gt;
 for &lt;a href="http://userstyles.org/users/183835"&gt;customizing&lt;/a&gt; the looks of various websites.&lt;/p&gt;

&lt;h2 id="dream-setup"&gt;Dream Setup&lt;/h2&gt;
&lt;p&gt;My dream setup would consist of a lightweight Ubuntu Laptop that I can carry around
that still has lots of processing power and battery life. I’ll prety much be satisfied
by any high-end Android phone as long as it has a decent battery life.&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Sat, 21 Sep 2013 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2013/09/21/aboard-the-nautilus/</guid></item><item><title>Inspecting .NET applications with ILSpy</title><link>https://tomforb.es/blog/inspecting-net-applications-with-ilspy/</link><description>Every once in a while I come across an application that is so comically insecure that I feel the urge to blog about it. The application in question is a .NET application to manage care homes and provide a Medical Administration Record for residents. Staff login to the app using a username and passwo...</description><author>Tom Forbes</author><pubDate>Thu, 19 Sep 2013 15:40:40 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/inspecting-net-applications-with-ilspy/</guid></item><item><title>Introducing SingleBugs the Bug Tracker for Single Developers</title><link>https://boyter.org/2013/09/introducing-singlebugs-bug-tracker-single-developers/</link><description>&lt;p&gt;Introducing the first beta release of SingleBugs, the bug tracker aimed at single/solo developers. Are you a solo developer? Do you find setting up Mantis/Fogbugs/Bugs.net/et.al too complex and a waste of your time? Do you want a single solution that easily syncs and backs up between your machines? Try SingleBugs.&lt;/p&gt;
&lt;p&gt;Guaranteed to save you time and money setting up a bug tracker. Guaranteed to be the fastest bug tracker you have ever used.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 16 Sep 2013 04:50:08 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/09/introducing-singlebugs-bug-tracker-single-developers/</guid></item><item><title>Disabling muting while typing in Google hangouts</title><link>/2013/09/12/Disabling-muting-while-typing-in-Google-hangouts/</link><description>&lt;p&gt;Google hangouts is awesome, its my preferred method for most audio/video calls these days. When running a group call I often dial into a separate phone if I have a better phone available for the group. It also got around the annoyance that when you are typing google automatically mutes you. This for most people is pretty subpar. While dialing in to the hangout can still be nice, you don&amp;rsquo;t have to do so to get rid of the annoying muting while typing. To fix such simply open up your terminal and run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; defaults write com.google.googletalkplugind exps -string [\&amp;quot;-tm\&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;This clever hack discovered courtesy of &lt;a href="http://www.twitter.com/timtyrrell"&gt;@timtyrrell&lt;/a&gt; passed along to me by &lt;a href="http://www.twitter.com/mattmanning"&gt;@mattmanning&lt;/a&gt; and &lt;a href="http://www.twitter.com/blakegentry"&gt;@blakegentry&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 12 Sep 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/09/12/Disabling-muting-while-typing-in-Google-hangouts/</guid></item><item><title>Diving into Postgres JSON operators and functions</title><link>/2013/09/11/Diving-into-Postgres-JSON-operators-and-functions/</link><description>&lt;p&gt;Just as &lt;a href="https://postgres.heroku.com/blog/past/2013/9/9/postgres_93_now_available/"&gt;PostgreSQL 9.3&lt;/a&gt; was coming out I had a need to take advantage of the JSON datatype and some of the &lt;a href="http://www.postgresql.org/docs/9.3/static/functions-json.html"&gt;operators and functions&lt;/a&gt; within it. The use case was pretty simple, run a query across a variety of databases, then take the results and store them. We explored doing something more elaborate with the columns/values, but in the end just opted to save the entire result set as JSON then I could use the operators to explore it as desired.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the general idea in code (using sequel):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;result = r.connection { |c| c.fetch(self.query).all }
mymodel.results = result.to_json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As the entire dataset was stored as some compressed JSON I needed to do a bit of manipulation to get it back into a form that was workable. Fortunately all the steps were fairly straightforward.&lt;/p&gt;
&lt;p&gt;First you want to unnest each result from the json array, in my case this looked like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT json_array_elements(result)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above will unnest all of the array elements so I have an individual result as JSON. A real world example would look something similar to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT json_array_elements(result)
FROM query_results
LIMIT 2;
json_array_elements
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;p&gt;{&amp;ldquo;column_name&amp;rdquo;:&amp;ldquo;data_in_here&amp;rdquo;}
{&amp;ldquo;column_name_2&amp;rdquo;:&amp;ldquo;other_data_in_here&amp;rdquo;}
(2 rows)&lt;/p&gt;
&lt;p&gt;From here based on the query I would want to get some specific value. In this case I&amp;rsquo;m going to search for the text key column_name_2:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT json_array_elements(result)-&amp;gt;'column_name_2'
FROM query_results
LIMIT 1;
json_array_elements
-----------------------
&amp;quot;other_data_in_here&amp;quot;
(1 rows)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;One gotcha I encountered was when I wanted to search for some value or exclude some value&amp;hellip; Expecting I could just compare the result of the above in a where statement I was sadly mistaken because the equals operator didn&amp;rsquo;t translate.&lt;/em&gt; My first attempt at fixing this was to cast in this form:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT json_array_elements(result)-&amp;gt;'column_name_2'::text
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The sad part is because of the operator the cast doesn&amp;rsquo;t get applied as I&amp;rsquo;d expect. Instead you&amp;rsquo;ll want to do:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT (json_array_elements(result)-&amp;gt;'column_name_2')::text
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course theres plenty more you can do with the &lt;a href="http://www.postgresql.org/docs/9.3/static/functions-json.html"&gt;JSON operators in the new Postgres 9.3&lt;/a&gt;. If you&amp;rsquo;ve already got JSON in your application give them a look today. And while slightly worse, if you&amp;rsquo;ve got JSON stored in a text field simply cast it with &lt;code&gt;::json&lt;/code&gt; to begin using the operators.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re looking for a deeper resource on Postgres I recommend the book &lt;a href="https://theartofpostgresql.com/?affiliate=cek"&gt;The Art of PostgreSQL&lt;/a&gt;. It is by a personal friend that has aimed to create the definitive guide to Postgres, from a developer perspective. If you use code CRAIG15 you&amp;rsquo;ll receive 15% off as well.&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Wed, 11 Sep 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/09/11/Diving-into-Postgres-JSON-operators-and-functions/</guid></item><item><title>The Fizzbuzz Bug Tracker A Bug Tracker for Single Developers</title><link>https://boyter.org/2013/09/fizzbuzz-bug-tracker/</link><description>&lt;p&gt;This serves as the announcement of my new bug tracker product I am working on.&lt;/p&gt;
&lt;p&gt;My needs are pretty specific and none of the existing bug trackers I have tried have meet the following goals.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Speed. Searching, adding projects/issues/comments should be instant. Any time waiting on the bug tracker is wasted time.&lt;/li&gt;
&lt;li&gt;Outlook style view of projects/issues/comments. This should allow me to get an overview of how I am tracking.&lt;/li&gt;
&lt;li&gt;Not require me to spin up a full web-server. I don&amp;rsquo;t want to have to install a full stack web-server just to track bugs.&lt;/li&gt;
&lt;li&gt;Sync across all devices. I want it to just appear on every device I own without me having to worry about backups or keeping things in sync.&lt;/li&gt;
&lt;li&gt;Be single user. I don&amp;rsquo;t want to have to login or perform user management.&lt;/li&gt;
&lt;li&gt;Support multiple projects. I also want to be able to have multiple issues per project.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With that in mind let me introduce the Fizzbuzz Bug Tracker. Fizzbuzz is a single executable that works on Windows, Linux and OSX (once I have a machine to compile it on). A suggested workflow is to copy it onto your Dropbox folder (or equivalent) where it will be synced across all devices. Fizzbuzz has a strong emphasis on speed. Adding projects or issues, searching across projects and issues, drilling into projects or issues is near instant.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Fri, 06 Sep 2013 08:22:26 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/09/fizzbuzz-bug-tracker/</guid></item><item><title>Collection of Letters for Neural Network OCR Training</title><link>https://boyter.org/2013/09/collection-letters-training/</link><description>&lt;p&gt;I was looking for this on Google the other day and unable to find it. Essentially what I needed was a collection of images which are all the same size, but of different fonts so that I use them for training Neural Networks and test other OCR techniques. Since I couldn&amp;rsquo;t find any I thought I would upload my own collection.&lt;/p&gt;
&lt;p&gt;I used the below images when working on my thesis. From memory over 20 different fonts and sizes were used to create about 200 examples of each letter. The full data set proved to be pretty accurate when it came to recognizing most examples of text I found on the web.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Tue, 03 Sep 2013 08:59:42 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/09/collection-letters-training/</guid></item><item><title>Saving Resources for Humans in PHP</title><link>https://boyter.org/2013/08/saving-resources-humans-php/</link><description>&lt;p&gt;One of the issues I have run into running searchcode.com is that a huge amount of time spent serving pages is serving them to bots (about 900,000 hits a day are from bots). I have been watching the load averages and they can spike to over 30.00 occasionally which is pretty bad for a 4 core/ht system. I don&amp;rsquo;t have any problems with bot&amp;rsquo;s really other then the fact that I cannot really control them. Sure you can specify crawl delays but its of limited use if the bot chooses to ignore it.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Tue, 27 Aug 2013 03:23:43 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/08/saving-resources-humans-php/</guid></item><item><title>The Rule of Thirds - followup</title><link>/2013/08/13/The-Rule-of-Thirds-followup/</link><description>&lt;p&gt;Several months back I wrote about how we do &lt;a href="http://www.craigkerstiens.com/2013/03/13/planning-and-prioritizing/"&gt;higher level, long term planning within the Heroku Postgres team&lt;/a&gt;. If you haven&amp;rsquo;t read the previous article please start there.&lt;/p&gt;
&lt;p&gt;The exercise or rule of thirds is intended to be approximate prioritization and not a perfect science. Since that time I&amp;rsquo;m familiar with some teams both in and out of Heroku who have attempted this exercise with varying levels of success. We&amp;rsquo;ve now done this process 4 times within the team and after the most recent exercise attempted to take some time to internalize why its worked well, creating some more specifics about the process. Heres an attempt to provide even more clarity:&lt;/p&gt;
&lt;h2 id="gather-data-ahead-of-time"&gt;
&lt;div&gt;
Gather data ahead of time
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;Its really common to have a list things to work on, but knowing the impact of those is commonly pure speculation. There may be some people that talk to customers, but even then its a subset of your actual customer base. Going into the exercise as much data you can have ahead of time on impact of features and specific problems helps. In our case we do this by:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Surveying current customers and users&lt;/li&gt;
&lt;li&gt;Surveying attriters&lt;/li&gt;
&lt;li&gt;Engaging with customer facing teams to hear trends&lt;/li&gt;
&lt;li&gt;Input from external parties such as analysts on trends&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="allow-for-casual-discussion"&gt;
&lt;div&gt;
Allow for casual discussion
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;We typically conduct our planning exercise at an offsite, this is a multi-day time of team bonding, planning, hacking. We intentionally schedule our planning excercise towards the end of the offsite. This allows us to have updates/presentations frmo the data we&amp;rsquo;ve gathered and from those that are customer facing. Presentations are meant to be short and direct, discussion can flow casually after. This gets a lot of people on the same page at a smaller level and reduces the problem of too many cooks in the kitchen come time for the actual exercise.&lt;/p&gt;
&lt;h2 id="the-rule-of-thirds"&gt;
&lt;div&gt;
The rule of thirds
&lt;/div&gt;
&lt;/h2&gt;
&lt;h3 id="creating-the-list"&gt;
&lt;div&gt;
Creating the list
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Coming to the exercise itself&amp;hellip; We begin by everyone writing a list of their ideas individually, this is meant to be a list of the features we want to place on the grid. At this point theres no prioritizing of difficulty or impact. In addition each list while individually created does not have to contain items that only pertain to you, its more a comprehensive list of all the things you can think of that may be important to do.&lt;/p&gt;
&lt;h3 id="bucketing-part-1"&gt;
&lt;div&gt;
Bucketing part 1
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Once individual lists are created you can then collectively or designate one or two people to clean it up. We do this in two forms:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Removing duplicate items, which there should be several of.&lt;/li&gt;
&lt;li&gt;Bucketing my a common/theme idea, this simply makes things more digestable&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you&amp;rsquo;re a big group of greater than 7 then it may be advisable to designate two people to do this exercise together. If a smaller group it can be manageable to coordinate collectively.&lt;/p&gt;
&lt;h3 id="bucketing-part-2"&gt;
&lt;div&gt;
Bucketing part 2
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Once you&amp;rsquo;ve removed dupes, identified themes, and removed excess items (depending on your team size you&amp;rsquo;ll find how many feels right - we aim an average of 5-6 per square for a team of 10) its then on to actually putting them on the grid. In the past we&amp;rsquo;ve done this a variety of ways but our most recent process seemed to be quiet efficient. We gave each item 60 seconds, at the end of that minute wherever the item was it was left there. This forced some quick discussion on impact and difficulty but in the end left us at a very good hit rate without taking multiple hours to complete the exercise.&lt;/p&gt;
&lt;h3 id="final-pass"&gt;
&lt;div&gt;
Final pass
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;We intentionally design it so that low effort and high impact is on the top right corner. Finally once everything is on there we allocate names to the tasks, and put boxes around items we&amp;rsquo;re planning to do in the coming months. With boxes make it very clear of what we are doing as well as explicitly things we are not. The initials or names make it clear of how loaded down people are. If your name is on 3 tasks that are high difficulty, then you&amp;rsquo;re likely over allocated.&lt;/p&gt;
&lt;p&gt;At this point things usually fall out pretty quickly and we emerge with some rough roadmap that in retrospect we&amp;rsquo;ve followed pretty accuately.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Tue, 13 Aug 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/08/13/The-Rule-of-Thirds-followup/</guid></item><item><title>C# Vector Space Implementation</title><link>https://boyter.org/2013/08/c-vector-space-implementation/</link><description>&lt;p&gt;Since I am writing lots of Vector Space implementations in Go, Python etc… I thought I would add another one in C#. This one is a little more verbose then either the Python or Go implementations. The verbosity is mostly due to not using any of the nice C# LINQ functionality which would really reduce the size.&lt;/p&gt;
&lt;p&gt;In any case here it is in case you are looking for a simple implementation of this useful class.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Tue, 13 Aug 2013 08:59:09 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/08/c-vector-space-implementation/</guid></item><item><title>GoLang Vector Space Implementation</title><link>https://boyter.org/2013/08/golang-vector-space-implementation/</link><description>&lt;p&gt;UPDATE – This is now actually available as a real Golang import with tests. Get it at &lt;a href="https://github.com/boyter/golangvectorspace"&gt;https://github.com/boyter/golangvectorspace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I have mentioned this before somewhere but one of the first things I usually attempt to implement in any programming language I want to play with is a vector space. Its my own personal FizzBuzz implementation. It usually covers everything I need to know in a language (imports, functions, string manipulation, math functions, iteration, maps etc…) so I consider it a good thing to get started with.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 12 Aug 2013 09:51:30 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/08/golang-vector-space-implementation/</guid></item><item><title>The missing PostgreSQL documentation</title><link>/2013/08/07/The-missing-PostgreSQL-documentation/</link><description>&lt;p&gt;For a couple of years I&amp;rsquo;ve complained about the Postgres documentation and at the same time paraded it as one of the best sets of documentation I&amp;rsquo;ve encountered. In many ways the reason I veer towards &lt;a href="http://www.postgresql.org"&gt;Postgres&lt;/a&gt; as well as &lt;a href="http://www.python.org"&gt;Python&lt;/a&gt; and &lt;a href="http://www.djangoproject.com"&gt;Django&lt;/a&gt; is the quality of their documentation. If you need to find details about something its documented, and more importantly well and thoroughly documented.&lt;/p&gt;
&lt;p&gt;In large part I came to Python by happenstance through &lt;a href="http://www.djangoproject.com"&gt;Django&lt;/a&gt;, and Postgres through happenstance of an employer. Yet, Django was very little of an accident. The Django Tutorial got me a large part of what I needed to know and more excited about development than I had been in some time. Python has done some work at adding docs to make this even better, sadly its still very much needed for PostgreSQL.&lt;/p&gt;
&lt;h3 id="whats-missing-in-the-postgres-docs"&gt;
&lt;div&gt;
Whats Missing in the Postgres Docs
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Theres a huge variety of types of documentation, off the top of my head theres:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reference docs (Postgres excels at this)&lt;/li&gt;
&lt;li&gt;Onboarding (Postgres tutorial huh?)&lt;/li&gt;
&lt;li&gt;Tailored guides (Postgres? I can haz? Nope&amp;hellip; We don&amp;rsquo;t understand&amp;hellip;.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Postgres is great if you know the name of what you&amp;rsquo;re looking for, but if you don&amp;rsquo;t you&amp;rsquo;re entirely left in the dark.&lt;/p&gt;
&lt;h3 id="understanding-the-power-of-postgres"&gt;
&lt;div&gt;
Understanding the power of Postgres
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Postgres is good enough at performance, good enough at usability, and awesome at how powerful and flexible it can be. But all of this is entirely lost if you have to know the esoteric name of what you&amp;rsquo;re looking for.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What the hell is an hstore&amp;hellip; In so many ways KVstore makes infintely more sense. In the same sense PLV8, I have to know not only what PL stands for but V8 as well, versus the JavaScript extension for Postgres.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I understand there are plenty of reasons why some of these things are the way they are, but its also limiting how great the broader perception is. Postgres externally is this hard to use DB, that well is just a database, versus giving developers a set of powerful and useful functions to make their lives better.&lt;/p&gt;
&lt;h3 id="the-solution"&gt;
&lt;div&gt;
The Solution
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Lets fix things, there are a ton of people that would love to know more about all things Postgres. This ranges from a good set of onboarding docs, to specific blog posts on topics that people are curious about. Just last week I got an email about improving &lt;strong&gt;the&lt;/strong&gt; Postgres tutorial&amp;hellip; Yes theres a tutorial hidden in the &lt;a href="http://www.postgresql.org/docs/9.2/static/tutorial.html"&gt;2000 page set of documentation for Postgres&lt;/a&gt;. Its simply old, mostly uninteresting, and well just needs to be completely recreated. A great alternative would be a few tutorials/guides for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Noobs to databases in general (Total 101 guide)&lt;/li&gt;
&lt;li&gt;Building and architecting your application with Postgres (App Devs)&lt;/li&gt;
&lt;li&gt;Administering and maintaining Postgres (DBAs)&lt;/li&gt;
&lt;li&gt;SQL and reporting in Postgres (consumers of data, analysts, product people, marketing, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If jumping in and contributing to fixing the core tutorial isn&amp;rsquo;t your cup of tea because you don&amp;rsquo;t want to learn and write in &lt;a href="http://www-sul.stanford.edu/tools/tutorials/html2.0/gentle.html"&gt;SGML&lt;/a&gt;, send a pull request to &lt;a href="http://postgresguide.com"&gt;postgresguide.com&lt;/a&gt; or do a [guest post on my blog](mailto:craig.kerstiens@gmail.com]. If thats too much effort please just let us know, what do you want to see - &lt;a href="mailto:craig.kerstiens@gmail.com"&gt;craig.kerstiens at gmail.com&lt;/a&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Wed, 07 Aug 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/08/07/The-missing-PostgreSQL-documentation/</guid></item><item><title>A look at Foreign Data Wrappers</title><link>/2013/08/05/A-look-at-Foreign-Data-Wrappers/</link><description>&lt;p&gt;There are two particular sets of features that continue to keep me very excited about the momentum of Postgres. And while PostgreSQL has had some great momentum in the past few years these features may give it an entirely new pace all together. One is extensions, which is really its own category. Dimitri Fontaine was talking about doing a full series just on extensions, so here&amp;rsquo;s hoping he does so I dont have to :)&lt;/p&gt;
&lt;p&gt;One subset of extensions which I consider entirely separate is the other thing, which is foreign data wrappers or FDWs. FDWs allow you to connect to other data sources from within Postgres. From there you can query them with SQL, join across disparate data sets, or join across different systems. Recently I had a good excuse to give the &lt;code&gt;postgres_fdw&lt;/code&gt; a try. And while I&amp;rsquo;ve blogged about the Redis FDW previously, the Postgres one is particularly exciting because with PostgreSQL 9.3 it will ship as a contrib module, which means all Postgres installers should have it&amp;hellip; you just have to turn it on.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at getting it setup and then dig into it a bit. First, because I don&amp;rsquo;t have Postgres 9.3 sitting around on my system I&amp;rsquo;m going to provision one from Heroku Postgres:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ heroku addons:add heroku-postgresql:crane --version 9.3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once it becomes available I&amp;rsquo;m going to connect to it then enable the extension:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ heroku pg:psql BLACK -acraig
# CREATE EXTENSION postgres_fdw;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now its there, so we can actually start using it. To use the FDW there&amp;rsquo;s four basic things you&amp;rsquo;ll want to do:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create the remote server&lt;/li&gt;
&lt;li&gt;Create a user mapping for the remote server&lt;/li&gt;
&lt;li&gt;Create your foreign tables&lt;/li&gt;
&lt;li&gt;Start querying some things&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="the-setup"&gt;
&lt;div&gt;
The setup
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;You&amp;rsquo;ll only need to do each of the following once, once you&amp;rsquo;re server, user and foreign table are all setup you can simply query away. This is a nice advantage over db_link which only exists for the set session. &lt;em&gt;One downside I did find was that you can&amp;rsquo;t use a full Postgres connection string, which would make setting it up much simpler&lt;/em&gt;. So onto setting up our server:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# CREATE SERVER app_db
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (dbname 'dbnamehere', host 'hostname-here);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we&amp;rsquo;ll actually create our user mapping. In this case we&amp;rsquo;ll take the remote username and password and map it to our current user we&amp;rsquo;re already connected with.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# CREATE USER MAPPING for user_current
SERVER app_db
OPTIONS (user 'remote_user', password 'remote_password');
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally we&amp;rsquo;re going to configure our tables. &lt;em&gt;There were some additional pains here as there wasn&amp;rsquo;t a perfectly clean way to generate the &lt;code&gt;CREATE TABLE&lt;/code&gt;. Sure you could pg_dump just that table, but overall it felt a bit cludgey.&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# CREATE FOREIGN TABLE users
(
id integer,
email text,
created_at timestamp,
first_name text,
last_name text
)
SERVER app_db OPTIONS (table_name 'users')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we&amp;rsquo;ve got all of our local data, as well as remote data. For that report against two databases where you previously wrote a ruby or python script, ran a query, constructed another query, then executed it you can directly do in your database. We can simply query our new table - &lt;code&gt;SELECT * FROM users LIMIT 5;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;But the real power of foreign data wrappers goes well beyond just Postgres to Postgres. Having a defined contract in translating from one system to another, will really allow reinventing the way we work with data. This is especially true in large datasets where doing ETL on terrabytes of data takes longer than asking the questions of it.&lt;/p&gt;
&lt;p&gt;While we&amp;rsquo;re waiting for more FDWs to be ready to use in production situations the Postgres FDW is a great start, &lt;em&gt;though the Redis one is on its way&lt;/em&gt;. Even better is that it ships with standard installs of Postgres, meaning it will see more usage and help push them to advance further.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;One final nicety, you&amp;rsquo;re not required to have ALL Postgres 9.3 DBs, just one that can then connect to the others, so go ahead and give it try :)&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Mon, 05 Aug 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/08/05/A-look-at-Foreign-Data-Wrappers/</guid></item><item><title>EverQuest Next Revealed</title><link>https://benovermyer.com/blog/2013/08/everquest-next-revealed/</link><description>&lt;img class="photo" src="https://benovermyer.com/blog/2013/08/everquest-next-revealed/&amp;#x2F;&amp;#x2F;benovermyer.com&amp;#x2F;processed_images&amp;#x2F;EQN_logo_color1.ed82b71ca4d9435a.jpg" /&gt;
&lt;p&gt;I'm writing this just a couple minutes after watching the EverQuest Next reveal video on Twitch. I couldn't watch it live yesterday, but it was totally worth the wait. For an hour and a half, I was on the edge of my chair. The introduction was a beautiful piece of sand performance art, which I otherwise won't talk about. The rest of the video was an introduction into what will probably be the single most revolutionary MMORPG to come out since 2003.&lt;/p&gt;
&lt;p&gt;Dave Georgeson, director of development for EverQuest Next, started things off with a reveal of the art style. Let me tell you, this is a gorgeous game. The whole thing is very painterly, and is rendered using a modified version of the engine powering Planetside 2.&lt;/p&gt;
&lt;p&gt;All of the races have been redone, and we were treated to concept art for several: the High Elf, the Dark Elf, the Human, the Dwarf, and the Kerran. The Dark Elf and the Kerran were probably the biggest departure from previous EQ designs. Kerrans are distinctly more lionesque, with pronounced lion's heads instead of the old cat faces and huge builds. Dark elves look like standard dark elves, except they have draconic eyes and short horns. There's a story behind that that I really want to hear.&lt;/p&gt;
&lt;p&gt;The art style for characters is exaggerated, even slightly cartoony. I'm really OK with that, especially since they're building SOEmote into the game from the beginning. It's easy to see the expressions of the players themselves on their characters, and that's marvelous for a roleplayer, but also for immersion and socializing in general.&lt;/p&gt;

&lt;img class="photo" src="https://benovermyer.com/blog/2013/08/everquest-next-revealed/&amp;#x2F;&amp;#x2F;benovermyer.com&amp;#x2F;processed_images&amp;#x2F;everquestnext_07.40655afe3d5594f3.jpg" /&gt;
&lt;p&gt;Movement is fantastic. Characters slide, leap, vault, grab, and otherwise interact with the terrain in a very natural way. With EQN's “active movement system,” players are free to really enjoy moving around in the world. There are items and spells that allow additional ways to move, like the Boots of the Zephyr in the video that allowed the players to float gently downward. Brilliant stuff.&lt;/p&gt;
&lt;p&gt;Then, we got into the Four Grails, as Dave put it.&lt;/p&gt;
&lt;h1 id="the-core-game"&gt;The Core Game&lt;/h1&gt;
&lt;p&gt;Grail 1 is the “Core Game.” This was the least impressive of the Grails, but it was still nice to see. Character evolution from a mechanical standpoint is based on collecting classes from around the world and mixing and matching abilities from them. It sounds like a hybrid of Guild Wars 2's system and Rift's system. Weapon choice matters, like it does in GW2.&lt;/p&gt;
&lt;h1 id="destructibility"&gt;Destructibility&lt;/h1&gt;
&lt;p&gt;Grail 2 is “Destructibility,” and this was the first mind-blowing revelation. The entire game world is built of voxels, despite looking natural and perfectly designed. It's fully destructible, even though it heals over time. It's like if SOE took a look at Minecraft and applied that on a grand scale. The way it works, too, is gorgeous. You can definitely see the aftermath of epic battles in the environment that it occurred in.&lt;/p&gt;
&lt;h1 id="a-life-of-consequence"&gt;A Life of Consequence&lt;/h1&gt;
&lt;p&gt;Grail 3 is “A Life of Consequence.” Besides the standard “every action you take matters” spiel, we were introduced to the idea of emergent AI in an MMO. SOE will create mob behavioral patterns - likes, dislikes, etc. - and then release mobs of that type into the world. They will live, react, and die according to how they're programmed to behave. This means it's entirely possible to have roving bands of orcs that actually decide to set up camp in a particular area - choose their own spawn point, as it were. It's also possible to drive them out.&lt;/p&gt;
&lt;h1 id="permanent-change"&gt;Permanent Change&lt;/h1&gt;
&lt;p&gt;Grail 4 is “Permanent Change.” For the most part, Dave talked about the Rallying Cry system, which is a little like a server-wide public quest that lasts 2-3 months each… and has permanent effect on the game world. These Rallying Cries are promised to be different on every server, and that along with the Life of Consequence and Destructibility Grails ensure that no two servers will have the same environment and history, let alone community.&lt;/p&gt;
&lt;h1 id="everquest-next-landmark"&gt;EverQuest Next Landmark&lt;/h1&gt;
&lt;p&gt;As if all this wasn't enough, then they got into the EverQuest Next Landmark game that's coming out later in 2013. Landmark sounds basically like Minecraft on an epic scale, except that one continent in each Landmark server will have EverQuest Next art direction enforced… and creations from those areas will make it into EverQuest Next as real, lasting landmarks.&lt;/p&gt;
&lt;h1 id="player-studio"&gt;Player Studio&lt;/h1&gt;
&lt;p&gt;On top of that, SOE's Player Studio will find a very interesting real money economy implementation for people who enjoy building things in Landmark; you'll be able to sell not only finished works, but components. The example that Dave gave was of a player creating a nice crenelated tower. People could buy that tower, then make castles from it and sell those castles, and the player who created the tower would get royalties based on how many of that tower were used in the castle design for every castle sold. It's a fascinating system.&lt;/p&gt;
&lt;p&gt;Basically, EverQuest Next sounds like the game I've been waiting for my entire gaming life. I really want to hear about how the crafting system works, and more about all the races, but… it sounds awe-inspiring. EverQuest Next takes player involvement in the game to a level never before seen.&lt;/p&gt;
&lt;h1 id="related-articles"&gt;Related articles&lt;/h1&gt;
&lt;p&gt;EverQuest Next - Landmark Focuses on Construction and Exploration, Is Free-to-Play&lt;/p&gt;
&lt;p&gt;EverQuest Next + Jeremy Soule = Geek Delight&lt;/p&gt;
&lt;p&gt;EverQuest Next Redefines Next-Gen MMOs Enhanced by Zemanta&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sat, 03 Aug 2013 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/08/everquest-next-revealed/</guid></item><item><title>Postgres Dollar Quoting</title><link>/2013/08/02/Postgres-Dollar-Quoting/</link><description>&lt;p&gt;After my most recent post on &lt;a href="/2013/07/29/documenting-your-postgres-database/"&gt;documenting your database&lt;/a&gt; I had a colleague and friend chime in:&lt;/p&gt;
&lt;p&gt;{% blockquote @danfarina &lt;a href="https://twitter.com/danfarina/status/362007008079126528"&gt;https://twitter.com/danfarina/status/362007008079126528&lt;/a&gt; %}
@craigkerstiens You may want to mention for another post the generality of dollar quoting: it&amp;rsquo;s not just for CREATE FUNCTION.
{% endblockquote %}&lt;/p&gt;
&lt;p&gt;Luckily I was able to convince him to create the post. You can read a bit more on him below, but without further adieu here&amp;rsquo;s a bit on dollar quoting within Postgres:&lt;/p&gt;
&lt;p&gt;Postgres supports two forms of entry of data literals into the system.
One is the familiar single-quote:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;=&amp;gt; SELECT 'hello';
?column?
----------
hello
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This format is problematic when one might be using single quotes in
the textual string.&lt;/p&gt;
&lt;p&gt;Postgres also supports another way to enter data
literals, most often seen in &lt;code&gt;CREATE FUNCTION&lt;/code&gt;, but can be profitably
used anywhere. This is called &amp;ldquo;dollar quoting,&amp;rdquo; and it looks like
this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;=&amp;gt; SELECT $$hello's the name of the game$$;
?column?
------------------------------
hello's the name of the game
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If one needs nested dollar quoting, one can specify a string, much
like the &amp;lsquo;heredoc&amp;rsquo; feature seen in some programming languages:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;=&amp;gt; SELECT $goodbye$hello's the name of the $$ game$goodbye$;
?column?
---------------------------------
hello's the name of the $$ game
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can appear anywhere where single quotes would otherwise be,
simplifying tasks like using contractions in database object comments,
for example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;=&amp;gt; CREATE TABLE described(a int);
=&amp;gt; COMMENT ON TABLE described IS $$I'm describing this,
including newlines and an apostrophe in the contraction &amp;quot;I'm.&amp;quot;$$;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or, alternatively, entry of literals for types that may include
apostrophes in their serialization, such as &amp;rsquo;text&amp;rsquo; or &amp;lsquo;json&amp;rsquo;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;=&amp;gt; CREATE TABLE json(data json);
=&amp;gt; INSERT INTO json(data) VALUES
($${&amp;quot;quotation&amp;quot;: &amp;quot;'there is no time like the present'&amp;quot;}$$);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="security"&gt;
&lt;div&gt;
Security
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Even though dollar quotes can be used to reduce the pain of many
quoting problems, don&amp;rsquo;t be tempted to use them to avoid SQL injection:
an adversary that knows one is using dollar quoting can still mount
exactly the same kind of attacks as if one were using single quotes.&lt;/p&gt;
&lt;p&gt;There is also no need, because any place a data literal can appear can
also be used with parameter binding (e.g. &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt;, &lt;code&gt;$3&lt;/code&gt;&amp;hellip;), which one&amp;rsquo;s
Postgres driver should support. Nevertheless, for data or scripts one
is working with by hand, dollar quoting can make things much easier to
read.&lt;/p&gt;
&lt;h3 id="about-the-author"&gt;
&lt;div&gt;
About the Author
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Daniel Farina is a long time colleague and friend, having worked together at 5 different companies. He&amp;rsquo;s part of the &lt;a href="https://twitter.com/danfarina/status/362007008079126528"&gt;Heroku Postgres&lt;/a&gt; team as the resident tuple groomer, and the creator of &lt;a href="https://github.com/wal-e/wal-e"&gt;WAL-E&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;As is always the case if you have articles you&amp;rsquo;d like to see created or if you&amp;rsquo;re interested in doing a guest post please feel free to drop me a line &lt;a href="mailto:craig.kerstiens@gmail.com"&gt;craig.kerstiens at gmail.com&lt;/a&gt;. And if you have articles you feel are helpful to others in the Postgres world drop me a note as well for including them in &lt;a href="http://www.postgresweekly.com"&gt;Postgres Weekly&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Fri, 02 Aug 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/08/02/Postgres-Dollar-Quoting/</guid></item><item><title>Automatically inline Python function calls</title><link>https://tomforb.es/blog/automatically-inline-python-function-calls/</link><description>Edit: Code is here on GitHub Calling functions in Python can be expensive. Consider this example: there are two statements that are being timed, the first one calls a function that returns an integer while the second one calls a function that returns the result of a second function call which return...</description><author>Tom Forbes</author><pubDate>Thu, 01 Aug 2013 18:54:18 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/automatically-inline-python-function-calls/</guid></item><item><title>Clean Repository Data Access in C#</title><link>https://boyter.org/2013/07/clean-repository-data-access-c/</link><description>&lt;p&gt;Mostly as a self reference here is an extremely clean data access pattern possible using C# and Entity Framework. It saves you the effort of mocking the database context as the code you end up writing is so simple it is all compile time checked.&lt;/p&gt;
&lt;p&gt;Essentially you define a very simple class which provides a single method for getting data (although you may want a save data method too) and make sure you add an interface to make unit testing/mocking easier.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 01 Aug 2013 02:52:14 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/07/clean-repository-data-access-c/</guid></item><item><title>Documenting your PostgreSQL database</title><link>/2013/07/29/Documenting-your-PostgreSQL-database/</link><description>&lt;p&gt;Just a few days ago I was surprised by what someone was doing with their database, and not in the typical horrifying travesty against mankind. Rather, it was a feature that while familiar with I&amp;rsquo;d never seen anyone fully take proper advantage of - &lt;code&gt;COMMENT&lt;/code&gt; or describing tables. Postgres has a nice facility for you to provide a description for just about anything:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Table&lt;/li&gt;
&lt;li&gt;Column&lt;/li&gt;
&lt;li&gt;Function&lt;/li&gt;
&lt;li&gt;Schema&lt;/li&gt;
&lt;li&gt;View&lt;/li&gt;
&lt;li&gt;Index&lt;/li&gt;
&lt;li&gt;Etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The specific use case was a database acting as a datamart pulling in data from multiple sources to be able to report against disparate data. Over the years I&amp;rsquo;ve seen this occur really one three ways, the first is that a limited set of people, typically one person, have knowledge over all the datasources and thus far the sole individual responsible for creating reports and answering questions of the data. The second, is wide open access to anyone that wishes for it. In this case you often have people asking questions of the data, and because they don&amp;rsquo;t understand the relationships coming up to entirely wrong conclusions. The final approach is to create some external documentation, entity relationship diagrams, data dictionaries, etc. This last one often works okay enough, but often suffers from lack of updates and being too heavyweight.&lt;/p&gt;
&lt;p&gt;A better solution, and all around good process is simply documenting clearly within the database itself. Simply comment each table and column, just as you would outside of your DB then it can be quite clear when inside the database working interactivly:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;COMMENT ON TABLE products IS 'Products catalog';
COMMENT ON COLUMN products.price is 'Current price of a single item purchased';
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While an obvious example above naming even the most mundance columns can help create more accurate reports. Then of course when you want to inspect your DB its quite clear:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\d+ users
# \d+ users
Table &amp;quot;public.users&amp;quot;
Column | Type | ... | Description
------------+-----------------------------+-...-+-----------------------------------------
id | integer | ... | auto serial pk
first_name | character varying(50) | ... | required first name of user
last_name | character varying(50) | ... | required first name of user
email | character varying(255) | ... | email address of account
data | hstore | ... | mix of data, city, state, gender
created_at | timestamp without time zone | ... | when account was created, not confirmed
updated_at | timestamp without time zone | ... | time any details were last updated
Indexes:
&amp;quot;idx_user_created&amp;quot; btree (date_trunc('day'::text, created_at))
Has OIDs: no
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But it doesn&amp;rsquo;t necessarily have to stop there. Which actually brings me to one other item, you should be commenting your SQL just the same. SQL comments can be done easily by just starting a line with &lt;code&gt;--&lt;/code&gt;, or you can have it at the end of the line with further info. Here&amp;rsquo;s a nice example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-- Query aggregates all project names that have open past due tasks grouped by email
SELECT
users.email,
array_to_string(array_agg(projects.name), ',')) as projects # Aggregate all projects and separate by comma
FROM
projects,
tasks,
users
-- A user has a project, which has tasks
WHERE projects.id = tasks.project_id
-- Check for tasks that are due before now and not done yet
AND tasks.due_at &amp;gt; tasks.completed_at
AND tasks.due_at &amp;lt; now()
AND users.id = projects.user_id
GROUP BY
users.email
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You comment your code, why shouldn&amp;rsquo;t you comment your database?&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Mon, 29 Jul 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/07/29/Documenting-your-PostgreSQL-database/</guid></item><item><title>Gigablast Aquired and Code Posted</title><link>https://boyter.org/2013/07/gigablast-aquired-code-posted/</link><description>&lt;p&gt;Interestingly it seems that Matt Well&amp;rsquo;s search engine Gigablast has been acquired by Yippy.com [&lt;a href="http://www.prnewswire.com/news-releases/yippy-inc-yipi-to-acquire-gigablast-inc-and-web-research-properties-llc-to-expand-consumer-search-enterprise-and-ediscovery-products-213120401.html"&gt;1&lt;/a&gt;]&lt;a href="http://www.prnewswire.com/news-releases/yippy-inc-yipi-to-acquire-gigablast-inc-and-web-research-properties-llc-to-expand-consumer-search-enterprise-and-ediscovery-products-213120401.html"&gt;1&lt;/a&gt; [&lt;a href="http://arnoldit.com/wordpress/2013/07/19/acquisition-of-gigablast-by-yippy-inc-leaves-some-questions-unanswered/"&gt;2&lt;/a&gt;]&lt;a href="http://arnoldit.com/wordpress/2013/07/19/acquisition-of-gigablast-by-yippy-inc-leaves-some-questions-unanswered/"&gt;2&lt;/a&gt; [&lt;a href="http://ca.finance.yahoo.com/news/yippy-inc-yipi-acquire-gigablast-130000100.html"&gt;3&lt;/a&gt;]&lt;a href="http://ca.finance.yahoo.com/news/yippy-inc-yipi-acquire-gigablast-130000100.html"&gt;3&lt;/a&gt; (&lt;a href="http://demo.yippy.com/"&gt;demo here http://demo.yippy.com/&lt;/a&gt;). Gigablast has always been one of my favorite search engines simply because it is so interesting. Started by a single guy, with an interesting blog and being one of the last true new indexes of the web it was always worth a look. While its sad to see it go this way I am happy that Matt presumably has been able to cash out on his creation. Well done to him. I must admit Gigablast had been going downhill for a while and this might explain why ProCog appeared and then vanished so quickly.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 29 Jul 2013 08:58:30 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/07/gigablast-aquired-code-posted/</guid></item><item><title>Reawakening the Starborn</title><link>https://benovermyer.com/blog/2013/07/reawakening-the-starborn/</link><description>&lt;p&gt;About a year and a half ago, I started a project to create a sci-fantasy sandbox MMORPG. It was called Starborn: Universe. I went through the trouble of getting a HeroEngine/HeroCloud environment and began learning the toolset. Design documents popped up in my Documents folder and on the dev blog I started for the project. Then, I got busy with other things, and Starborn: Universe went dark. Until now. I'm dusting off the design documents, but Starborn: Universe is as much of an experiment as it is a game. See, my theory is that online player-driven games can start with very little and grow over time. The idea of the “Lean Startup” can apply just as much to an MMORPG as it can to an iOS app. The trick is that MMORPGs are hard to produce. They have a lot of moving parts and require a lot of resources on the part of the developer and operator. So how does one or two people accomplish this monumental feat? By starting small, and iterating quickly. If you're curious as to what I have in mind, head over to the &lt;a href="https://starbornuniverse.wordpress.com/" rel="external"&gt;Starborn: Universe devlog&lt;/a&gt;. That's where I'll be writing about Starborn.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sat, 27 Jul 2013 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/07/reawakening-the-starborn/</guid></item><item><title>CoffeeScript's Scoping is Madness</title><link>https://donatstudios.com/CoffeeScript-Madness</link><description>&lt;p&gt;&lt;a href="https://coffeescript.org/"&gt;CoffeeScript&lt;/a&gt; is a programming language that compiles to JavaScript. Its mission is to &amp;quot;expose the good parts of JavaScript in a simple way&amp;quot;. I've  heard a lot of interest in it lately from various channels. &lt;/p&gt;
&lt;p&gt;After a coworkers departure, I inherited maintenance on our deployment bot, and it was written in CoffeeScript. While trying to make some small modifications, I ended up getting unexpected issues I didn't understand. Things I did not touch were suddenly breaking. I did not understand until I investigated the generated JavaScript.&lt;/p&gt;
&lt;p&gt;It ends up CoffeeScripts approach to scoping of variables is to not scope variables. There is no shadowing. There is no &lt;code&gt;var&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt; nor &lt;code&gt;const&lt;/code&gt; equivalent, there is simply no way to explicitly define scope. &lt;/p&gt;
&lt;p&gt;Variables in CoffeeScript are scoped to their outermost definition, regardless of whether the name was already in use elsewhere. When you use a variable of a name, its scope now includes all inner scopes, trampling any existing definitions of the variable in those scopes.&lt;/p&gt;
&lt;p&gt;Let's examine the following examples:&lt;/p&gt;
&lt;div style="display: grid;"&gt;
&lt;strong&gt;CoffeeScript&lt;/strong&gt;
&lt;pre&gt;&lt;code&gt;test = (x) -&amp;gt;
  y = 10
  x + y;

alert test 5&lt;/code&gt;&lt;/pre&gt;
&lt;strong&gt;Generated JavaScript&lt;/strong&gt;
&lt;pre&gt;&lt;code&gt;var test;

test = function(x) {
  var y;
  y = 10;
  return x + y;
};

alert(test(5));&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now let's make one small change and define a variable &lt;code&gt;y&lt;/code&gt; in the outer scope, outside the function.&lt;/p&gt;
&lt;div style="display: grid;"&gt;
&lt;strong&gt;CoffeeScript&lt;/strong&gt;
&lt;pre&gt;&lt;code&gt;y = 0;
test = (x) -&amp;gt;
  y = 10
  x + y;

alert test 5&lt;/code&gt;&lt;/pre&gt;
&lt;strong&gt;Generated JavaScript&lt;/strong&gt;
&lt;pre&gt;&lt;code&gt;var test, y;

y = 0;

test = function(x) {
  y = 10;
  return x + y;
};

alert(test(5));&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;Notice the highlighting indicating the scope of the &lt;code&gt;y&lt;/code&gt; variable. By defining &lt;code&gt;y&lt;/code&gt; in the global scope all subsequent &lt;code&gt;y&lt;/code&gt;'s are also now that global. You may no longer have a variable named &lt;code&gt;y&lt;/code&gt; in your code, at any deeper scope. The outer &lt;code&gt;y&lt;/code&gt; is the only &lt;code&gt;y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Creating a global of a name given overrides all subsequent definitions.&lt;/p&gt;
&lt;p&gt;In JavaScript &lt;code&gt;var&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt;, and &lt;code&gt;const&lt;/code&gt; keywords define the scope of a variable. Leave it out and it scopes downward until it hits a &lt;code&gt;var&lt;/code&gt; definition of that variable &lt;em&gt;or&lt;/em&gt; the global level. This means that inner scopes inherits from outer scopes &lt;em&gt;unless&lt;/em&gt; it defines its own scope of the variable.  CoffeeScript on the other hand offers you no method to scope a variable. Scoping is entirely left to the lowest level use of a &lt;em&gt;variable name&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This behavior is dangerous and makes code very difficult to maintain. The problem is twofold. Firstly, when writing a function, you need to be aware of all shallower scopes variable definitions, as not to trample them. Secondly, when altering code at any scope but the outermost, you need to be aware of all deeper scopes variables as to not trample any of them. &lt;/p&gt;
&lt;p&gt;The only &amp;quot;safe&amp;quot; way to write CoffeeScript is to assume all variable names are global. In practice they are.&lt;/p&gt;
&lt;p&gt;There have been proposed solutions, such as a Go-lang style &lt;code&gt;:=&lt;/code&gt; for inner scoping, but these have not been accepted as of this writing. The creator of CoffeeScript, Jeremy Ashkenas, when questioned about it by Armin Ronacher on Twitter replied:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Not gonna happen ;) Forbidding shadowing altogether is a huge win, and a huge conceptual simplification.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is not true for applications of any scale larger than toy. It makes development more complex, having to check every inner scope before using a new variable name. This is not simpler. The entire behaviour of all inner scopes can change with a single bad variable defintion.&lt;/p&gt;
&lt;h2&gt;Finally&lt;/h2&gt;
&lt;p&gt;CoffeeScripts goal of &amp;quot;expos[ing] the good parts of JavaScript in a simple way&amp;quot; was &lt;strong&gt;missed&lt;/strong&gt;.  Instead of improving JavaScript's scoping which can be kind of daunting to learn, they actually made it worse. If you want to improve JavaScript make every variable &lt;em&gt;local&lt;/em&gt; until explicitly defined global, as is the behavior in the vast majority of languages.&lt;/p&gt;
&lt;p&gt;JavaScripts &amp;quot;&lt;em&gt;global unless defined as local&lt;/em&gt;&amp;quot; behavior is weird, but manageable. CoffeeScript's &amp;quot;&lt;em&gt;local until defined &lt;strong&gt;elsewhere&lt;/strong&gt; globally&lt;/em&gt;&amp;quot; behavior on the other hand is simply difficult to predict and makes it easy to accidentally change the entire meaning of code even when you entirely understand the behavior.&lt;/p&gt;
&lt;p&gt;It is a &lt;strong&gt;bad&lt;/strong&gt; behavior, period.&lt;/p&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;I'd like to also suggest reading Armin Ronacher's &lt;a href="https://lucumr.pocoo.org/2011/12/22/implicit-scoping-in-coffeescript/"&gt;The Problem with Implicit Scoping in CoffeeScript&lt;/a&gt;.  It eloquently describes the problem from a slightly different angle.&lt;/p&gt;
&lt;h2&gt;Update&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I've a fight on Reddit &lt;a href="https://www.reddit.com/r/programming/comments/1j1cw7/coffeescripts_scoping_is_madness/"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I've irked Reginald Braithwaite, the author of &lt;a href="https://leanpub.com/coffeescript-ristretto"&gt;CoffeeScript Ristretto&lt;/a&gt;, so badly he's giving away &lt;a href="https://twitter.com/raganwald/status/360501252162981888"&gt;100 copies of his book for free&lt;/a&gt;!
&lt;ul&gt;
&lt;li&gt;The author has upgraded me to &lt;em&gt;&lt;a href="https://web.archive.org/web/20221122115820/https://twitter.com/raganwald/status/360514948956303361"&gt;Not Wrong&lt;/a&gt;&lt;/em&gt;™!&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Donat Studios</author><pubDate>Fri, 26 Jul 2013 01:19:44 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/CoffeeScript-Madness</guid></item><item><title>SSDs are awesome, buy one.</title><link>https://tomforb.es/blog/ssd-s-are-awesome/</link><description>I recently brought a Samsung 840 Series Pro 256GB 2.5 inch SATA Solid State Drive and its easily the best PC hardware purchase I have ever made. Before I purchased it I was thinking about replacing my laptop as it was getting pretty sluggish, despite having decent specs even 2 years after I purchase...</description><author>Tom Forbes</author><pubDate>Thu, 25 Jul 2013 22:54:58 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/ssd-s-are-awesome/</guid></item><item><title>Why I still recommend Windows</title><link>https://captnemo.in/blog/2013/07/21/why-i-still-recommend-windows/</link><description>&lt;p&gt;Even though I am a long time Linux user, and a big time fan of the many Linux distros that I’ve tried out over time, I still go around recommending Windows to people who ask me for advice. The only exception I make is when the person in question is a developer, in which case I try to convert them to the Church of Linux.&lt;/p&gt;

&lt;p&gt;The main reason I recommend windows to non-developers is because it is a far better operating system than most Linux distributions (for general public). Now, before you bring out your pitchforks, hear me out.&lt;/p&gt;

&lt;p&gt;The first and foremost reason that I give is that Windows sports a far better integration across all its services. Nautilus/Nemo in the Linux world do not reach same level of integration that Windows Explorer does. For instance, just look at the way the “Send To” feature works in explorer. To add a folder to the send to entry, you just have to add a shortcut to that folder inside the special “Send To” folder. On nautilus, the equivalent would be going about installing an extension, and editing a configuration file by hand.&lt;/p&gt;

&lt;p&gt;Or take a look at how the “Play All” feature in Explorer. Or the “Libraries” feature in Windows 7. Or the simple way that you handle file sharing in Windows. Even though Linux has (arguably better) Samba support for files sharing, you have to go about editing a handful of files to make it work. I personally find apache easier to configure to just share files one way.&lt;/p&gt;

&lt;p&gt;Games are another reason. Even though Steam is available on Linux, all of the non-Valve triple-A titles are missing on Linux. Even though I continue to buy and play the Humble Bundles that offer Linux as a platform, I’m reminded of the stark reality every day when my friends ask me if I’ve played a recent title such as Call of Duty, Metro, NFS or even Swapper.&lt;/p&gt;

&lt;p&gt;The next peeve that comes to my mind is the ridiculous driver support. It has been improving since a long time, but its still &lt;em&gt;not there&lt;/em&gt;. Even Ubuntu needs to fetch proprietary drivers for my WiFi support on Broadcom, which needs an internet connection in the first place. This means I need to find out a LAN network connection to even start using Ubuntu. Similarly the pain I’d to go through to install drivers for Ralink network drivers on a friend’s laptop was immense. I can never use circular scrolling or touchpad zoom on my laptop in Linux because there are still no drivers available anywhere for it. And don’t get me started on UEFI boot issues. No matter what people believe or pretend, hardware support is just not good enough to be relied on in the Linux world. As a side note, I haven’t synced my iPad in Ubuntu since I shifted to iOS 5, and apple driver support on Linux will remain abysmal forever just because iTunes will never be released for Linux. The last version of iOS that had music sync support (via libimobiledevice) was iOS 4.0 (released 3 years ago in June 2010).&lt;/p&gt;

&lt;p&gt;Next I want to point put out the upgrade pain that everyone has to go through. It’s like a constant rite of passage, which turns a Linux noob into an actual user. I am yet to do an Ubuntu upgrade which went smoothly and didn’t break a thing; and I’ve been upgrading my Ubuntu since 10.04 was released. The &lt;a href="http://askubuntu.com/questions/tagged/upgrade"&gt;upgrade tag&lt;/a&gt; on askubuntu is chock full of horror stories.&lt;/p&gt;

&lt;p&gt;Another thing that frustrates me to no end is that the Ubuntu Dash, and the GNOME Overview are both slow as hell. I’m currently using Cinnamon, which is faster than both of these, but still an order of magnitude slower than the Windows Start Menu. Synpase is better, but &lt;a href="http://askubuntu.com/questions/174838/can-i-change-synapse-shortcut-to-super-windows-key-alone"&gt;cannot be set as the deafult&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I was using Windows 7 on my cousin’s laptop these last few days and I remembered the favourite app that I used to no end: Everything. It is the quickest file search I’ve ever used. The alternatives, in the Linux world are synapse, zeitgeist, and plain old locate command. The only issue is that I’ve to manually run updatedb manually, while Everything was always up to date, using the NTFS File Journal. To this date, I am yet to find a good enough alternative to Everything.&lt;/p&gt;

&lt;p&gt;It is true that Windows lacks many of the good things that Linux distros provide, such as the excellent package management support, POSIX compatibility, and the plethora of tools we get on the command line; but at the same time, it is also a better operating system for most of the masses. I’ll continue to recommend Windows to all my non-developer friends till “The year of Desktop Linux” arrives.&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Sun, 21 Jul 2013 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2013/07/21/why-i-still-recommend-windows/</guid></item><item><title>Returning to Skyrim</title><link>https://benovermyer.com/blog/2013/07/returning-to-skyrim/</link><description>&lt;p&gt;The last time I posted about Skyrim, it was shortly after release. You can read the first in the series here. At the time, I was playing on the Xbox 360 version. This time around, I've purchased the Legendary Edition for PC. I'm also playing a Destruction mage instead of the heavily armed and armored warrior I focused on in the 360 version.&lt;/p&gt;
&lt;p&gt;Besides taking a completely different character route this time around, I'm also focusing much more on quests other than the main line. I own a small house that I've built but not yet furnished, gotten a fair ways through the College of Winterhold quest line, and continue to light up vampires that seem to crop up all the time in areas I'm traveling to.&lt;/p&gt;
&lt;p&gt;I heard so many awesome things about mods for the game that I just had to get the PC version. That, and I couldn't take screenshots in the 360 version, which was infuriating for someone who blogs about games. Today, I read an article someone reblogged on Reddit about &lt;a href="http://www.pcgamer.com/behind-falskaar-a-massive-new-skyrim-mod-and-the-19-year-old-who-spent-a-year-building-it/" rel="external"&gt;a mod called Falskaar&lt;/a&gt;. Falskaar is unique in that it was produced chiefly by a 19 year old who declined to go to university in order to produce the mod. It took him a full year, and he's aiming to get a job at Bethesda by proving his dedication.&lt;/p&gt;
&lt;p&gt;By all accounts, it's a damned good mod. I look forward to installing it when I finish with vanilla Skyrim.&lt;/p&gt;
&lt;p&gt;If you're interested in hearing further about my adventures in Skyrim, by all means, let me know in the comments. Otherwise, next week I'll be writing about a topic near and dear to my heart…. sci-fantasy sandbox MMORPGs.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sat, 20 Jul 2013 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/07/returning-to-skyrim/</guid></item><item><title>List of useful CAPTCHA Decoding Articles</title><link>https://boyter.org/2013/07/list-captcha-decoding-articles/</link><description>&lt;p&gt;This website ranks quite high in most search engines for the search term &amp;ldquo;captcha decoding&amp;rdquo; or some permutation of it. As such here are a collection of useful links if you are looking into doing such a thing. If any more come up I will be sure to update this post.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.boyter.org/decoding-captchas/"&gt;http://www.boyter.org/decoding-captchas/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Shameless self promotion but this link is why this page ranks so highly. Its an article I wrote some time ago about how to go about decoding a simple CAPTCHA. There is full source code and the principles can be applied to 90% of CAPTCHA&amp;rsquo;s out there. For the record it only came about because a colleague bet me that I couldn&amp;rsquo;t decode his websites CAPTCHA which was the one used in the article. Of course I waited till he changed it before publishing.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Fri, 19 Jul 2013 02:46:43 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/07/list-captcha-decoding-articles/</guid></item><item><title>Displaying a processes output on a web page with Websockets and Python</title><link>https://tomforb.es/blog/displaying-a-processes-output-on-a-web-page-with-websockets-and-python/</link><description>A few days ago a colleague of mine asked me how you would pipe the standard output of a process into a browser. I hacked around for a few hours and came up with a websockets based solution (using Twisted and Autobahn.ws ) that you can see below ( Your browser needs to support WebSockets, sorry IE9 a...</description><author>Tom Forbes</author><pubDate>Mon, 15 Jul 2013 21:40:38 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/displaying-a-processes-output-on-a-web-page-with-websockets-and-python/</guid></item><item><title>About</title><link>https://boyter.org/about/</link><description>&lt;p&gt;I&amp;rsquo;m a software developer by trade who after years of leaving articles and blog posts all over the place has finally gotten around to consolidating them all into this single site.&lt;/p&gt;
&lt;p&gt;I am a professional software engineer who has been working in development with a focus on testing for over 15 years. In that time I have played an integral part in developing and implementing testing methodologies for all sorts of projects including,&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 11 Jul 2013 07:02:47 GMT</pubDate><guid isPermaLink="true">https://boyter.org/about/</guid></item><item><title>Decoding CAPTCHA’s</title><link>https://boyter.org/decoding-captchas/</link><description>&lt;p&gt;&lt;img alt="Decoding CAPTCHA&amp;rsquo;s Book" src="https://boyter.org/static/decoding-captchas/booksmall.jpeg" /&gt;&lt;/p&gt;
&lt;p&gt;Looking for a practical guide to CAPTCHA decoding? All About CAPTCHA’s. This eBook will teach you how to identify weaknesses and exploit CAPTCHA’s from beginning to end. &lt;a href="https://leanpub.com/decodingcaptchas/"&gt;Buy now using Leanpub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Most people don’t know this but my honors thesis was about using a computer program to read text out of web images. My theory was that if you could get a high level of successful extraction you could use it as another source of data which could be used to improve search engine results. I was even quite successful in doing it, but never really followed my experiments up. My honors adviser &lt;a href="http://csusap.csu.edu.au/~jbgao/"&gt;Dr Junbin Gao http://csusap.csu.edu.au/~jbgao/&lt;/a&gt; had suggested the following writing my thesis I should write some form of article on what I had learnt. Well I finally got around to doing it. While what follows is not exactly what I was studying it is something I wish had existed when I started looking around.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 11 Jul 2013 06:00:02 GMT</pubDate><guid isPermaLink="true">https://boyter.org/decoding-captchas/</guid></item><item><title>hstore vs. JSON - Which to use in Postgres</title><link>/2013/07/03/hstore-vs.-JSON-Which-to-use-in-Postgres/</link><description>&lt;p&gt;If you&amp;rsquo;re deciding what to put in &lt;a href="http://www.amazon.com/Seven-Databases-Weeks-Modern-Movement/dp/1934356921?tag=mypred-20"&gt;Postgres and what not to&lt;/a&gt;, consider that Postgres can be a &lt;a href="/2012/06/11/schemaless-django/"&gt;perfectly good schema-less database&lt;/a&gt;. Of course as soon as people realized this then the common comes a question, is hstore or JSON better. Which do I use and in what cases. Well first, if you&amp;rsquo;re not familiar check out some previous material on them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.postgresql.org/docs/9.2/static/hstore.html"&gt;hstore on PostgresGuide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.postgresql.org/docs/9.2/static/hstore.html"&gt;hstore in Postgres docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.craigkerstiens.com/2012/06/11/schemaless-django/"&gt;hstore with Django&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://wiki.postgresql.org/wiki/What's_new_in_PostgreSQL_9.2#JSON_datatype"&gt;JSON datatype&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://postgres.heroku.com/blog/past/2013/6/5/javascript_in_your_postgres/"&gt;JavaScript support in Postgres&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&amp;rsquo;re already up to date with both of them, but still wondering which to use lets dig in.&lt;/p&gt;
&lt;h3 id="hstore"&gt;
&lt;div&gt;
hstore
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;hstore is a key value store directly within your database. Its been a common favorite of mine and has been for some time. hstore gives you flexibility when working with your schema, as you don&amp;rsquo;t have to define models ahead of time. Though its two big limitations are that 1. it only deals with text and 2. its not a full document store meaning you can&amp;rsquo;t nest objects.&lt;/p&gt;
&lt;p&gt;Though major benefits of hstore include the ability to index on it, robust support for various operators, and of course the obvious of flexibility with your data. Some of the basic operators available include:&lt;/p&gt;
&lt;p&gt;Return the value from column&lt;code&gt;foo&lt;/code&gt; for key &lt;code&gt;bar&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;foo-&amp;gt;'bar'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Does the specified column &lt;code&gt;foo&lt;/code&gt; contain a key &lt;code&gt;bar&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;foo?'bar'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Does the specified column &lt;code&gt;foo&lt;/code&gt; contain a value of &lt;code&gt;baz&lt;/code&gt; for key &lt;code&gt;bar&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;foo@&amp;gt;'bar-&amp;gt;baz'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perhaps one of the best parts of hstore is that you can index on it. In particular Postgres &lt;code&gt;gin&lt;/code&gt; and &lt;code&gt;gist&lt;/code&gt; indexes allow you to index all keys and values within an hstore. A talk by &lt;a href="http://www.twitter.com/XoF"&gt;Christophe Pettus&lt;/a&gt; of PgExperts actually highlights some &lt;a href="http://thebuild.com/presentations/pg-as-nosql-pgday-fosdem-2013.pdf"&gt;performance details of hstore with indexes&lt;/a&gt;. To give away the big punchline in several cases hstore with gin/gist beats mongodb in performance.&lt;/p&gt;
&lt;h3 id="json"&gt;
&lt;div&gt;
json
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;JSON in contrast to hstore is a full document datatype. In addition to nesting objects you have support for more than just text (read numbers). As you insert JSON into Postgres it will automatically ensure its valid JSON and error if its well not. JSON gets a lot better come Postgres 9.3 as well with &lt;a href="http://www.postgresql.org/docs/devel/static/functions-json.html"&gt;some built in operators&lt;/a&gt;. Though if you need more functionality in it today you should look at &lt;a href="https://code.google.com/p/plv8js/wiki/PLV8"&gt;PLV8&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="which-to-use"&gt;
&lt;div&gt;
Which to Use
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;So which do you actually want to use in your application? If you&amp;rsquo;re already using JSON and simply want to store it in your database then the JSON datatype is often the correct pick. However, if you&amp;rsquo;re just looking for flexibility with your data model then hstore is likely the path you want to take. hstore will give you much of the flexibility you want as well as a good ability to query your data in a performant manner. Of course much of this starts to change in Postgres 9.3.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re looking for a deeper resource on Postgres I recommend the book &lt;a href="https://theartofpostgresql.com/?affiliate=cek"&gt;The Art of PostgreSQL&lt;/a&gt;. It is by a personal friend that has aimed to create the definitive guide to Postgres, from a developer perspective. If you use code CRAIG15 you&amp;rsquo;ll receive 15% off as well.&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Wed, 03 Jul 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/07/03/hstore-vs.-JSON-Which-to-use-in-Postgres/</guid></item><item><title>10 Years Ago, in an MMO far, far away</title><link>https://benovermyer.com/blog/2013/06/10-years-ago-in-an-mmo-far-far-away/</link><description>&lt;p&gt;Ten years ago nearly to the day, Star Wars: Galaxies launched to the world. As a remembrance of the adventures I had there, I'm writing now about the game as it was in those days and the community that surrounded it. As you read this, you may wish to listen to the playlist on YouTube that starts with the above video. It's a wonderful collection of the music from the game, familiar audio glitches included.&lt;/p&gt;




&lt;div class="dress-image"&gt;
    &lt;img alt="A screenshot of the features page from the first Star Wars: Galaxies website" src="https://benovermyer.com/blog/2013/06/10-years-ago-in-an-mmo-far-far-away/&amp;#x2F;&amp;#x2F;benovermyer.com&amp;#x2F;processed_images&amp;#x2F;OriginalFeaturesPage.a5b1887d1fc2374d.jpg" /&gt;
    
    &lt;div class="caption"&gt;The features page for the first SWG website&lt;/div&gt;
    
&lt;/div&gt;

&lt;p&gt;One of the things I remember reading first about Star Wars: Galaxies was an interview with lead world artist John Roy about procedural planet generation, and how he would discover features of the landscape that were new even to the designers. That got me really excited about exploring these worlds that I'd only read about or seen on the big screen. I'm not sure how often this technique is employed in modern MMORPGs. My impression is that the vast majority of current worlds are slowly crafted by hand by artists, which is why we have so many beautiful vistas but so few boring areas to contrast them with. If all we ever see is beauty, we start to tire of it and look for something better.&lt;/p&gt;
&lt;p&gt;I miss the rolling hills of Corellia where my first SWG toon “grew up.” Another thing that I truly miss about Star Wars: Galaxies is the wait times at the starports. You could only travel to another planet if you bought a ticket for a starship and waited at a starport for one. They arrived in ten minute intervals, which means frequently large groups of players would congregate at the main starports while waiting to travel to another planet. It made for some great conversations, and new friends.&lt;/p&gt;




&lt;div class="dress-image"&gt;
    &lt;img alt="A screenshot of a starport in Star Wars: Galaxies" src="https://benovermyer.com/blog/2013/06/10-years-ago-in-an-mmo-far-far-away/&amp;#x2F;&amp;#x2F;benovermyer.com&amp;#x2F;processed_images&amp;#x2F;starport.be230e6bad6d47b0.jpg" /&gt;
    
    &lt;div class="caption"&gt;A starport in Star Wars: Galaxies&lt;/div&gt;
    
&lt;/div&gt;

&lt;p&gt;Something else I miss about Star Wars: Galaxies was the grind. As a crafter who played before the concept of “practice mode” was introduced, I would sit there and grind out components to level up my skill for hours. When I ran out of materials or empty space in my inventory, I'd make a backpack, shove the extra items in there, and head out to my personal harvesters for more materials. This was before anyone was able to build medium or heavy harvesters, so there were still vast fields of personal harvesters dotting the landscape.&lt;/p&gt;




&lt;div class="dress-image"&gt;
    &lt;img alt="An image of a personal mineral extractor from SWG" src="https://benovermyer.com/blog/2013/06/10-years-ago-in-an-mmo-far-far-away/&amp;#x2F;&amp;#x2F;benovermyer.com&amp;#x2F;processed_images&amp;#x2F;Personal_Mineral_Extractor.f465e0046c576571.jpg" /&gt;
    
    &lt;div class="caption"&gt;A personal mineral extractor&lt;/div&gt;
    
&lt;/div&gt;

&lt;p&gt;The grind, at least for SWG crafting, meant long periods of sitting there doing the exact same motions over and over again. This sounds really boring, but frequently after about five minutes of doing this, I would hit a kind of altered state of mind - a vaguely pleasant feeling of just “being.” The only other time I've ever felt that is when practicing Zen meditation, and I sorely miss it.&lt;/p&gt;
&lt;p&gt;Before vehicles were introduced, everyone had to walk everywhere. Shuttles and starports were jammed full of players on their way someplace. Player cities didn't exist yet, but there were always massive collections of player houses exactly 1 km outside of every major NPC city. It made those cities feel a lot like real cities - you would always be passing by other players on your way either into the city core for transport, into the suburbs for shopping or socializing, or out into the wilderness for adventuring and hunting. Every city had its own distinctive feel, too, on my home server of Chilastra.&lt;/p&gt;




&lt;div class="dress-image"&gt;
    &lt;img alt="A screenshot of Corellia" src="https://benovermyer.com/blog/2013/06/10-years-ago-in-an-mmo-far-far-away/&amp;#x2F;&amp;#x2F;benovermyer.com&amp;#x2F;processed_images&amp;#x2F;correlia1.fc2c83f4d1bf5de1.jpg" /&gt;
    
    &lt;div class="caption"&gt;Corellia had some beautiful vistas&lt;/div&gt;
    
&lt;/div&gt;

&lt;p&gt;Coronet on Corellia was where I first landed, and it's where I spent the first few months of the game. It felt very rugged, like a city on the fringe. Theed, on Naboo, was where the entertainers and image designers hung out. It was definitely a “pretty” city. Mos Eisley was… well, a desert city. Because of all the difficult, unbuildable terrain surrounding Mos Eisley, it wasn't nearly as dense as the others. I think the players more nostalgic for A New Hope landed there. The other cities, like Restuss on Rori and the Imperial Outpost on Talus, had much smaller and more focused populations. Later, when they allowed players to build on some of the more advanced planets like Dantooine and Lok, more interesting communities started springing up.&lt;/p&gt;
&lt;p&gt;In the end, Star Wars: Galaxies really was the best MMORPG experience I've ever had. The early months, even with all the bugs, network issues, and missing content (capes!?), are permanently etched in my memory as a wonderful time. Rest in peace, SWG.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sat, 29 Jun 2013 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/06/10-years-ago-in-an-mmo-far-far-away/</guid></item><item><title>Pivoting in Postgres</title><link>/2013/06/27/Pivoting-in-Postgres/</link><description>&lt;p&gt;Earlier today on an internal Heroku group alias there was a &lt;a href="https://postgres.heroku.com/dataclips"&gt;dataclip&lt;/a&gt; shared. The dataclip listed off some data grouped by a category, there was a reply a few minutes later with a modification to the query that used the &lt;code&gt;crosstab&lt;/code&gt; function to pivot directly in SQL. There were immediately several reactions on the list that went something like this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="mindblown" src="https://f.cl.ly/items/1b0G101r0B2W243b2933/Image%202013.06.27%202%3A06%3A23%20PM.gif" /&gt;&lt;/p&gt;
&lt;p&gt;While a mostly simple function in Postgres (there are a few rough edges), it really is all too handy. So here it is in action. Taking some data that looks like&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;row identifier, in this case date&lt;/li&gt;
&lt;li&gt;category grouping, in this case OS&lt;/li&gt;
&lt;li&gt;value&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Given a really basic query that generates some sample data it may look something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT generate_series AS date,
b.desc AS TYPE,
(random() * 10000 + 1)::int AS val
FROM generate_series((now() - '100 days'::interval)::date, now()::date, '1 day'::interval),
(SELECT unnest(ARRAY['OSX', 'Windows', 'Linux']) AS DESC) b;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You get results that look like:&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;But of course this isn&amp;rsquo;t overly helpful in comparing day to day overall. You can do so on a OS by OS basis, but its annoying enough as is. The easy solution is to simply use a pivot table on your data. Most people at this point would pull it up into Excel or Google Docs, or you can do it directly in Postgres. To do so you&amp;rsquo;ll first enable the extension &lt;code&gt;tablefunc&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CREATE EXTENSION tablefunc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you&amp;rsquo;ll use the crosstab function. The function looks something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT *
FROM crosstab(
'SELECT row_name, category_grouping, value FROM foo',
'SELECT category_names FROM bar')
AS
ct_result (category_name text, category1 text, category2 text, etc.)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lets see it an actual action. Given the same query we used to generate fake data we can actually pivot on it now directly in PostgreSQL:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT *
FROM crosstab(
'SELECT
a date,
b.desc AS os,
(random() * 10000 + 1)::int AS value
FROM generate_series((now() - ''100 days''::interval)::date, now()::date, ''1 DAY''::interval) a,
(SELECT unnest(ARRAY[''OSX'', ''Windows'', ''Linux'']) AS DESC) b ORDER BY 1,2
','SELECT unnest(ARRAY[''OSX'', ''Windows'', ''Linux''])'
)
AS ct(date date, OSX int, Windows int, Linux int);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And see some results:&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;Have fun analyzing your data directly in your DB now. And as always if you have feedback/questions/requests please feel free to drop me a line &lt;a href="mailto:craig.kerstiens@gmail.com"&gt;craig.kerstiens@gmail.com&lt;/a&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 27 Jun 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/06/27/Pivoting-in-Postgres/</guid></item><item><title>Javascript Functions for PostgreSQL</title><link>/2013/06/25/Javascript-Functions-for-PostgreSQL/</link><description>&lt;p&gt;Javascript in Postgres has gotten a good bit of love lately, part of that is from &lt;a href="http://postgres.herpku.com"&gt;Heroku Postgres&lt;/a&gt; recently &lt;a href="https://postgres.heroku.com/blog/past/2013/6/5/javascript_in_your_postgres/"&gt;adding support for Javascript&lt;/a&gt; and part from a variety of people championing the power of it such as &lt;a href="http://twitter.com/leinweber"&gt;@leinweber&lt;/a&gt; (&lt;a href="http://www.youtube.com/watch?v=fRupMAVdmWA"&gt;Embracing the web with JSON and PLV8&lt;/a&gt;) and &lt;a href="http://twitter.com/selenamarie"&gt;@selenamarie&lt;/a&gt; (&lt;a href="https://speakerdeck.com/selenamarie/schema-liberation-with-json-and-plv8-and-postgres"&gt;schema liberation with JSON and PLV8&lt;/a&gt;). In a recent conversation it was pointed out that it seems a bit of headache to have to create your own functions, or at least having an initial collection would make it that much more powerful. While many can look forward to &lt;a href="http://www.postgresql.org/docs/9.3/static/functions-json.html"&gt;PostgreSQL 9.3&lt;/a&gt; which will have a bit more built in support for JSON a few functions can really help make it more useful today.&lt;/p&gt;
&lt;p&gt;These are courtesy of &lt;a href="http://bitfission.com"&gt;Will Leinweber&lt;/a&gt;. For each of the following functions I&amp;rsquo;ll highlight an example of using it as well. To get an idea of the data its being run on:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;select * from example;
data
--------------------------------------------
{&amp;quot;name&amp;quot;:&amp;quot;Craig Kerstiens&amp;quot;, +
&amp;quot;age&amp;quot;:27, +
&amp;quot;siblings&amp;quot;:1, +
&amp;quot;numbers&amp;quot;:[ +
{&amp;quot;type&amp;quot;:&amp;quot;work&amp;quot;, +
&amp;quot;number&amp;quot;:&amp;quot;123-456-7890&amp;quot;}, +
{&amp;quot;type&amp;quot;:&amp;quot;home&amp;quot;, +
&amp;quot;number&amp;quot;:&amp;quot;456-123-7890&amp;quot;}]}
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="get_text"&gt;
&lt;div&gt;
get_text
&lt;/div&gt;
&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;CREATE OR REPLACE FUNCTION
get_text(key text, data json)
RETURNS text AS $$
return data[key];
$$ LANGUAGE plv8 IMMUTABLE STRICT;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then using the function:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;select get_text('name', data) from example;
get_text
----------------
Craig Kerstiens
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="get_numeric"&gt;
&lt;div&gt;
get_numeric
&lt;/div&gt;
&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;CREATE OR REPLACE FUNCTION
get_numeric(key text, data json)
RETURNS numeric AS $$
return data[key];
$$ LANGUAGE plv8 IMMUTABLE STRICT;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then using the function:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;select get_numeric('siblings', data) from example;
get_text
----------------
1
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="json_select"&gt;
&lt;div&gt;
json_select
&lt;/div&gt;
&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;create or replace function
json_select(selector text, data json)
returns json as $$
exports = {};
(function(a){function z(a){return{sel:q(a)[1],match:function(a){return y(this.sel,a)},forEach:function(a,b){return x(this.sel,a,b)}}}function y(a,b){var c=[];x(a,b,function(a){c.push(a)});return c}function x(a,b,c,d,e,f){var g=a[0]===&amp;quot;,&amp;quot;?a.slice(1):[a],h=[],i=!1,j=0,k=0,l,m;for(j=0;j&amp;lt;g.length;j++){m=w(b,g[j],d,e,f),m[0]&amp;amp;&amp;amp;(i=!0);for(k=0;k&amp;lt;m[1].length;k++)h.push(m[1][k])}if(h.length&amp;amp;&amp;amp;typeof b==&amp;quot;object&amp;quot;){h.length&amp;gt;=1&amp;amp;&amp;amp;h.unshift(&amp;quot;,&amp;quot;);if(u(b))for(j=0;j&amp;lt;b.length;j++)x(h,b[j],c,undefined,j,b.length);else for(l in b)b.hasOwnProperty(l)&amp;amp;&amp;amp;x(h,b[l],c,l)}i&amp;amp;&amp;amp;c&amp;amp;&amp;amp;c(b)}function w(a,b,c,d,e){var f=[],g=b[0]===&amp;quot;&amp;gt;&amp;quot;?b[1]:b[0],h=!0,i;g.type&amp;amp;&amp;amp;(h=h&amp;amp;&amp;amp;g.type===v(a)),g.id&amp;amp;&amp;amp;(h=h&amp;amp;&amp;amp;g.id===c),h&amp;amp;&amp;amp;g.pf&amp;amp;&amp;amp;(g.pf===&amp;quot;:nth-last-child&amp;quot;?d=e-d:d++,g.a===0?h=g.b===d:(i=(d-g.b)%g.a,h=!i&amp;amp;&amp;amp;d*g.a+g.b&amp;gt;=0));if(h&amp;amp;&amp;amp;g.has){var j=function(){throw 42};for(var k=0;k&amp;lt;g.has.length;k++){try{x(g.has[k],a,j)}catch(l){if(l===42)continue}h=!1;break}}h&amp;amp;&amp;amp;g.expr&amp;amp;&amp;amp;(h=p(g.expr,a)),b[0]!==&amp;quot;&amp;gt;&amp;quot;&amp;amp;&amp;amp;b[0].pc!==&amp;quot;:root&amp;quot;&amp;amp;&amp;amp;f.push(b),h&amp;amp;&amp;amp;(b[0]===&amp;quot;&amp;gt;&amp;quot;?b.length&amp;gt;2&amp;amp;&amp;amp;(h=!1,f.push(b.slice(2))):b.length&amp;gt;1&amp;amp;&amp;amp;(h=!1,f.push(b.slice(1))));return[h,f]}function v(a){if(a===null)return&amp;quot;null&amp;quot;;var b=typeof a;b===&amp;quot;object&amp;quot;&amp;amp;&amp;amp;u(a)&amp;amp;&amp;amp;(b=&amp;quot;array&amp;quot;);return b}function u(a){return Array.isArray?Array.isArray(a):b.call(a)===&amp;quot;[object Array]&amp;quot;}function t(a,b,c){var d=b,g={},j=i(a,b);j&amp;amp;&amp;amp;j[1]===&amp;quot; &amp;quot;&amp;amp;&amp;amp;(d=b=j[0],j=i(a,b)),j&amp;amp;&amp;amp;j[1]===f.typ?(g.type=j[2],j=i(a,b=j[0])):j&amp;amp;&amp;amp;j[1]===&amp;quot;*&amp;quot;&amp;amp;&amp;amp;(j=i(a,b=j[0]));for(;;){if(j===undefined)break;if(j[1]===f.ide)g.id&amp;amp;&amp;amp;e(&amp;quot;nmi&amp;quot;,j[1]),g.id=j[2];else if(j[1]===f.psc)(g.pc||g.pf)&amp;amp;&amp;amp;e(&amp;quot;mpc&amp;quot;,j[1]),j[2]===&amp;quot;:first-child&amp;quot;?(g.pf=&amp;quot;:nth-child&amp;quot;,g.a=0,g.b=1):j[2]===&amp;quot;:last-child&amp;quot;?(g.pf=&amp;quot;:nth-last-child&amp;quot;,g.a=0,g.b=1):g.pc=j[2];else{if(j[1]!==f.psf)break;if(j[2]===&amp;quot;:val&amp;quot;||j[2]===&amp;quot;:contains&amp;quot;)g.expr=[undefined,j[2]===&amp;quot;:val&amp;quot;?&amp;quot;=&amp;quot;:&amp;quot;*=&amp;quot;,undefined],j=i(a,b=j[0]),j&amp;amp;&amp;amp;j[1]===&amp;quot; &amp;quot;&amp;amp;&amp;amp;(j=i(a,b=j[0])),(!j||j[1]!==&amp;quot;(&amp;quot;)&amp;amp;&amp;amp;e(&amp;quot;pex&amp;quot;,a),j=i(a,b=j[0]),j&amp;amp;&amp;amp;j[1]===&amp;quot; &amp;quot;&amp;amp;&amp;amp;(j=i(a,b=j[0])),(!j||j[1]!==f.str)&amp;amp;&amp;amp;e(&amp;quot;sex&amp;quot;,a),g.expr[2]=j[2],j=i(a,b=j[0]),j&amp;amp;&amp;amp;j[1]===&amp;quot; &amp;quot;&amp;amp;&amp;amp;(j=i(a,b=j[0])),(!j||j[1]!==&amp;quot;)&amp;quot;)&amp;amp;&amp;amp;e(&amp;quot;epex&amp;quot;,a);else if(j[2]===&amp;quot;:has&amp;quot;){j=i(a,b=j[0]),j&amp;amp;&amp;amp;j[1]===&amp;quot; &amp;quot;&amp;amp;&amp;amp;(j=i(a,b=j[0])),(!j||j[1]!==&amp;quot;(&amp;quot;)&amp;amp;&amp;amp;e(&amp;quot;pex&amp;quot;,a);var k=q(a,j[0],!0);j[0]=k[0],g.has||(g.has=[]),g.has.push(k[1])}else if(j[2]===&amp;quot;:expr&amp;quot;){g.expr&amp;amp;&amp;amp;e(&amp;quot;mexp&amp;quot;,a);var l=o(a,j[0]);j[0]=l[0],g.expr=l[1]}else{(g.pc||g.pf)&amp;amp;&amp;amp;e(&amp;quot;mpc&amp;quot;,a),g.pf=j[2];var m=h.exec(a.substr(j[0]));m||e(&amp;quot;mepf&amp;quot;,a),m[5]?(g.a=2,g.b=m[5]===&amp;quot;odd&amp;quot;?1:0):m[6]?(g.a=0,g.b=parseInt(m[6],10)):(g.a=parseInt((m[1]?m[1]:&amp;quot;+&amp;quot;)+(m[2]?m[2]:&amp;quot;1&amp;quot;),10),g.b=m[3]?parseInt(m[3]+m[4],10):0),j[0]+=m[0].length}}j=i(a,b=j[0])}d===b&amp;amp;&amp;amp;e(&amp;quot;se&amp;quot;,a);return[b,g]}function s(a){if(a[0]===&amp;quot;,&amp;quot;){var b=[&amp;quot;,&amp;quot;];for(var c=c;c&amp;lt;a.length;c++){var d=r(d[c]);b=b.concat(d[0]===&amp;quot;,&amp;quot;?d.slice(1):d)}return b}return r(a)}function r(a){var b=[],c;for(var d=0;d&amp;lt;a.length;d++)if(a[d]===&amp;quot;~&amp;quot;){if(d&amp;lt;2||a[d-2]!=&amp;quot;&amp;gt;&amp;quot;)c=a.slice(0,d-1),c=c.concat([{has:[[{pc:&amp;quot;:root&amp;quot;},&amp;quot;&amp;gt;&amp;quot;,a[d-1]]]},&amp;quot;&amp;gt;&amp;quot;]),c=c.concat(a.slice(d+1)),b.push(c);if(d&amp;gt;1){var e=a[d-2]===&amp;quot;&amp;gt;&amp;quot;?d-3:d-2;c=a.slice(0,e);var f={};for(var g in a[e])a[e].hasOwnProperty(g)&amp;amp;&amp;amp;(f[g]=a[e][g]);f.has||(f.has=[]),f.has.push([{pc:&amp;quot;:root&amp;quot;},&amp;quot;&amp;gt;&amp;quot;,a[d-1]]),c=c.concat(f,&amp;quot;&amp;gt;&amp;quot;,a.slice(d+1)),b.push(c)}break}if(d==a.length)return a;return b.length&amp;gt;1?[&amp;quot;,&amp;quot;].concat(b):b[0]}function q(a,b,c,d){c||(d={});var f=[],g,h;b||(b=0);for(;;){var j=t(a,b,d);f.push(j[1]),j=i(a,b=j[0]),j&amp;amp;&amp;amp;j[1]===&amp;quot; &amp;quot;&amp;amp;&amp;amp;(j=i(a,b=j[0]));if(!j)break;if(j[1]===&amp;quot;&amp;gt;&amp;quot;||j[1]===&amp;quot;~&amp;quot;)j[1]===&amp;quot;~&amp;quot;&amp;amp;&amp;amp;(d.usesSiblingOp=!0),f.push(j[1]),b=j[0];else if(j[1]===&amp;quot;,&amp;quot;)g===undefined?g=[&amp;quot;,&amp;quot;,f]:g.push(f),f=[],b=j[0];else if(j[1]===&amp;quot;)&amp;quot;){c||e(&amp;quot;ucp&amp;quot;,j[1]),h=1,b=j[0];break}}c&amp;amp;&amp;amp;!h&amp;amp;&amp;amp;e(&amp;quot;mcp&amp;quot;,a),g&amp;amp;&amp;amp;g.push(f);var k;!c&amp;amp;&amp;amp;d.usesSiblingOp?k=s(g?g:f):k=g?g:f;return[b,k]}function p(a,b){if(a===undefined)return b;if(a===null||typeof a!=&amp;quot;object&amp;quot;)return a;var c=p(a[0],b),d=p(a[2],b);return l[a[1]][1](c,d)}function o(a,b){function c(a){return typeof a!=&amp;quot;object&amp;quot;||a===null?a:a[0]===&amp;quot;(&amp;quot;?c(a[1]):[c(a[0]),a[1],c(a[2])]}var d=n(a,b?b:0);return[d[0],c(d[1])]}function n(a,b){b||(b=0);var c=m(a,b),d;if(c&amp;amp;&amp;amp;c[1]===&amp;quot;(&amp;quot;){d=n(a,c[0]);var f=m(a,d[0]);(!f||f[1]!==&amp;quot;)&amp;quot;)&amp;amp;&amp;amp;e(&amp;quot;epex&amp;quot;,a),b=f[0],d=[&amp;quot;(&amp;quot;,d[1]]}else!c||c[1]&amp;amp;&amp;amp;c[1]!=&amp;quot;x&amp;quot;?e(&amp;quot;ee&amp;quot;,a+&amp;quot; - &amp;quot;+(c[1]&amp;amp;&amp;amp;c[1])):(d=c[1]===&amp;quot;x&amp;quot;?undefined:c[2],b=c[0]);var g=m(a,b);if(!g||g[1]==&amp;quot;)&amp;quot;)return[b,d];(g[1]==&amp;quot;x&amp;quot;||!g[1])&amp;amp;&amp;amp;e(&amp;quot;bop&amp;quot;,a+&amp;quot; - &amp;quot;+(g[1]&amp;amp;&amp;amp;g[1]));var h=n(a,g[0]);b=h[0],h=h[1];var i;if(typeof h!=&amp;quot;object&amp;quot;||h[0]===&amp;quot;(&amp;quot;||l[g[1]][0]&amp;lt;l[h[1]][0])i=[d,g[1],h];else{i=h;while(typeof h[0]==&amp;quot;object&amp;quot;&amp;amp;&amp;amp;h[0][0]!=&amp;quot;(&amp;quot;&amp;amp;&amp;amp;l[g[1]][0]&amp;gt;=l[h[0][1]][0])h=h[0];h[0]=[d,g[1],h[0]]}return[b,i]}function m(a,b){var d,e=j.exec(a.substr(b));if(e){b+=e[0].length,d=e[1]||e[2]||e[3]||e[5]||e[6];if(e[1]||e[2]||e[3])return[b,0,c(d)];if(e[4])return[b,0,undefined];return[b,d]}}function k(a,b){return typeof a===b}function i(a,b){b||(b=0);var d=g.exec(a.substr(b));if(!d)return undefined;b+=d[0].length;var h;d[1]?h=[b,&amp;quot; &amp;quot;]:d[2]?h=[b,d[0]]:d[3]?h=[b,f.typ,d[0]]:d[4]?h=[b,f.psc,d[0]]:d[5]?h=[b,f.psf,d[0]]:d[6]?e(&amp;quot;upc&amp;quot;,a):d[8]?h=[b,d[7]?f.ide:f.str,c(d[8])]:d[9]?e(&amp;quot;ujs&amp;quot;,a):d[10]&amp;amp;&amp;amp;(h=[b,f.ide,d[10].replace(/\\([^\r\n\f0-9a-fA-F])/g,&amp;quot;$1&amp;quot;)]);return h}function e(a,b){throw new Error(d[a]+(b&amp;amp;&amp;amp;&amp;quot; in '&amp;quot;+b+&amp;quot;'&amp;quot;))}function c(a){try{if(JSON&amp;amp;&amp;amp;JSON.parse)return JSON.parse(a);return(new Function(&amp;quot;return &amp;quot;+a))()}catch(b){e(&amp;quot;ijs&amp;quot;,b.message)}}var b=Object.prototype.toString,d={bop:&amp;quot;binary operator expected&amp;quot;,ee:&amp;quot;expression expected&amp;quot;,epex:&amp;quot;closing paren expected ')'&amp;quot;,ijs:&amp;quot;invalid json string&amp;quot;,mcp:&amp;quot;missing closing paren&amp;quot;,mepf:&amp;quot;malformed expression in pseudo-function&amp;quot;,mexp:&amp;quot;multiple expressions not allowed&amp;quot;,mpc:&amp;quot;multiple pseudo classes (:xxx) not allowed&amp;quot;,nmi:&amp;quot;multiple ids not allowed&amp;quot;,pex:&amp;quot;opening paren expected '('&amp;quot;,se:&amp;quot;selector expected&amp;quot;,sex:&amp;quot;string expected&amp;quot;,sra:&amp;quot;string required after '.'&amp;quot;,uc:&amp;quot;unrecognized char&amp;quot;,ucp:&amp;quot;unexpected closing paren&amp;quot;,ujs:&amp;quot;unclosed json string&amp;quot;,upc:&amp;quot;unrecognized pseudo class&amp;quot;},f={psc:1,psf:2,typ:3,str:4,ide:5},g=new RegExp('^(?:([\\r\\n\\t\\ ]+)|([~*,&amp;gt;\\)\\(])|(string|boolean|null|array|object|number)|(:(?:root|first-child|last-child|only-child))|(:(?:nth-child|nth-last-child|has|expr|val|contains))|(:\\w+)|(?:(\\.)?(\\&amp;quot;(?:[^\\\\\\&amp;quot;]|\\\\[^\\&amp;quot;])*\\&amp;quot;))|(\\&amp;quot;)|\\.((?:[_a-zA-Z]|[^\\0-\\0177]|\\\\[^\\r\\n\\f0-9a-fA-F])(?:[_a-zA-Z0-9\\-]|[^\\u0000-\\u0177]|(?:\\\\[^\\r\\n\\f0-9a-fA-F]))*))'),h=/^\s*\(\s*(?:([+\-]?)([0-9]*)n\s*(?:([+\-])\s*([0-9]))?|(odd|even)|([+\-]?[0-9]+))\s*\)/,j=new RegExp('^\\s*(?:(true|false|null)|(-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)|(&amp;quot;(?:[^\\]|\\[^&amp;quot;])*&amp;quot;)|(x)|(&amp;amp;&amp;amp;|\\|\\||[\\$\\^&amp;lt;&amp;gt;!\\*]=|[=+\\-*/%&amp;lt;&amp;gt;])|([\\(\\)]))'),l={&amp;quot;*&amp;quot;:[9,function(a,b){return a*b}],&amp;quot;/&amp;quot;:[9,function(a,b){return a/b}],&amp;quot;%&amp;quot;:[9,function(a,b){return a%b}],&amp;quot;+&amp;quot;:[7,function(a,b){return a+b}],&amp;quot;-&amp;quot;:[7,function(a,b){return a-b}],&amp;quot;&amp;lt;=&amp;quot;:[5,function(a,b){return k(a,&amp;quot;number&amp;quot;)&amp;amp;&amp;amp;k(b,&amp;quot;number&amp;quot;)&amp;amp;&amp;amp;a&amp;lt;=b}],&amp;quot;&amp;gt;=&amp;quot;:[5,function(a,b){return k(a,&amp;quot;number&amp;quot;)&amp;amp;&amp;amp;k(b,&amp;quot;number&amp;quot;)&amp;amp;&amp;amp;a&amp;gt;=b}],&amp;quot;$=&amp;quot;:[5,function(a,b){return k(a,&amp;quot;string&amp;quot;)&amp;amp;&amp;amp;k(b,&amp;quot;string&amp;quot;)&amp;amp;&amp;amp;a.lastIndexOf(b)===a.length-b.length}],&amp;quot;^=&amp;quot;:[5,function(a,b){return k(a,&amp;quot;string&amp;quot;)&amp;amp;&amp;amp;k(b,&amp;quot;string&amp;quot;)&amp;amp;&amp;amp;a.indexOf(b)===0}],&amp;quot;*=&amp;quot;:[5,function(a,b){return k(a,&amp;quot;string&amp;quot;)&amp;amp;&amp;amp;k(b,&amp;quot;string&amp;quot;)&amp;amp;&amp;amp;a.indexOf(b)!==-1}],&amp;quot;&amp;gt;&amp;quot;:[5,function(a,b){return k(a,&amp;quot;number&amp;quot;)&amp;amp;&amp;amp;k(b,&amp;quot;number&amp;quot;)&amp;amp;&amp;amp;a&amp;gt;b}],&amp;quot;&amp;lt;&amp;quot;:[5,function(a,b){return k(a,&amp;quot;number&amp;quot;)&amp;amp;&amp;amp;k(b,&amp;quot;number&amp;quot;)&amp;amp;&amp;amp;a&amp;lt;b}],&amp;quot;=&amp;quot;:[3,function(a,b){return a===b}],&amp;quot;!=&amp;quot;:[3,function(a,b){return a!==b}],&amp;quot;&amp;amp;&amp;amp;&amp;quot;:[2,function(a,b){return a&amp;amp;&amp;amp;b}],&amp;quot;||&amp;quot;:[1,function(a,b){return a||b}]};a._lex=i,a._parse=q,a.match=function(a,b){return z(a).match(b)},a.forEach=function(a,b,c){return z(a).forEach(b,c)},a.compile=z})(typeof exports==&amp;quot;undefined&amp;quot;?window.JSONSelect={}:exports)
return JSON.stringify(
exports.match(selector,
data));
$$ LANGUAGE plv8 IMMUTABLE STRICT
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then using the function:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;select json_select('.name nth-child(1)', data) as name, json_select('.numbers', data) as phone
from example;
name | phone
--------------------+------------------------------------------------------------------------------------------
[&amp;quot;Craig Kerstiens&amp;quot;] | [[{&amp;quot;type&amp;quot;:&amp;quot;work&amp;quot;,&amp;quot;number&amp;quot;:&amp;quot;456-123-7890&amp;quot;},{&amp;quot;type&amp;quot;:&amp;quot;home&amp;quot;,&amp;quot;number&amp;quot;:&amp;quot;123-456-7890&amp;quot;}]]
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="javascript-injection-attack"&gt;
&lt;div&gt;
javascript injection attack
&lt;/div&gt;
&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;create or replace function
js(src text) returns text as $$
return eval(
&amp;quot;(function() { &amp;quot; + src + &amp;quot;})&amp;quot;
)();
$$ LANGUAGE plv8;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Have any others you feel are essential when starting to work with JSON? Let me know &lt;a href="mailto:craig.kerstiens@gmail.com"&gt;craig.kerstiens@gmail.com&lt;/a&gt;. Beyond that give JSON and JavaScript a try inside your database.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Tue, 25 Jun 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/06/25/Javascript-Functions-for-PostgreSQL/</guid></item><item><title>The Joys of UNIX Keyboards</title><link>https://donatstudios.com/UNIX-Keyboards</link><description>&lt;h2&gt;I fell in love with a dead keyboard layout.&lt;/h2&gt;
&lt;p&gt;A decade or so ago while helping a friends father clean out an old building, we came across an ancient Sun Microsystems server. We found it curious. &lt;em&gt;Everything&lt;/em&gt; about it was different from what we were used to. The command line was black text on a white background, the connectors strange and foreign, and the keyboard layout was bizarre.&lt;/p&gt;
&lt;p&gt;We never did much with it; turning it on made all the lights in his home dim, and our joint knowledge of UNIX was nonexistent. It sat in his bedroom for years supporting his television at the foot of his bed.&lt;/p&gt;
&lt;p&gt;I never forgot that keyboard though. The thought that there was this alternative layout out there seemed intriguing to me.&lt;/p&gt;
&lt;h2&gt;I am ruined for all other keyboards…&lt;/h2&gt;
&lt;p&gt;Mac is the main platform at my new job. I found myself unhappy with Apple keyboards; they are flat, bland, and completely unsatisfying to type on. I dug out an old AppleDesign keyboard, and used that for several months but I still needed something more.&lt;/p&gt;
&lt;p&gt;I read about Happy Hacking Keyboard, and after some deliberation decided to give it a try. I thought I could learn to accept most of the layout changes, but the lack of arrow keys on the &amp;quot;Professional&amp;quot; model made me squirm a little. Luckily there is a &amp;quot;Lite&amp;quot; version that includes arrow keys.&lt;/p&gt;
&lt;p&gt;I purchased the &lt;a href="https://amzn.com/B0000U1DJ2"&gt;Happy Hacking Keyboard Lite2&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;The Happy Hacking Keyboard much like the Sun Microsystem keyboard I found years earlier features a UNIX layout. They designed it with typing at a terminal in mind.&lt;/p&gt;
&lt;h2&gt;A Better Layout&lt;/h2&gt;
&lt;p&gt;For those unfamiliar with UNIX keyboards, there are a few distinctions.&lt;/p&gt;
&lt;img alt="Happy Hacking Keyboard" src="https://donatstudios.com/assets/43/hhkb.png" style="display: block; float: right; margin-left: 22px; margin-bottom: 22px;" /&gt; 
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;Control&lt;/strong&gt; key moved to the &lt;strong&gt;Caps Lock&lt;/strong&gt; keys usual position. This makes it much easier to hit common commands than its usual location, often without ever leaving home row. I can't imagine why anyone thought &lt;strong&gt;Caps Lock&lt;/strong&gt; should have had this prominent of placement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;Meta&lt;/strong&gt; (&lt;strong&gt;◆ / ⌘ / Windows&lt;/strong&gt;) key is in its rightful place next to the space bar, as on a Mac keyboard.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;Backspace&lt;/strong&gt; key moved down a row to be above the &lt;strong&gt;Enter&lt;/strong&gt; key. This change is my favorite change. Having a small reach, normally my hands have to leave home row to hit backspace. but on a UNIX board I have no issue hitting it with my pinky with the rest of my fingers remaining firmly on home row.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Escape&lt;/strong&gt; is also in reach of home row, placed where you would usually find &lt;strong&gt;~&lt;/strong&gt;. I could have done without this change, but it is fine.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;~&lt;/strong&gt; and &lt;strong&gt;\&lt;/strong&gt; have moved to the usual location of the &lt;strong&gt;Backspace&lt;/strong&gt;. Working exclusively on UNIX systems now, I don't mind the &lt;strong&gt;\&lt;/strong&gt; being harder to reach. I could understand a Windows user finding this irritating.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The HHKB is a minimal version of the UNIX keyboard. To this end the &lt;strong&gt;F Keys&lt;/strong&gt; are mapped to &lt;strong&gt;Fn + 1, 2, 3, etc&lt;/strong&gt;. The HHKB encourages you to stay on home row; you can hit any key on the keyboard without leaving it. I find my typing accuracy and speed to have improved thanks to its use.&lt;/p&gt;
&lt;p&gt;The HHKB features one more change I don't care for. The &lt;strong&gt;Backspace&lt;/strong&gt; key by &lt;em&gt;default&lt;/em&gt; performs &lt;strong&gt;Forward Delete&lt;/strong&gt;. Luckily changing this is easy by flipping a toggle switch on the back of the board.&lt;/p&gt;
&lt;h2&gt;Closing&lt;/h2&gt;
&lt;p&gt;I recommend this keyboard to &lt;em&gt;anyone&lt;/em&gt; who spends a lot of time at the terminal. You are able to do more of what you need without ever leaving home row, every important key is within reach.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Elsewhere&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Discussion on &lt;a href="https://news.ycombinator.com/item?id=21912184"&gt;Hacker News&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Mentioned on BSD Now Podcast: &lt;a href="https://www.bsdnow.tv/333"&gt;Episode 333&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>Donat Studios</author><pubDate>Wed, 19 Jun 2013 02:10:51 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/UNIX-Keyboards</guid></item><item><title>Explaining your PostgreSQL data</title><link>/2013/06/13/Explaining-your-PostgreSQL-data/</link><description>&lt;p&gt;I&amp;rsquo;ve written a bit before about &lt;a href="http://www.craigkerstiens.com/2013/01/10/more-on-postgres-performance/"&gt;understanding the output&lt;/a&gt; from &lt;code&gt;EXPLAIN&lt;/code&gt; and &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt; in PostgreSQL. Though understandably getting a grasp on execution plans could probably use some more guidance. Yet, this time around I&amp;rsquo;m taking a bit of a cop out and highlighting a few tools instead of documenting myself, which I&amp;rsquo;ve done in a talk I&amp;rsquo;ve frequently given &lt;a href="https://speakerdeck.com/craigkerstiens/postgres-demystified-1"&gt;Postgres Demystified&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Explain explained" src="https://f.cl.ly/items/2Y0A0H2B2q3C0622261C/Screenshot_6_13_13_9_57_AM.png" /&gt;&lt;/p&gt;
&lt;h3 id="getting-at-the-data"&gt;
&lt;div&gt;
Getting at the Data
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;The first small thing you can do is actually retrieve the data in JSON form. By adding in &lt;code&gt;(format json)&lt;/code&gt; right after your &lt;code&gt;EXPLAIN&lt;/code&gt; or &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt; command it&amp;rsquo;ll as you&amp;rsquo;d expect return it in JSON. To give an example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# EXPLAIN SELECT * FROM users LIMIT 1;
QUERY PLAN
--------------------------------------------------------------
Limit (cost=0.00..0.03 rows=1 width=812)
-&amp;gt; Seq Scan on users (cost=0.00..1.50 rows=50 width=812)
(2 rows)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in JSON format:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;EXPLAIN (format json) SELECT * FROM users LIMIT 1;
QUERY PLAN
------------------------------------------------
[ +
{ +
&amp;quot;Plan&amp;quot;: { +
&amp;quot;Node Type&amp;quot;: &amp;quot;Limit&amp;quot;, +
&amp;quot;Startup Cost&amp;quot;: 0.00, +
&amp;quot;Total Cost&amp;quot;: 0.03, +
&amp;quot;Plan Rows&amp;quot;: 1, +
&amp;quot;Plan Width&amp;quot;: 812, +
&amp;quot;Plans&amp;quot;: [ +
{ +
&amp;quot;Node Type&amp;quot;: &amp;quot;Seq Scan&amp;quot;, +
&amp;quot;Parent Relationship&amp;quot;: &amp;quot;Outer&amp;quot;,+
&amp;quot;Relation Name&amp;quot;: &amp;quot;users&amp;quot;, +
&amp;quot;Alias&amp;quot;: &amp;quot;users&amp;quot;, +
&amp;quot;Startup Cost&amp;quot;: 0.00, +
&amp;quot;Total Cost&amp;quot;: 1.50, +
&amp;quot;Plan Rows&amp;quot;: 50, +
&amp;quot;Plan Width&amp;quot;: 812 +
} +
] +
} +
} +
]
(1 row)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While its on my list to build some interesting apps by pulling in the JSON input, others may be equally as interested in taking advantage of this data in its JSON form. If you take a shot at building something with this output, as always I&amp;rsquo;d love to hear about it - &lt;a href="mailto:craig.kerstiens@gmail.com"&gt;craig.kerstiens@gmail.com&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="despez"&gt;
&lt;div&gt;
Despez
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Of course if you&amp;rsquo;re itch isn&amp;rsquo;t in better tools for Postgres, you may just want to have a solution that works today. While its not perfect, one of the best ones out there is &lt;a href="http://explain.depesz.com/"&gt;Dezpez&amp;rsquo;s explain tool&lt;/a&gt;. You can take any execution plan and paste it in and get some better visual representation of the result. You can also &lt;a href="http://explain.depesz.com/s/vL1"&gt;share them as well&lt;/a&gt;.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 13 Jun 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/06/13/Explaining-your-PostgreSQL-data/</guid></item><item><title>Build a Better Warrior in Rift</title><link>https://benovermyer.com/blog/2013/06/build-a-better-warrior-in-rift/</link><description>&lt;p&gt;I've been playing Rift a lot lately, and the more I play, the better I understand the ins and outs of being a Warrior. This post has a few of my thoughts on the subject of tuning warrior builds. The class is really versatile, but focuses heavily on two aspects - tanking and dealing damage. That much is obvious. What is less obvious is that there are several ways to do each of these. My personal preference is for dealing respectable amounts of damage to multiple enemies while being able to take a lot of punishment before going down. My favorite ability for staying in the fight is &lt;strong&gt;No Permission to Die&lt;/strong&gt;. It's in the fifth tier of the Warlord soul, and it can be a godsend. If you die within ten seconds of triggering it, you are resurrected at 50% of your maximum health. Properly timed, it can really save your bacon. Also, it's not on global cooldown, so it's really hard to NOT time it right if you have a good sense of your combat situation. My next favorite ability is &lt;strong&gt;Cornered Beast&lt;/strong&gt;, which is the 32 point unlock for the Champion soul. It hits up to 6 enemies for a ton of damage over time AND generates Attack Points over time, making it a powerful threat-building ability. Awesome for tanks, and for area effect damage. Along with Warlord and Champion, picking the Reaver soul allows for a ridiculous amount of survivability. It has a number of abilities that boost armor, endurance, and resistances. A balanced mix of the three souls, like the &lt;a href="http://rift.magelo.com/en/stc/zzkBLlckIkrhz00zvl0V0ocMzzvlz0Vhzo" rel="external"&gt;build linked here (Champion (32) / Warlord (23) / Reaver (21))&lt;/a&gt;, will give you a decent AoE tanking playstyle. You won't win any DPS races, but it will keep you in the fight for a good long time.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sat, 08 Jun 2013 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/06/build-a-better-warrior-in-rift/</guid></item><item><title>Postgres Indexing - A collection of indexing tips</title><link>/2013/05/30/Postgres-Indexing-A-collection-of-indexing-tips/</link><description>&lt;p&gt;Even from intial reviews of my previous post on expression based indexes I received a lot of questions and feedback around many different parts of indexing in Postgres. Here&amp;rsquo;s a mixed collection of valuable tips and guides around much of that.&lt;/p&gt;
&lt;h3 id="unused-indexes"&gt;
&lt;div&gt;
Unused Indexes
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;In an earlier tweet I joked about some SQL that would generate the SQL to add an index to every column:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# SELECT 'CREATE INDEX idx_'
|| table_name || '_'
|| column_name || ' ON '
|| table_name || ' (&amp;quot;'
|| column_name || '&amp;quot;);'
FROM information_schema.columns;
?column?
---------------------------------------------------------------------
CREATE INDEX idx_pg_proc_proname ON pg_proc (&amp;quot;proname&amp;quot;);
CREATE INDEX idx_pg_proc_pronamespace ON pg_proc (&amp;quot;pronamespace&amp;quot;);
CREATE INDEX idx_pg_proc_proowner ON pg_proc (&amp;quot;proowner&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;The reasoning behind this is guessing whether an index will be helpful can be a bit hard within Postgres. So the easy solution is to add indexes to everything, then just observe if they&amp;rsquo;re being used. &lt;em&gt;Of course you want to add it to all tables/columns because you never know if core of Postgres may be missing some needed ones&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As included with the &lt;a href="https://github.com/heroku/heroku-pg-extras"&gt;pg-extras plugin for Heroku&lt;/a&gt; you can run a query to show you all unused indexes. On Heroku simply install the plugin the run &lt;code&gt;heroku pg:unused_indexes&lt;/code&gt; to show the size and number of times an index scan has been used. On a non Heroku Postgres database you can run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# SELECT
schemaname || '.' || relname AS table,
indexrelname AS index,
pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size,
idx_scan as index_scans
FROM pg_stat_user_indexes ui
JOIN pg_index i ON ui.indexrelid = i.indexrelid
WHERE NOT indisunique AND idx_scan &amp;lt; 50 AND pg_relation_size(relid) &amp;gt; 5 * 8192
ORDER BY pg_relation_size(i.indexrelid) / nullif(idx_scan, 0) DESC NULLS FIRST,
pg_relation_size(i.indexrelid) DESC;
table | index | index_size | index_scans
---------------------+--------------------------------------------+------------+-------------
public.grade_levels | index_placement_attempts_on_grade_level_id | 97 MB | 0
public.observations | observations_attrs_grade_resources | 33 MB | 0
public.messages | user_resource_id_idx | 12 MB | 0
(3 rows)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="costs-of-indexing"&gt;
&lt;div&gt;
Costs of Indexing
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;There are really a couple of primary costs when it comes to indexing your data. The first is the overall size of the index. Indexes take size on disk, fortunately in most cases disk is pretty cheap. If you&amp;rsquo;re limited on disk size and not on your current performance then its pretty clear the trade-off you want to take. If you do need to get the size of your index you can do that by running:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# SELECT pg_size_pretty(pg_total_relation_size('idx_name'));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The harder trade off to look at is the cost in terms of throughput. As your data comes in there&amp;rsquo;s a cost for maintaining that index as the data within it has to be computed. If you&amp;rsquo;re doing crazy regex&amp;rsquo;s in your index then you can expect this to have an impact on your throughput.&lt;/p&gt;
&lt;h3 id="composite-indexes-vs-multiple-indiviual-indexes"&gt;
&lt;div&gt;
Composite Indexes vs. Multiple Indiviual Indexes
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;A composite index is an index that includes multiple columns. Given an example table of purchases:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# \d purchases
Table &amp;quot;public.purchases&amp;quot;
Column | Type | Modifiers
-------------+-----------------------------+-----------
id | integer | not null
item | integer |
quantity | integer |
color | integer |
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You might want to add an index on item and quantity together. You can do this with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CREATE INDEX idx_purchases_item_quantity_color ON purchases (item, quantity, color)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From now on if you included item and quantity in a query its likely it would use this index just as it would if you used item, quantity and color. If you have a large varied set of data within each of these such an index can prove very useful. The caveat is that if you&amp;rsquo;re querying against only quantity and color then this index is useless, it &lt;strong&gt;must&lt;/strong&gt; include the item column.&lt;/p&gt;
&lt;p&gt;In contrast if you have three individual indexes Postgres may combine these or simply use one that would be the most efficient out of the three.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CREATE INDEX idx_purchases_item ON purchases (item);
CREATE INDEX idx_purchases_quantity ON purchases (quantity);
CREATE INDEX idx_purchases_color ON purchases (color);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course in this case if you query any individual column it would use the index if appropriate.&lt;/p&gt;
&lt;h3 id="what-else"&gt;
&lt;div&gt;
What Else
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;What else do you want to know about Postgres Indexing? Drop me a line &lt;a href="mailto:craig.kerstiens@gmail.com"&gt;craig.kerstiens at gmail.com&lt;/a&gt; or hop over to &lt;a href="http://www.postgresguide.com"&gt;Postgres Guide&lt;/a&gt; and &lt;a href="http://postgresguide.com/performance/indexes.html"&gt;read a little there&lt;/a&gt; or even contribute some articles of your own.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 30 May 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/05/30/Postgres-Indexing-A-collection-of-indexing-tips/</guid></item><item><title>Postgres Indexes – Expression/Functional Indexing</title><link>/2013/05/29/Postgres-Indexes-Expression/Functional-Indexing/</link><description>&lt;p&gt;Postgres is rich with options for indexing. First you&amp;rsquo;ve got a variety of types, and beyond that you can do a variety of things with each of these such as create unique indexes, use conditions to index only a portion of your data, or create indexes based on complex expressions or functions. In cases where you commonly use various PostgreSQL functions in your application or reporting you can get some great gains from this.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at a really simple case. Given a basic user table:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# \dt users
Table &amp;quot;public.users&amp;quot;
Column | Type | Modifiers
------------+-----------------------------+-----------
id | integer | not null
email | character varying(255) |
created_at | timestamp without time zone |
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You may commonly want to run a report against it showing your signups by date. Let&amp;rsquo;s say you do this by running the query:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT
count(*),
date_trunc('day', created_at)
FROM
users
GROUP BY
2;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you&amp;rsquo;re commonly using &lt;code&gt;date_trunc('day', created_at)&lt;/code&gt; for grouping, filtering, or projecting it out you can get some great gains by creating an index on this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# CREATE INDEX idx_user_created ON users(date_trunc('day', created_at));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Of course you can go beyond the built in functions of Postgres and use more complicated functions you create yourself. For example if you have JSON stored within PostgreSQL, have PLV8 enabled, and want to create a Javascript function to parse and return the text for a given key:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# CREATE OR REPLACE FUNCTION
get_text(key text, data json)
RETURNS text $$
return data[key];
$$ LANGUAGE plv8 IMMUTABLE STRICT;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Of note in the above function is &lt;code&gt;IMMUTABLE&lt;/code&gt; and &lt;code&gt;STRICT&lt;/code&gt;. Immutable specifies that the function given the same inputs will return the same result. Strict means that if you send in &lt;code&gt;NULL&lt;/code&gt; values you&amp;rsquo;ll get a null result.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Given some example data inside your JSON field:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
&amp;quot;name&amp;quot;: &amp;quot;Craig Kerstiens&amp;quot;,
&amp;quot;location&amp;quot;: &amp;quot;San Francisco&amp;quot;,
&amp;quot;numbers&amp;quot;: [
{
&amp;quot;type&amp;quot;: &amp;quot;work&amp;quot;,
&amp;quot;number&amp;quot;: &amp;quot;123.456.7890&amp;quot;
},
{
&amp;quot;type&amp;quot;: &amp;quot;home&amp;quot;,
&amp;quot;number&amp;quot;: &amp;quot;987.654.3210&amp;quot;
}
]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you wanted to return just the name you could index on:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# CREATE INDEX idx_name ON users(get_text('name', json_data));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or even combine with built ins for a case-insensitive version:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# CREATE INDEX idx_name ON users(lower(get_text('name', json_data)));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Indexes like all of the above can be useful when you&amp;rsquo;re filtering on something that postgres can take advantage of. In most cases any conditions with the exception of a &lt;code&gt;LIKE&lt;/code&gt; beginning with a &lt;code&gt;%&lt;/code&gt; work for this. With Postgres 9.2 even a count(*) in certain cases can take advantage of the index because of index only scans.&lt;/p&gt;
&lt;p&gt;Whether you&amp;rsquo;re looking to take advantage of all the power of Javascript with JSON or another procedural langauge – or simply speed up a basic report using built in functions expression indexes can give you some great benefits.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re looking for a deeper resource on Postgres I recommend the book &lt;a href="https://theartofpostgresql.com/?affiliate=cek"&gt;The Art of PostgreSQL&lt;/a&gt;. It is by a personal friend that has aimed to create the definitive guide to Postgres, from a developer perspective. If you use code CRAIG15 you&amp;rsquo;ll receive 15% off as well.&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Wed, 29 May 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/05/29/Postgres-Indexes-Expression/Functional-Indexing/</guid></item><item><title>My SQL Bad Habits</title><link>/2013/05/26/My-SQL-Bad-Habits/</link><description>&lt;p&gt;I&amp;rsquo;m reasonably proficient at SQL – &lt;em&gt;a coworker when pseudocoding some logic for him pointed out that my pseudocode is what he thought was executable SQL&lt;/em&gt;. I&amp;rsquo;m fully capable of writing clear and readable SQL – which most SQL is not. Despite that I still have several bad habits when it comes to SQL. Without further adieu heres some of my dirty laundry so hopefully others can not make the same mistakes.&lt;/p&gt;
&lt;h3 id="ordergroup-by-column-numbers"&gt;
&lt;div&gt;
Order/Group by Column Numbers
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;When quickly iterating on a query its a lot less typing to put the column number as the thing you want to order by. Here&amp;rsquo;s a quick lightweight example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT
email,
created_at
FROM
users
ORDER BY 2 DESC
LIMIT 5;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives me my last 5 users that have signed up for my site. Of course as soon as I have this I may want to add some data to it, like their first name so I can send them a welcome email. I quickly alter the query to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT
email,
first_name,
created_at
FROM
users
ORDER BY 2 DESC
LIMIT 5;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now I have 5 users that have signed up ordered by their first name. Sure its obvious when you have 1 column you&amp;rsquo;re ordering by, but when you have &lt;code&gt;GROUP BY 1, 2, 3, 4, 5, 6&lt;/code&gt; which is actually open in one of my tabs currently its a bit more confusing&amp;hellip;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Though if you really want to have some fun, share a query with someone that looks something like this:&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT
email as &amp;quot;3&amp;quot;,
first_name &amp;quot;2&amp;quot;,
created_at &amp;quot;1&amp;quot;
FROM
users
ORDER BY &amp;quot;1&amp;quot;, &amp;quot;3&amp;quot; DESC
LIMIT 5;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="implicit-joins"&gt;
&lt;div&gt;
Implicit Joins
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;I seldom use the syntax &lt;code&gt;INNER JOIN&lt;/code&gt;. Instead I simply put the two tables in my where clause and ensure I have a where condition. The problem with ensuring I have a where condition is sometimes I don&amp;rsquo;t, especially when you&amp;rsquo;re dealing with 3 tables.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT
email,
product.name,
product.price
FROM
users,
orders,
items
WHERE users.id = orders.user_id
AND orders.id = items.order_id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Is less clear (especially when dealing with 5-6 tables) than the alternative:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT
email,
product.name,
product.price
FROM users
INNER JOIN orders on users.id = orders.user_id
INNER JOIN items on orders.id = items.order_id
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="lack-of-comments"&gt;
&lt;div&gt;
Lack of comments
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;I comment my SQL far less than I comment my code, yet it can be done just as easily. For example I have this in one of my queries:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT convert_from(CAST(E'\\x' || array_to_string(ARRAY(
SELECT
CASE
WHEN length(r.m[1]) = 1
THEN encode(convert_to(r.m[1], 'SQL_ASCII'), 'hex')
ELSE substring(r.m[1] from 2 for 2)
END
FROM regexp_matches(url_here, '%[0-9a-f][0-9a-f]|.', 'gi') AS r(m)
), '') AS bytea), 'UTF8');
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While this has its own issues theres no documentation around what this actually does, in contrast:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;--- DECODES url ---
SELECT convert_from(CAST(E'\\x' || array_to_string(ARRAY(
SELECT
CASE
WHEN length(r.m[1]) = 1
THEN encode(convert_to(r.m[1], 'SQL_ASCII'), 'hex')
ELSE substring(r.m[1] from 2 for 2)
END
FROM regexp_matches(url_here, '%[0-9a-f][0-9a-f]|.', 'gi') AS r(m)
), '') AS bytea), 'UTF8');
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Comments also work well inline at the end of a line.&lt;/p&gt;
&lt;h3 id="large-manually-generated-lists"&gt;
&lt;div&gt;
Large Manually Generated Lists
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;A lot of times in working with some specific data set I&amp;rsquo;ll manually or automatically generate a list that I want to filter. A common example is filtering out staging/dev environments. I&amp;rsquo;ll often manually search and prune the list, then save that result for the queries I&amp;rsquo;m going to build going forward. This is a bit of effort but still feels reasonable the downside is it results in something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT
foo
FROM
bar
WHERE
bar.id NOT IN (34723, 42735, 32321, 47205, 20375, 30261, 26194, 109371, 9313, 6351, 20184, 50273, 34735, 39854, 23954, 25323, 23405, 30528, 50182, 29340, 47659, ... and the list goes on)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;SQL is meant to be reasonable for containing some level of logic. Data changes, hard coding keys is going to bite you at some point, spend the extra effort and re-use something thats clear.&lt;/p&gt;
&lt;h3 id="what-else"&gt;
&lt;div&gt;
What else
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m sure theres plenty more; I suspect within a few minutes of sitting down with someone they could point out some other bad habits. While I know mine at least some of mine I still often know the trade-off. What are yours? I&amp;rsquo;d love to hear to document them for others so hopefully they can prevent developing the same bad habits. Let me know; &lt;!-- raw HTML omitted --&gt;&lt;a href="mailto:craig.kerstiens@gmail.com"&gt;craig.kerstiens@gmail.com&lt;/a&gt;&lt;!-- raw HTML omitted --&gt;&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Sun, 26 May 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/05/26/My-SQL-Bad-Habits/</guid></item><item><title>Learning Ruby on Rails: Why? How? Pitfalls?</title><link>https://www.brightball.com/articles/learning-ruby-on-rails-why-how-pitfalls</link><description>I've always been a proponent of the "right tool for the job" approach to programming.  Different languages are well suited for different situations. Over the past 2 years I've spent a great deal of time with Ruby on Rails after coming from a background of PHP, Java and Perl.  Here's how I got started and some of the lessons I learned along the way.</description><author>Brightball Articles</author><pubDate>Thu, 09 May 2013 19:00:00 GMT</pubDate><guid isPermaLink="true">https://www.brightball.com/articles/learning-ruby-on-rails-why-how-pitfalls</guid></item><item><title>CX – Conference Experience (Facilitating Communication)</title><link>/2013/04/29/CX-Conference-Experience-Facilitating-Communication/</link><description>&lt;p&gt;Following up on my earlier post about CX or Conference Experience – I&amp;rsquo;m going to dig in a bit on how you get good conversation to happen. In the past two years I&amp;rsquo;ve been to nearly 20 conferences, I&amp;rsquo;ve been to conferences with great talks, with great parties, with great swag, and hands down my favorite conferences have always been a result of great conversation. With the number of talks that are recorded and immediately available online after, &lt;em&gt;what can I say I&amp;rsquo;m a hallway track guy&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve seen a number of conferences intentionally design around this concept, in some ways the unconference is purely a hallway track conference. I&amp;rsquo;ve also seen conferences that weren&amp;rsquo;t clearly planned for this and have pulled off some of the best situations where people turn their phones off and engage in real conversation.&lt;/p&gt;
&lt;h2 id="breaks"&gt;
&lt;div&gt;
Breaks
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;Breaks are always a hard part to balance. Every conference organizer I&amp;rsquo;ve talked to felt they had the perfect mix for breaks. If you&amp;rsquo;re designing for convesation then you need to allow time for conversation to actually happen. Whether a multi-track or single track conference 15 minutes for breaks doesn&amp;rsquo;t give you the time to actually engage in conversation. If multitrack its time enough to grab a drink then head to the next room. If single track its time to have the entire room leave and then come back.&lt;/p&gt;
&lt;p&gt;Even 30 minute breaks fall into this category. At a multitrack conference I&amp;rsquo;m usually saying hi to enough people during a 30 minute break that I don&amp;rsquo;t have the chance to really get deep into a conversation. If I do it usually results in skipping the next talk.&lt;/p&gt;
&lt;h2 id="staggered-talks"&gt;
&lt;div&gt;
Staggered Talks
&lt;/div&gt;
&lt;/h2&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;h2 id="locations-for-conversations"&gt;
&lt;div&gt;
Locations for Conversations
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;Having places for people to get away an talk is critical, in a venue that only has 1 main room and no convenient places for a quick coffee or beer it becomes very hard for conversations to happen. If its on the agenda to facilitate such things thats great, but going a step further and allowing for it to be facilitated naturally is even better. On more than one occasion I&amp;rsquo;ve been mid conversation wtih someone, we cut it off agreeing to pick it back up at the next break only to never locate them again for the rest of the conference. I&amp;rsquo;d have just as much preferred to continue the conversation there, but sadly there was in the middle of a talk room with no where else feasible to go.&lt;/p&gt;
&lt;h2 id="water"&gt;
&lt;div&gt;
Water
&lt;/div&gt;
&lt;/h2&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;This one caught me by surprise&amp;hellip; The event was &lt;a href="http://py.codeconf.com/"&gt;PyCodeConf in Miami&lt;/a&gt; and it was one of the evening activities – a pool party with food, drinks, and mariachi band. Early into the evening, inevitably someone was thrown into the pool (by friends in a general good nature), but thus ruining a lovely iPhone. As a result I&amp;rsquo;m pretty most people, just as I did, went to their rooms but their cell phone away, or set it near their stuff. Much of the rest of the evening was an entirely internet and twitter free evening. Causing lots of uninterrupted conversations to happen and resulted in a pool full of geeks.&lt;/p&gt;
&lt;h2 id="welcoming-noobs"&gt;
&lt;div&gt;
Welcoming noobs
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;The big difference between just assuming this will happen and actively working to facilitate it is who gets involved in the conversation. For a first time presenter there&amp;rsquo;s a wealth of nerves about talking. For a first time attendee there&amp;rsquo;s a wealth of knowledge to soak up. First time attendees may not feel as comfortable interjecting them into a conversation, approaching presenters, or talking to someone they&amp;rsquo;ve been following for years – &lt;em&gt;yet they have just as much to add as anyone else&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Creating places where more conversation is happening helps ease this and build a better community.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Mon, 29 Apr 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/04/29/CX-Conference-Experience-Facilitating-Communication/</guid></item><item><title>CX – Conference Experience (People)</title><link>/2013/04/29/CX-Conference-Experience-People/</link><description>&lt;p&gt;Following up on my earlier post about CX or Conference Experience – I&amp;rsquo;m going to dig in a bit on getting the right people there. There&amp;rsquo;s a lot of different ways to approach this from having a good ratio of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Designers to Developers&lt;/li&gt;
&lt;li&gt;Females to Males&lt;/li&gt;
&lt;li&gt;Noobs to well known community members&lt;/li&gt;
&lt;li&gt;Overall lack of suits&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While this is by no means a how we can solve all of the above problems, theres some bas&lt;/p&gt;
&lt;h2 id="talks"&gt;
&lt;div&gt;
Talks
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;Quality talks are obviously important. A conference should at whatever cost ensure that the talks are good. This can happen a variety of ways, but regardless of the method you should ensure talks are worthwhile; since this is largely what most people are paying to attend for.&lt;/p&gt;
&lt;h3 id="invite-only"&gt;
&lt;div&gt;
Invite-only
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Perhaps the easiest way to do this is via invite only to speakers you know will do a good job. The downside ot this of course is that you must already know enough people to fill out a good agenda, and also you limit the ability for others to contribute.&lt;/p&gt;
&lt;h3 id="coachingpracticing"&gt;
&lt;div&gt;
Coaching/Practicing
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;This is not an either/or option with any of the other pieces for getting a good agenda. Having presenters do a trial run can ensure a minimum level of quality, and working with them to coach them can help make the talk even more effective. Its likely that the organizers know the audience as well as anyone, so no one better than them to help with this. Of course this is a time sink for both parties, but can give good returns. Of course this could be done independent of a specific conference such as through &lt;a href="http://speakup.io/"&gt;speakup&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;At a very least getting a quick run through, outline, or something of that nature can ensure that a presenter doesn&amp;rsquo;t fill a 45 minute talk slot with only 5 minutes of content.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="open-cfp"&gt;
&lt;div&gt;
Open CFP
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Likely the most common approach to getting speakers is having an entirely open CFP. Its typical then that either the organizers or a speaker selection commitee then discusses and makes selections. This can usually work to have a nice balance of experienced and known to be good speakers and newer less experienced speakers that can have great potential as well.&lt;/p&gt;
&lt;h3 id="open-open-cfp"&gt;
&lt;div&gt;
Open Open CFP
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Going even further is an open CFP where all talks are published after the CFP then voted on. While this does a great deal to ensure transparency, it doesn&amp;rsquo;t necessarily improve ensuring theres a great line up of speakers. Being able to write an interesting talk proposal is an entirely separate process from delivering an interesting talk.&lt;/p&gt;
&lt;h3 id="blind"&gt;
&lt;div&gt;
Blind?
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s a common question lately for both the open CFP and open open ones one whether to do blind review of the talks. The logic here is an attempt to be entirely fair, versus having some bias. This is an understandable goal, but can come at the expense of quality. Truth be told; I&amp;rsquo;m not entirely sure of a way to balance this.&lt;/p&gt;
&lt;h2 id="choosing"&gt;
&lt;div&gt;
Choosing
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s definitely not a one size fits all. If you&amp;rsquo;re goal is to provide a good list of talks then you should keep that in mind in how you decide your talks. If you&amp;rsquo;re goal is to pull others in then it should be shaped differently. Zach Holman recently talked a bit about this and had some interesting ideas to &lt;a href="http://zachholman.com/posts/the-conference-circuit/"&gt;minimize risk for new speakers&lt;/a&gt;.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Mon, 29 Apr 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/04/29/CX-Conference-Experience-People/</guid></item><item><title>The Drawback to Web Frameworks</title><link>https://www.brightball.com/articles/the-drawback-to-web-frameworks</link><description>Web frameworks are great, don't get me wrong here. They provide a structure and consistency across projects that will transcend developers over the life of a system while dramatically simplifying the code base amongst other wonderful side effects. But what's the downside?</description><author>Brightball Articles</author><pubDate>Mon, 29 Apr 2013 20:37:00 GMT</pubDate><guid isPermaLink="true">https://www.brightball.com/articles/the-drawback-to-web-frameworks</guid></item><item><title>"Make it faster."</title><link>https://www.brightball.com/articles/make-it-faster</link><description>I'm obsessed with performance tuning.  It's an itch that can never fully be scratched.  A sickness that can never be cured.  Here's the story of how I caught the bug.</description><author>Brightball Articles</author><pubDate>Sun, 28 Apr 2013 05:22:00 GMT</pubDate><guid isPermaLink="true">https://www.brightball.com/articles/make-it-faster</guid></item><item><title>CX – Conference Experience (Talks)</title><link>/2013/04/27/CX-Conference-Experience-Talks/</link><description>&lt;p&gt;A couple of weekends ago I had the great opportunity to attend &lt;a href="http://lessconf.com"&gt;lessconf&lt;/a&gt;. It was an all around great conference, and as a result of the greatness I ended up having a conversation with a few people around conference experience. I must give much of the credit to &lt;a href="http://twitter.com/swiftalphaone"&gt;Swift&lt;/a&gt;, as he mentioned he&amp;rsquo;d already been thinking alot about this since &lt;a href="http://waza.heroku.com"&gt;Waza&lt;/a&gt;. In general it feels like there&amp;rsquo;s a few key themes that any conference should focus on, then a lot of small things that can really push it over the top. Here&amp;rsquo;s a few:&lt;/p&gt;
&lt;p&gt;In general the key areas for any great conference are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Talks&lt;/li&gt;
&lt;li&gt;Great people&lt;/li&gt;
&lt;li&gt;Ensuring communication happens&lt;/li&gt;
&lt;li&gt;Bonus points&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Digging in deeper on the first area&amp;hellip;&lt;/p&gt;
&lt;h2 id="talks"&gt;
&lt;div&gt;
Talks
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;Quality talks are obviously important. A conference should at whatever cost ensure that the talks are good. This can happen a variety of ways, but regardless of the method you should ensure talks are worthwhile; since this is largely what most people are paying to attend for.&lt;/p&gt;
&lt;h3 id="invite-only"&gt;
&lt;div&gt;
Invite-only
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Perhaps the easiest way to do this is via invite only to speakers you know will do a good job. The downside ot this of course is that you must already know enough people to fill out a good agenda, and also you limit the ability for others to contribute.&lt;/p&gt;
&lt;h3 id="coachingpracticing"&gt;
&lt;div&gt;
Coaching/Practicing
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;This is not an either/or option with any of the other pieces for getting a good agenda. Having presenters do a trial run can ensure a minimum level of quality, and working with them to coach them can help make the talk even more effective. Its likely that the organizers know the audience as well as anyone, so no one better than them to help with this. Of course this is a time sink for both parties, but can give good returns. Of course this could be done independent of a specific conference such as through &lt;a href="http://speakup.io/"&gt;speakup&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;At a very least getting a quick run through, outline, or something of that nature can ensure that a presenter doesn&amp;rsquo;t fill a 45 minute talk slot with only 5 minutes of content.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="open-cfp"&gt;
&lt;div&gt;
Open CFP
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Likely the most common approach to getting speakers is having an entirely open CFP. Its typical then that either the organizers or a speaker selection commitee then discusses and makes selections. This can usually work to have a nice balance of experienced and known to be good speakers and newer less experienced speakers that can have great potential as well.&lt;/p&gt;
&lt;h3 id="open-open-cfp"&gt;
&lt;div&gt;
Open Open CFP
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Going even further is an open CFP where all talks are published after the CFP then voted on. While this does a great deal to ensure transparency, it doesn&amp;rsquo;t necessarily improve ensuring theres a great line up of speakers. Being able to write an interesting talk proposal is an entirely separate process from delivering an interesting talk.&lt;/p&gt;
&lt;h3 id="blind"&gt;
&lt;div&gt;
Blind?
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s a common question lately for both the open CFP and open open ones one whether to do blind review of the talks. The logic here is an attempt to be entirely fair, versus having some bias. This is an understandable goal, but can come at the expense of quality. Truth be told; I&amp;rsquo;m not entirely sure of a way to balance this.&lt;/p&gt;
&lt;h2 id="choosing"&gt;
&lt;div&gt;
Choosing
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s definitely not a one size fits all. If you&amp;rsquo;re goal is to provide a good list of talks then you should keep that in mind in how you decide your talks. If you&amp;rsquo;re goal is to pull others in then it should be shaped differently. Zach Holman recently talked a bit about this and had some interesting ideas to &lt;a href="http://zachholman.com/posts/the-conference-circuit/"&gt;minimize risk for new speakers&lt;/a&gt;.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Sat, 27 Apr 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/04/27/CX-Conference-Experience-Talks/</guid></item><item><title>The Impossible Assignment</title><link>https://www.brightball.com/articles/the-impossible-assignment</link><description>I had the opportunity to visit the class of one of my legendary former professors yesterday and got to share a classic story about him...the time he gave us an impossible assignment.</description><author>Brightball Articles</author><pubDate>Thu, 25 Apr 2013 20:12:00 GMT</pubDate><guid isPermaLink="true">https://www.brightball.com/articles/the-impossible-assignment</guid></item><item><title>Create Better Villains for your Adventure</title><link>https://benovermyer.com/blog/2013/04/create-better-villains-for-your-adventure/</link><description>&lt;p&gt;Villains are the mainstay of any good adventure. With very few exceptions, there is always some form of evil mind plotting dark things in the background. Whether this is a mindless mob of creatures that just happens to be devouring the locals, or a masterfully devious court magician manipulating a king to sinister ends, you can't get away from the guys.&lt;/p&gt;
&lt;p&gt;This blog post aims to assist you in building memorable villains that are more than just numbers on a sheet of paper. If you're a player and not a game master, the character building advice in here might help you too, but this is specifically geared towards the folks weaving the story behind the encounters.&lt;/p&gt;
&lt;h1 id="the-nature-of-a-villain"&gt;The Nature of a Villain&lt;/h1&gt;
&lt;p&gt;While it's fairly obvious that a villain exists to ruin the lives of good people, a truly memorable villain has much more than that going on. He has his own motives and desires. He may be acting in accordance with his own morals, or he might not care at all.&lt;/p&gt;
&lt;p&gt;Most frequently, a villain's goals shouldn't be an end, but a way to reach some other starting point. The kobold king isn't sending raiding parties out to nearby villages because he feels like it; he's weakening the nearby human presence so his people can expand outward from their all-too-small cave system.&lt;/p&gt;
&lt;p&gt;The depth of a villain's forward thinking depends on how intelligent you want him to be. Don't restrict a villain's planning just because he's a minor NPC in your adventure. Players will inevitably do something you don't expect, and if they just happen to latch onto your minor villain, you'll then have a direction to take that in.&lt;/p&gt;
&lt;h1 id="journey-of-the-hero"&gt;Journey of the Hero&lt;/h1&gt;
&lt;p&gt;The player characters will only grow stronger as a result of having a characterful villain as their foil. You can consider your adventure a success when not only does it give your PCs the magical loot of awesomeness they've been waiting for, but it also encourages them to reconsider their characters' actions and motives.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Joseph Campbell's Hero with a Thousand Faces is a fantastic guide to setting up an epic story. His writings on the “road of trials” in particular are relevant to creating worthwhile villains for the players.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A player character that's just starting out usually has weak stats, basic equipment, and almost zero personality. She might have a single personality quirk or cliché that her player jots down to guide her role-playing, but rarely will players take the time to build a full story for their characters. After all, that's what they're hoping you will do.&lt;/p&gt;
&lt;p&gt;As the PC encounters and interacts with your adventure's many challenges, locations, and characters, she will grow in both power and personality. If her player is into role-playing, this will happen sooner rather than later, and with more depth. She will need a good villain, though, to balance that development against.&lt;/p&gt;
&lt;h1 id="brainstorming"&gt;Brainstorming&lt;/h1&gt;
&lt;p&gt;Creating a villain should start with looking at what you want to achieve with the adventure and with the campaign at large. An adventure isn't a set narrative that you can just write and expect to stay the way you wrote it. The players will do things you don't expect and interact with the environment in ways that force you to adapt the adventure to fit their actions. As such, your villain should support your goal with the adventure, rather than just play to the script.&lt;/p&gt;
&lt;p&gt;Jot down a few notes about your adventure's premise. Is it a classic battle of good versus evil? Is it a day in the life of an adventurer? Is it an exploration of the unknown? Think about your favorite movies or books that fit the theme you're going for. What twists in those stories really got your blood pumping?&lt;/p&gt;
&lt;h2 id="potential-for-loss"&gt;Potential for Loss&lt;/h2&gt;
&lt;p&gt;Think about what would really hurt the player characters. I don't mean in terms of hit points lost or character sheets thrown away – I mean tragedies that specifically target each PC's hopes, dreams, and beliefs. Whether the players are into role-playing or not only determines whether you have more or less fodder for this; it's still possible to make a tactical gamer sit back in his chair with a thud when his character loses something dear to him. It usually just changes the context.&lt;/p&gt;
&lt;p&gt;Build something of that potential loss into each villain of the adventure. You don't need to include every player character in every adventure, but you shouldn't focus on only one player character either. Also, choose a handful of NPCs and target their potential for loss also. It helps build a living world when you include characters other than the players' in your adventures.&lt;/p&gt;
&lt;h2 id="potential-for-gain"&gt;Potential for Gain&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Saruman was originally a hero, but gave in to temptation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now think about what the villain can offer the player characters. Temptation plays on base emotions; use it. For tactical gamers, this could be a particular piece of loot that they want desperately. For role-players, it might be a bit of information about a relative they've been searching for. For every player, write down at least one thing that the villain might have the ability to provide.&lt;/p&gt;
&lt;p&gt;As with the potential for loss, also make sure that some of your NPCs stand to gain something by working with the villain. Even if that incorruptible priest of all that is good can't possibly be turned to the dark side, the players might not know that, and that creates tension. Tension is what every great story (and adventure) is built on.&lt;/p&gt;
&lt;h1 id="villains-are-story-generators"&gt;Villains are Story Generators&lt;/h1&gt;
&lt;p&gt;Other than trying to provoke emotional tension from players through the potential for loss or gain, a good villain should also act as a way to move the story along. The best stories, whether they're explosion-ridden Hollywood blockbusters or 1500-page literary masterpieces, are about the heroes changing in some way over the course of the story. Villains are almost always the catalyst for that change.&lt;/p&gt;
&lt;p&gt;If your players are craving action, send a wave of minor baddies against them. Let them know that the villain made this happen, whether directly or indirectly. Weave a spider's web with your villain at the center. Even if he is not of the evil genius persuasion, he's still fully capable of planning ahead.&lt;/p&gt;
&lt;h1 id="summary-tl-dr-version"&gt;Summary / TL;DR Version&lt;/h1&gt;
&lt;p&gt;Keep your villains close to your players' hearts. Tension is a great story device, so use it. Tempt the PCs. Hurt the PCs. Make a list of the villain's goals and aspirations.&lt;/p&gt;
&lt;p&gt;And, above all else, remember: villains are not just stat blocks, they're people too.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sat, 20 Apr 2013 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/04/create-better-villains-for-your-adventure/</guid></item><item><title>Heroku's Acquisition 2 Years Later</title><link>/2013/04/18/Herokus-Acquisition-2-Years-Later/</link><description>&lt;p&gt;Just over two years ago, Heroku was acquired. I was around and peripheral to this just before the acquisition and came on board only barely after. While there is a large group of people that have been there longer than I have (several for 4+ years) I&amp;rsquo;m still commonly asked how things have changed, how things work, and other questions of that nature. I wrote about some of these processes over a year ago in the months after joining Heroku around our &lt;a href="/2011/12/02/how-heroku-works-hiring/"&gt;hiring&lt;/a&gt;, our &lt;a href="/2011/11/02/how-heroku-works-teams-tools/"&gt;teams&lt;/a&gt;, and &lt;a href="/2011/11/07/how-heroku-works-maker-day/"&gt;how we work&lt;/a&gt;. Many of these things haven&amp;rsquo;t changed, and yet almost always at a conference I&amp;rsquo;m asked how are things different since being acquired.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s my personal take (and while I don&amp;rsquo;t typically include this – &lt;em&gt;to be safe, this is not an official Heroku view of what&amp;rsquo;s changed&lt;/em&gt;).&lt;/p&gt;
&lt;h3 id="are-things-different-since-the-acquisition"&gt;
&lt;div&gt;
Are things different since the acquisition?
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Heroku in many ways operates like a wholly owned subsidiary or as an independent business within Salesforce. We still have our own office space, our own IT (if you can even call it that), and in general entirely own workflow. I have a salesforce email account that automatically forwards to my Heroku google apps account, and that&amp;rsquo;s about as much as I know about it. In fact, we&amp;rsquo;re currently preparing for our new office and its planned to be our home for somewhere between the next 5-10 years.&lt;/p&gt;
&lt;p&gt;At the same time some things do flow through Salesforce, some of those things are logistical some strategic. First the perhaps most unfortunate part – hiring. This has not really changed &lt;a href="/2011/12/02/how-heroku-works-hiring/"&gt;how we hire&lt;/a&gt;, but rather once you are coming on board theres more paperwork. In general this is the most painful part that instead of 1/2 pieces of paper theres a few to sign. At the same time some of these come with some greater gains such as benefit, etc. To be honest I dont fully recall what all of the paper work is, but either way there is a bit more of it. The other area we really see this effect is expense accounts. All expenses flow through concur, which in my opinion is a pretty good solution. I&amp;rsquo;ve used many worse expense solutions and seen few if any better.&lt;/p&gt;
&lt;h3 id="do-they-influence-the-product"&gt;
&lt;div&gt;
Do they influence the product?
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Not really&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In general we at Heroku aim to have some broader alignment around what we&amp;rsquo;re trying to accomplish. Salesforce believes in helping their customers become a &lt;a href="http://www.youtube.com/watch?v=BwaZwm2dTCA"&gt;customer company&lt;/a&gt;. We believe that developers are worth of great experiences. Salesforce believes in ensuring its customers are successful. Heroku believes that developers should focus on adding value of their customers not just keeping the lights on. In all of these things its important to have alignment. Not for the company we&amp;rsquo;re building for the next six weeks or six months, but for the next six years. Given both Salesforce&amp;rsquo;s and Heroku&amp;rsquo;s worldview I believe what we&amp;rsquo;re trying to accomplish is in good alignment.&lt;/p&gt;
&lt;p&gt;But does Salesforce influence our product roadmap? No, we aim to listen to our customers problems and build to solve those problems and through that improve the way software is delivered. At the time Salesforce acquired us, the pieces of &lt;a href="https://blog.heroku.com/archives/2011/5/31/celadon_cedar"&gt;Cedar&lt;/a&gt; were already in motion; including Procfile support, logplex, and other pieces. Later was fully productized Cedar and which was a goal we&amp;rsquo;d long had – making other languages such as Node, &lt;a href="https://blog.heroku.com/archives/2011/8/25/java"&gt;Java&lt;/a&gt;, and &lt;a href="https://blog.heroku.com/archives/2011/9/28/python_and_django"&gt;Python&lt;/a&gt; available. This wasn&amp;rsquo;t driven because Salesforce wanted Java, but because we saw value in delivering the same value of the platform to other communities.&lt;/p&gt;
&lt;h3 id="have-we-changed"&gt;
&lt;div&gt;
Have we changed?
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Sure, we&amp;rsquo;ve changed, but I&amp;rsquo;d surmise very little if at all due to Salesforce. We&amp;rsquo;ve grown from a 20 person company to now over 100. We were a primarily local team and now have people all over. Company offsites get a bit harder to coordinate with 100 people, and finding a date that absoluely everyone can make it is nearly impossible. Many of our changes are more strictly a change of growth than they are because of Salesforce.&lt;/p&gt;
&lt;h3 id="i-dont-get-it-why-acquire-you-then"&gt;
&lt;div&gt;
I dont get it, why acquire you then?
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Because we&amp;rsquo;re aligned in a much bigger vision, we can both work together long term to accomplish our goal.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The internet is changing the world; software is everywhere.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I believe Salesforce truly understands this. Heroku does as well (though, at the time of the acquisition I fully suspect many Herokai held their breath to see how it would all go). Six weeks went by without trying to &amp;lsquo;change us&amp;rsquo;, then six months, and here we are over two years later. In many ways so many of us have started to better understand that Salesforce truly understands the above.&lt;/p&gt;
&lt;p&gt;If you understand the above, then you know that delivering software and improving that process gives any business a competitive advantage. This is at the core of the value we aim to provide. E.g. If you ranked all companies in terms of how strong they aligned with Heroku, Salesforce might be at the &lt;em&gt;very&lt;/em&gt; top.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 18 Apr 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/04/18/Herokus-Acquisition-2-Years-Later/</guid></item><item><title>Profiling Django templates with Django-Debug-Toolbar</title><link>https://tomforb.es/blog/profiling-django-templates-with-django-debug-toolbar/</link><description>My last post about the speed of Django’s templating language caused a bit of a stir and it was clear that people didn’t really have a clue how long the templates were taking to render in their applications. Enter Template-timings Template-timings is a panel for Django-debug-toolbar (which everyone s...</description><author>Tom Forbes</author><pubDate>Thu, 18 Apr 2013 23:46:58 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/profiling-django-templates-with-django-debug-toolbar/</guid></item><item><title>Using array_agg in Postgres – powerful and flexible</title><link>/2013/04/17/Using-array_agg-in-Postgres-powerful-and-flexible/</link><description>&lt;p&gt;In almost any application it&amp;rsquo;s common to want to aggregate some set of values together, commonly in a comma separated form. Most developers do this by running a query to get much of the raw data, looping over the data and pushing it into a set, appending each new value to the appropriate key. Hopefully, it&amp;rsquo;s not a surprise that there&amp;rsquo;s a much better way to do this with PostgreSQL.&lt;/p&gt;
&lt;p&gt;Postgres has a flexible and robust &lt;a href="/2012/08/20/arrays-in-postgres/"&gt;array datatype&lt;/a&gt; that comes with a variety of functions. Even without taking advantage of the array datatype in &lt;a href="/2012/11/06/django-and-arrays/"&gt;your application&lt;/a&gt;, you can still take advantage of some of the functions to get the functionality you need. Lets take a look at an example schema and use case.&lt;/p&gt;
&lt;h3 id="an-example"&gt;
&lt;div&gt;
An example
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Given a project management application, you may have &lt;code&gt;users&lt;/code&gt; who have &lt;code&gt;projects&lt;/code&gt; that have &lt;code&gt;tasks&lt;/code&gt;. An example piece of functionality might be to send an email with a list of all projects that have tasks that are past their due dates of completion. Your schema might look something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; # \d users
Table &amp;quot;public.users&amp;quot;
Column | Type | Modifiers
------------+-----------------------------+-----------
id | integer | not null
email | character varying(255) |
...
# \d projects
Table &amp;quot;public.projects&amp;quot;
Column | Type | Modifiers
------------+-----------------------------+-----------
id | integer | not null
user_id | integer | not null
name | character varying(255) | not null
...
# \d tasks
Table &amp;quot;public.tasks&amp;quot;
Column | Type | Modifiers
--------------+-----------------------------+-----------
id | integer | not null
project_id | integer | not null
completed_at | timestamp without time zone |
due_at | timestamp without time zone |
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To get a list of all projects that have tasks that haven&amp;rsquo;t been completed, you would start with something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT
projects.name
FROM
projects,
tasks
WHERE projects.id = tasks.project_id
AND tasks.due_at &amp;gt; tasks.completed_at
AND tasks.due_at &amp;gt; now()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This would give you a list of projects which you could then easily join this with users:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT
users.email
projects.name
FROM
projects,
tasks,
users
WHERE projects.id = tasks.project_id
AND tasks.due_at &amp;gt; tasks.completed_at
AND tasks.due_at &amp;gt; now()
AND users.id = projects.user_id
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point you&amp;rsquo;ve got everything you need to pull this up into Ruby, Python, or other language of your choice and then build the full set. However if this is thousands or even hundreds of results you&amp;rsquo;ll be spending more time than necessary, grouping this data for a sensible email. With 3 other small changes you can have this already formatted for you to immediately send of in an email. The first is using a handy function called &lt;code&gt;array_agg&lt;/code&gt; which will aggregate items and then you can format them how you wish. The second is just ensuring you&amp;rsquo;re grouping correctly. Finally you&amp;rsquo;ll want to unnest the array so it formats the data in a clean way for you.&lt;/p&gt;
&lt;p&gt;Looking at it all put together:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT
users.email,
array_to_string(array_agg(projects.name), ',')) as projects
FROM
projects,
tasks,
users
WHERE projects.id = tasks.project_id
AND tasks.due_at &amp;gt; tasks.completed_at
AND tasks.due_at &amp;gt; now()
AND users.id = projects.user_id
GROUP BY
users.email
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This would give you a nice clean result of projects that have overdue tasks that you could then send to the user in an email:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; email | projects
---------------------------+-------------------
craig.kerstiens@gmail.com | blog, timetracker
craig@heroku.com | foo, bar, baz
&lt;/code&gt;&lt;/pre&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Wed, 17 Apr 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/04/17/Using-array_agg-in-Postgres-powerful-and-flexible/</guid></item><item><title>Building a Search Result Extract Generator in PHP</title><link>https://boyter.org/2013/04/building-a-search-result-extract-generator-in-php/</link><description>&lt;p&gt;During some contracting I was doing recently there was a requirement to implement some search logic using only PHP. There are no issues with that but it turns out I couldn&amp;rsquo;t find a decent extract generator handy as usually one would just plug into the search engines provided version to do this.&lt;/p&gt;
&lt;p&gt;Off the top of my head I could only think of one example I was aware of which lives in &lt;a href="http://www.sphider.eu/"&gt;Sphider&lt;/a&gt; (for the record it lives in searchfuncs.php from line 529 to 566). Sadly it has a few issues. Firstly the code is rather difficult to understand, and more importantly it usually has accuracy issues. A quick search turned up this link &lt;a href="http://stackoverflow.com/questions/1436582/how-to-generate-excerpt-with-most-searched-words-in-php"&gt;http://stackoverflow.com/questions/1436582/how-to-generate-excerpt-with-most-searched-words-in-php&lt;/a&gt; on StackOverflow. The second answer looked promising but its even more difficult to understand and a bit of profiling showed some performance issues will all of the regex going on in there.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Wed, 17 Apr 2013 02:23:56 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/04/building-a-search-result-extract-generator-in-php/</guid></item><item><title>Scaling Evangelism – Creating Advocates</title><link>/2013/04/16/Scaling-Evangelism-Creating-Advocates/</link><description>&lt;p&gt;The first area I tend to think about when it comes to developer marketing is around advocates. A simple definition of an advocate is &lt;em&gt;someone that speaks/writes in favor of some thing&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Creating advocates is a means of creating more of myself to go out and talk loudly and ideally effectively. However, they do take time to cultivate and it is a hard item to track. But by cultivating advocates I&amp;rsquo;m able to scale what would otherwise be a bottleneck of my own personal time.&lt;/p&gt;
&lt;h3 id="mentorship"&gt;
&lt;div&gt;
Mentorship
&lt;/div&gt;
&lt;/h3&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;The people in your group of 3 you&amp;rsquo;ll have nearly daily communications with, even if quick. These are the first people you think to work and collaborate with. It&amp;rsquo;s the case with all, but especially so here that there may be some strong mutual benefit. With both the groups of 3 and 12 you&amp;rsquo;ll be looking to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Co-author content with&lt;/li&gt;
&lt;li&gt;Collaborate on projects&lt;/li&gt;
&lt;li&gt;Help amplify their content&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="helping-them-succeed"&gt;
&lt;div&gt;
Helping them Succeed
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;For a few years I&amp;rsquo;ve followed a similar process to this. Essentially creating advocates is done through first &lt;strong&gt;making them successful&lt;/strong&gt;, then empowering to talk about their success. I&amp;rsquo;ve often done this by giving people a private channel to me – through IM, SMS, Phone, Skype, or even in person. Sure its easy enough to get my work email address, its a pretty easy one to guess, and even at that address I do aim to respond to every request. These channels in reality don&amp;rsquo;t make me more available; but they do allow a different type of communication to happen.&lt;/p&gt;
&lt;p&gt;My personal approach has found it more out of place to ask how someones weekend was over email – IM or Skype make this easy. Broader questions of how someones actually doing in life generally are much easier to do over a coffee or a beer. This allows for a deeper relationship; at the same time I can ensure everyone I interact with is successful. It&amp;rsquo;s easier to ensure someones successful if they&amp;rsquo;re willing to talk to you, actually connecting with people enables this.&lt;/p&gt;
&lt;h3 id="communicate"&gt;
&lt;div&gt;
Communicate
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Once someones been successful theres usually some value in their story. This doesn&amp;rsquo;t need to come in a marketing-ese approach though. Instead contribute back the value of what you did to the broader community with &lt;a href="http://blog.mailgun.net/post/how-tealeaf-academy-increased-student-engagement-3x/"&gt;clear steps how they can get the same benefit&lt;/a&gt;. For many developers they feel talking about their own success is a bit of imposter syndrome. While this isn&amp;rsquo;t always the case; if it is you can help to work with someone to highlight the value in what they&amp;rsquo;ve done. This could be as simple as some encouragement to actually helping review drafts of blog posts.&lt;/p&gt;
&lt;p&gt;Of course once someones started talking about what they were able to accomplish help them celebrate the success. Yelling from the rooftops only helps to further their efforts and give them the confidence to do it all over again.&lt;/p&gt;
&lt;h3 id="conclusion"&gt;
&lt;div&gt;
Conclusion
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;To create advocates you don&amp;rsquo;t have to write a list of people you wish to shoot for, but realizing there are limiitations on your time can help you be more intentional. Knowing that where you spend your time and who you spend it with has a cost can allow you to be more explicit about ensuring you&amp;rsquo;re providing value to them, from there it should naturally run its course. Want to discuss this more? Email me at &lt;a href="mailto:craig.kerstiens@gmail.com"&gt;craig.kerstiens at gmail.com&lt;/a&gt;.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Tue, 16 Apr 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/04/16/Scaling-Evangelism-Creating-Advocates/</guid></item><item><title>Doing Marketing (for developers) Differently</title><link>/2013/04/12/perspective-on-developer-marketing/</link><description>&lt;p&gt;As developers we can tend to be a fickle bunch; especially in certain open source communities. We like to see intelligence and systems applied to things, hope for a better world through making things open, and appreciate when others relate to our world as we often attempt to relate to theirs. Marketing is often a loaded word when it comes to developers – leaving mixed feelings about webinars, email campaigns, and the like.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A quick clarification in terms of marketing I&amp;rsquo;m referring to product marketing, but of a technical product. This is based on the idea that &lt;a href="http://thenewkingmakers.com/"&gt;developers are the new kingmakers&lt;/a&gt; and when marketing a product to them it needs to be done differently.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;While many of the above steps can add immense value, they often miss when it comes to developers. By changing these processes only slightly there can be much more efficiency in connecting with and actually delivering the value you hope for to developers.&lt;/p&gt;
&lt;h3 id="email-marketing"&gt;
&lt;div&gt;
Email Marketing
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;This is an area that there are more and more companies already starting to solve the right problems. Companies like &lt;a href="http://intercom.io"&gt;intercom.io&lt;/a&gt; and &lt;a href="http://customer.io"&gt;customer.io&lt;/a&gt; are allowing for better tracking of what users are doing and notifying them at the &lt;em&gt;right&lt;/em&gt; time instead of via massive impersonal campaigns. Developers build systems that take into account similar factores every day, you should be doing the same.&lt;/p&gt;
&lt;p&gt;Emails that are sent at the wrong time or miss on what someone is trying to do can often do more damage towards building a rapport than good. Pushing content to solve a recent issue or problem at a relevant time should be table stakes for any email thats sent.&lt;/p&gt;
&lt;h3 id="community-engagement"&gt;
&lt;div&gt;
Community Engagement
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Whether at conferences or in online collaborations developers are more social than so many give them credit for. We appreciate when things are done to improve the greater good particularly for developers, but often for the world as well. From supporting individual developers or projects financially such as through &lt;a href="http://www.gittip.com"&gt;gittip&lt;/a&gt; or &lt;a href="http://www.kickstarter.com/projects/andrewgodwin/schema-migrations-for-django"&gt;certain kickstarter projects&lt;/a&gt; all the way to employing developers to &lt;a href="http://www.twitter.com/tenderlove"&gt;work full time on open source&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="being-better-than-webinars"&gt;
&lt;div&gt;
Being Better Than Webinars
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;After doing a webinar for a particular audience I had a &lt;a href="http://www.heroku.com"&gt;Heroku&lt;/a&gt; co-worker come up to me. This individual has contributed many ideas that have become core functionality such as the &lt;a href="#"&gt;Cedar stack&lt;/a&gt; and is generally open minded and listens very well. He came up to me and genuinely asked, &amp;ldquo;so what is a webinar?&amp;rdquo; I explained its like a live webcast with an opportunity for questions at the end. He was quiet for minute and responded, &amp;ldquo;Why can&amp;rsquo;t we just say that?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;There are some words that simply send off the wrong signals. Webinar rather clearly is one of those. As a community we&amp;rsquo;ve shown that we have a desire for this kind of content. The &lt;a href="http://www.lanyrd.com"&gt;conference community&lt;/a&gt; has continued to grow steadily, and while they are many parts to every conference a pretty common one is the talk track itself. A talk at a conference is essentially a live in person webinar, of course the experience is often a bit richer.&lt;/p&gt;
&lt;p&gt;Instead of the term webinar what is wrong with online office hours or webcasts with an opportunity for questions? Even doing the same thing with a different name is underdelivering on what we&amp;rsquo;re capable of.&lt;/p&gt;
&lt;p&gt;I welcome hearing from others directly at &lt;a href="mailto:craig.kerstiens@gmail.com"&gt;craig.kerstiens@gmail.com&lt;/a&gt; on what they&amp;rsquo;re doing to engage with developers thats working. Not only working in the sense of eyeballs or dollars, but in adding value, in improving communities, in make the world better for developers. If there&amp;rsquo;s enough interest would be happy to post more detail around things I&amp;rsquo;ve seen work and what I hear works for others.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Fri, 12 Apr 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/04/12/perspective-on-developer-marketing/</guid></item><item><title>More holes than swiss cheese</title><link>https://tomforb.es/blog/more-holes-than-swiss-cheese/</link><description>tl;dr Never trust user input. Note: Before I published this I contacted the owner of the site and he has since replaced it with a new and more secure version When I browse the net I often see the hallmarks of a security issue with websites that I visit, and little alarm bells go off in my head. I wa...</description><author>Tom Forbes</author><pubDate>Thu, 11 Apr 2013 23:24:30 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/more-holes-than-swiss-cheese/</guid></item><item><title>Profession Talents for Ingenium</title><link>https://benovermyer.com/blog/2013/04/profession-talents-for-ingenium/</link><description>&lt;p&gt;This post presents a prototype profession mechanic we're working on for Ingenium 2nd Edition. We're looking at giving each profession its own Profession Talent to add a little more variety to the game.&lt;/p&gt;
&lt;p&gt;The Priest profession from first edition was pretty…. plain, and there was nothing priestly about her, other than role-playing ques. So with this new mechanic, she gets a Talent that reinforces her role as a messenger of the gods.&lt;/p&gt;
&lt;p&gt;The priest profession from first edition was presented like this:&lt;/p&gt;
&lt;h1 id="priest"&gt;Priest&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Starting Talent Pool:&lt;/strong&gt; Mystic&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Attributes:&lt;/strong&gt; +1 Magical Aptitude&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Speed:&lt;/strong&gt; 3&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hit Points:&lt;/strong&gt; 1d8&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Advancement:&lt;/strong&gt; Healing Arts&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Starting Gold:&lt;/strong&gt; 1d4 x 5&lt;/p&gt;
&lt;p&gt;Priests are those divine focal points who channel their gods' will into physical manifestations. Their magic is not based on arcane rules and laws; rather, they are blessed as Chosen and receive gifts of power for as long as they serve their gods.&lt;/p&gt;
&lt;p&gt;The flavor text stands in Second Edition, but there are a number of changes. Here's the new Priest block:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Starting Talent Pool:&lt;/strong&gt; White Magic&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Attribute Bonus:&lt;/strong&gt; +1 Magical Aptitude&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hit Die:&lt;/strong&gt; d6&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Talent:&lt;/strong&gt; Exorcism&lt;/p&gt;
&lt;h2 id="exorcism"&gt;Exorcism&lt;/h2&gt;
&lt;p&gt;The Priest has the divine gift and knowledge to pull a demon out of a possession victim. She makes a Willpower roll against the demon's Challenge Level, and if the total is higher, the demon vacates the possessed body as a cloud of roiling black smoke. The victim then returns to his original stats, and if this causes any damage he has sustained to exceed his normal maximum Hit Points, he dies instantly. If his Willpower was at least half of the demon's, he remembers everything he did while possessed. A failed exorcism increases the Challenge Level of the target demon by 1.&lt;/p&gt;
&lt;h1 id="about-profession-talents"&gt;About Profession Talents&lt;/h1&gt;
&lt;p&gt;Every profession gets a unique Talent with this mechanic, and one that scales with the character's power. She will never out-level her profession Talent.&lt;/p&gt;
&lt;p&gt;Also, by adding “Profession Talents,” we add another option for expansion down the road.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sat, 06 Apr 2013 03:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/04/profession-talents-for-ingenium/</guid></item><item><title>Unlocking Hillsborough</title><link>https://3059274a.danpalmer-me.pages.dev/2013-04-06-unlocking-hillsborough/</link><description>&lt;p&gt;I&amp;rsquo;m writing this on the train home from &lt;a href="http://rewiredstate.org"&gt;Rewired State&lt;/a&gt;&amp;rsquo;s latest event: &lt;a href="http://rewiredstate.org/hacks/national-hack-the-government-2013"&gt;National Hack the Government Day 2013&lt;/a&gt; (&lt;a href="http://eventifier.co/event/nhtg13/"&gt;event summary page&lt;/a&gt;). It was another great event with the same friendly atmosphere that goes along with so many (especially Rewired State&amp;rsquo;s) developer events. My friend &lt;a href="http://twitter.com/elliotjh"&gt;Elliot&lt;/a&gt; and I won in one of the categories, and so this post is mostly about what we did, how we did it, and why we think it&amp;rsquo;s important.&lt;/p&gt;</description><author>Dan Palmer</author><pubDate>Sat, 06 Apr 2013 02:00:00 GMT</pubDate><guid isPermaLink="true">https://3059274a.danpalmer-me.pages.dev/2013-04-06-unlocking-hillsborough/</guid></item><item><title>Why I Blog</title><link>/2013/03/31/Why-I-Blog/</link><description>&lt;p&gt;I blog because I&amp;rsquo;m lazy. There&amp;rsquo;s more too it though: In any given day I may explain something to someone, the first time I do this I make a bit of a mental note. The second time I do this, especially within a short time frame I make a physical note of this in the form of the title of a blog post. Once I&amp;rsquo;m already to a second time of doing this its almost inevitable I&amp;rsquo;ll continue repeating myself – and its valuable to others.&lt;/p&gt;
&lt;h3 id="becoming-replaceable"&gt;
&lt;div&gt;
Becoming replaceable
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;My goal in doing this is actually to become heavily replaceable. Keeping information locked away means I&amp;rsquo;m the only one capable of doing it. Making myself highly replaceable means I can continue to work on new and interesting things.&lt;/p&gt;
&lt;h3 id="lots-can-be-shared"&gt;
&lt;div&gt;
Lots can be shared
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;I don&amp;rsquo;t recall exactly where I read it, I believe it may have been &lt;a href="http://www.twitter.com/monkchips"&gt;James Governor&lt;/a&gt;, but any email that doesn&amp;rsquo;t contain proprietary info or trade secrets should be blogged. I fully expect the sentiment around this is something to the effect that anything that contains good ideas/learning/processes can also be helpful to others.&lt;/p&gt;
&lt;h3 id="distilling-information"&gt;
&lt;div&gt;
Distilling information
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;For every time I explain something I often linger about one piece too long, hit something that doesn&amp;rsquo;t need to be discussed, or miss something entirely. Putting an idea or guide together in written form you re-read it, which is hard to do when simply verbally explaining. If you&amp;rsquo;ve video taped yourself before for public speaking practice you know this is an awkward but valuable experience. Its much easier to practice as an exercise in writing.&lt;/p&gt;
&lt;h3 id="economies-of-scale"&gt;
&lt;div&gt;
Economies of scale
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;While in some ways I am absolutely lazy when I blog I get economies of scale I couldn&amp;rsquo;t otherwise have. On a given day on a high day I may have 15 one on one conversations. Every post has the opportunity to become a one on one conversation.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;One on one conversation is my preferred method instead of in a large group. In a related area I&amp;rsquo;ve been having an ongoing conversation wth &lt;a href="http://www.twitter.com/rwdaigle"&gt;Ryan Daigle&lt;/a&gt; on whether blog posts should have comments. I opt for having you reach out to me directly via &lt;a href="mailto:craig.kerstiens@gmail.com"&gt;email&lt;/a&gt;, he believes comments should be available. Putting this in words crystalizes that to me its just relative to how you prefer to interact.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="summary"&gt;
&lt;div&gt;
Summary
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;As with any other post, this is one conversation I&amp;rsquo;ve now had a few times over. Hopefully this gives some basis to why I feel others should contribute content as well. Whether you want make your self dispensible, refine your thoughts, or reach new economies of scale I believe its a worthwhile exercise for many. If you have other reasons you feel its valuable as always please &lt;a href="mailto:craig.kerstiens@gmail.com"&gt;reach out&lt;/a&gt;.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Sun, 31 Mar 2013 23:55:56 GMT</pubDate><guid isPermaLink="true">/2013/03/31/Why-I-Blog/</guid></item><item><title>Being Defiant: Finishing Out Rift's Free Tier</title><link>https://benovermyer.com/blog/2013/03/being-defiant-finishing-out-rifts-free-tier/</link><description>&lt;p&gt;Today is the last day of March and the last day I'll be writing about the MMORPG Rift as it applies to tabletop RPGs. If you've missed any of these posts, you might want to check them out. Go ahead, I'll wait.&lt;/p&gt;
&lt;p&gt;This post is a retrospective and has little to do with tabletop RPGs. If you're just looking for new ways to experience your favorite RPG, come back next week – I've got something very interesting planned!&lt;/p&gt;

&lt;img class="photo" src="https://benovermyer.com/blog/2013/03/being-defiant-finishing-out-rifts-free-tier/&amp;#x2F;&amp;#x2F;benovermyer.com&amp;#x2F;processed_images&amp;#x2F;rift-sidious.0a3618da0dec8507.jpg" /&gt;
&lt;p&gt;Generally, it takes me about one month to get bored of an MMORPG. I'll steep myself in the lore, powerlevel up to about 75-90% of endgame, get involved in crafting, and then… burn out. The novelty factor wears off, and I stop playing.&lt;/p&gt;
&lt;p&gt;Most of the time, it's not a conscious decision to stop playing. I'll just go a day without playing the game, since I find something else I want to do more that one day. Then two days go by. Then three. Before I realize it, it's been over a week since I last logged in, and I have no intention of going back.&lt;/p&gt;
&lt;p&gt;A rare handful of MMORPGs keep my interest for longer than that. The list so far has been Star Wars: Galaxies and World of Warcraft. Now, I'm adding Rift to the list.&lt;/p&gt;

&lt;img class="photo" src="https://benovermyer.com/blog/2013/03/being-defiant-finishing-out-rifts-free-tier/&amp;#x2F;&amp;#x2F;benovermyer.com&amp;#x2F;processed_images&amp;#x2F;rift-amun.bb92924a55ecf1be.jpg" /&gt;
&lt;p&gt;I originally reinstalled the game because it was going to be free and I'd heard good things about Dimensions. So, I did, and started this blog series to tie the game to tabletop gaming. It just clicked. The novelty factor has worn off, and I'm still playing. That bodes well for its longevity, and I'm going to resubscribe.&lt;/p&gt;
&lt;p&gt;The Dimensions are awesome. The fishing is weirdly addictive. And playing an MMO with a great and friendly community is refreshing.&lt;/p&gt;
&lt;p&gt;If you're interested in trying it out, jump on the Faeblight server and look me up. I'll be playing either my Eth cleric Amun or my Kelari mage Sidious.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sun, 31 Mar 2013 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/03/being-defiant-finishing-out-rifts-free-tier/</guid></item><item><title>Being Defiant: Currencies Beyond Gold and Silver</title><link>https://benovermyer.com/blog/2013/03/being-defiant-currencies-beyond-gold-and-silver/</link><description>&lt;p&gt;In Rift, there are five ways to acquire new armor and weapons. You can take it from the corpses of monsters you kill. You can run through dungeons, collecting new pieces from the tougher monsters and bosses. You can run from rift to rift, defeating the planar invaders and getting new gear from the rift rewards. You can craft it or purchase it from other players who craft gear. You can also use special currencies earned through various means to purchase new gear from special NPC merchants.&lt;/p&gt;
&lt;p&gt;In existing tabletop RPGs, there are really only three ways to get gear – buying it from merchants, looting bodies, and finding it lying around in dungeons.&lt;/p&gt;
&lt;p&gt;Many MMORPG loot mechanics won't work in a tabletop RPG because the gear just appears in the player's inventory when certain conditions are met. In a tabletop game, gear rarely just appears. I've touched on crafting in tabletop RPGs before, so this time around I'll focus on special currencies.&lt;/p&gt;
&lt;h1 id="rift-s-currency-for-planar-invasions"&gt;Rift's Currency for Planar Invasions&lt;/h1&gt;
&lt;p&gt;In games like Rift and World of Warcraft, you receive units of these currencies for achieving feats of excellence. For example, in Rift, you earn “planarite” and “sourcestone” for defeating planar invaders. Sourcestone is much rarer than planarite, each unit of its most common version being worth 50 planarite. It's only awarded for helping defeat special rift events like full invasions.&lt;/p&gt;
&lt;img alt="A screenshot of the currencies tab in Rift" class="photo" src="https://benovermyer.com/blog/2013/03/being-defiant-currencies-beyond-gold-and-silver/currencies-tab.jpg" /&gt;
&lt;p&gt;While there's only one version of planarite, there are multiple types of sourcestone, each being dropped by progressively more difficult planar invaders. In order to get the higher sourcestones, you must defeat higher-level invaders.&lt;/p&gt;
&lt;p&gt;All of these can be traded in for impressive, rare gear. The best items cost a combination of sourcestone and planarite.&lt;/p&gt;
&lt;h1 id="how-to-deal-with-special-currencies-in-tabletop-games"&gt;How to Deal with Special Currencies in Tabletop Games&lt;/h1&gt;
&lt;p&gt;In tabletop RPGs, by comparison, you're looking at a single currency – gold, credits, silver, whatever. In some games there are multiple types of currency but only one “track.” For example, in Dungeons &amp;amp; Dragons, you have copper, silver, electrum, gold, and platinum, but they're all just higher denominations of each other. This currency is accepted everywhere from all merchants.&lt;/p&gt;
&lt;p&gt;To make sense, a unique currency needs to be widespread in use and creation, and to make sense in a setting, the powers-that-be need to allow that currency to exist alongside the official currency of the realm. That last part is historically difficult to come by, but in fictional worlds, we can gloss over that fact.&lt;/p&gt;
&lt;p&gt;The best reason to include a currency like this is to gate powerful gear behind difficult tasks. It also provides a way to uniquely theme gear and work in factional alliances and reputation.&lt;/p&gt;
&lt;p&gt;You could make up a large order dedicated to service to a particular god, for example. Instead of just being all priests or all paladins, this order could include a variety of skilled craftsmen who produce special gear. The craftsmen may only part with the gear in exchange for a special currency that only the order uses. Higher-ranking members of this order may be giving the PCs quests, and in gratitude for their help, rewards them with some of the order's currency.&lt;/p&gt;
&lt;p&gt;This also offers role-playing opportunities, oddly enough. Possession of particular currencies could trigger interesting reactions from NPCs. Maybe they're associated with the producer of the currency. Maybe they're afraid of the producer. Maybe it's more complicated than that.&lt;/p&gt;
&lt;p&gt;If it makes sense for your setting, try adding a special currency and unique rewards for that currency to your next adventure. It just might take your campaign in a very interesting direction.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sun, 24 Mar 2013 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/03/being-defiant-currencies-beyond-gold-and-silver/</guid></item><item><title>Bird Watching</title><link>https://blog.nawaz.org/posts/2013/Mar/bird-watching/</link><description>&lt;p&gt;A friend of mine recently took his bird watching hobby to another
level. Armed with a 400mm lens, a scope and a sturdy tripod, he and his
wife scour the local area for birds. The absence of leaves makes it
easier to find them. &lt;a class="footnote-reference" href="#footnote-1" id="footnote-reference-1"&gt;[1]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I met up with them …&lt;/p&gt;</description><author>Beetle Space</author><pubDate>Fri, 15 Mar 2013 09:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.nawaz.org/posts/2013/Mar/bird-watching/</guid></item><item><title>Prioritizing and Planning within Heroku Postgres</title><link>/2013/03/13/planning-and-prioritizing/</link><description>&lt;p&gt;Over a year ago I blogged about Heroku&amp;rsquo;s approach to &lt;a href="http://www.craigkerstiens.com/2011/11/02/how-heroku-works-teams-tools/"&gt;Teams and Tools&lt;/a&gt;. Since that time Heroku has grown from around 25 people to over 100, we&amp;rsquo;ve continued to iterate and find new tools that work for how we do things. For many of the &lt;a href="http://www.amazon.com/Inspired-Create-Products-Customers-Love/dp/0981690408?ref=as_li_tf_tl?ie=UTF8&amp;amp;tag=mypred-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0932633439"&gt;product management&lt;/a&gt; and software engineering books I&amp;rsquo;ve read I&amp;rsquo;ve yet to find something that helps a team priorize in a fashion I that feels right.&lt;/p&gt;
&lt;p&gt;One process emerged nearly a year ago from within the &lt;a href="https://postgres.heroku.com"&gt;Heroku Postgres&lt;/a&gt; team and is now followed by many others. Within a team this process is now commonly conducted each 6 months. Lets take a look at how this process looks&lt;/p&gt;
&lt;h3 id="it-starts-with-ideas"&gt;
&lt;div&gt;
It Starts with Ideas
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Hopefully having ideas of things to work on isn&amp;rsquo;t a problem, if it is just go spend some time with customers – listen to their problems, see how they use the product, then come back and write down the ideas. For most teams this is simply an excercise of thinking back and writing it down. Some teams at Heroku have resorted to keeping running backlogs of things they&amp;rsquo;d like to do this. We do this by keeping a Trello board which columns for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New ideas&lt;/li&gt;
&lt;li&gt;Ponies&lt;/li&gt;
&lt;li&gt;Stallions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Ponies and Stallions are things that would be great to do, however a sizeable amount of work must be done on them and we&amp;rsquo;re not currently tackling them. Ponies are less sizeable and likely to get done not in coming weeks but perhaps in coming months up to a year. Stallions are great but large effort and may or may not get done but in the category of things we would like to be able to do.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;ve got your ideas whether in your head on a backlog we begin by writing them out typically on sticky notes or index cards.&lt;/p&gt;
&lt;h3 id="laying-it-all-out"&gt;
&lt;div&gt;
Laying it all out
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;From here we create a simple grid:&lt;/p&gt;
&lt;p&gt;&lt;img alt="grid" src="https://f.v1.n0.cdn.getcloudapp.com/items/1x1J2u0g390C1u1A1R1a/Screenshot_3_8_13_10_37_AM.png" /&gt;&lt;/p&gt;
&lt;p&gt;The grid has two axis. One is for impact the other for difficulty. At this point we aim to lay out every idea that we&amp;rsquo;ve already written down into a quadrant. Commonly this is done at team offsites where the team is free of distractions and able to devote appropriate time to it. Being able to accomplish this in one sitting with the team is important to having cohesion around the result.&lt;/p&gt;
&lt;h3 id="a-plan"&gt;
&lt;div&gt;
A plan
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;At this point hopefully its quite obvious what you want to tackle. If there&amp;rsquo;s anything in the top right it should be an easy win for something for you to focus on. From we often transcribe this into a powerpoint/keynote document and highlight things that we will definitely aim to accomplish in the next 6 months as well as things we&amp;rsquo;re intentionally not working on. This leaves us with an artifact of both things we will work on and explicit things we wont work on.&lt;/p&gt;
&lt;p&gt;&lt;img alt="grid" src="https://f.v1.n0.cdn.getcloudapp.com/items/2J3K2E0q2z2P0y0C0M3B/Screenshot_3_9_13_8_45_AM.png" /&gt;&lt;/p&gt;
&lt;h3 id="what-works-for-us"&gt;
&lt;div&gt;
What works for us
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;In general we try to have more work than we can tackle to ensure we&amp;rsquo;re constrained in a good form and not wasting idle time of people. Ensuring we&amp;rsquo;re selective about the things we&amp;rsquo;re working on and that we&amp;rsquo;re working on the right things works for us. We&amp;rsquo;ve found this simple exercise valuable for many teams to plan and ensure we&amp;rsquo;re working on those right things. Of course this may not work for everyone but for our goals and culture aligns well for us.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;ve got simple but unique techniques that work for your team as always would love to hear about them – &lt;a href="mailto:craig.kerstiens@gmail.com"&gt;craig.kerstiens@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Wed, 13 Mar 2013 22:55:56 GMT</pubDate><guid isPermaLink="true">/2013/03/13/planning-and-prioritizing/</guid></item><item><title>Just how slow are Django templates?</title><link>https://tomforb.es/blog/just-how-slow-are-django-templates/</link><description>Edit 2: I made a Django debug toolbar panel that profiles your Django templates and all their components. You can find it here: https://pypi.python.org/pypi/django-debug-toolbar-template-timings Edit: It appears that Django does have some form of template caching. The graphs have been updated to inc...</description><author>Tom Forbes</author><pubDate>Wed, 13 Mar 2013 20:17:38 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/just-how-slow-are-django-templates/</guid></item><item><title>Fixing Database Connections in Django</title><link>/2013/03/07/Fixing-django-db-connections/</link><description>&lt;p&gt;If you&amp;rsquo;re looking to get better performance from your Django apps you can check out &lt;a href="http://www.amazon.com/Pro-Django-Experts-Voice-Development/dp/1430210478?ref=as_li_tf_tl?ie=UTF8&amp;amp;tag=mypred-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0932633439"&gt;Pro Django&lt;/a&gt;, &lt;a href="http://www.amazon.com/PostgreSQL-High-Performance-Gregory-Smith/dp/184951030X?ref=as_li_tf_tl?ie=UTF8&amp;amp;tag=mypred-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0932633439"&gt;PostgreSQL High Performance&lt;/a&gt;, or read some my earlier posts on &lt;a href="http://www.craigkerstiens.com/2013/01/10/more-on-postgres-performance/"&gt;Postgres Performance&lt;/a&gt;. All of these are of course good things to do – you can also start by correcting an incredibly common but also painful performance issue, that until 1.6 is unaddressed in Django.&lt;/p&gt;
&lt;p&gt;Django&amp;rsquo;s current default behavior is to establish a connection for each request within a Django application. In many cases any particularly in distributed cloud environments this is a large time sink of your response time. An example application running on &lt;a href="http://www.heroku.com"&gt;Heroku&lt;/a&gt; shows a typical connection time of 70ms. A large part of this time is the SSL negotiation that occurs in connecting to your database, &lt;em&gt;which is a good practice to ensure security of your data&lt;/em&gt;. Regardless, this is a long time in simply establishing a connection. As a point of comparisson its commonly encourage that most queries to your database are under 10ms.&lt;/p&gt;
&lt;p&gt;An example that highlights this in a small lightweight application shows the bulk of a request time being within a connection displayed by &lt;a href="http://www.newrelic.com"&gt;New Relic&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="connection time" src="https://f.cl.ly/items/0X3u0e3Q3G0L19263k2Z/Screenshot_3_6_13_1_12_PM.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="connection time" src="https://f.cl.ly/items/1h2w450F3n0X1m1c0S38/Screenshot_2_22_13_3_18_PM-2.png" /&gt;&lt;/p&gt;
&lt;p&gt;One option to remedy this is by running a connection pooler on your Database side such as &lt;a href="http://www.pgpool.net/mediawiki/index.php/Main_Page"&gt;Pgpool&lt;/a&gt; or &lt;a href="http://pgfoundry.org/projects/pgbouncer"&gt;PgBouncer&lt;/a&gt;. In fact &lt;a href="http://www.askthepony.com/blog/2011/07/getting-django-on-heroku-prancing-8-times-faster/"&gt;Ask the Pony&lt;/a&gt; already highlighted these potential gains. While running an external DB they&amp;rsquo;re essentially testing the benefits of conncetion pooling. This is an obvious gain and can be in a much more lightweight format.&lt;/p&gt;
&lt;h3 id="connection-pooling-in-django"&gt;
&lt;div&gt;
Connection Pooling in Django
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;As Django establishes a connection on each request it has an opportunity to both pool connections and persist connections. There are two major options for pooling, each works quite well with Django and provides some dramatic improvements. While the first request may take the 70ms of connection time, subsequent requests show absolutely no connection time since the connection already exists. This is highlighed by these two comparissons of before and after in actually the times it grabs a connection:&lt;/p&gt;
&lt;p&gt;&lt;img alt="before" src="https://f.cl.ly/items/2H0J2x3P2L2K2n0M3i38/Screen_Shot_2013-02-22_at_8.28.21_PM.png" /&gt;
&lt;img alt="after" src="https://f.cl.ly/items/0T1l1I03433u0c0t3e2o/Screen_Shot_2013-02-22_at_8.28.36_PM.png" /&gt;&lt;/p&gt;
&lt;p&gt;Clearly theres plenty of value to having a persistent connection or a pool within Django itself. As of today theres a few options for that:&lt;/p&gt;
&lt;h3 id="django-postgrespool"&gt;
&lt;div&gt;
Django-PostgresPool
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;The first &lt;a href="https://github.com/kennethreitz/django-postgrespool"&gt;Django-PostgresPool&lt;/a&gt; is created by &lt;a href="http://twitter.com/kennethreitz"&gt;kennethreitz&lt;/a&gt;. As in general I&amp;rsquo;d encourage the use of &lt;a href=""&gt;dj_database_url&lt;/a&gt; you can easily begin using his package (once installed) with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import dj_database_url
DATABASE = { 'default': dj_database_url.config() }
DATABASES['default']['ENGINE'] = 'django_postgrespool'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An important thing to note is if you&amp;rsquo;re using &lt;a href="http://south.aeracode.org/"&gt;South&lt;/a&gt; you&amp;rsquo;ll also want to setup the adapter for it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SOUTH_DATABASE_ADAPTERS = {
'default': 'south.db.postgresql_psycopg2'
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="djorm-ext-pool"&gt;
&lt;div&gt;
djorm-ext-pool
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;The second option &lt;a href="https://github.com/niwibe/djorm-ext-pool"&gt;djorm-ext-pool&lt;/a&gt; is created by &lt;a href="http://twitter.com/niwibe"&gt;niwibe&lt;/a&gt;. Once you&amp;rsquo;ve installed &lt;code&gt;djorm-ext-pool&lt;/code&gt; you then add it to your &lt;code&gt;INSTALLED_APPS&lt;/code&gt; within your &lt;code&gt;settings.py&lt;/code&gt;. From here then you can setup your pool:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;DJORM_POOL_OPTIONS = {
&amp;quot;pool_size&amp;quot;: 20,
&amp;quot;max_overflow&amp;quot;: 0
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="django-db-pool"&gt;
&lt;div&gt;
django-db-pool
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;The third and final option is &lt;a href="https://github.com/gmcguire/django-db-pool"&gt;django-db-pool&lt;/a&gt;. You can set it up with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;DATABASES = {'default': dj_database_url.config()}
DATABASES['default']['ENGINE'] = 'dbpool.db.backends.postgresql_psycopg2'
DATABASES['default']['OPTIONS'] = {
'MAX_CONNS': 10
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="gotchas"&gt;
&lt;div&gt;
Gotchas
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Each of these does work with recent versions of Django, though in some cases there are gotchas. If using a prodution worthy python web server such as Gunicorn or uwsgi and running with gevent or eventlet some edge cases can present themselves. Regardless of potential gotchas it is worth attempting this and of course providing feedback to maintainers and the community as you find those.&lt;/p&gt;
&lt;h3 id="the-future"&gt;
&lt;div&gt;
The future
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Django more recently has directly started to address these issues of large costs of establishing a connection. The first major step here is &lt;a href="https://github.com/django/django/commit/2ee21d"&gt;this patch&lt;/a&gt; from &lt;a href="http://twitter.com/aymericaugustin"&gt;Aymeric&lt;/a&gt;. You can find more dicussion around this particular patch &lt;a href="https://groups.google.com/forum/#!topic/django-developers/NwY9CHM4xpU/discussion"&gt;here&lt;/a&gt;. Essentially with this patch which will hit in Django 1.6 developers then get a persistent connection which will help reduce the time. If you&amp;rsquo;re interested in trying the 1.6 master you can do this by adding it to your requirements.txt as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https://github.com/django/django/archive/master.zip
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point it does not introduce pooling which could allow even more gains, though I&amp;rsquo;m sure if there&amp;rsquo;s enough need it&amp;rsquo;ll be on a roadmap at some point. Though, as it stands today before 1.6 your best bet is one of the above options.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 07 Mar 2013 22:55:56 GMT</pubDate><guid isPermaLink="true">/2013/03/07/Fixing-django-db-connections/</guid></item><item><title>Simple database read scaling without sharding in rails</title><link>/2013/03/06/Simple-database-read-scaling-without-sharding-in-rails/</link><description>&lt;p&gt;In an earlier post I provided a high level &lt;a href="http://www.craigkerstiens.com/2012/11/30/sharding-your-database/"&gt;overview of sharding&lt;/a&gt;. Sharding while a very solid approach to scaling capacity versus simply only relying on vertical scaling can also be a time intensive one. Additionally in some cases certain sites may only need extra capacity for a short lived period of time. Fortunately theres a nice middle ground alternative for scaling capacity that works well in quite a few cases. It even has a benefit that can potentially in place of sharding.&lt;/p&gt;
&lt;p&gt;This method results in scaling your reads to replica databases, you can do this on Heroku by taking advantage of followers. A follower is a read only database on Heroku Postgres that receives asynchronous updates of your data usually only lagging a very few commits behind. This means you can write all of your data to the leader (main) database, and then read from another.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;While you can arbitrarily do this there&amp;rsquo;s some major benefits to doing it based on the models. This is because Postgres maintains a cache on each instance its running on. Though you may have the same dataset, Postgres maintains frequently accessed or queried data in the cache giving you better performance. For more on this you can read earlier posts on &lt;a href="http://www.craigkerstiens.com/2012/11/30/sharding-your-database/"&gt;PostgreSQL Performance&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="setting-it-up-with-rails"&gt;
&lt;div&gt;
Setting it up with Rails
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;With a follower database created you can begin adding support for this to your application. The first thing is to add the gem to your Gemfile:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gem 'ar-octopus', :require =&amp;gt; &amp;quot;octopus&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then of course to install it with &lt;code&gt;bundle install&lt;/code&gt;. Now we can actually begin to add the code needed to have specific models access the follower.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;octopus:
shards:
shard_sqlite:
adapter: sqlite3
database: db/db_one.sqlite3
pool: 5
timeout: 5000
shard_pgsql:
adapter: postgresql
username: postgres
password:
database: db_two
encoding: unicode
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;a&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Project &amp;lt; ActiveRecord::Base
octopus_establish_connection(:adapter =&amp;gt; &amp;quot;sqlite3&amp;quot;, :database =&amp;gt; &amp;quot;db_one&amp;quot;)
end&lt;/code&gt;&lt;/pre&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Wed, 06 Mar 2013 22:55:56 GMT</pubDate><guid isPermaLink="true">/2013/03/06/Simple-database-read-scaling-without-sharding-in-rails/</guid></item><item><title>Finding fried chicken with C-Sharp, Mono and ServiceStack</title><link>https://tomforb.es/blog/finding-fried-chicken-with-c-mono-and-servicestack/</link><description>I think I just solved a very first world problem - Where to find the nearest takeaway that sells fried chicken. When you are stumbling out of Spiders at 1am in the morning and craving some SFC goodness the last thing you want to do is wander the backstreets of hull in the cold looking for an open ta...</description><author>Tom Forbes</author><pubDate>Sat, 02 Mar 2013 23:57:06 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/finding-fried-chicken-with-c-mono-and-servicestack/</guid></item><item><title>Why Code Search is Difficult</title><link>https://boyter.org/2013/02/why-code-search-is-difficult/</link><description>&lt;p&gt;I was chatting with a colleague the other day and he was asking me why code search is a difficult problem. After all its not quite as dynamic as the web so it should be easier to index.&lt;/p&gt;
&lt;p&gt;In truth its a mixed bag. Some things like like crawling are easy, others such as indexing are much harder then you would think. I thought I would write down why this is.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Fri, 01 Mar 2013 01:26:36 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/02/why-code-search-is-difficult/</guid></item><item><title>Getting more out of psql (The PostgreSQL CLI)</title><link>/2013/02/21/more-out-of-psql/</link><description>&lt;p&gt;&lt;em&gt;After my last post I had a variety of readers reach out about many different tweaks they&amp;rsquo;d made to their workflows using with psql. One people &lt;a href="https://github.com/chanmix51/"&gt;Grégoire Hubert&lt;/a&gt; had a wondeful extensive list of items. Grégoire has been a freelance in web development and he has worked with Postgresql for some time now in addition to being the author of Pomm. Without further ado heres what he has to say on how he uses psql:&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="get-the-most-of-psql"&gt;
&lt;div&gt;
Get the most of psql
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;Psql, the CLI postgreSQL client, is a powerful tool. Sadly, lot of developers are not aware of the features and instead look for a GUI to provide what they need. Let&amp;rsquo;s fly over what can psql do for you.&lt;/p&gt;
&lt;h2 id="feel-yourself-at-home"&gt;
&lt;div&gt;
Feel yourself at home
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;One of the most common misconception people have about CLI is «They are a poor user interface». C&amp;rsquo;mon, the CLI is &lt;strong&gt;the most efficient user interface ever&lt;/strong&gt;. There is nothing to disturb you from what you are doing and you are by far fastest without switching to your mouse all the time. Let&amp;rsquo;s see how we can configure psql at our convenience.&lt;/p&gt;
&lt;p&gt;First, you&amp;rsquo;ll have managed to choose a nice and fancy &lt;a href="http://hivelogic.com/articles/top-10-programming-fonts"&gt;terminal font&lt;/a&gt; like monofur or inconsolata. Do not underestimate the power of the font&lt;/p&gt;
&lt;p&gt;&lt;img alt="monofur font in action" src="https://public.coolkeums.org/github/power_font.png" /&gt;&lt;/p&gt;
&lt;p&gt;The nice line style shown above can be set with &lt;code&gt;\pset linestyle unicode&lt;/code&gt; and &lt;code&gt;\pset border 2&lt;/code&gt;. This is just an example of the many environment variables you can play with to get your preferred style of working out of psql.&lt;/p&gt;
&lt;p&gt;For example, I found the character ¤ the most accurate to express nullity (instead of default &lt;code&gt;NULL&lt;/code&gt;). Let&amp;rsquo;s just &lt;code&gt;\pset null ¤&lt;/code&gt; and here it is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT * FROM very_interesting_stat;
┌──────┬──────┬──────┬──────┬──────┐
│ a │ b │ c │ d │ e │
├──────┼──────┼──────┼──────┼──────┤
│ 9.06 │ ¤ │ ¤ │ ¤ │ ¤ │
│ 7.30 │ 3.55 │ 7.57 │ 3.31 │ ¤ │
│ 7.20 │ 5.08 │ ¤ │ 6.58 │ 5.90 │
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another hugely value to get environment variables is colors in the prompt. Colors in the prompt are important because it makes easier to spot where output starts and ends between two interactions at the console. The &lt;a href="http://www.postgresql.org/docs/9.2/static/app-psql.html#APP-PSQL-PROMPTING"&gt;PROMPT1&lt;/a&gt; environment variable will even let you set an indicator to notify you are inside a transaction or not, give this a try for a sweet surprise&amp;hellip;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\set PROMPT1 '%[%033[33;1m%]%x%[%033[0m%]%[%033[1m%]%/%[%033[0m%]%R%# '
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I also like to disable the pager by default &lt;code&gt;\pset pager off&lt;/code&gt; and display the time every issued query takes &lt;code&gt;\timing&lt;/code&gt;. If you are used to psql, you may notice in the picture above, some content is wrapped. This is &lt;code&gt;\pset format wrapped&lt;/code&gt; option.&lt;/p&gt;
&lt;p&gt;Of course, writing all that on every connection would be a pain, so just write them in a &lt;code&gt;~/.psqlrc&lt;/code&gt; file, it will be sourced every time psql is launched.&lt;/p&gt;
&lt;p&gt;If you are familiar with &lt;code&gt;bash&lt;/code&gt; or other recent unix shells, you might also declare aliases in your configuration file. You can do the same with psql. For example if you want to have a query for slow queries such as from this &lt;a href="/2013/01/10/more-on-postgres-performance/"&gt;earlier post&lt;/a&gt; but not have to remember the query every time you can set it up as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\set show_slow_queries
'SELECT
(total_time / 1000 / 60) as total_minutes,
(total_time/calls) as average_time, query
FROM pg_stat_statements
ORDER BY 1 DESC
LIMIT 100;'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, just entering &lt;code&gt;:show_slow_queries&lt;/code&gt; in your psql client will launch this query and give you the results:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; total_time | avg_time | query
------------------+------------------+------------------------------------------------------------
295.761165833319 | 10.1374053278061 | SELECT id FROM users WHERE email LIKE ?
219.138564283326 | 80.24530822355305 | SELECT * FROM address WHERE user_id = ? AND current = True
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="psql-at-your-fingertips"&gt;
&lt;div&gt;
Psql at your fingertips
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;Now you have got a fancy prompt, here is the real question you ask, what can psql do for me ? and &lt;code&gt;\?&lt;/code&gt; has all of the answers. It has built-in queries to describe almost all database objects from tables to operators, indexes, triggers etc&amp;hellip; with clever auto-completion. Not only completion on tables and columns &amp;ndash; but also on aliases (sweet), &lt;strong&gt;SQL commands&lt;/strong&gt; (w00t) and database objects.&lt;/p&gt;
&lt;p&gt;Now we can enter some SQL commands. As usual, you need to check in the documentation how the heck to write this damn &lt;code&gt;ALTER TABLE&lt;/code&gt;. Relax, psql proposes inline documentation. Just enter &lt;code&gt;\h alter table&lt;/code&gt; (auto complete w00t) and you ll be ok.&lt;/p&gt;
&lt;h3 id="interacting-with-your-editor"&gt;
&lt;div&gt;
Interacting with your editor
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;psql provides two very handy commands: \e and \i. This last command sources a sql file in the client&amp;rsquo;s current session. \e edits the last command using the editor defined in the &lt;code&gt;EDITOR&lt;/code&gt; shell environment variables (aka vim). This grant you with real editor feature when it comes to writing long queries. What psql does, it saves the buffer in a temporary file and fires up the editor with that file. Once the editor is terminated, psql sources the file. Of course, you can use your editor to save queries in other places where they would be under version control, but the \e has a serious limitation: it spawns only the last query. Even if you sent several queries on the same line. (Note that \r clears psql&amp;rsquo;s last query buffer).&lt;/p&gt;
&lt;p&gt;Note: &lt;code&gt;\ef my_function&lt;/code&gt; opens stored function source code (With auto completion, I know, it&amp;rsquo;s awesome).&lt;/p&gt;
&lt;p&gt;Vim users can here benefit from Vim&amp;rsquo;s server mode. If you launch a vim specifying a server name (let&amp;rsquo; say &amp;ldquo;PSQL&amp;rdquo;) somewhere, and set the EDITOR variable as is &lt;code&gt;export EDITOR=&amp;quot;vim --servername PSQL --remote-tab-wait&lt;/code&gt; then psql will open a new tab on the running vim with the last query and run it as soon as you close this tab. Tmux or gnu/screen users will split their screen to have Vim and psql running on the same terminal window.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Vim, psql and tmux" src="https://public.coolkeums.org/github/vim_tmux.png" /&gt;&lt;/p&gt;
&lt;h3 id="call-a-friend"&gt;
&lt;div&gt;
Call a friend
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Vim power users know it is possible to pipe a buffer (or selection) directly in a program that can be &amp;hellip; psql (Using the &lt;code&gt;:w !psql&lt;/code&gt; syntax). Even from the shell, you might want to take advantage of the fantastic &lt;code&gt;\copy&lt;/code&gt; feature that loads formated file in the database (I use it to load apache logs). But always having to specify connection parameters are a hassle. Let&amp;rsquo;s use shell environment instead. Psql is sensitive to the following variables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PGDATABASE&lt;/li&gt;
&lt;li&gt;PGHOST&lt;/li&gt;
&lt;li&gt;PGPORT&lt;/li&gt;
&lt;li&gt;PGUSER&lt;/li&gt;
&lt;li&gt;PGCLUSTER (debian wrapper).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Set them once for all in you shell environment and call &lt;code&gt;psql&lt;/code&gt; to connect to the database. In case you want to skip password prompt, you can store your pass in a 600 mode access file named &lt;code&gt;.pgpass&lt;/code&gt; in your home (do not do that on shared or exposed computers). Although this is nice for development database servers, I do NOT recommend this for production servers since it should not be easy to mess with them.&lt;/p&gt;
&lt;p&gt;Resource for additional information is &amp;hellip; the man page and &lt;a href="http://www.postgresql.org/docs/9.2/static/index.html"&gt;Postgres Docs&lt;/a&gt;. All &lt;a href="http://www.postgresql.org/docs/9.2/static/index.html"&gt;PostgreSQL documentation&lt;/a&gt; is an example of what software reference documentation should be. Enjoy!&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 21 Feb 2013 22:55:56 GMT</pubDate><guid isPermaLink="true">/2013/02/21/more-out-of-psql/</guid></item><item><title>HtmlToWord</title><link>https://tomforb.es/blog/htmltoword/</link><description>You can find the code here on github and the package here on PyPi I have written and continue to maintain a reporting system for a group of pentesters. During/after the tests the results and details are inputted into a web application using a WYSIWYG editor called Redactor (which is pretty awesome!)...</description><author>Tom Forbes</author><pubDate>Mon, 18 Feb 2013 07:38:08 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/htmltoword/</guid></item><item><title>How I work with Postgres – psql, My PostgreSQL Admin</title><link>/2013/02/13/How-I-Work-With-Postgres/</link><description>&lt;p&gt;On at least a weekly basis and not uncommonly multiple times in a single week I get this question:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://twitter.com/neilmiddleton"&gt;@neilmiddleton&lt;/a&gt;
I&amp;rsquo;ve been hunting for a nice PG interface that works within other things. PGAdmin kinda works, except the SQL editor is a piece of shit&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sometimes it leans more to, what is the Sequel Pro equivilant for Postgres. My default answer is I just use psql, though I do have to then go on to explain how I use it. For those just interested you can read more below or just get the highlights here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set your default &lt;code&gt;EDITOR&lt;/code&gt; then use \e&lt;/li&gt;
&lt;li&gt;On postgres 9.2 and up &lt;code&gt;\x auto&lt;/code&gt; is your friend&lt;/li&gt;
&lt;li&gt;Set history to unlimited&lt;/li&gt;
&lt;li&gt;&lt;code&gt;\d&lt;/code&gt; all the things&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before going into detail on why psql works perfectly fine as an interface I want to rant for a minute about what the problems with current editors are and where I expect them to go in the future. First this is not a knock on the work thats been done on previous ones, for their time PgAdmin, phpPgAdmin, and others were valuable tools, but we&amp;rsquo;re coming to a point where theres a broader set of users of databases than ever before and empowering them is becoming ever more important.&lt;/p&gt;
&lt;p&gt;Empowering developers, DBA&amp;rsquo;s, product people, marketers and others to be comfortable with their database will lead to more people taking advantage of whats in their data. &lt;a href="/2013/01/10/more-on-postgres-performance/"&gt;pg_stat_statements&lt;/a&gt; was a great start to this laying a great foundation for valuable information being captured. Even with all of the powerful stats being captured in the statistics of PostgreSQL so many are still terrified when they see something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; QUERY PLAN
----------------------------------------------------------------------------------------------------------------
Hash Join (cost=4.25..8.62 rows=100 width=107) (actual time=0.126..0.230 rows=100 loops=1)
Hash Cond: (purchases.user_id = users.id)
-&amp;gt; Seq Scan on purchases (cost=0.00..3.00 rows=100 width=84) (actual time=0.012..0.035 rows=100 loops=1)
-&amp;gt; Hash (cost=3.00..3.00 rows=100 width=27) (actual time=0.097..0.097 rows=100 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 6kB
-&amp;gt; Seq Scan on users (cost=0.00..3.00 rows=100 width=27) (actual time=0.007..0.042 rows=100 loops=1)
Total runtime: 0.799 ms
(7 rows)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Empowering more developers by surfacing this information in a digestable form, such as building on top of &lt;code&gt;pg_stat_statements&lt;/code&gt; tools such as &lt;a href="http://datascope.heroku.com"&gt;datascope&lt;/a&gt; by &lt;a href="http://www.twitter.com/leinweber"&gt;@leinweber&lt;/a&gt; and getting this to be part of the default admin we will truly begin empowering a new set of user.&lt;/p&gt;
&lt;p&gt;But enough of a detour, those tools aren&amp;rsquo;t available today. If you&amp;rsquo;re interested in helping build those to make the community better please reach out. For now I live in a work where I&amp;rsquo;m quite content with simple ole &lt;code&gt;psql&lt;/code&gt; here&amp;rsquo;s how:&lt;/p&gt;
&lt;h3 id="editor"&gt;
&lt;div&gt;
Editor
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Ensuring you&amp;rsquo;ve exported your preferred editor to the environment variable &lt;code&gt;EDITOR&lt;/code&gt; when you run \e it will allow you to view and edit your last run query in your editor of choice. This works for vim, emacs, or even sublime text.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export EDITOR=subl
psql
\e
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Gives me:&lt;/p&gt;
&lt;p&gt;&lt;img alt="sublime text" src="https://f.cl.ly/items/2I0f3M0B1T3k0d290v3k/Screenshot_2_12_13_9_58_AM.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note you need to make sure you connect with psql and have your editor set, once you do that saving and exiting the file will then execute the query&lt;/em&gt;&lt;/p&gt;
&lt;h3 id="x-auto"&gt;
&lt;div&gt;
\x auto
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;psql has long had a method of formatting output. You can toggle this on and off easily by just running the &lt;code&gt;\x&lt;/code&gt; command. Running a basic query you get the output:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT *
FROM users
LIMIt 1;
id | first_name | last_name | email | data | created_at | updated_at | last_login
----+------------+-----------+----------------------------+------------+---------------------+---------------------+---------------------
1 | Rosemary | Wassink | Rosemary.Wassink@yahoo.com | &amp;quot;sex&amp;quot;=&amp;gt;&amp;quot;F&amp;quot; | 2010-07-01 18:16:00 | 2011-05-14 11:47:00 | 2011-06-07 23:04:00
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With toggling the output and re-running the same query we can see how its now formatted:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\x
Expanded display is on.
craig=# SELECT * from users limit 1;
-[ RECORD 1 ]--------------------------
id | 1
first_name | Rosemary
last_name | Wassink
email | Rosemary.Wassink@yahoo.com
data | &amp;quot;sex&amp;quot;=&amp;gt;&amp;quot;F&amp;quot;
created_at | 2010-07-01 18:16:00
updated_at | 2011-05-14 11:47:00
last_login | 2011-06-07 23:04:00
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using &lt;code&gt;\x auto&lt;/code&gt; will automatically put this in what Postgres believes is the most intelligible format to read it in.&lt;/p&gt;
&lt;h3 id="psql-history"&gt;
&lt;div&gt;
psql history
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Hopefully this needs no justification&amp;hellip; having an unlimited history of all your queries is incredibly handy. Ensuring you set the following environment variables will ensure you never lose that query you ran several months ago again:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export HISTFILESIZE=
export HISTSIZE=
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="d"&gt;
&lt;div&gt;
\d
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;And while the last on the list one of the first things I do when connecting to any database is check out whats in it. I don&amp;rsquo;t do this by running a bunch of queries but rather checking out the schema and then poking at definitions of specific tables. &lt;code&gt;\d&lt;/code&gt; and variations on it are incredibly handy for this. Here&amp;rsquo;s a few highlights below:&lt;/p&gt;
&lt;p&gt;Listing all relations with simply &lt;code&gt;\d&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\d
List of relations
Schema | Name | Type | Owner
--------+------------------+---------------+-------
public | products | table | craig
public | products_id_seq | sequence | craig
public | purchases | table | craig
public | purchases_id_seq | sequence | craig
public | redis_db0 | foreign table | craig
public | users | table | craig
public | users_id_seq | sequence | craig
(7 rows)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;List only all tables with &lt;code&gt;dt&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\dt
List of relations
Schema | Name | Type | Owner
--------+-----------+-------+-------
public | products | table | craig
public | purchases | table | craig
public | users | table | craig
(3 rows)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Describe a specific relation with &lt;code&gt;\d RELATIONNAMEHERE&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\d users
Table &amp;quot;public.users&amp;quot;
Column | Type | Modifiers
------------+-----------------------------+----------------------------------------------------
id | integer | not null default nextval('users_id_seq'::regclass)
first_name | character varying(50) |
last_name | character varying(50) |
email | character varying(255) |
data | hstore |
created_at | timestamp without time zone |
updated_at | timestamp without time zone |
last_login | timestamp without time zone |
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One more pro-tip if you&amp;rsquo;re running a transaction with many tables and forget which are involved in it you can run &amp;lsquo;\d *transaction*&amp;rsquo; and it&amp;rsquo;ll display tables curently affected.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Have a tool you prefer, have something you use daily in psql that I missed, or interested in helping create a new admin experience please reach out and lets talk craig.kerstiens at gmail.com&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Wed, 13 Feb 2013 22:55:56 GMT</pubDate><guid isPermaLink="true">/2013/02/13/How-I-Work-With-Postgres/</guid></item><item><title>World of Warcraft, Modern RPGs, and the Gear Grind</title><link>https://benovermyer.com/blog/2013/02/world-of-warcraft-modern-rpgs-and-the-gear-grind/</link><description>&lt;p&gt;After a full year of not playing, yesterday I jumped back into World of Warcraft. I'd heard enough good things about the latest changes that I decided to give it another shot. It remains to be seen whether that'll last or not. Something that did make me pause, though, is the obvious reminder that WoW is based on a gear grind. As soon as my character, a &lt;a href="http://us.battle.net/wow/en/character/kelthuzad/Exsecratus/simple" rel="external"&gt;worgen warlock named Exsecratus&lt;/a&gt;, made it to the new continent, I almost immediately replaced my raid epic gear from the Cataclysm days with greens. Today's junk is better than yesterday's hard-won treasure. That theme carries across many modern MMORPGs, but in all honesty, it's also present in tabletop RPGs these days. Dungeons &amp;amp; Dragons is one of the worst culprits, but there are plenty of others. That got me to thinking. Is the gear grind necessarily bad? The perpetual need to have better equipment may seem like a thin excuse to keep people playing a game, but taken as a component of a larger and more complex system, it's a reliable foundation to build on. In a game like &lt;a href="http://silvergryphongames.com/games/Ingenium/" rel="external"&gt;my own Ingenium&lt;/a&gt;, where if you have too many static modifiers it makes the randomization provided by the dice useless, a gear grind based on incremental bonus increases wouldn't make much sense. However, if there were a game out there that had more complex calculation involved with point bonuses, then having a Sword +513 wouldn't necessarily be any more unbalanced than a Sword +3. The trick is that to get to that level, you need to involve multiplication and division in the core mechanic, and that's the real holdup for a tabletop RPG. Let's face it - most tabletop gamers don't want to sit and recalculate their stats every time they pick up a new item. In video games it's possible because the game itself handles it automatically in the background without the player even being aware of the math. To introduce infinitely-scaling item stats into a tabletop RPG, you would have to do one of two things - either create a phone/tablet app to handle the math for you, or make the math so simplified that it would be possible to calculate quickly. Being a web developer by profession, I'm partial to the first one. These days it's not unreasonable to expect gamers to have a smartphone. How would you handle bringing the gear grind into a tabletop game?&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sun, 10 Feb 2013 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/02/world-of-warcraft-modern-rpgs-and-the-gear-grind/</guid></item><item><title>Introducing django-db-tools</title><link>/2013/02/08/Introducing-django-db-tools/</link><description>&lt;p&gt;For any successful web application there is likely to come a time when you need to conduct some large migration on the backend. I dont mean simple add a &lt;a href="http://www.craigkerstiens.com/2012/05/07/why-postgres-part-2/"&gt;column here or add an index there&lt;/a&gt;, but rather truly sizeable migrations&amp;hellip; Going from &lt;a href="http://lanyrd.com/blog/2012/lanyrds-big-move/"&gt;MySQL to Postgres&lt;/a&gt; or migrating from an older version of Postgres such as a &lt;a href="http://blog.sendhub.com/post/30041247598/how-to-upgrade-a-legacy-heroku-database"&gt;32 bit instance&lt;/a&gt; to a newer 64 bit instance. In these cases the default approach is to just schedule downtime often throwing up a splash screen saying so.&lt;/p&gt;
&lt;p&gt;For many sites this approach is simply wrong and lazy, with little effort you can improve the experience and there by ease the burden in conducting these types of migrations. By having the ability to turn your site into a read only mode which &lt;a href="http://twitter.com/simonw"&gt;Simon Wilson&lt;/a&gt; talked about in his post on Lanyrd you can still continue to operate just in a limited capacity. &lt;a href="http://www.aeracode.org/2012/11/13/one-change-not-enough/"&gt;Andrew Godwin&lt;/a&gt; further talks about some of this as well in regards to the Lanyrd move and even includes the script they used to &lt;a href="https://github.com/lanyrd/mysql-postgresql-converter/"&gt;migrate data from MySQL to Postgres&lt;/a&gt;. Though just in talking with Simon about this a week ago it occurred to me they had not released the code for their read-only mode.&lt;/p&gt;
&lt;p&gt;Finally onto the announcing, today I&amp;rsquo;m releasing &lt;a href="https://github.com/craigkerstiens/django-db-tools"&gt;django-db-tools&lt;/a&gt;. This is currently a very lightweight utility that allows you to flip your site into two modes.&lt;/p&gt;
&lt;h3 id="anonymous-mode"&gt;
&lt;div&gt;
Anonymous Mode
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;For sites that offer a bulk of their data to unauthenticated users anonymous mode will be what you want. This ensures all users appear logged out and thus cannot interact with data. To enable anonymous mode you&amp;rsquo;d simple set the environment variable or config var on heroku as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;READ_ONLY_MODE = True
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="restricting-posts"&gt;
&lt;div&gt;
Restricting POSTs
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;The other bucket of sites is one that allows users to stay logged in but not insert data. Django did not appear to have a convenient means to know whether data was actually being inserted into the DB or not. As a good practice when inserting data it should be receiving a HTTP POST. The &lt;code&gt;GET_ONLY_MODE&lt;/code&gt; mimmicks all POSTs as if they were sent via GETs thus hopefully eliminating inserting data into your application. To turn it on simply set the environment variabel or config var on heroku to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GET_ONLY_MODE = True
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="installing"&gt;
&lt;div&gt;
Installing
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;The tool itself is largely middleware, to install:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;pip install django-db-tools&lt;/code&gt; or add it to your &lt;code&gt;requirements.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;db_tools&lt;/code&gt; to your &lt;code&gt;INSTALLED_APPS&lt;/code&gt; in your &lt;code&gt;settings.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;'dbtools.middleware.ReadOnlyMiddleware',&lt;/code&gt; to your &lt;code&gt;MIDDLEWARE_CLASSES&lt;/code&gt; in &lt;code&gt;settings.py&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="contributing"&gt;
&lt;div&gt;
Contributing
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;As with all code this is largely a work in progress. There&amp;rsquo;s many items still to do such as providing default copy and error pages and potentially handling other edge cases. I&amp;rsquo;d welcome others to contribute and give feedback if they find it helpful or how it can be improved on Github.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Fri, 08 Feb 2013 22:55:56 GMT</pubDate><guid isPermaLink="true">/2013/02/08/Introducing-django-db-tools/</guid></item><item><title>Want to write a search engine? Have some links</title><link>https://boyter.org/2013/01/want-to-write-a-search-engine-have-some-links/</link><description>&lt;p&gt;A recent comment I left on Hacker News managed to get quite a lot of up-votes which surprised me since it was effectively just a collection of links about search engines. You can read the full thread at &lt;a href="http://news.ycombinator.com/item?id=5129530"&gt;http://news.ycombinator.com/item?id=5129530&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Anyway since it did do so well I thought I would flesh it out with some more information. Here are a collection of posts/blogs/discussions which go into the details of how to write a search engine.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 31 Jan 2013 01:29:36 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/01/want-to-write-a-search-engine-have-some-links/</guid></item><item><title>Crafting in Tabletop RPGs</title><link>https://benovermyer.com/blog/2013/01/crafting-in-tabletop-rpgs/</link><description>&lt;p&gt;One of the systems near and dear to my heart in MMORPGs is crafting. I love being able to make things from materials that I've collected myself, and in so doing improve my own capabilities without having to rely on an external source (e.g., loot, or vendors). Very few tabletop RPGs have ever attempted to include a crafting system, and those that have (Dungeons &amp;amp; Dragons, I'm looking at you) focus primarily on high-cost, high-powered magical items. Here, I explain how a crafting system for a tabletop RPG might work, taking several cues from MMORPGs. Crafting in MMORPGs has three primary component systems - gathering, refining, and building finished items. Gathering is the collection of raw resources from the world. This usually takes the form of withdrawing units of resources from a resource node that randomly spawns in the world. Refining takes those raw materials and works them into usable forms. For example, smelting iron ore into iron bars is one such process. This step is sometimes optional. Building finished items takes resources and puts them together into a final usable form. In MMORPGs, the process of actually crafting the item is abstracted away such that the player doesn't need to worry about things like quenching steel in the proper temperature of liquid. Tabletop RPGs generally can't follow MMORPG mechanics, since a lot of the latter is based on intensive calculation behind the scenes. With crafting, my perception is that it's not popular because it's not a story component - in a tabletop gaming session, anything that smacks of busywork is not going to go over well. To address that concern, there are two possibilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make the whole crafting process fun and exciting, or&lt;/li&gt;
&lt;li&gt;Make the crafting process something that happens between adventures.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Personally, I think a mix of the two is ideal. The gathering process should be divided into two parts - acquiring rare raw materials through normal adventuring, and acquiring mundane raw materials in a quick process that occurs between gaming sessions. The refining process should be purely between sessions, unless it's something story-bound like imbuing a raw material with a specific magical aura that can only be done by a powerful hermit-mage that lives in the…. you get the picture. The crafting of the final item could go either way, though I'd tend to put it at the very beginning of a game session before the actual adventure starts to “prime” players' minds. A big component of crafting, and one of its greatest variables, is time. In real life, it takes a long time to smith a sword. In World of Warcraft, it takes seconds. Crafting in tabletop RPGs, as a character activity, should take little time. Crafting is a secondary system, and it's not epic to say that your character spent a month of in-game down time smithing a new longsword in a borrowed forge while the other members of the party twiddled their thumbs. This problem can be explained away in two ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Give the character NPC assistants to do the crafting for him, or&lt;/li&gt;
&lt;li&gt;Make the crafting process itself something magical that takes little time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I prefer the first option, since it involves more story hooks and feels less like a deus ex machina. If a player discovers he has the materials to make an upgraded suit of armor just as a session is about to begin, you can allow him to do that and retcon that he contracted the work out while he was adventuring in the last session. This can tend to make retconning a standard, accepted practice for crafting, but I think that's of minor concern in this case. The other consideration when designing a crafting system for use in a tabletop RPG is the effect this can have on player equipment and expectations of loot. As such, it can't be designed in a vacuum - it needs to be part of the system from the beginning, or you risk turning a game into a Monty Haul campaign inadvertently. The secret here is in the timing - you can gate the frequency of crafting more powerful items by introducing a crafting skill advancement system and making it as restrictive as you like, thereby keeping crafted items in line with looted items (or not, if that's what you prefer). The Dungeons &amp;amp; Dragons system of spending experience to craft powerful items is one way to gate the acquisition of crafted items, but I think it's fundamentally flawed in that it makes little sense from a story point of view. Sauron didn't lose part of his essence to craft the One Ring - he just lost time and resources. To make something, a player has three resources available to him - Time, Money, and Effort. The ratio can vary between those three, but if you abstract out those concepts, you can arrive at a more sensible requirement ladder than Dungeons &amp;amp; Dragons'. In the end, crafting is a perfectly viable addition to a gaming system, as long as it's well-integrated with the rest of the game. I'm working on one such system for inclusion in a game of mine, and I like to think the players will love it.&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sun, 13 Jan 2013 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/01/crafting-in-tabletop-rpgs/</guid></item><item><title>More on Postgres Performance</title><link>/2013/01/10/More-on-Postgres-Performance/</link><description>&lt;p&gt;If you missed my previous post on &lt;a href="/2012/10/01/understanding-postgres-performance/"&gt;Understanding Postgres Performance&lt;/a&gt; its a great starting point. On this particular post I&amp;rsquo;m going to dig in to some real life examples of optimizing queries and indexes.&lt;/p&gt;
&lt;h3 id="it-all-starts-with-stats"&gt;
&lt;div&gt;
It all starts with stats
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;I wrote about some of the &lt;a href="https://postgres.heroku.com/blog/past/2012/12/6/postgres_92_now_available/"&gt;great new features in Postgres 9.2&lt;/a&gt; in the recent announcement on support of Postgres 9.2 on &lt;a href="https://www.heroku.com"&gt;Heroku&lt;/a&gt;. One of those awesome features, is &lt;a href="http://www.postgresql.org/docs/9.2/static/pgstatstatements.html"&gt;pg_stat_statements&lt;/a&gt;. Its not commonly known how much information Postgres keeps about your database (beyond the data of course), but in reality it keeps a great deal. Ranging from basic stuff like table size to cardinality of joins to distribution of indexes, and with pg_stat_statments it keeps a normalized record of when queries are run.&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;p&gt;First you&amp;rsquo;ll want to turn on pg_stat_statments:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CREATE extension pg_stat_statements;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What this means it would record both:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT id
FROM users
WHERE email LIKE 'craig@heroku.com';
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT id
FROM users
WHERE email LIKE 'craig.kerstiens@gmail.com';
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To a normalized form which looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT id
FROM users
WHERE email LIKE ?;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="understanding-them-from-afar"&gt;
&lt;div&gt;
Understanding them from afar
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;While Postgres collects a great deal of this information dissecting it to something useful is sometimes more mystery than it should be. This simple query will show a few very key pieces of information that allow you to begin optimizing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT
(total_time / 1000 / 60) as total_minutes,
(total_time/calls) as average_time,
query
FROM pg_stat_statements
ORDER BY 1 DESC
LIMIT 100;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above query shows three key things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The total time a query has occupied against your system in minutes&lt;/li&gt;
&lt;li&gt;The average time it takes to run in milliseconds&lt;/li&gt;
&lt;li&gt;The query itself&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Giving an output something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; total_time | avg_time | query
------------------+------------------+------------------------------------------------------------
295.761165833319 | 10.1374053278061 | SELECT id FROM users WHERE email LIKE ?
219.138564283326 | 80.24530822355305 | SELECT * FROM address WHERE user_id = ? AND current = True
(2 rows)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="what-to-optimize"&gt;
&lt;div&gt;
What to optimize
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;A general rule of thumb is that most of your very common queries that return 1 or a small set of records should return in ~ 1 ms. In some cases there may be queries that regularly run in 4-5 ms, but in most cases ~ 1 ms or less is an ideal.&lt;/p&gt;
&lt;p&gt;To pick where to begin I usually attempt to strike some balance between total time and long average time. In this case I&amp;rsquo;d start with the second probably, as on the first one I could likely shave an order of magnitude off, on the second I&amp;rsquo;m hopeful to shave two order of magnitudes off thus reducing the time spent on that query from a cumulative 220 minutes down to 2 minutes.&lt;/p&gt;
&lt;h3 id="optimizing"&gt;
&lt;div&gt;
Optimizing
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;From here you probably want to first example my other detail on understanding the explain plan. I want to highlight some of this with a more specific case based on the second query above. The above second query on an example data set does contain an index on user_id and yet there&amp;rsquo;s still high query times. To start to get an idea of why I would run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;EXPLAIN ANALYZE
SELECT *
FROM address
WHERE user_id = 245
AND current = True
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This would yield results:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=4690.88..4690.88 rows=1 width=0) (actual time=519.288..519.289 rows=1 loops=1)
-&amp;gt; Nested Loop (cost=0.00..4690.66 rows=433 width=0) (actual time=15.302..519.076 rows=213 loops=1)
-&amp;gt; Index Scan using idx_address_userid on address (cost=0.00..232.52 rows=23 width=4) (actual time=10.143..62.822 rows=1 loops=8)
Index Cond: (user_id = 245)
Filter: current
Rows Removed by Filter: 14
Total runtime: 219.428 ms
(1 rows)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hopefully not being too overwhelmed by this due to having read the other detail on &lt;a href="/2012/10/01/understanding-postgres-performance/"&gt;query plans&lt;/a&gt; we can see that it is using an index as expected. The difference is its having to fetch 15 different rows from the index then discard the bulk of them. The number of rows discarded is showcased by the line:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Rows Removed by Filter: 14
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;This is just one more of the many improvements in Postgres 9.2 alongside pg_stat_statements.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To further optimize this we would great a conditional OR composite index. A conditional would be where only current = true, where as the composite would index both values. A conditional is commonly more valuable when you have a smaller set of what the values may be, meanwhile the composite is when you have a high variability of values. Creating the conditional index:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;CREATE INDEX CONCURRENTLY idx_address_userid_current ON address(user_id) WHERE current = True;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can then see the query plan is now even further improved as we&amp;rsquo;d hope:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;EXPLAIN ANALYZE
SELECT *
FROM address
WHERE user_id = 245
AND current = True
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=4690.88..4690.88 rows=1 width=0) (actual time=519.288..519.289 rows=1 loops=1)
-&amp;gt; Index Scan using idx_address_userid_current on address (cost=0.00..232.52 rows=23 width=4) (actual time=10.143..62.822 rows=1 loops=8)
Index Cond: ((user_id = 245) AND (current = True))
Total runtime: .728 ms
(1 rows)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re looking for a deeper resource on Postgres I recommend the book &lt;a href="https://theartofpostgresql.com/?affiliate=cek"&gt;The Art of PostgreSQL&lt;/a&gt;. It is by a personal friend that has aimed to create the definitive guide to Postgres, from a developer perspective. If you use code CRAIG15 you&amp;rsquo;ll receive 15% off as well.&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 10 Jan 2013 22:55:56 GMT</pubDate><guid isPermaLink="true">/2013/01/10/More-on-Postgres-Performance/</guid></item><item><title>Code a Search Engine in PHP Part 5</title><link>https://boyter.org/2013/01/code-for-a-search-engine-in-php-part-5/</link><description>&lt;p&gt;[Are you really interested in learning how to Write a Search Engine from Scratch? Click this link and register your interest for my book about how to do so.][1]&lt;/p&gt;
&lt;p&gt;This is part 5 of a 5 part series.&lt;/p&gt;
&lt;p&gt;[Part 1][2] – [Part 2][3] – [Part 3][4] – [Part 4][5] – [Part 5][6] – [Downloads/Code][7]&lt;/p&gt;
&lt;p&gt;So we need to convert the indexer to a method that wont consume as much memory. Looking at how it works now we can determine a few areas that could be improved before we implement out new method.```
public function index(array $documents) {
$documenthash = array(); // so we can process multiple documents faster&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 10 Jan 2013 07:34:18 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/01/code-for-a-search-engine-in-php-part-5/</guid></item><item><title>Code a Search Engine in PHP Part 4</title><link>https://boyter.org/2013/01/code-for-a-search-engine-in-php-part-4/</link><description>&lt;p&gt;&lt;a href="https://leanpub.com/creatingasearchenginefromscratch"&gt;Are you really interested in learning how to Write a Search Engine from Scratch? Click this link and register your interest for my book about how to do so.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is part 4 of a 5 part series.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.boyter.org/2013/01/code-for-a-search-engine-in-php-part-1/%22"&gt;Part 1&lt;/a&gt; – &lt;a href="http://www.boyter.org/2013/01/code-for-a-search-engine-in-php-part-2/"&gt;Part 2&lt;/a&gt; – &lt;a href="http://www.boyter.org/2013/01/code-for-a-search-engine-in-php-part-3/"&gt;Part 3&lt;/a&gt; – &lt;a href="http://www.boyter.org/2013/01/code-for-a-search-engine-in-php-part-4/"&gt;Part 4&lt;/a&gt; – &lt;a href="http://www.boyter.org/2013/01/code-for-a-search-engine-in-php-part-5/"&gt;Part 5&lt;/a&gt; – &lt;a href="http://www.boyter.org/2013/01/code-for-a-search-engine-in-php-part-5/#downloads"&gt;Downloads/Code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So previously we had 4 main issues identified. Im going to go with low hanging fruit and add a simple porn filter.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 10 Jan 2013 07:31:34 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/01/code-for-a-search-engine-in-php-part-4/</guid></item><item><title>Code a Search Engine in PHP Part 3</title><link>https://boyter.org/2013/01/code-for-a-search-engine-in-php-part-3/</link><description>&lt;p&gt;[Are you really interested in learning how to Write a Search Engine from Scratch? Click this link and register your interest for my book about how to do so.][1]&lt;/p&gt;
&lt;p&gt;This is part 3 of a 5 part series.&lt;/p&gt;
&lt;p&gt;[Part 1][2] – [Part 2][3] – [Part 3][4] – [Part 4][5] – [Part 5][6] – [Downloads/Code][7]&lt;/p&gt;
&lt;p&gt;At this point I had a large chunk of the web sitting on my disk waiting to be indexed. The first thing we need to think about is what are we going to index. Since we are dealing with HTML files we have marked up content can can pick to a certain extent what we want to index on. For our search im going to index on the title and the meta description tags. Titles are still a part of search engine ranking algorithms as many people search for things like &amp;ldquo;Yahoo&amp;rdquo; and &amp;ldquo;Facebook&amp;rdquo; and the title/URL usually contains this information. The meta description had fallen out of favor with being something search engines use these days due to being gamed, but since its unlikely the top 1 million are going to be doing this I am going to use it as well. These two terms should work fairly well at our scale and ensure our index isn&amp;rsquo;t too massive. We can always add the rest of page content at a later point.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 10 Jan 2013 07:27:57 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/01/code-for-a-search-engine-in-php-part-3/</guid></item><item><title>Code a Search Engine in PHP Part 2</title><link>https://boyter.org/2013/01/code-for-a-search-engine-in-php-part-2/</link><description>&lt;p&gt;&lt;a href="https://leanpub.com/creatingasearchenginefromscratch"&gt;Are you really interested in learning how to Write a Search Engine from Scratch? Click this link and register your interest for my book about how to do so.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is part 2 of a 5 part series.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.boyter.org/2013/01/code-for-a-search-engine-in-php-part-1/%22"&gt;Part 1&lt;/a&gt; – &lt;a href="http://www.boyter.org/2013/01/code-for-a-search-engine-in-php-part-2/"&gt;Part 2&lt;/a&gt; – &lt;a href="http://www.boyter.org/2013/01/code-for-a-search-engine-in-php-part-3/"&gt;Part 3&lt;/a&gt; – &lt;a href="http://www.boyter.org/2013/01/code-for-a-search-engine-in-php-part-4/"&gt;Part 4&lt;/a&gt; – &lt;a href="http://www.boyter.org/2013/01/code-for-a-search-engine-in-php-part-5/"&gt;Part 5&lt;/a&gt; – &lt;a href="http://www.boyter.org/2013/01/code-for-a-search-engine-in-php-part-5/#downloads"&gt;Downloads/Code&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The first implementation has a few issues that are pretty apparent. Chiefly is performance. Secondly it stores the index in a single folder which is loosely related to the first. Finally it shows duplicates in the search results. Lets fix the above and test things again to see how far we can go.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 10 Jan 2013 05:03:54 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/01/code-for-a-search-engine-in-php-part-2/</guid></item><item><title>Code a Search Engine in PHP Part 1</title><link>https://boyter.org/2013/01/code-for-a-search-engine-in-php-part-1/</link><description>&lt;p&gt;[Are you really interested in learning how to Write a Search Engine from Scratch? Click this link and register your interest for my book about how to do so.][1]&lt;/p&gt;
&lt;p&gt;This is part 1 of a 5 part series.&lt;/p&gt;
&lt;p&gt;[Part 1][2] – [Part 2][3] – [Part 3][4] – [Part 4][5] – [Part 5][6] – [Downloads/Code][7]&lt;/p&gt;
&lt;p&gt;I imagine that if you have landed on this page you probably have an interest in search and search engines. Not only that, you have probably read the following [Why Writing Your Own Search Engine is Hard by Anna Patterson (of Cuil fame) http://queue.acm.org/detail.cfm?id=988407][8] If not, go read it and come back here. I have always had an interest in search and indexing I thought I would take the time to write a simple indexer as a way of testing if I had actually learnt anything.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 10 Jan 2013 04:55:54 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2013/01/code-for-a-search-engine-in-php-part-1/</guid></item><item><title>Conquering 2013: Goals for the Year</title><link>https://benovermyer.com/blog/2013/01/conquering-2013-goals-for-the-year/</link><description>&lt;p&gt;I'm joining the vast numbers of bloggers who are publicly declaring their goals for the new year right now. Scott Dinsmore of Live Your Legend fame has challenged people to, well, Live Your Legend in 2013, and offers a &lt;a href="https://web.archive.org/web/20221002031539/http://liveyourlegend.net/free-2013-goal-setting-guide/" rel="external"&gt;Goal Setting &amp;amp; Action Workbook&lt;/a&gt; to help achieve that. I took four hours this morning to fill it out and plan my goals for the year, and this blog post summarizes the results of that. Two of my six big goals for the year have to do with gaming, but the rest are personal goals. I'll share all of them with you after the jump.&lt;/p&gt;
&lt;h1 id="goal-1-release-a-computer-game"&gt;Goal #1) Release a Computer Game&lt;/h1&gt;
&lt;p&gt;I've worked, briefly, in the computer game industry. I've started numerous game projects. But I've never actually released a finished game. 2013 is the year to change that. While I won't be releasing my dream game this year (the MMORPG tentatively called &lt;a href="https://starbornuniverse.wordpress.com/" rel="external"&gt;Starborn: Universe&lt;/a&gt;), I'm going to fire off a single-player action sandbox game called Starborn: Genesis. My release goal is by December 1, 2013. Future blog posts will detail this, my most difficult goal of 2013, as I work on it.&lt;/p&gt;
&lt;h1 id="goal-2-join-a-local-developer-group"&gt;Goal #2) Join a Local Developer Group&lt;/h1&gt;
&lt;p&gt;This goal is much smaller than #1. The purpose, though, is no less important; it has been said that you are an average of the five people you spend the most time with, and all of the five people I hang out with most are at best only tangentially related to computer game development. I want to connect with people more, and I especially want to connect with others who are passionate about computer game development. Joining a local developer group is an important part of that.&lt;/p&gt;
&lt;h1 id="goal-3-take-a-vacation-with-treasure-to-hawaii"&gt;Goal #3) Take a Vacation with Treasure to Hawaii&lt;/h1&gt;
&lt;p&gt;My wife Treasure and I have not yet taken a vacation outside of the Midwest. As both of us have traveled the world and love new places, this is a problem. This year, I'm committing to getting us both to Hawaii for a week in June, near or on our 4th anniversary. It will be an event to remember, I'm sure! Now I just need to figure out how to pay for it…&lt;/p&gt;
&lt;h1 id="goal-4-lead-a-yoga-class"&gt;Goal #4) Lead a Yoga Class&lt;/h1&gt;
&lt;p&gt;I don't know a thing about yoga. I've never taken a class and know only a few movements from Wii Fit. So why would I make a goal to lead a class? Because I'm interested in it, and no one ever achieved anything meaningful by aiming low. I'll need to join a class and become proficient enough over the coming year to teach a community class by the end of December. I've already picked out the location and instructor to help me achieve that. It's just a matter of getting it done.&lt;/p&gt;
&lt;h1 id="goal-5-reach-1-000-visitors-per-month-on-dicejockey"&gt;Goal #5) Reach 1,000 Visitors Per Month On Dicejockey&lt;/h1&gt;
&lt;p&gt;Yep, my blog wasn't going to slide by without a major goal this year. Dicejockey's not about Top Ten lists or Five Steps to Success, but I like to think I say things worth talking about, and that's worth pushing harder on. My life is my passion, and Dicejockey is a window to that passion. With a little luck and an extra dose of hard work, I hope to make Dicejockey a popular choice for gaming geeks.&lt;/p&gt;
&lt;h1 id="goal-6-collaborate-on-something-with-tasha"&gt;Goal #6) Collaborate on Something With Tasha&lt;/h1&gt;
&lt;p&gt;My sister Tasha and I don't talk very frequently. This isn't because we're not on speaking terms; it's just because we don't have much in common. This year I want to change that. We're both very passionate about a wide variety of topics, and I'm sure we can find something to truly connect on. I've got a tentative plan on how to achieve this goal, and I really want to get closer to my family, so I know I'll meet this goal by year's end. So those are my goals for 2013. How about you? What are you looking to achieve this year?&lt;/p&gt;</description><author>Ben Overmyer's Site</author><pubDate>Sat, 05 Jan 2013 02:00:00 GMT</pubDate><guid isPermaLink="true">https://benovermyer.com/blog/2013/01/conquering-2013-goals-for-the-year/</guid></item></channel></rss>