forked from creationix/howtonode.org
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdb.json
1 lines (1 loc) · 54.4 KB
/
db.json
1
{"Asset":{"w4c9m4cuuemg49ec":{"_id":"w4c9m4cuuemg49ec","source":"themes/landscape/source/js/script.js","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/js/script.js","path":"js/script.js"},"cv6yxl8nyrk9qvio":{"_id":"cv6yxl8nyrk9qvio","source":"themes/landscape/source/css/style.styl","mtime":1392706498000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/css/style.styl","path":"css/style.styl"},"m2hciu1s567do07i":{"_id":"m2hciu1s567do07i","source":"themes/landscape/source/css/fonts/FontAwesome.otf","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/css/fonts/FontAwesome.otf","path":"css/fonts/FontAwesome.otf"},"78gh5mn5ej159vdi":{"_id":"78gh5mn5ej159vdi","source":"themes/landscape/source/css/fonts/fontawesome-webfont.eot","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/css/fonts/fontawesome-webfont.eot","path":"css/fonts/fontawesome-webfont.eot"},"cf8kvfu5wwc2jtq7":{"_id":"cf8kvfu5wwc2jtq7","source":"themes/landscape/source/css/fonts/fontawesome-webfont.svg","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/css/fonts/fontawesome-webfont.svg","path":"css/fonts/fontawesome-webfont.svg"},"2pf21md0ev8jlfod":{"_id":"2pf21md0ev8jlfod","source":"themes/landscape/source/css/fonts/fontawesome-webfont.ttf","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/css/fonts/fontawesome-webfont.ttf","path":"css/fonts/fontawesome-webfont.ttf"},"s7sj4sgobbvv76gv":{"_id":"s7sj4sgobbvv76gv","source":"themes/landscape/source/css/fonts/fontawesome-webfont.woff","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/css/fonts/fontawesome-webfont.woff","path":"css/fonts/fontawesome-webfont.woff"},"2705yevvif51u49p":{"_id":"2705yevvif51u49p","source":"themes/landscape/source/css/images/banner.jpg","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/css/images/banner.jpg","path":"css/images/banner.jpg"},"zbpxyhfgntoxxju2":{"_id":"zbpxyhfgntoxxju2","source":"themes/landscape/source/fancybox/blank.gif","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/blank.gif","path":"fancybox/blank.gif"},"fly692xxn9gmvfoh":{"_id":"fly692xxn9gmvfoh","source":"themes/landscape/source/fancybox/fancybox_loading.gif","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/fancybox_loading.gif","path":"fancybox/fancybox_loading.gif"},"ivxw0qpphjykyxu3":{"_id":"ivxw0qpphjykyxu3","source":"themes/landscape/source/fancybox/fancybox_loading@2x.gif","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/fancybox_loading@2x.gif","path":"fancybox/fancybox_loading@2x.gif"},"iaqe95e1lvg1le64":{"_id":"iaqe95e1lvg1le64","source":"themes/landscape/source/fancybox/fancybox_overlay.png","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/fancybox_overlay.png","path":"fancybox/fancybox_overlay.png"},"4e1em4pk6z4b9mhf":{"_id":"4e1em4pk6z4b9mhf","source":"themes/landscape/source/fancybox/fancybox_sprite.png","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/fancybox_sprite.png","path":"fancybox/fancybox_sprite.png"},"7q0uczkhn7oep1p0":{"_id":"7q0uczkhn7oep1p0","source":"themes/landscape/source/fancybox/fancybox_sprite@2x.png","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/fancybox_sprite@2x.png","path":"fancybox/fancybox_sprite@2x.png"},"g0ydyukno5isl3h1":{"_id":"g0ydyukno5isl3h1","source":"themes/landscape/source/fancybox/jquery.fancybox.css","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/jquery.fancybox.css","path":"fancybox/jquery.fancybox.css"},"3ihueipe74cu3h3a":{"_id":"3ihueipe74cu3h3a","source":"themes/landscape/source/fancybox/jquery.fancybox.js","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/jquery.fancybox.js","path":"fancybox/jquery.fancybox.js"},"sxlr5vfbfxxjyp2c":{"_id":"sxlr5vfbfxxjyp2c","source":"themes/landscape/source/fancybox/jquery.fancybox.pack.js","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/jquery.fancybox.pack.js","path":"fancybox/jquery.fancybox.pack.js"},"gf0n6fnky1p72m77":{"_id":"gf0n6fnky1p72m77","source":"themes/landscape/source/fancybox/helpers/fancybox_buttons.png","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/helpers/fancybox_buttons.png","path":"fancybox/helpers/fancybox_buttons.png"},"okmbkofgewg2js0b":{"_id":"okmbkofgewg2js0b","source":"themes/landscape/source/fancybox/helpers/jquery.fancybox-buttons.css","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/helpers/jquery.fancybox-buttons.css","path":"fancybox/helpers/jquery.fancybox-buttons.css"},"g2x8a6m6tksvu7mc":{"_id":"g2x8a6m6tksvu7mc","source":"themes/landscape/source/fancybox/helpers/jquery.fancybox-buttons.js","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/helpers/jquery.fancybox-buttons.js","path":"fancybox/helpers/jquery.fancybox-buttons.js"},"j5q7bd6zo41chjyn":{"_id":"j5q7bd6zo41chjyn","source":"themes/landscape/source/fancybox/helpers/jquery.fancybox-media.js","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/helpers/jquery.fancybox-media.js","path":"fancybox/helpers/jquery.fancybox-media.js"},"ki3os5914yswlbkg":{"_id":"ki3os5914yswlbkg","source":"themes/landscape/source/fancybox/helpers/jquery.fancybox-thumbs.css","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/helpers/jquery.fancybox-thumbs.css","path":"fancybox/helpers/jquery.fancybox-thumbs.css"},"a5czop2rzsmktug5":{"_id":"a5czop2rzsmktug5","source":"themes/landscape/source/fancybox/helpers/jquery.fancybox-thumbs.js","mtime":1392700843000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/themes/landscape/source/fancybox/helpers/jquery.fancybox-thumbs.js","path":"fancybox/helpers/jquery.fancybox-thumbs.js"},"yex844fhvhukkugg":{"_id":"yex844fhvhukkugg","source":"source/images/test.jpg","mtime":1392701775000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/source/images/test.jpg","path":"images/test.jpg"},"i21zefz1xmruavo1":{"_id":"i21zefz1xmruavo1","source":"source/images/librato-metrics-test-with-nodejs-graph.png","mtime":1373651152000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/source/images/librato-metrics-test-with-nodejs-graph.png","path":"images/librato-metrics-test-with-nodejs-graph.png"},"16jbdxhwljzb19tw":{"_id":"16jbdxhwljzb19tw","source":"source/images/librato-metrics-test-with-nodejs-demo.png","mtime":1373651152000,"modified":false,"full_source":"/Users/aaronfay/sandbox/newblog/source/images/librato-metrics-test-with-nodejs-demo.png","path":"images/librato-metrics-test-with-nodejs-demo.png"}},"Cache":{"0estvahz13qkgwzk":{"_id":"0estvahz13qkgwzk","content":"title: Hello World\ndate: 2014-02-17 22:20:43\ntags:\n---\n\nWelcome to [Hexo](http://zespia.tw/hexo)! This is your very first post. Check [documentation](http://zespia.tw/hexo/docs) to learn how to use.\n\n## Some other stuff\n![image](/images/test.jpg)\n\n{% gist 1396929 %}\n","mtime":1392703901000,"source":"_posts/hello-world.md"},"tzpl4wrzsnh7mzlb":{"_id":"tzpl4wrzsnh7mzlb","content":"title: Github, Setuptools, and What I Learned Today\ndate: 2012-08-08 12:00:00\ncategories:\n - programming\ntags:\n - git\n - github\n - dvcs\n---\n\nHow's that for a title? I just have to say, [git][] is pretty awesome, but I'm assuming you knew that. I read an article today where (for the first time I've seen) someone was making a case for [bazaar][] over git. I used [bazaar][] for our development team for almost two years, it was my \"upgrade\" to \"distributed\" over subversion. Sorry, can't find the article. In a nutshell, 20 out of dvcs users [on that webpage] prefer git over bzr. Maybe corn flakes too...\n\n### tldr;\nClick the little 'X' in the upper-right corner...\n\n## good, bad, indifferent\nI'm not really going to argue points about the two systems today, all I'll say is that I'm totally digging git. And my motivation is several-fold:\n\n * [Video][] - __Summary__: Linus Torvalds tells Google staff how stupid they are 'coz they don't use git... over and over and over again.\n * Like, the internets use github, both of them, duhh\n * I get to use it at work :)\n\n[git]: http://github.com\n[bazaar]: bazaar.canonical.com\n[Video]: http://www.youtube.com/watch?v=4XpnKHJAok8\n\n### Further rationale\nBazaar was great, don't get me wrong, but some of my newest most favorite features are (in no particular order):\n\n * [On-the-fly branching!](http://www-cs-students.stanford.edu/~blynn/gitmagic/ch04.html) How cool is that?? In bzr (or svn) a branch would require a different folder. In-place branches are wicked.\n * [Submodules](http://git-scm.com/book/en/Git-Tools-Submodules) Is there another system where this actually works?\n * [Rebase](http://git-scm.com/book/en/Git-Branching-Rebasing) OMFG nuff said.\n\nThere's more, but that's on the top of my list right now.\n\n## mixin(setuptools)\nOne of the neat things about settling in with a new development team is the things that I learn. At the top of my list are:\n\n * the things I've been doing right,\n * the things I've been doing wrong.\n\nOf the latter, the first that comes to mind is [setuptools][]. I've been managing Python dependencies manually for the last several years, in my mind, somehow, convinced that efficient dependency management in Python was somehow flawed, or \"seldom agreed upon\". Probably a result of me being in a hurry most of the time.\n\nThankfully, I've seen the light! A colleague at work turned me back on to [virtualenv][], and I now realize what I've been missing in python all along: __a reliable, simple deployment strategy__. I'll have to write more on that workflow later.\n\n[setuptools]: http://pypi.python.org/pypi/setuptools/\n[virtualenv]: http://pypi.python.org/pypi/virtualenv/\n\n## mixin(git)\nThis part is my favorite: without too much trouble, you can configure setuptools to pull from a github repo (or probably any other repo). There are only two criteria:\n\n * The remote project must be [setuptools-compatible][]\n * The endpoint must provide a tarball (equivalent to an .egg)\n\n[setuptools-compatible]: http://packages.python.org/an_example_pypi_project/setuptools.html#setting-up-setup-py\n\nIn the `setup.py` you only need specify the tarball location in a specific way in the `dependency_links` kwarg.\n\nEg: \n\n``` python\nfrom setuptools import setup\n\n#other stuff here\n...\n\nsetup(\n name = \"my-project\",\n version = \"1.0.0\",\n author = \"Aaron Fay\",\n author_email = \"me@gmail.com\",\n description = (\"Simple python setuptools package.\"),\n license = \"BSD\",\n keywords = \"example python package setuptools\",\n url = \"http://my.url\",\n packages = ['an_example_pypi_project',],\n long_description = \"My description\"\n install_requires = [\n 'my_other_package==1.0.0' ## look here!\n ],\n dependency_links = [\n 'https://github.com/AaronFay/my-other-package/tarball/master#egg=my_other_package-1.0.0'\n ]\n)\n```\n\n\nThe trick in all this is the `#egg=my_other_package-1.0.0` part, setuptools will recognize the package name and match it up with a required package in `install_requires`. It even has a pretty smart way to [differentiate package versions](http://packages.python.org/distribute/setuptools.html#specifying-your-project-s-version).\n\n### wrapping up\nWithout too much trouble, a very efficient development/production workflow can be set up with the combination of virtualenv, git, and setuptools. It's definitely an exciting time to be in software development.\n\nUntil next time.\n\naf","mtime":1392779895000,"source":"_posts/github-setuptools-awesomeness.markdown"},"4mr0zvfzpk081xbv":{"_id":"4mr0zvfzpk081xbv","content":"title: Learning Perl, List and Scalar context note \ndate: 2012-11-30 12:00:00\ncategories:\n - programming\ntags:\n - perl\n---\n\nToday I ran across an interesting feature of Perl, as I was trying to test a variable key against a hash, essentially a key search. I'm still surprised at how accessible things are in Perl when I go to do something complicated, I find there is usually a very simple way to do it, clearly by design.\n\n## An Example\nSearching against a set of keys in perl is quite simple, given the following hash:\n\n``` perl\n%foo = (\n 'bar' =>'baz', \n 'biz'=>'bad', \n 'bat'=>'buz'\n);\n```\n\n... testing for a key match is quite simple:\n\n``` perl\n$match = grep {/bar/} keys %foo;\nprint $match; # prints '1'\n```\n\n### Up the ante\nFor a bit of code that I'm working on, I need a little more complicated search though, I'm testing a dynamic string against the set of keys for a given hash, turns out the answer is equally simple:\n\n``` perl\n$search_string = 'bar';\n$match = grep {/$search_string/} keys %foo;\nprint $match; # prints '1'\n```\n \nPretty straight forward. This example doesn't really give a lot of power just yet, mostly because the regular expressions are over-simplified. It was in my next example that the nature of `list` and `scalar` context started to become clear to me in Perl. According to [this page on the perldoc site](http://perldoc.perl.org/functions/grep.html), \"[grep] returns the list value consisting of those elements for which the expression evaluated to true. In scalar context, returns the number of times the expression was true.\"\n\nThis is neat. In the first example below, we get the match count, and the second, we get a list of matches from the same `grep`. The only difference is the context assignment, denoted by `$` or `@`.\n\n``` perl \n# get results in scalar context\n$moo = grep {/^b/} keys %foo;\nprint $moo; # 3\n\n# get results in list context\n@moo = grep {/^b/} keys %foo;\nprint @moo; # batbarbiz\n```\n\n## Scalar wut?\n[This article](http://www.comp.leeds.ac.uk/Perl/scalars.html) describes a _scalar_ as the \"most basic kind of variable in Perl... [they] hold both strings and numbers, and are remarkable in that strings and numbers are completely interchangable.\" Maybe remarkable if you are coming from C, or a strict language where dynamic typing is not allowed.\n\n### A little deeper\nA **scalar** turns out to be just a _variable_, but one that can only hold a _single value_. If you need more than one value, you need a list, and a lookup, you need a hash. Scalar variables in Perl can be a number, a string, even a reference to a more complicated type. In the the case of an [array reference](http://www.thegeekstuff.com/2010/06/perl-array-reference-examples/) or a [hash reference](http://www.thegeekstuff.com/2010/06/perl-hash-reference/), you can think of the scalar variable as a _pointer_ to the original object, which can be merrily passed around at will.\n\n``` perl \n%hash = ('foo'=>'bar'); # my hash\n$ref = \\%hash; # $ref is a hash reference\n\n$obj->my_sub($ref); # pass the reference to a subroutine\n```\n\nThis language is wierd. [Larry Wall](http://en.wikipedia.org/wiki/Larry_Wall) must have thought he build the best thing ever when he created Perl. If feels a lot like `vim`, except that you have about 6-10 possible ways to do any given command. **TIMTOWTDI** is a great mindset for a language in terms of flexibility, but as soon as you get into someone else's code, you realize you don't know anything about the language again.\n\nUntil next time,\nAf","mtime":1392779903000,"source":"_posts/learning-perl-list-scalar-context.markdown"},"wrmstwdx753qk1l1":{"_id":"wrmstwdx753qk1l1","content":"title: Trying out Librato Metrics with Node.js\ndate: 2012-10-18 12:00:00\ncategories:\n - monitoring\ntags: \n - node.js\n - metrics\n - librato\n - charts\n - fun\n---\n\nI've started helping out with a little bit of sysadmin at work, since our systems\nteam is swamped most of the time. My task is to do an audit on our [Nagios][] \nsystem and make sure everything is up to snuff. We're running [Nagios][] 3 on \none machine and [NRPE][] to pull performance data from the cluster (about 20 machines). [NRPE][] is\na plugin to execute scripts remotely to gather [performance data][].\n\n[Nagios]: http://www.nagios.org/\n[NRPE]: http://exchange.nagios.org/directory/Addons/Monitoring-Agents/NRPE--2D-Nagios-Remote-Plugin-Executor/details\n\nNagios can do both active and passive measurements, meaning it can execute scripts\nremotely, or sit and listen as your machines push data into it. We're only using\nthe remote execution method (via [NRPE]). One of the downsides to this is having\nto set up new machines with the scripts and plugins for Nagios. You have to set up\nboth the script and config on the remote machine, and then configure the Nagios \nmachine to know what scripts to run remotely. Even with all that, it does a good\njob, and seems fairly performant.\n\n## Graphs and more graphs\nNagios has some good graphs for reviewing [performance data][], and lots of options\nfor configuring and customizing things based on your preferences. However, like\nmany aging open-source projects, Nagios feels a little clunky, and it's graphing \nsystem, while extendable (by the looks of things) isn't quite as shiny as some of\nthe newer systems I've looked at.\n\nA typical Nagios graph looks like this (image from [IT Slave](http://www.it-slav.net/)):\n![nagios graph](/images/librato-metrics-test-with-nodejs-graph.png)\n\n[performance data]: http://nagios.sourceforge.net/docs/3_0/perfdata.html\n\nThe graphs are really good as they stand, you can zoom in to find out more detail \non a set of measurements, and you can stack your measurements together for \ncorrelation, but it's not very user-friendly, and requires nearly a sysadmin to\naccomplish.\n\n## Correlating data\nOne of the interesting things about having a lot of measurements, is finding fun\nand interesting ways to mash them together. I ran into [Librato Metrics][] the \nother day while looking at some different options for graphing systems information\nin the cloud. I don't want to replace Nagios, by any means, for what it does, it \ndoes really well.\n\n__What I want is a better way to correlate data.__\n\n[Librato Metrics][] has an [api][] available for several languages so you can \npost metrics information to their system on the fly. Compared to [Datadog][] \n(which also looks very awesome, btw) who charges $15/host/month, [Librato Metrics][]\ncharges based on measurements, and they have a nifty little chart on their\n[pricing page][] to give you an idea of the cost to use their service. According to\nthat page, each measurement is going to cost you $0.000002 per measurement.\n\nI did the math, for the ~180 measurements we run at work every 90 seconds, it would\ncost us about $12/month to use their service (compared to ~$300/month on Datadog \nfor 20 hosts). The flip side to that is, Datadog has a whole bunch of 1-click \nintegration scripts to get up and running, while Librato is still a bit of a \nWIP in that area. No skin to me.\n\n[Librato Metrics]: https://metrics.librato.com/\n[api]: http://dev.librato.com/v1/metrics#metrics\n[Datadog]: http://www.datadoghq.com/ \n[pricing page]: https://metrics.librato.com/pricing\n\n\n### So what do they offer?\n[Librato Metrics][] is really a data aggregation service, they offer the ability\nfor you to create measurements with a namespace and a source, and then give you\na myriad of ways to graph and correlate that data using instruments. Don't just\ntake it from me, go check out [their video](https://metrics.librato.com/) and see\nfor yourself. \n\nSome of the things that make this system fairly attractive is the use of [Highcharts][]\nfor the graphing, and a really slick theme that is nice to look at. Their dashboards \nare a fancy way to mash a whole bunch of instruments into one place.\n\n[Highcharts]: http://highcharts.com/\n\n## A poor demo\nI've only had limited time to get started with the system, but I wrote a quick little\ndemo script in [node.js](http://nodejs.org) (of course) and tried it out on my EC2 instance. \n\nFor the demo I pushed load averages at 1, 5, and 15 minutes, as well as free memory on\nthe machine (measured between 0.01 and 1.00).\n\nHere's the result:\n![quick metrics test](/images/librato-metrics-test-with-nodejs-demo.png)\n\nTo get the performance data, I just pulled down [node-fibonacci](https://github.com/fvdm/nodejs-fibonacci)\nand asked my EC2 machine to calculate the fibonacci sequence for to a ridiculous length (three\nmillion trillion or something)... needless to say, it stressed out the machine a bit...\n\nHere's my node script to push data to Librato, it uses [node-librato-metrics][] and [os-monitor][]:\n\n[node-librato-metrics]: https://github.com/holidayextras/node-librato-metrics\n[os-monitor]: https://github.com/lfortin/node-os-monitor\n\n``` javascript\nvar osm = require('os-monitor')\n , librato = require('librato-metrics')\n ;\n\nclient = librato.createClient({\n email: '<put your email here>',\n token: '<put your token here>'\n});\nosm.start({delay: 90000});\nosm.on('monitor', function (event) {\n client.post('/metrics', {\n gauges: [\n {name: 'aws.instance01.cpu1', value: event.loadavg[0]},\n {name: 'aws.instance01.cpu5', value: event.loadavg[1]},\n {name: 'aws.instance01.cpu15', value: event.loadavg[2]},\n {name: 'aws.instance01.memusage', value: (event.freemem/event.totalmem) * 100}\n ]\n }, function (err, response) {\n if (err) {\n throw err;\n }\n });\n});\n```\n\nIt basically takes an OS measurement on CPU and calculates free memory every 90 seconds.\nThen it pushes that information to librato, and carries on. Since it's node, the whole \noperation happens asynchronously and everybody's happy.\n\n### HipChat\nDid I mention they have 1-click \"send this snapshot to [HipChat][]\" also? That's just fun.\n\n[HipChat]: http://www.hipchat.com/\n\n## Happy happy!\n\nThere you have it, fun fun. Can't wait to start profiling some scripts and \naggregating some other data with this thing.\n\nCheers,\nAf","mtime":1392779916000,"source":"_posts/librato-metrics-test-with-nodejs.markdown"},"8eplp0x4sh95hmk7":{"_id":"8eplp0x4sh95hmk7","content":"title: On Learning and Development\r\ndate: 2012-12-05 12:00:00\r\ntags:\r\n - rant\r\n---\r\n\r\nI want to write about the topic of learning, and how it pertains to my every day life in the workplace. I \r\nspent 18 months at my previous position, first by myself, and very quickly surrounded by a small team. We were working\r\nfor a company that took great pride in being different, focused, and innovative. A company that made every effort to \r\nsolve the needs of the client when noone else could or wanted to.\r\n\r\n## Learning as a necessity\r\nI don't think it's disputed by anyone that learning is necessary to become adept at whatever your position is. It \r\n_certainly_ was in mine. But it cannot stop there.\r\n\r\n__Learning is as necessary to development as water is to life.__\r\n\r\nIt's not enough to solve different problems in software development using the same patterns. It's not enough to \r\ntickle the boundaries of your \"programming comfort zone\". One of the demands of the position I was in at that time was \r\nto meet constant deadlines, and often overlapping ones. I'm quite proud to say I met all of them, and that the only \r\nthing that made that possible was _continuous learning_.\r\n\r\n## Continuous Learning\r\nThis is the kind of learning that means when you find a new technology that looks like it solves a problem that you \r\nhave, you try it. You dive right in and find out if it's going to do what it says it does. And then you do it again.\r\nYou jump ship on frameworks. You jump ship on technology stacks, because each one has something different to offer.\r\n\r\nJust as a problem can be solved in any language, so can a project be solved in any stack. It doesn't matter what the \r\nstack is. What matters is that you learn it, because that makes you better. \r\n\r\n__*Today it doesn't matter that you know a language, or a framework. If you're not good at learning, then you're \r\nalready losing the game*__.\r\n\r\n## Developer rot\r\nThere is such a thing in the software field as [software rot](http://en.wikipedia.org/wiki/Software_rot), meaning if\r\nthe environment is changing, and your software is not being updated to suit the environment, it starts to become a \r\nliability, and eventually rots and dies.\r\n\r\nSimilarly, a developer that has not taken the opportunity to be up-to-date with the current environment and culture \r\n(and I mean \"software culture\") of the internet is suffering what I am coining today as \"Developer Rot\". \r\n\r\nA developer who is suffering developer rot is one who is trying to solve new problems using the same old tools. The \r\ntools work, but the environment is not the same. 12-month objectives are no longer feasible, 6 months is no longer an \r\nacceptible amount of time to put into a software project. Because we are learning creatures, and we do improve over\r\ntime, we want to think we can write it faster and better this time around, and we really can! But the timeline for \r\ndevelopment within a given framework or toolchain is going to be fairly fixed. Boilerplate exists, component \r\nintegration needs design, there are shiny new requirements for the project, and now your timeline is shorter. This is\r\nthe reality of the entire evolution of my software career.\r\n\r\n## The real problem\r\n*\"What problem does <insert new thing here> solve that I can do in <insert my language/framework here>?\"*\r\n\r\n**The problem of time.** \r\n\r\nIf you spend (to pick a number) 20 hours to build a project using your current tools, and the new tool \r\npromises to cut your time in half, you have 10 hours now to learn that new tool. The gain beyond that becomes several-\r\nfold: \r\n\r\n * you're learning new things\r\n * you're becoming a better developer\r\n * you're saving time\r\n * you're giving more value to your clients\r\n * you're supporting new technologies\r\n * you're becoming a future advocate for these tools\r\n * you're showing others how to do the same\r\n\r\nYou are also going to save that much time again on your next project, and you're going to have fun. Excitement is a \r\nhuge motivator, in fact, I would argue it's the _only real_ motivator.\r\n\r\n## The time is now\r\nIf you are saying, *\"those tools look nice, but I don't have the time to learn them...\"* then you are already suffering \r\nfrom this condition. You will need to adopt and learn the tools as you encounter them, when they promise to solve your\r\nproblems faster and better. And you need to continue to adopt. If you can solve a problem well in one language, you \r\ncan solve it well in any language. If you can properly implement a project in one stack, you can implement it in any\r\nstack. \r\n\r\n*\"But I'll have 50 projects in 50 different software stacks...\"* Look at the internet: is it all written in Java? Can you\r\neven tell most of the time? Use [good conventions](http://www.12factor.net/) to guide you and then dive in.\r\n\r\n## Netucation\r\n\"Real school\" is starting to not mean much anymore. The new school is the internet. And the internet is changing. Every.\r\nSingle. Day. Knowing a couple languages isn't going to get you very far any more. Your best friend in the new web is\r\nthe _ability to learn_. Don't fight change, embrace it...\r\n\r\nHere are a few suggested exit points...\r\n\r\n * [http://nodejs.org/](http://nodejs.org)\r\n * [http://www.mongodb.org/](http://www.mongodb.org/)\r\n * [http://meteor.com/](http://meteor.com/)\r\n * [http://mojolicio.us/](http://mojolicio.us/)\r\n * [https://github.com/substack/dnode](https://github.com/substack/dnode)\r\n * [http://git-scm.com/](http://git-scm.com/)\r\n * [http://djangoproject.com/](http://djangoproject.com/)\r\n * [http://flask.pocoo.org/](http://flask.pocoo.org/)\r\n * [http://nevir.github.com/groc/](http://nevir.github.com/groc/)\r\n * [http://phantomjs.org/](http://phantomjs.org/)\r\n * [http://pivotal.github.com/jasmine/](http://pivotal.github.com/jasmine/)\r\n\r\n#### Good luck\r\nAaron\r\n\r\n_Edit_: I just ran across this blog post by [Jeff Atwood](https://www.google.ca/search?q=jeff+atwood&sugexp=chrome,mod=13&sourceid=chrome&ie=UTF-8) \r\nthat validated my entire train of thought, [link](http://www.codinghorror.com/blog/2007/06/learning-or-learning-how-to-learn.html).\r\n","mtime":1392779929000,"source":"_posts/on-learning-and-development-aka-developer-rot.markdown"},"n2s7hctl3j4rcmgb":{"_id":"n2s7hctl3j4rcmgb","content":"title: On learning Perl and TDD\r\ndate: 2012-10-29 12:00:00\r\ncategories:\r\n - programming\r\ntags:\r\n - rant\r\n---\r\n\r\nI want to start off by saying that `Perl` has to be one of the most _fantastic_\r\nlanguages I've every had to work in. I'm not really learning it because I have\r\na keen interest in Perl, I'm learning to be helpful regarding the legacy codebase\r\nat [my work](http://strathcom.ca/).\r\n\r\n## A little grind goes a long way...\r\nI wrote a bit of a script, after spending a few weeks perusing through a hefty \r\ncodebase, and even with a little bit of [Programming Perl][] under my belt, I \r\nstill don't have the skill to just roll out a lot of code off the top of my head. To \r\nmake sure I was putting some test coverage in place (of which there isn't in\r\nthis particular project), I looked up `Test::Simple` and `Test::More` and started\r\nthe file that would house my tests.\r\n\r\nI found after I have covered the existing code that I was looking at my new \r\nfunction stubs, and wondering how to best describe what they were going to do. Without \r\neven really thinking about it, I started writing tests to say, \"It should\r\ndo this, or that\" and in a couple minutes I had created a [spec][] for the \r\nfunction I was writing. \r\n\r\n## Almost like fun\r\nThe neat thing is, having the spec in place allowed me to play with the code a\r\nlittle bit to see if it was doing what I wanted when I tried different things. \r\nIf you recall, Perl has that \"There Is Moar Than One Way To Do It\"(TM) thing, \r\nwhich can be a good and a bad thing, but more about that later. \r\n\r\nThe real fun is when I made the realization that I was actually doing [Test Driven Development][] \r\nto learn Perl. [TDD][] is something I've always thought would benefit my coding\r\nstyle, but I never really realized how until today.\r\n\r\nUntil next time,\r\nAf\r\n\r\n\r\n[Programming Perl]: http://shop.oreilly.com/product/9780596000271.do\r\n[spec]: http://en.wikipedia.org/wiki/Behavior-driven_development\r\n[Test Driven Development]: http://en.wikipedia.org/wiki/Test-driven_development\r\n[TDD]: http://en.wikipedia.org/wiki/Test-driven_development\r\n\r\n","mtime":1392779946000,"source":"_posts/on-learning-perl-and-tdd.markdown"},"p6odc4mx0lal3nnu":{"_id":"p6odc4mx0lal3nnu","content":"title: Paramiko, PySFTP, and 'cd' problem\ndate: 2012-08-24 12:00:00\ntags: \n - Python\n - paramiko\n - ssh\n - sftp\n - PySFTP\ncategories:\n - programming\n---\n\nAt my [current position][] I'm getting the opportunity to do a lot of testing with \n[selenium][] (which I'll talk about later) and [vagrant][]. One of the things that \nI need to accomplish during testing is dynamically starting the development environment\nin \"TEST MODE\" to perform functional testing against the webapp backend.\n\n[current position]: http://www.strathcom.ca/\n[selenium]: http://seleniumhq.org/\n[vagrant]: http://vagrantup.com/\n\n## Remote execute\nI was `ssh`-ing into the server ok using [this ssh script][] (based on [paramiko]), \nsomething like:\n\n```\n>>> client = ssh.Connection('localhost', username='vagrant', password='vagrant', port=2222)\n>>> client.execute('pwd')\n['/home/vagrant\\n']\n```\n \nThe issue that I was having is _changing directories_. A simple `cd ..` didn't seem\nto want to do the trick:\n\n```\n>>> client.execute('cd ..')\n[]\n>>> client.execute('pwd')\n['/home/vagrant\\n']\n```\n\nI started thinking it's a permission issue or something, but, no, the `vagrant` user\nshould be root, nothing seemed to make the simple command execution work, at least, \nI can't think of another way to change directory on a linux box. And to make things\nmore intersting, it didn't seem to matter if I used [PySFTP][] or the aforementioned \n[ssh.py][], the result was the same.\n\n## Turns out to be simple\nI'm not exactly sure why, but [this post][] on [teh Stack][] led me to the solution, \nturns out it was simple:\n\n```\n>>> client.execute('cd ..; pwd')\n['/home\\n']\n```\n \nJust needed to execute the commands together. Why? Your guess is as good as mine...\n\nAf\n\n[this ssh script]: http://zeth.net/post/332/\n[ssh.py]: http://zeth.net/post/332/\n[PySFTP]: http://code.google.com/p/pysftp/\n[this post]: http://stackoverflow.com/questions/8932862/how-do-i-change-directories-using-paramiko\n[teh Stack]: http://stackoverflow.com/\n[paramiko]: http://www.lag.net/paramiko/\n","mtime":1392779956000,"source":"_posts/paramiko-pysftp-change-directory.markdown"},"g1hq4wj9uj13pzlh":{"_id":"g1hq4wj9uj13pzlh","content":"title: Finding DBI hostname in Perl\ndate: 2013-05-25 12:00:00\ntags:\n - perl\n - note to self\n---\n\nI had a scenario where I needed to find the hostname that DBI was using dynamically, I posted this here so I could find it again.\n\n[Link to original article](http://compgroups.net/comp.lang.perl.misc/dbi-get-hostname/376472)\n","mtime":1392779971000,"source":"_posts/perl-finding-dbi-hostname.markdown"},"6l52fssrex5uybs1":{"_id":"6l52fssrex5uybs1","content":"title: dependency sets for pip\ndate: 2013-10-05 12:00:00\ncategories: programming\ntags:\n - python\n - packaging\n---\n\nOn of the things I enjoy about building projects with [nodejs](http://nodejs.org/)\nis using [npm](http://npmjs.org), specifically the `devDependencies` part of \n`package.json`. This allows you to have one set of dependencies that are \ninstalled in production, but have extra dependencies installed for development,\nsuch as test libraries, deploy tools, etc. To get the development dependencies\nwith `npm` you run:\n\n``` bash\n$ npm intall --dev\n```\n\n## how about pip\nIt turns out if you are using `pip` 1.2 or newer, you can now do the same thing\nin your `setup.py` file for Python packages.\n\nAn example `setup.py` file:\n\n``` python\n#!/usr/bin/env python\n\nfrom setuptools import setup\nfrom myproject import __version__ \n\nrequired = [\n 'gevent',\n 'flask',\n ...\n]\n\nextras = {\n 'develop': [\n 'Fabric',\n 'nose',\n ]\n}\n\nsetup(\n name=\"my-project\",\n version=__version__,\n description=\"My awsome project.\",\n packages=[\n \"my_project\"\n ],\n include_package_data=True,\n zip_safe=False,\n scripts=[\n 'runmyproject',\n ],\n install_requires=required,\n extras_require=extras,\n)\n```\n\nTo install this normally (in \"edit\" mode) you'd run:\n\n``` bash\n$ pip install -e .\n```\n\nTo install the `develop` set of dependencies you can run:\n\n``` bash\n$ pip install -e .[develop]\n```\n\nAs you can see, you can have multiple sets of extra dependencies and call them\nwhatever you want.\n\nHave fun, \nAaron\n\n","mtime":1392779987000,"source":"_posts/pip-and-dependency-sets.markdown"},"1c7vda7yojrawhok":{"_id":"1c7vda7yojrawhok","content":"title: setuptools, pip, and custom python index\ndate: 2013-07-13 12:00:00\ncategories:\n - programming\ntags:\n - python\n - pip\n - packaging\n--- \n\nIn modern-day software development for the web I find that we end up trying many different ways to deploy code. While [at work](http://strathcom.com/) we're using python as our primary programming language, I've enjoyed the [node.js philosophy][1], especially the practice of [Small Kernels of Functionality][1] and [Loosely Coupled Components][1]. \n\nFrom [the article][5]:\n\n > \"...why package two modules together if you can simply break them apart into two kernels of functionality which are codependent?\"\"\n\nProblem\n---\nOne of the core sore points for me right now is the existence of \"common\" libraries in our work. It's common to have a piece of code that is needed in the current project, but doesn't particularly belong there. The approach (I often see) is to create said \"common\" library and deploy that with all of the projects that need the code. The major resistance to putting this in an individual package is probably the overhead of maintaining a separate repository for the individual code, along with the pull/commit/push/tag/release cycle that comes with it to make changes to a potentially developing module. So in the end, we end up with the \"common\" library.\n\nThe problem with is many-fold though:\n\n * dependency chains are not explicit,\n * the \"common\" library grows over time,\n * the same library becomes disorganized,\n * it's not clear later on how to break things out because it's not clear what projects are using what parts of the library,\n * the library with all theses different pieces of functionality [breaks the rule of single responsibility][6].\n\nBack to the [node.js philosophy][1], if you've ever used [npm][2] before, you know that there are [tons and tons of modules][3] available for node (as an interesting sidenode, npmjs module counts are growing by 94 modules/day at the time of writing [[link][3]]). The recommended approach is to keep modules small, and publish them independently so they can be used explicitly across applications. [James Halliday writes about this approach on his blog][4].\n\nBack to Python\n---\n[Python has been criticized for having painful package management][7]. At work, we currently use [setuptools][8] for installing packages from [Github][9], and it does a pretty decent job. [As I've written before][10] you can specify `dependency_links` in the `setup.py` file to pull tarballs from any source control system that will provide them. Like I said, this works pretty well.\n\nMypi\n---\nI've also recently set up a [mypi][11] private package index for our work, so we can start moving towards small, reusable python packages. I've also looked at [djangopypi][12] and [djangopypi2][13], the latter being a [bootstrap][14]-converted fork of the former. Both these projects seem to add a little more functionality around users management, and of course they're built on [Django][14], which means you get the nice Django admin at the same time. I haven't had time to do a full comparison, that will have to come later. For the time being, [mypi][11] seems to do the trick nicely.\n\nWhere setuptools falls apart\n---\nTurns out, using [pip][15], you can just [specify a custom index][16] in your `~/.pip/pip.conf` and then `pip install <packagename>` and you're good to go. That's fine for installing one-off modules, however, automating the entire depenedency installation process wasn't obvious at first. \n\nSetuptools fail\n---\nMy scenario had 2 projects, **Project A** and **Project B**. **Project A** relies on custom packages in my [mypi][11] index, and is published to the package also. **Project B** has a single dependency on **Project A**. Using [setuptools][8] `python setup.py install` would find **Project A** in the private package index (via `dependency_links`), but none of *Project A*'s custom index dependencies were being found, despite having specified the `dependency_links` in that project.\n\nLong story longer (and the answer)\n---\nThe answer just turned out to be a little bit more understanding of the evolution of python package management, [specifically this little tidbit about pip][17]:\n\n> \"Internally, pip uses the setuptools package, and the pkg_resources module, which are available from the project, Setuptools.\"\n\nTurns out [pip][15] spits out the setuptools configuration (whatever you have in your `setup.py`) into a `/<project-name>.egg-info/` folder, *including* `dependency_links`. \n\n\nTo get the [pip][15] equivalent of `python setup.py develop` just run:\n \n ``` bash\n# -e means 'edit'\n$ pip install -e .\n```\n\nTo get the same for `python setup.py install` run:\n\n``` bash\n$ pip install .\n```\n\n **The super-cool thing about this is** that `dependency_links` no longer need to be set in the `setup.py` files as [pip][15] will use the custom index set up in the `~/.pip/pip.conf` file.\n\n### Done and done\nI think this solution will solve some of the problem of having all the git/Github overhead involved in releases. With a simple `fab` setup, release candidates and formal releases can be incremented and deployed in a way that feels a little more clean and independent of the git workflow, while still maintaining source control. I'm hoping it will promote users to push modules early in a 'sharable' way to the private index so they can be easily installed for others. All in all, it feels cleaner to do it this way for me.\n\nHope that helps someone else down the road. Now we have a nice private registry for our python packages, and an easy way to automate their installation.\n\n\n**Note** It appears that [djangopypi][12] is actually maintained by Disqus, that may make it a good reason to use the project, as it will probably be maintained for a longer period. I will explore that option and write up a comparison later.\n\n[1]: http://blog.nodejitsu.com/the-nodejs-philosophy\n[2]: http://npmjs.org\n[3]: http://modulecounts.com/\n[4]: http://substack.net/how_I_write_modules\n[5]: http://blog.nodejitsu.com/the-nodejs-philosophy\n[6]: http://en.wikipedia.org/wiki/Single_responsibility_principle\n[7]: http://www.simplistix.co.uk/presentations/python_package_management_08/python_package_management_08.pdf\n[8]: https://pythonhosted.org/setuptools/index.html\n[9]: http://github.com/\n[10]: http://blog.aaronfay.ca/github-setuptools-awesomeness\n[11]: http://exhuma.github.io/mypi/\n[12]: https://github.com/disqus/djangopypi\n[13]: https://djangopypi2.readthedocs.org/en/latest/\n[14]: http://djangoproject.com/\n[15]: http://www.pip-installer.org/en/latest/\n[16]: http://exhuma.github.io/mypi/index-config.html#downloading-installing-packages-from-the-index\n[17]: http://www.pip-installer.org/en/release-1.4/logic.html#setuptools-pkg-resources","mtime":1392780010000,"source":"_posts/setuptools-pip-custom-python-index.markdown"},"k9qgyr7lw385pxvw":{"_id":"k9qgyr7lw385pxvw","content":"title: SublimeText 2 Snippet for ko.computed\r\ndate: 2012-09-13 12:00:00\r\ncategories:\r\n - programming\r\ntags:\r\n - sublime text\r\n - snippet\r\n---\r\n\r\nIf you're not using [SublimeText2][], you really don't know what you're missing...\r\nJust head on over to the [home page][] and see a few of the features that make \r\nthis just a fantastic editor. I won't go into detail just yet...\r\n\r\n[SublimeText2]: http://www.sublimetext.com/2\r\n[home page]: http://www.sublimetext.com/2\r\n\r\n## Snippets\r\nWhat I wanted to write about today is snippets. The snippet system in [SublimeText2][]\r\nis quite... well... _sublime_. But I was originally having trouble getting them to work (or\r\nso I thought).\r\n\r\nMy snippet (javascript) looked like this:\r\n\r\n``` xml\r\n<!-- Note: not actually working -->\r\n<snippet>\r\n <content><![CDATA[\r\n${1:self}.${2:method} = ko.computed(function () {\r\n ${3:// content}\r\n}, ${1:self});\r\n]]></content>\r\n <tabTrigger>comp</tabTrigger>\r\n <scope>source.javascript</scope>\r\n</snippet>\r\n```\r\n \r\n... and what I failed to realize was that the `source.javascript` line should \r\nactually by `source.js`. Ah well, problem solved.\r\n\r\n``` xml\r\n<!-- Working, hooray! -->\r\n<snippet>\r\n <content><![CDATA[\r\n${1:self}.${2:method} = ko.computed(function () {\r\n ${3:// content}\r\n}, ${1:self});\r\n]]></content>\r\n <tabTrigger>comp</tabTrigger>\r\n <scope>source.js</scope>\r\n</snippet>\r\n```\r\n \r\n### What this snippet does\r\nThe snippet in question is for firing off blazing fast `ko.computed` definitions.\r\nBy typing `comp<tab>` you get a bit of code that looks like this:\r\n\r\n``` javascript\r\nself.method = ko.computed(function () {\r\n // content\r\n}, self);\r\n```\r\n \r\nTo start with, both `self`s are highlighted, as per Sublime Text 2's multi-select\r\nstyle. Sweet. Hit `<tab>` and we jump to `method` selected, fill that in, hit \r\n`tab` one more time, and now `// content` is the current selection, fill in to finish.\r\n\r\nThis snipped can be got [here][].\r\n\r\n\r\n> Tip: can't find your `Packages` folder? In Sublime Text 2, select `Preferences > Browse Packages` and browse to the `User` folder.\r\n\r\nCheers,\r\nAaron\r\n\r\n[here]: https://gist.github.com/3717681\r\n","mtime":1392780029000,"source":"_posts/sublimetext2-snippets.markdown"},"kilcletm6uu2ym0z":{"_id":"kilcletm6uu2ym0z","content":"title: The problem with MVC\ndate: 2012-08-30 12:00:00\ncategories:\n - programming\ntags:\n - mvc\n - javascript\n---\n\nI'm a modern-day hack: I read a bit, books and online, I mash together chunks of code and frameworks to try and make things work (or break), I like to try things that few have attempted, with pretty decent success. For the longest time I didn't feel entirely comfortable in my shoes as a \"programmer\", meaning that I was writing code, my shit was working, but I felt I never met the generally-accepted criteria of a modern programmer. One of the things that kept me feeling unworthy was my lack of the use of teh [\"MVC\"][1] in my works.\n\n\n## Model-View-Controller\nI'm not going to go too far into what [MVC][1] is, if you're reading this, then you already have a good idea already. Besides, there are [internets][] out there to tell you what it is. I'm here to talk about why you should be using it.\n\n\n__The problem with MVC is that it's *misunderstood*.__\n\nMisunderstood for several reasons:\n\n * because I think the term itself has become a [buzzword][]. To the layperson or aspiring programmer, the concept of MVC is just another term among a slew of catch phrases that one encounters trying to decode the mystery of developing for the web, \n * next, it seems every new framework that totes the label 'MVC' isn't really a true representation of the pattern, or else it's some derivation of MVC that still doesn't really explain what it is.\n * last, MVC can be hard, or at least hard to pick up and understand. Let's look at an example of that next.\n\n## Picking on someone...\nTake the Actionscript framework [Robotlegs][], for example. There are several key components to setting up a project with that framework ([have a look at their flow diagram](http://www.robotlegs.org/diagram/)):\n\n * Views\n * Mediators\n * Context\n * Commands\n * Actors\n * Services\n\nDon't get me wrong, [Robotlegs][] is a great framework, but it's no wonder people are confused! Before successfully getting a project off the ground with Robotlegs, I think it took me 2 or 3 attempts to get my head wrapped around the minimal requirements. I mean, in all of this, which one is the Model? Where's the Controller? There isn't even a 'View' class in Robotlegs.\n\n*It felt like pulling teeth to really 'get it'.*\n\n## If it's so crazy, then why use it?\n\nLots of times when I read about MVC, I see lots of words like \"clean code separation\", \"visual flexibility\", \"better workflow\", etc. I think everyone who has thought about MVC but isn't using it yet needs that last little bit to really convince them:\n\n__MVC is about *sanity*.__ \n\nSanity because and MVC or similar (MVVM, MVCS, MV*) pattern helps you separate your application layers, which, without practice, is hard to do. But without regurgitating all the other buzz words and phrases to try and convince you it's worth using, let's make up a new idea about MVC:\n\n> \n> __*Data state representation bindings.*__\n> \n\nLet me clarify that: __bindings that automatically change the interface to represent the state of the data__. This means (in the case of a browser\nor something similar) that when you click an item, you don't reach in with your code and change the page or another element on \nthe page, you change your data instead. And if you have your bindings set up properly (or your framework for that matter), then \nthe view updates for you. With this kind of setup you can wire as many views to a single piece of data as you want, and in order\nto update them all, you only need change the state of the data, and they will all automatically update.\n\nSee? _Sanity_. \n\n### Time to grow up...\nIf you're not using some MV -ish framework or some kind of bindings for your project, there will never be a better\ntime than now. You owe yourself a little sanity, take the plunge. You'll thank yourself in the end.\n\n_af_\n\n\n[1]: http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller\n[internets]: http://en.wikipedia.org/wiki/Internets\n[buzzword]: http://en.wikipedia.org/wiki/Buzzword\n[Robotlegs]: http://www.robotlegs.org/\n","mtime":1392780047000,"source":"_posts/the-problem-with-mvc.markdown"},"5vz2rbx7g5oy8444":{"_id":"5vz2rbx7g5oy8444","content":"title: On code and change...\r\ndate: 2013-03-01 12:00:00\r\ncategories:\r\n - general programming\r\ntags:\r\n - rant\r\n - testing\r\n---\r\n\r\n## Thoughts in general:\r\n\r\n * develop like the code is going to change, make sure it's changeable, test it, refactor it, fail early, experiment and request feedback\r\n * deploy like it's going to change, plan for scaling (even if you don't have to), modularize, and automate whenever possible\r\n * create infrastructure like it's going to change, adopt methods that let you pull out pieces and put in new ones.\r\n\r\nYour setup is going to change, program like that's the only thing that will remain constant.\r\n\r\n### On Testing\r\n\r\nTesting is not about finding bugs. It's not even really about making sure a piece of code works, you could do that yourself. Testing is to make sure *you can change it later*.\r\n\r\n### On projects\r\nWhen you set up a project, if you have no built-in or prescribed way of specifying the dependencies of the project, you're going to find yourself pulling your hair out down the road. You **are** going to have to wipe it out and start from scratch at one point, or even if you don't, you still need to replicate the setup for stage, and production, and another developer. Save yourself some trouble, use the package management system or your language, or the one prescribed by the community. [Setuptools][1] for Python, [npm][2] for node, [gem][3] for ruby. Manage your own packages with these. It will save you mondo time down the road. If your language doesn't have package management, bail, find a language that does.\r\n\r\n### and a rant\r\nIf you're using Perl, use [cpan minus][4], cpan is a pain, [cpanm][4] removes some of the pain. If you're using php, well, god help you.\r\n\r\n[1]: http://pythonhosted.org/an_example_pypi_project/setuptools.html\r\n[2]: https://www.npmjs.org/\r\n[3]: http://rubygems.org/\r\n[4]: http://search.cpan.org/~miyagawa/App-cpanminus-1.7001/bin/cpanm\r\n","mtime":1392779852000,"source":"_posts/this-is-going-to-change.md"},"gho3cxid7tt4ymo8":{"_id":"gho3cxid7tt4ymo8","content":"title: Zombie.js just sucks\r\ndate: 2012-08-28 12:00:00\r\ntags:\r\n - rant\r\n---\r\n\r\n<div style=\"border:1px solid grey; padding: 5px; margin: 10px 0; background-color:#feffdb\">\r\n<strong>Note: Zombie.js has had several new releases since I wrote this post.</strong> I've\r\ncaved in and tried it again, and the newer version of Zombie seems to be working\r\nout better than previous versions. Future post(s) to come.\r\n</div>\r\n\r\n## Zombie.js\r\n\r\nI've been waiting for quite a while to try out [zombie.js][]. It seems like the \r\n\"End All.\" of hard-to-test-super-complex-setup systems, for instance, a system\r\nwhere you have a SSO with several redirects, then multi-panel single page app\r\nwith a lot of ajax requests and dynamic resources. Unit tests are one thing, but\r\nI really wanted to test that the whole setup was going to perform as expected.\r\n\r\n## #epicfail\r\n\r\nAfter a day and a half (and part of an evening), I think that [zombie.js][] is \r\nprobably trying to be a little too magical. On my [Vagrant][] box (Ubuntu Precise\r\nserver) I'm running Node v0.8.6. At first I tried the setup with [Mocha][] as \r\nprescribed in the [docs][], but to no avail. The biggest problem: our SSO\r\nsystem does a couple redirects when you hit the application page, and just like\r\nanother user expressed in [this discussion][], my `.then()` callback fires way\r\ntoo prematurely, and never hits the actual redirect. Specifying the wait time \r\ndidn't help any either.\r\n\r\n## Frustration at it's finest\r\n\r\nI'm not one to give up, I rarely let a hard problem get by me, but this isn't \r\njust a 'tricky' API I think. I think it's an immature project. Harsh, I know, \r\nbut have a look at this example:\r\n\r\n``` javascript\r\nvar zombie = require('zombie')\r\n , browser = new zombie.Browser\r\n ;\r\n\r\nbrowser.load('<html />', function () {\r\n console.log('foo')\r\n});\r\n```\r\n\r\n\r\nAccording to the [documentation][], `browser.load`...\r\n\r\n> Loads this HTML, processes events and calls the callback.\r\n\r\nBut it actually gives: \r\n\r\n```\r\nTypeError: Object #<Browser> has no method 'load'\r\n at repl:1:10\r\n at REPLServer.self.eval (repl.js:111:21)\r\n at Interface.<anonymous> (repl.js:250:12)\r\n at Interface.EventEmitter.emit (events.js:88:17)\r\n at Interface._onLine (readline.js:199:10)\r\n at Interface._line (readline.js:517:8)\r\n at Interface._ttyWrite (readline.js:735:14)\r\n at ReadStream.onkeypress (readline.js:98:10)\r\n at ReadStream.EventEmitter.emit (events.js:115:20)\r\n at emitKey (readline.js:1057:12)\r\n```\r\n\r\nAm I just doing something plain wrong? \r\n\r\n### So the tally is...\r\n__Zombies 1, Aaron 0__\r\n\r\nAs a side note, [selenium][] is looking to do exactly what I want.\r\n\r\n[zombie.js]: http://zombie.labnotes.org/\r\n[Vagrant]: http://vagrantup.com/\r\n[docs]: http://zombie.labnotes.org/\r\n[Mocha]: http://visionmedia.github.com/mocha/\r\n[selenium]: http://seleniumhq.org\r\n[this discussion]: https://groups.google.com/forum/?hl=en#!searchin/zombie-js/redirect/zombie-js/ng2biQw6u5w/Ch_WcL_PFkMJ \r\n[documentation]: http://zombie.labnotes.org/API#browser-load-html-callback\r\n","mtime":1392780056000,"source":"_posts/zombiejs-sucks.markdown"}}}