<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ronin coder &#187; code</title>
	<atom:link href="http://rcoder.net/content/category/code/feed" rel="self" type="application/rss+xml" />
	<link>http://rcoder.net</link>
	<description>Code, food, pinball, beer, and bikes. It&#039;s hard living in a place this awesome.</description>
	<lastBuildDate>Mon, 26 Jul 2010 20:30:50 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A Tale of Two Conferences</title>
		<link>http://rcoder.net/content/a-tale-of-two-conferences</link>
		<comments>http://rcoder.net/content/a-tale-of-two-conferences#comments</comments>
		<pubDate>Mon, 26 Jul 2010 20:30:50 +0000</pubDate>
		<dc:creator>lennon</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[conferences]]></category>
		<category><![CDATA[osbridge]]></category>
		<category><![CDATA[oscon]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://rcoder.net/?p=453</guid>
		<description><![CDATA[This summer, I attended (and gave presentations at) two conferences here in Portland: Open Source Bridge and OSCON. Broadly, the subject matter and target audience for these two events are similar (web developers, open source programmers, sysadmins, and mobile developers) but their approach, culture, and (for lack of a better word) &#8220;personalities&#8221; are quite different.
Overall, [...]]]></description>
			<content:encoded><![CDATA[<p>This summer, I attended (and gave presentations at) two conferences here in Portland: <a href="http://opensourcebridge.org/">Open Source Bridge</a> and <a href="http://oscon.com/">OSCON</a>. Broadly, the subject matter and target audience for these two events are similar (web developers, open source programmers, sysadmins, and mobile developers) but their approach, culture, and (for lack of a better word) &#8220;personalities&#8221; are quite different.</p>
<p>Overall, I think that OSBridge more effectively captured the spirit of the community from which it springs. The lack of the usual sponsored keynotes, expo hall stuffed with vendors, and &#8220;big shot&#8221; community leaders made the software itself, and the community building it, the main attraction. OSCON, by contrast, is much more focused on <em>products</em> in the OSS space, and talks are often a sales presentation wrapped in a technical overview.</p>
<p>On the downside, the quality of talks at OSBridge was highly variable. With fewer proposals to choose from, it was inevitable that some weaker or less-experienced speakers would end up on the program. (Hell, they even let <em>me</em> speak.) OSCON attracts a pretty stellar level of presentation, with rare exceptions (again, yours truly) and has an air of legitimacy that helps convince employers and sponsors to support the event.</p>
<p>I also don&#8217;t think that the commercial focus of OSCON is inherently a <em>bad</em> thing. I for one am happy to get paid to work with and on open source software, and I don&#8217;t begrudge those attempting to derive their livelihood entirely from it a few minutes to pitch their wares. If anything, I think the Portland tech community should be <em>more</em> focused on commercializing their projects, the better to sustain and improve the pool of talented developers who choose to live and work here.</p>
<p>Unfortunately, OSCON has two critical flaws. First and foremost, it&#8217;s too expensive. While the catered lunches, free coffee, and after-hours parties are all lovely in their own right, the total cost of the conference (around $1200 for the normal sessions only, and closer to $1800 with a full set of tutorials, plus airfare and lodging) puts it out of reach for many developers who simply want to get together and hack and share tips with their peers.</p>
<p>Secondly, many of the &#8220;keynote&#8221; presentations are simply apologia from proprietary OS and platform vendors, and really shouldn&#8217;t have a place in a conference focused on open source. I don&#8217;t mind hearing a pitch from a talented speaker, but market-speak-centric presentations on &#8220;cloud computing&#8221; and &#8220;open standards&#8221; are anathema to the DIY spirit of a true hacker&#8217;s conference.</p>
<p>Sadly, addressing both of these issues concurrently is a serious challenge, as I can only presume that Microsoft, et. al., paid handsomely for the opportunity to present themselves. Other events manage to keep costs down, however, so I assume there&#8217;s some room for cost savings that wouldn&#8217;t require moving the event to a spare O&#8217;Reilly warehouse and catering it entirely with Folger&#8217;s coffee and stale PB&#038;J sandwiches.</p>
<p>Personally, I find I have more fun (and often learn more) at smaller, more focused events like JSConf, Ruby Future, DjangoCon. Emerging Languages Camp was another perfect example of this &#8212; by stripping down the focus of the event, the organizers and speakers crammed an incredible amount of high-quality content into two days. </p>
<p>I find myself wondering if OSCON might not work better if it were split into an &#8220;executive&#8221; event focused on platform and service offerings, and the &#8220;hacker&#8221; gathering which narrowed in on code, tooling, and collaboration. I still very much enjoy getting to see community leaders like Rob Pike and Larry Wall speak, and will happily continue attending OSCON if I can do so safe in the knowledge that I don&#8217;t be inundated with salesdroids throughout the week.</p>
]]></content:encoded>
			<wfw:commentRss>http://rcoder.net/content/a-tale-of-two-conferences/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Code Reading</title>
		<link>http://rcoder.net/content/code-reading</link>
		<comments>http://rcoder.net/content/code-reading#comments</comments>
		<pubDate>Fri, 23 Oct 2009 18:58:55 +0000</pubDate>
		<dc:creator>lennon</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://rcoder.net/?p=415</guid>
		<description><![CDATA[We do full code reviews at my shop &#8212; no code goes into production without at least two pairs of eyes on every line of the change.
As I switch between projects, I find myself willing to be absolutely ruthless in my code reviews when reading other people&#8217;s Python code. When I&#8217;m looking at PHP or [...]]]></description>
			<content:encoded><![CDATA[<p>We do full code reviews at my shop &#8212; no code goes into production without at least two pairs of eyes on every line of the change.</p>
<p>As I switch between projects, I find myself willing to be absolutely <em>ruthless</em> in my code reviews when reading other people&#8217;s Python code. When I&#8217;m looking at PHP or Ruby source, I expect a certain amount of license to be taken with indentation, naming, and even encapsulation. Python? No dice. If you&#8217;re gonna use the language, use it <em>right</em>.</p>
<p>Use a less-than-descriptive variable name? Rejected.</p>
<p>Call an internal implementation method (ex.: <code>_do_stuff()</code>) outside the class that defined it (even in a unit test)? Rejected.</p>
<p>Let a line go over 120 characters in width? Rejected.</p>
<p>Forget to provide a useful comment for the test used in an <code>if:</code> block? Rejected.</p>
<p>I <em>probably</em> should be just as strict with PHP, Ruby, etc., but the culture doesn&#8217;t seem to be as forgiving of hard-and-fast style guidelines in those communities.</p>
]]></content:encoded>
			<wfw:commentRss>http://rcoder.net/content/code-reading/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django for Rails devs</title>
		<link>http://rcoder.net/content/django-for-rails-devs</link>
		<comments>http://rcoder.net/content/django-for-rails-devs#comments</comments>
		<pubDate>Mon, 05 Oct 2009 22:20:45 +0000</pubDate>
		<dc:creator>lennon</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://rcoder.net/?p=396</guid>
		<description><![CDATA[I&#8217;ve recently made the transition from full-time Rails development to a mix of technologies including, in large part, Django. Since I was a Python guy before I ever started using Ruby, the transition has mostly been an easy one, but there are some fairly significant differences in design and philosophy between the two frameworks that [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently made the transition from full-time Rails development to a mix of technologies including, in large part, <a href="http://djangoproject.com">Django</a>. Since I was a Python guy before I ever started using Ruby, the transition has mostly been an easy one, but there are some fairly significant differences in design and philosophy between the two frameworks that are worth thinking about if you&#8217;re picking a platform for a new project. Given that most of the comparisons out there on the Intertubes seem to be woefully out of date &#8212; the first page of <a href="http://www.google.com/search?q=django+rails+comparison">Google results</a> is mostly populated by articles that are 3-4 years old &#8212; I thought I might toss out some of my own highly-subjective observations out there anyone else trying to evaluate both stacks.</p>
<h2>Similarities</h2>
<p>Generally, the two projects are more alike than they are different, at least from the POV of a working web developer. Either one will give you a nice boost in productivity when building non-trivial applications where time-to-market trumps hard performance, runtime platform, or office politics. Much as Ruby and Python offer similar competitive advantage to the teams using them, neither Rails and Django will leave you struggling to keep up with other agile web development teams (or conversely, easily coasting past them).</p>
<p>Both Django and Rails have fairly powerful object-relational layers baked-in, and have good support for popular open source databases, including MySQL, PostgreSQL, and SQLite3. They both offer flexible URL mapping/routing tools, fairly easy-to-learn standard template formats, and (at least for Rails >= 2.3) the ability to insert middleware into the fast path of your request/response cycle, either to manipulate the request data, or to short-circuit loading in cases where you don&#8217;t need the whole framework for a particular client request.</p>
<p>In addition, both frameworks benefit from an active, supportive community that will help you get up to speed and answer questions. The <a href="http://docs.djangoproject.com/en/dev/">online</a> <a href="http://guides.rubyonrails.org/">documentation</a> for each project is fairly extensive, although I personally feel that the Django folks have done a better job of pulling the 80% of the docs that most developers need when they&#8217;re getting started into one place, with a consistent style and voice.</p>
<h2>Django wins</h2>
<p>There are a couple of big ones: <a href="#forms">form classes</a> and idiomatic use of <a href="#modules">Python modules</a>.</p>
<h3 id="forms">Form classes</h3>
<p>This is, without a doubt, my favorite feature of Django that simply has no real equivalent in Rails. Basically, a Django form lets you de-couple the HTML editing UI for a model from its storage and business logic. The big win here is due to the fact that form validation != domain model validation. Depending on your application, you want to allow users to populate forms with more or less information than would be stored in a single model class instance, and validate those forms using their own internal validation logic, rather than delegating all validation decisions to the model class.</p>
<p>As a case in point, consider a simple comment form. If you add a <a href="http://en.wikipedia.org/wiki/CAPTCHA">CAPTCHA</a> to the form, you could make your Django form class perform checking of that field, and display errors in CAPTCHA solving alongside those affecting the other comment fields, without forcing the comment model to even be aware that its views relied on such protections. Furthermore, once that form class was implemented, you could re-use it in any number of views without duplicating the display or validation logic. This is simply a better way to build views than the Rails model of helpers and shared controller methods, and I would encourage the Rails community to find <a href="http://github.com/defunkt/mustache">some way</a> to provide more support for structured views, especially in the areas of form handling.</p>
<h3 id="modules">Python modules</h3>
<p>Ruby and Python both support modules as a namespace construct. However, much as Ruby classes default to having private instance variables and public methods, the Ruby module type is largely opaque except when used as a mixin to a class implementation. Few Ruby libraries would be written to use instances of the <code>Module</code> type directly; rather, they would expect either an instance of some class, or a hash mapping symbols to objects. In Python, however, modules are &#8220;open&#8221; by default, with any defined names visible both inside and outside the module &#8212; just as Python objects default to being public bags of attributes.</p>
<p>This leads to one very natural means to connecting applications and components in a Django project: passing modules (or module names) as first-class constructs. Want to &#8220;mount&#8221; all the URLs in a pluggable Django app into your project? Use <code>include('myapp.urls')</code>. Want to override the content model classes used in a CMS workflow app? Parameterize the application with an optional model namespace module, and look up the needed model classes in that module at runtime. Dependency injection, &#8220;duck typed&#8221; polymorphism, etc., can all happen at the module level, and the entire Django framework (and well-written reusable applications that use it) capitalize quite effectively on this capability.</p>
<h2>Rails wins</h2>
<p>There are two major areas where Rails stomps Django: <a href="#testing">testing tools</a> and database <a href="migrations">schema migrations</a>.</p>
<h3 id="testing">Testing tools</h3>
<p>This one should be obvious to anyone who compares recent <a href="http://en.oreilly.com/rails2009/public/schedule/topic/General">conference</a> <a href="http://www.djangocon.org/2009/conference/schedule/">talk</a> or <a href="http://www.googlefight.com/index.php?lang=en_GB&#038;word1=rails+testing&#038;word2=django+testing">blog post</a> titles from the Rails and Django worlds. For those who don&#8217;t want to click through: RailsConf had 3-4x as many testing-focused sessions, and it was mentioned in many if not most other talks. The highly-scientific Google Fight also shows a much higher amount of online discussion of Rails testing, adding further anecdotal evidence to support the argument that the Rails community is at least <me>talking about</em> testing a lot more than their Django counterparts.</p>
<p>Rails developers, as a community, have been thoroughly bitten by the testing bug, and are always on the lookup for better ways to write more copious and useful collections of tests for their applications. This has led to the development of great tools like <a href="http://rspec.info">RSpec</a>, <a href="http://www.thoughtbot.com/projects/shoulda">Shoulda</a>, <a href="http://github.com/brynary/webrat">WebRat</a>, and <a href="http://cukes.info">Cucumber</a> for authoring tests, along with a huge supporting cast of libraries, reporting tools, and howto guides to make testing as easy as possible for Rails developers. Django has <a href="http://docs.djangoproject.com/en/dev/topics/testing/#testcase">TestCase</a> and <a href="http://docs.djangoproject.com/en/dev/topics/testing/#module-django.test.client">TestClient</a>, with a smattering of support from other Python tools like <a href="http://pypi.python.org/pypi/windmill">Windmill</a> and <a href="http://code.google.com/p/python-nose/">python-nose</a> to speed things along.</p>
<p>I recognize that most of the Ruby modules I linked to above are not part of the Rails core, and than there are lots of similarities in the features available for testing in either Ruby or Python. The difference is that most Rails developers I&#8217;ve talked to <em>use</em> the full breadth of testing tools available to them, and extol their use to others, while the Django community takes a much more lackadaisical attitude about testing outside of the Django core. (Even the bundled &#8220;contrib&#8221; apps in Django often have weak test coverage &#8212; as an example, there are <em>zero</em> included unit or doctests for the <code>django.contrib.admin</code> in my local django trunk checkout at r11578).</p>
<h3 id="migrations">Schema migrations</h3>
<p>ActiveRecord migrations are not <em>the</em> solution for all possible database changes in real-world applications, but they cover <em>most</em> cases in a consistent, easy-to-learn way. Once they learn a handful of migration library methods, Rails developers can happily write clear, lightweight database manipulation routines that allow their application database to evolve as requirements change without having to resort to non-portable low-level SQL queries. This is a Good Thing &trade;, and worth emulating in other frameworks.</p>
<p><a href="http://south.aeracode.org/">South</a> is an entirely-reasonable implementation of a very similar model. The Django core team should adopt it as part of the platform, or implement their own simplified version. This is an obvious case where <a href="http://www.famous-quotes.net/Quote.aspx?The_perfect_is_the_enemy_of_the_good">the perfect is the enemy of the good</a>.</p>
<h2>Conclusions</h2>
<p>Generally, I&#8217;m pretty happy about working with Django instead of Rails these days. Whereas I spent days struggling with obscure classloading issues trying to trivially extend the Rails framework, I&#8217;ve been able to make use of the module-driven pluggability of Django to swap out cache backends, template libraries, and entire domain model namespaces in my Django apps without much more than a brief foray into the source for an external library or two. Modulo the testing issues I raised above, and the lack of a really good equivalent to <a href="http://www.activemerchant.org/">ActiveMerchant</a>, I would call myself a fairly satisfied Django user, at least until the <a href="http://rcoder.net/content/never-do-today">next</a> <a href="http://liftweb.net/">big</a> <a href="http://chicagoboss.org/">thing</a> comes along.</p>
<p>There are some less technical reasons to consider Django over Rails, as well. First, who doesn&#8217;t love any typically male-dominated developer community which adopts such a <a href="http://dl-client.getdropbox.com/u/10320/django/wallpaper/magic-django-pony-iphone.html">ridiculous mascot</a>? Also, I attended both RailsConf and DjangoCon this year, and have to say that I enjoyed the latter quite a bit more. The <a href="http://railspikes.com/2008/6/27/just-say-no-to-railsconf-vegas">difference</a> in <a href="http://www.djangocon.org/conference/location/">location</a> for the two conferences may have altered my perceptions a bit, but I personally had more fun at DjangoCon. I also didn&#8217;t overhear anyone describe themselves as a &#8220;rockstar&#8221; at there, which was just fine with me.</p>
]]></content:encoded>
			<wfw:commentRss>http://rcoder.net/content/django-for-rails-devs/feed</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>For all our sakes</title>
		<link>http://rcoder.net/content/for-all-our-sakes</link>
		<comments>http://rcoder.net/content/for-all-our-sakes#comments</comments>
		<pubDate>Tue, 28 Jul 2009 17:34:00 +0000</pubDate>
		<dc:creator>lennon</dc:creator>
				<category><![CDATA[code]]></category>

		<guid isPermaLink="false">http://rcoder.net/?p=378</guid>
		<description><![CDATA[I've switched jobs twice in the last 12 months. It's certainly not unheard of in my trade to bounce around a bit, and it's not the first time I've had the experience. It has reminded me of many of the unique challenges associated with trying to quickly get up to speed with a body of existing code, and especially those idioms and misfeatures which most complicate the ramp-up process.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve switched jobs twice in the last 12 months. It&#8217;s certainly not unheard of in my trade to bounce around a bit, and it&#8217;s not the first time I&#8217;ve had the experience. It has, however, reminded me of many of the unique challenges associated with trying to quickly get up to speed with a body of existing code, and especially those idioms and misfeatures which most complicate the ramp-up process.</p>
<p>Since most of what I work on these days is web application code, the issues below will be focused there, but most of the basic concepts should hold true for most any type of programming.</p>
<p>So, here are my top three recommendations for anyone who expects other people to have to eventually read or maintain their webapp code:</p>
<h4>Logic/template separation</h4>
<p>Web developers need to be willing to switch between 4-5 languages from moment to moment: HTML, CSS, JS, SQL, and a general-purpose language for business logic. That being said, for the sake of all who will read your code after you write it (including your future self), avoid interleaving languages arbitrarily within a single logical block of code (method, source file, or module). </p>
<p>I still routinely see markup, Javascript, and Python/PHP/Ruby code mixed in the same source file, usually with one language nested inside a loop defined in a another, emitting yet another syntax for consumption by the browser.</p>
<p>If you&#8217;re generating dynamic Javascript, create a JSON array which can be iterated over by plain, static JS code, rather than interpolating values directly into JS method calls. Similarly, when producing HTML, minimize the logic in the &#8220;template&#8221; sections of code. If you&#8217;re interleaving database queries, &#8216;foreach&#8217; loops, and emission of <tt>&lt;tr&gt;</tt> and <tt>&lt;li&gt;</tt> elements, it will be nigh-impossible to change the business logic being used without also breaking the layout, and visa versa.</p>
<h4>Commented code blocks</h4>
<p>If you&#8217;re using version control, there should be no need to leave large blocks of code commented out or disabled. (If you&#8217;re not using version control, stop reading this immediately and go buy a book on Subversion, Git, or Mercurial. Come back when you have your version control workflow established.) Commit messages, revision diffs, branches, and supplementary documentation (such as a team wiki, another tool in the &#8220;must have&#8221; category) should provide a sufficient amount of sideband communication about proposed or unfinished code. </p>
<p>If you leave large amounts of inactive code lying around, on the other hand, you&#8217;re encouraging bit-rot and cargo-cult design. Your commented-out code will not have test coverage, or be kept up to date with internal API and schema changes.</p>
<p>None of this applies to <em>example</em> code &#8212; usage tips provided in comment blocks for documentation purposes are handy, as long as they&#8217;re kept up to date.  I object specifically to <em>operational</em> code which is disabled en masse rather than removed.</p>
<h4>Conventional coding</h4>
<p>Even after settling on a programming language and framework, most teams still have a lot of leeway in terms of how to structure their code. Naming conventions, whitespace, inline documentation, and module layout are usually left largely up to you. However, there are some major benefits you can realize simply by imposing some basic rules for consistent coding style across your entire project.</p>
<p>You should start with basic syntactic conventions: 4-space tabstops, braces in K&#038;R style, class names in StudlyCaps, etc. At some point, you may want to make a full cleanup pass across your codebase that does nothing but enforce these standards to avoid polluting your working patches with simple readability cleanups. </p>
<p>From there you can move on to more semantically-meaningful rules: no mutable global variables, JavaDoc/PHPDoc/Python ReST Docstrings for all public API entry points, use bind params instead of string interpolation when building SQL queries, etc.</p>
<h4>The payoff</h4>
<p>As you move through the code making these changes, you&#8217;ll find certain regular and repeated patterns emerge as the line noise of differing style and sloppy coding evaporates. <em>Now</em> you&#8217;re ready to start refactoring. Lift duplicated code into utility functions, bundle those functions into classes with shared state or domain knowledge, and then arrange those classes into useful packages.</p>
<p>Most of the responsibility for these tasks falls squarely on the shoulder of the development team. However, management has a critical role to play as well: when your developers begin grumbling about unmaintainable code, before giving them leave to start over or abandon existing working applications, press gently to see if a bit of housekeeping like what I&#8217;ve outlined above might let them work a little longer with the current implementation. </p>
<p>There are any number of reasons why an old implementation can and should be abandoned &#8212; obsolete technology, dramatically changed requirements, heavy turnover &#8212; but &#8220;ugly&#8221; or &#8220;messy&#8221; code shouldn&#8217;t be sufficient justification on its own.</p>
]]></content:encoded>
			<wfw:commentRss>http://rcoder.net/content/for-all-our-sakes/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Better late than never</title>
		<link>http://rcoder.net/content/better-late-than-never</link>
		<comments>http://rcoder.net/content/better-late-than-never#comments</comments>
		<pubDate>Tue, 10 Mar 2009 23:19:11 +0000</pubDate>
		<dc:creator>lennon</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[pdf]]></category>
		<category><![CDATA[school]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://rcoder.net/?p=361</guid>
		<description><![CDATA[I was reading a brief but interesting post surveying the current state of the art in security as programming language features, and realized that a lot of the links overlapped with the material from the paper I wrote for my security theory course a while back. Rather than re-post all of those as a blog [...]]]></description>
			<content:encoded><![CDATA[<p>I was reading a <a href="http://radian.org/notebook/languages-and-security-reading">brief but interesting</a> post surveying the current state of the art in security as programming language features, and realized that a lot of the links overlapped with the material from the paper I wrote for my <a href="http://www.cs.pdx.edu/user/coursedetails/152">security theory course</a> a while back. Rather than re-post all of those as a blog entry, I thought I should probably just put a link to the <a href="/wp-content/uploads/final-paper.pdf">finished PDF</a>.</p>
<p>Given that this was a school paper, I hope that folks will forgive the somewhat stilted grammar and obviously-academic format. If you get nothing else from it, though, the bibliography may at least be of interest.</p>
]]></content:encoded>
			<wfw:commentRss>http://rcoder.net/content/better-late-than-never/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Never do today what you can put off &#8217;til tomorrow</title>
		<link>http://rcoder.net/content/never-do-today</link>
		<comments>http://rcoder.net/content/never-do-today#comments</comments>
		<pubDate>Fri, 06 Mar 2009 00:58:18 +0000</pubDate>
		<dc:creator>lennon</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[rant]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://rcoder.net/?p=352</guid>
		<description><![CDATA[In many ways, this is a golden age for web developers: we have a bunch of good, high-level frameworks for writing apps in highly-productive dynamic languages and a solid corpus of best practices for testing, service API design, and data serialization. We don&#8217;t have to deal with dog-slow CGI scripts, complicated J2EE stacks, or proprietary [...]]]></description>
			<content:encoded><![CDATA[<p>In many ways, this is a golden age for web developers: we have a bunch of <a href="http://rubyonrails.org/">good</a>, <a href="http://github.com/sinatra/sinatra">high-level</a> <a href="http://www.djangoproject.com/">frameworks</a> for writing apps in <a href="http://ruby-lang.org/">highly-productive</a> <a href="http://python.org/">dynamic</a> <a href="http://php.net/">languages</a> and a solid corpus of best practices for <a href="http://rspec.info/">testing</a>, service <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">API design</a>, and <a href="http://www.json.org/">data serialization</a>. We don&#8217;t have to deal with dog-slow CGI scripts, complicated J2EE stacks, or proprietary ColdFusion code that only runs atop expensive application servers.</p>
<p>Unfortunately, all is not wine and roses (or scotch and bacon, or whatever). The major dynamic webapp frameworks push you by convention into doing the bulk of your application work syncronously in the request-processing loop, rather than asynchronously in a background thread. All of the accumulated wisdom about building responsive graphical user interfaces gets thrown out and re-discovered by each framework&#8217;s user community, resulting in a <a href="http://github.com/purzelrakete/workling/tree/master">multitude</a> <a href="http://backgroundrb.rubyforge.org/">of</a> <a href="http://codeforpeople.rubyforge.org/svn/bj/trunk/README">solutions</a> for the basic problem of pushing work into a queue and dealing with it later.</p>
<p>As the fine folks at Twitter so famously <a href="http://www.slideshare.net/Blaine/scaling-twitter">discovered</a>, synchronous processing puts a hard upper limit on how much (and how quickly) you can scale an application. Even at the much more modest loads my <a href="http://kenai.com/">current project</a> at work receives, there are quite a few performance problems that can&#8217;t be solved by simply throwing more stuff in memcached and hoping for the best.</p>
<p><a href="http://www.paperplanes.de/archives/2008/10/6/merbs_run_later_coming_to_a/">Some</a> <a href="http://blog.urbantastic.com/post/81336210/tech-tuesday-the-fiddly-bits">folks</a> are starting to catch on, and bake asynchronous processing into their frameworks by default, but the solutions tend to either be limited to very particular deployment and application models, or <a href="http://yaws.hyber.org/">esoteric</a> in the extreme. Meanwhile, desktop application authors continue to politely chuckle at all of our bumbling, and old-skool enterprise developers look at our hackish background-worker implementations and (rightly) consider them to be toys compared to the classic &#8220;big boy&#8221; <a href="http://www.sun.com/software/products/message_queue/index.xml">message</a> <a href="http://www-01.ibm.com/software/integration/wmq/">queueing</a> <a href="http://www.microsoft.com/windowsserver2003/technologies/msmq/default.mspx">solutions</a>, or even the newer <a href="http://www.rabbitmq.com/">open source</a> <a href="http://activemq.apache.org/">alternatives.</a></p>
<p>The next generation of web application frameworks should be designed around the idea that work is done asynchronously <em>by default</em>, with a fallback to syncronous jobs only in cases where a user needs to see the result immediately. Since applications also need to scale across a potentially large and heterogenous set of CPUs and servers, those delayed jobs also may not be running in the same memory space as the web application itself. That means machine and language-agnostic serialization, <a href="http://incubator.apache.org/thrift/">fast network IPC</a>, and callback and event-driven programming.</p>
<p>Developers who grok these concepts now will have a leg up on the competition when building tomorrow&#8217;s crop of web applications.</p>
]]></content:encoded>
			<wfw:commentRss>http://rcoder.net/content/never-do-today/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Two steps forward, one step back</title>
		<link>http://rcoder.net/content/two-steps-forward-one-step-back</link>
		<comments>http://rcoder.net/content/two-steps-forward-one-step-back#comments</comments>
		<pubDate>Wed, 11 Feb 2009 22:10:23 +0000</pubDate>
		<dc:creator>lennon</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[long]]></category>
		<category><![CDATA[rant]]></category>
		<category><![CDATA[scm]]></category>

		<guid isPermaLink="false">http://rcoder.net/?p=343</guid>
		<description><![CDATA[Once upon a time, there was RCS, and then CVS. They tracked normal edits to a set of text files reasonbly well, and coupled with telnet or ssh, even made it relatively straightforward for a trusted group of collaborators to share their changes with each other. Some people used other proprietary tools (Perforce, Visual Source [...]]]></description>
			<content:encoded><![CDATA[<p>Once upon a time, there was RCS, and then CVS. They tracked normal edits to a set of text files reasonbly well, and coupled with telnet or ssh, even made it relatively straightforward for a trusted group of collaborators to share their changes with each other. Some people used other proprietary tools (Perforce, Visual Source Safe, etc.) but they tended to be either a) expensive b) really, really lousy or c) both. Among the open source crowd, at least, CVS dominated the version control space for many years.</p>
<p>Then came Subversion. It improved on many of the failings of CVS &#8212; notably, Windows support was dramatically better, repositories could be shared over HTTP, and many operations that just didn&#8217;t work in CVS (renames, binary diffs, etc.) performed reasonably well out of the box. To this day, Subversion is a reasonable choice for many projects, especially given the advanced level of support for it in IDEs, graphical repository browsers, and the like.</p>
<p>Much of the reason for that diversity of useful tooling built atop Subversion, of course, is that it was written in C, and built with an eye towards allowing high-level languages to use bindings into the same runtime libraries upon which the &#8217;svn&#8217; command itself relied. In fact, Python, Perl, Java, and Ruby are all supported by the core Subversion maintainers, and additional bindings using those same underlying libraries are available for a number of other languages.</p>
<p>Enter the distributed version control systems: Git, Mercurial, Bazaar, Darcs, and their ilk. The basic workflow they offer is in some ways more like RCS than it is Subversion: each developer works locally against their own copy of a repository, and they share their work via patch files and periodic synchronization. (This is of course a gross over-simplifaction, as all of them offer much more sophisicated change-tracking under the hood than RCS did, but the user-visible behavior is still reminiscent.) However, their ability to maintain change history across many developers and systems without forcing everyone to eventually squash their work down into a single source tree makes a number of new modes of project management possible, or at least much easier than before.</p>
<p>All of the above DVCS systems potentially offer a huge gain of productivity for many developers, since you can easily experiment with changes locally, selectively share only those modifications which you wish to, and continue working without being connected to the central repository. (This is especially significant for those whose employers maintain draconian firewall rules and disallow off-site access to their source control.)</p>
<p>Unfortunately, none of the popular DVCS systems have anything resembling the level of cross-language API support that Subversion does. Mercurial and Bazaar are both implemented in Python, making access from other Python code quite fast, and that from any other language painfully slow. Git is implemented in C, but without a supported and documented core library of functions designed to be used to facilitate access from other languages. Darcs is written in Haskell, which means only crazy mathematicians and CS majors have any ability or interest in using it. (I&#8217;m kidding here, but the point remains that Haskell isn&#8217;t exactly the most useful substrate for scripting language bindings.)</p>
<p>The fallout from all of this is that we&#8217;re left using wrapper libraries which fork out to the command-line tools for each DVCS. Such wrappers have a number of problems: the performance sucks, the internal APIs are usually only as robust as the set of regular expressions you write to parse the output of the commands, and almost no work is shared between the various wrapper implementations.</p>
<p>Don&#8217;t get me wrong: as a simple version control tool, I&#8217;ve found Git in particular (and distributed version control in general) to be a big step up from the old centralized-repository model. However, the very eighties-esque fork-and-regexp-scrape model for IPC &#8212; coupled with the lack of an obvious &#8220;best of breed&#8221; leader in the DVCS space &#8212; means that I (along with anyone else trying to support DVCS in a general-purpose way) end up doing a lot of low-level grunt work when we could be building real value for users.</p>
<p>Even something as simple as a standard dump format for a common subset of the information available from the popular DVCS types would be a start. I do know that, for the time being, I&#8217;m stuck supporting a bunch of very brittle code which relies on the various idiosyncratic console output formats of each version-control system.</p>
<p>Playing prognosticator, I would even go so far as to suggest that the first DVCS system to provide supported, documented interfaces in a number of popular programming languages could climb to the top of the dogpile that exists currently and emerge as a clear standard.</p>
]]></content:encoded>
			<wfw:commentRss>http://rcoder.net/content/two-steps-forward-one-step-back/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Daily git-svn</title>
		<link>http://rcoder.net/content/daily-git-svn</link>
		<comments>http://rcoder.net/content/daily-git-svn#comments</comments>
		<pubDate>Tue, 20 Jan 2009 17:55:50 +0000</pubDate>
		<dc:creator>lennon</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[vcs]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://rcoder.net/?p=332</guid>
		<description><![CDATA[My team at Sun uses Subversion to host our &#8220;authoritative&#8221; source repository for Project Kenai. However, since most work is done on the trunk, many of us find it more convenient to work locally with Git, using the git svn subcommand heavily to keep ourselves up-to-date without interfering with others&#8217; work.
When I first started using [...]]]></description>
			<content:encoded><![CDATA[<p>My team at Sun uses Subversion to host our &#8220;authoritative&#8221; source repository for <a href="http://kenai.com/">Project Kenai</a>. However, since most work is done on the trunk, many of us find it more convenient to work locally with Git, using the <a href="http://www.kernel.org/pub/software/scm/git/docs/git-svn.html"><code>git svn</code></a> subcommand heavily to keep ourselves up-to-date without interfering with others&#8217; work.</p>
<p>When I first started using this combo, I had some early trouble keeping my local Git repository from getting horribly b0rked whenever there were edits made to the same files I had been working on locally. Having used CVS and Subversion for so long, I initially assumed such conflicts (and the manual merge steps they entailed) were simply part of the equation, even when working with a proper DVCS. However, by applying a little more discipline to my use of local branches, I&#8217;ve been able to basically eliminate manual merges, except in cases where the exact same line has literally been edited by multiple people.</p>
<p>My first, most critical discovery was to <em>never</em> use the <code>fetch</code> command. Instead, use <code>rebase</code>. Second, never pull the latest changes from Subversion into a working feature branch; instead, switch to your master branch, create a new branch for merging (I usually call mine &#8220;svn-merge&#8221;), and do your rebase there. After the rebase has finished, merge in your feature branch changes, and then use <code>dcommit</code> to push your changes upstream.</p>
<p>As an example, here are to commands I would use to check out a new local Git clone of the main Subverion repository, work on a single command, and then push it back into SVN:</p>
<pre>viper:Work$ git svn clone https://example.com/svn/repo/trunk -r500:HEAD repo
# ... lots of Git output here ...
viper:Work$ cd repo
viper:repo$ git checkout -b issue-123
# ... hack, hack, hack...
viper:repo$ git commit -m "fix for issue #123"
viper:repo$ git checkout master
viper:repo$ git checkout -b svn-merge
viper:repo$ git svn rebase
# ... watch results for conflicts ...
viper:repo$ git merge --squash issue-123
viper:repo$ git commit -m "ISSUE-123: fixed"
viper:repo$ git svn dcommit -e
# ... $EDITOR launches, allows you to write useful commit message for svn ...
viper:repo$ git checkout master
viper:repo$ git merge svn-merge</pre>
<p>This may seem like a lot of extra branch switching, localized commits, etc., but the end result has been worth it (for me, at least). If you following this process, you can be relatively certain that your master branch will only ever mirror changes that have been made in Subversion.</p>
<p>Insuring that the master branch is always &#8220;clean&#8221; (i.e., has no conflicting commits) with regard to the shared svn tree makes it easy to switch temporarily to another feature branch if you have an urgent bugfix or simple change to make, while your bigger changes happily sit on another feature branch waiting to be pushed.</p>
<p><strong>Updated Mar. 4, 2009:</strong> Changed merge to use <code>--squash</code> option, so that many local Git commits can be combined into a single upstream revision.</p>
]]></content:encoded>
			<wfw:commentRss>http://rcoder.net/content/daily-git-svn/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Killfile 2.0</title>
		<link>http://rcoder.net/content/killfile-2</link>
		<comments>http://rcoder.net/content/killfile-2#comments</comments>
		<pubDate>Tue, 25 Nov 2008 19:24:02 +0000</pubDate>
		<dc:creator>lennon</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[short]]></category>

		<guid isPermaLink="false">http://rcoder.net/?p=320</guid>
		<description><![CDATA[There&#8217;s been an persistent blog-wank-fest making the rounds over the last few weeks about the state of the Ruby community: whether it&#8217;s become more or less &#8220;fun&#8221;, &#8220;creative&#8221;, etc. I&#8217;m not going to reward any of the participants with a link, but I do offer the following balm if you, like me, are a bit [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been an persistent blog-wank-fest making the rounds over the last few weeks about the state of the Ruby community: whether it&#8217;s become more or less &#8220;fun&#8221;, &#8220;creative&#8221;, etc. I&#8217;m not going to reward any of the participants with a link, but I do offer the following balm if you, like me, are a bit sick of hearing about it:</p>
<pre>
%w(open-uri rss resolv uri rubygems hpricot).each {|lib| require lib }

blog_url = ARGV.shift

blog_hdoc = Hpricot.parse(open(blog_url))
rss_links = blog_hdoc / :head / 'link[@type="application/rss+xml"]'

feed_rss = RSS::Parser.parse(rss_links.first['href'])

rants = feed_rss.items.select {|i| t = i.title; t =~ /rant/i &amp;&amp; t =~ /ruby/i }

if rants.empty?
  puts "Okay, you get a pass."
else
  puts "Bad blogger! No biscuit!"
  hostname = URI.parse(blog_url).host
  ip_addr = Resolv.getaddress(hostname)
  `sudo route add -host #{hostname} gw 127.0.0.1`
end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://rcoder.net/content/killfile-2/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Granting just enough power, but no more</title>
		<link>http://rcoder.net/content/granting-just-enough-power-but-no-more</link>
		<comments>http://rcoder.net/content/granting-just-enough-power-but-no-more#comments</comments>
		<pubDate>Thu, 13 Nov 2008 00:32:17 +0000</pubDate>
		<dc:creator>lennon</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://rcoder.net/?p=308</guid>
		<description><![CDATA[Sometimes you have a group of users who need to run certain commands on a server, and no others. It&#8217;s not necessarily that you don&#8217;t trust them. The point is simply that they don&#8217;t need a full-blown shell account, and you&#8217;re understandably reluctant to give it to them.
There are countless ways to set up a [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes you have a group of users who need to run certain commands on a server, and no others. It&#8217;s not necessarily that you don&#8217;t trust them. The point is simply that they don&#8217;t <em>need</em> a full-blown shell account, and you&#8217;re understandably reluctant to give it to them.</p>
<p>There are countless ways to set up a restricted account that can use only certain commands, but most of them are either extremely special-purpose, or rather difficult to set up. (Locking down SSH sessions inside a chroot jail, for example, requires almost as work as just setting up a dedicated virtual machine for your untrusted users.)</p>
<p>Furthermore, none of the existing solutions were written by me, to address exactly the needs I have for such a &#8220;sandbox&#8221; environment. Most notably, I don&#8217;t want users to even have to remember which commands are available to them. In many cases, they may only be using these tools every few months, and remembering cryptic UNIX-y command paths and syntax is hard enough even when you use something every day.</p>
<p>And so, I give you <a href="http://github.com/rcoder/menush/tree/master">menush</a>, a simple shell replacement which presents users with a list of available commands from which the user may choose. It loops until the user exits via the menu (or uses Ctrl-C/Ctrl-D to end the session).</p>
<p>To set it up on your own server, you&#8217;ll need to copy the file into a known location (say, <code>/usr/local/sbin</code>), then add a line to your <code>/etc/shells</code> file pointing to it. For each user you want to lock into a sandbox, edit their password entry using <code>vipw</code> (or your <code>passwd</code> editing method of choice) and change the last field from <code>/bin/bash</code> or similar to the full path to <code>menush</code>.</p>
<p>Then, create the directory <code>/etc/menush</code>, and write your default menu file (<code>/etc/menush/__default__</code>). On startup, <code>menush</code> will look in that directory for a file with the same name as the user being logged in; if that file is absent, the default will be loaded instead. The format for the menu files is documented in the README, but it&#8217;s just a YAML file. (Also, bonus points for the first person to correctly identify the gaping security hole in the provided example.)</p>
<p>The code is written in a fairly portable, POSIX-y style, so it should work on Linux, BSD, or OS X. Feel free to send me suggestions, pull requests, or rants about the horrible security holes I left because I banged this whole thing out in like two hours and then spent a bunch of time blogging about it instead of reviewing my own code.</p>
]]></content:encoded>
			<wfw:commentRss>http://rcoder.net/content/granting-just-enough-power-but-no-more/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
