<?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>No, I am better than that! &#187; Web</title>
	<atom:link href="http://rickosborne.org/blog/category/programming/web/feed/" rel="self" type="application/rss+xml" />
	<link>http://rickosborne.org/blog</link>
	<description>Striving to subdue the mediocrity.</description>
	<lastBuildDate>Sun, 21 Aug 2011 23:27:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Bind SERVFAIL on slave zone</title>
		<link>http://rickosborne.org/blog/2011/08/bind-servfail-on-slave-zone/</link>
		<comments>http://rickosborne.org/blog/2011/08/bind-servfail-on-slave-zone/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 05:53:11 +0000</pubDate>
		<dc:creator>Rick Osborne</dc:creator>
				<category><![CDATA[Web]]></category>
		<guid isPermaLink="false">http://rickosborne.org/blog/?p=1322</guid>
		<description><![CDATA[This is for my own future reference. I had a problem earlier tonight where the slave DNS server my domains wouldn&#8217;t return anything but SERVFAIL for any domain. The server was up and running and the config files hadn&#8217;t changed, but it just wouldn&#8217;t give any useful answers. The log (in /var/log/named/bind.log) only gave messages [...]]]></description>
			<content:encoded><![CDATA[<p>This is for my own future reference.</p>
<p>I had a problem earlier tonight where the slave DNS server my domains wouldn&#8217;t return anything but SERVFAIL for any domain.  The server was up and running and the config files hadn&#8217;t changed, but it just wouldn&#8217;t give any useful answers.</p>
<p>The log (in <kbd>/var/log/named/bind.log</kbd>) only gave messages like:</p>
<pre>general: warning: zone rickosborne.org/IN: expired</pre>
<p>I tried using <kbd>rndc</kbd> on the slave to retransfer the zones, upped the debug trace logging, and even eventually stopped and restarted Bind.  No change.</p>
<p>On a whim, I restarted the master Bind.  This produced a more useful error:</p>
<pre>security: error: client a.b.c.d#nnn: request has invalid signature: TSIG rickosborne: tsig
 verify failure (BADTIME)</pre>
<p>That <kbd>BADTIME</kbd> message comes up when the clocks on the master and slave get more than 5 minutes out of sync.  The master server&#8217;s clock was off by ~15 minutes.</p>
<p>The virtual server, running on Xen, ignored any attempts to set the clock.  I tried plain old <kbd>date</kbd> and <kbd>ntpdate</kbd>, and both appeared to work, but were actually silently ignored.  There&#8217;s a magical incantation to fix that:</p>
<pre>echo 1 &gt; /proc/sys/xen/independent_wallclock</pre>
<p>So, yeah.  That was a fun 2 hours of my life to track down and fix.  I hope it helps someone else.</p>
]]></content:encoded>
			<wfw:commentRss>http://rickosborne.org/blog/2011/08/bind-servfail-on-slave-zone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Because no one in Web Dev uses interfaces</title>
		<link>http://rickosborne.org/blog/2011/03/because-no-one-in-web-dev-uses-interfaces/</link>
		<comments>http://rickosborne.org/blog/2011/03/because-no-one-in-web-dev-uses-interfaces/#comments</comments>
		<pubDate>Fri, 25 Mar 2011 00:26:09 +0000</pubDate>
		<dc:creator>Rick Osborne</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[adb]]></category>
		<category><![CDATA[couchdb]]></category>
		<category><![CDATA[mongodb]]></category>
		<guid isPermaLink="false">http://rickosborne.org/blog/?p=1305</guid>
		<description><![CDATA[One of my long-standing assertions is that perfect OOP is amusing and all, but it tends to stumble a bit when it comes to web development. Interfaces are my go-to example for this. How often, in everyday real-world web development, are you suddenly going to need to swap out one Model class for another? &#8220;Well, [...]]]></description>
			<content:encoded><![CDATA[<p>One of my long-standing assertions is that perfect OOP is amusing and all, but it tends to stumble a bit when it comes to web development.  Interfaces are my go-to example for this.  How often, in everyday real-world web development, are you suddenly going to need to swap out one Model class for another?  &ldquo;Well, it&#8217;s Tuesday, so we need to load the Oracle layer instead of the Access layer.&rdquo;</p>
<p>To prove myself wrong, I built interfaces into this term&#8217;s <em>Advanced Database Structures</em> final exam practical.  The course has changed a bit since I started teaching it almost 2 years ago (holy crap!).  The core objectives are the same, but the underlying technology has been migrated to CouchDB and MongoDB.</p>
<p>From the exam instructions:</p>
<blockquote><p>You will be refactoring an existing application to work against a MongoDB database and a CouchDB database.  The codebase has been set up so that the application works as-is against a MySQL database and you can easily switch back and forth between each of the databases without having to modify anything other than the two Model classes you are responsible for.</p></blockquote>
<p class="noindent" style="float:right;margin:0 0 1.5em 1.5em"><a href="/blog/wp-content/uploads/2011/03/fsail-home.png"><img src="/blog/wp-content/uploads/2011/03/fsail-home-300x195.png" title="fsa.il link shortening service" width="300" height="195" class="aligncenter" /></a></p>
<p>The application I give them is a really simple proof-of-concept link shortening service called &ldquo;<kbd>fsa.il</kbd>&rdquo; and works the same way any other does: you input a long URL and your name, and you get a short URL back.  You can also come back later and track click-through and referring URL statistics.</p>
<p>Along the top of the page are tabs for three persistence layer choices: MySQL, MongoDB, and CouchDB.  The code they are given to start has a service that keeps track of your preferred data layer in your Session and handles all of the object creation for you.  The students, who built the MySQL version of the app for last month&#8217;s final exam, are given a working MySQL class, an interface for the persistence layer, and two stubbed-out skeleton classes for the other two layers.  Oh, and data dumps for quick import into all three layers.</p>
<p class="noindent" style="float:right; margin: 0 0 1em 1em;"><a href="/blog/wp-content/uploads/2011/03/php-impl.png"><img src="/blog/wp-content/uploads/2011/03/php-impl-300x149.png" alt="" title="Exam: Build out classes to talk to CouchDB and MongoDB" width="300" height="149" class="aligncenter size-medium wp-image-1314" /></a></p>
<p>That&#8217;s it.  That&#8217;s the exam.  The students just need to make the app work against the other two databases.  The interface definition is only five functions, and ends up yielding ~150-200 lines of code they need to bang out over 3&frac12; hours.</p>
<p>I think it&#8217;s a fun exam, but more importantly it&#8217;s a great piece for each student&#8217;s portfolio.  How much of a rock star would you look like on an interview if you could show a piece of code that worked against both relational and non-relational persistence layers without a truckload of third-party code?</p>
<p>It&#8217;s interesting writing code that will work against all three layers at the same time.  Naming conventions play a big part.  It&#8217;s easy in SQL to write a query that aliases column names to something friendlier to code:</p>
<pre class="sql">SELECT
    id AS linkID,
    long_url AS longURL,
    creator_name AS fullName,
    created_date AS createdDate
FROM link_links
WHERE (id = :linkId)</pre>
<p>And while you <em>could</em> use Map functions in CouchDB and MongoDB to alias your document field names, that seems like a heckuva waste.  Instead, you have to think about it a little bit harder beforehand.  If you don&#8217;t, you end up doing translation of array key names at the Model layer, which again seems sub-optimal.</p>
<p class="noindent" style="float:right; margin: 0 0 1em 1em;"><a href="/blog/wp-content/uploads/2011/03/mongo-console.png"><img src="/blog/wp-content/uploads/2011/03/mongo-console-300x174.png" alt="" title="The MongoDB Console" width="300" height="174" class="aligncenter size-medium wp-image-1310" /></a></p>
<p>The seemingly-minor differences between the implementations of Map/Reduce in CouchDB and MongoDB also some into play.  For example, when using the <kbd>group()</kbd> method in MongoDB you get an array back instead of a cursor, which means you can&#8217;t chain the <kbd>sort()</kbd> or <kbd>limit()</kbd> methods and have to do those in your Model.</p>
<p class="noindent" style="float:right;margin:0 0 1.5em 1.5em;"><a href="/blog/wp-content/uploads/2011/03/couchdb-futon.png"><img src="/blog/wp-content/uploads/2011/03/couchdb-futon-300x169.png" alt="" title="Editing a document in CouchDB Futon" width="300" height="169" class="aligncenter size-medium wp-image-1309" /></a></p>
<p>Sorting in CouchDB can also be tricky.  CouchDB assumes that you want to sort by your key and doesn&#8217;t give you any way to sort by value, making Top 10 lists a real pain to do.  You&#8217;re back to sorting in your Model.</p>
<p>String manipulation functions are another friction point.  SQL has a bevy of them, such as <kbd>LEFT()</kbd> and even the dreaded <kbd>LIKE</kbd>.  No such luck in either MongoDB or CouchDB.  You have to fake them in JavaScript.  Compare:</p>
<pre class="sql">WHERE (LEFT(:link, link_len) = link_start)</pre>
<p>Versus:</p>
<pre class="javascript">function(obj, prev) {
    if("http://".substr(0, obj.linkLen) === obj.linkStart)
        prev.count++;
}</pre>
<p>While that&#8217;s doable, and arguably potentially more powerful, it certainly isn&#8217;t what I would call <em>elegant</em>.  Similarly, CouchDB&#8217;s <kbd>startkey</kbd> and <kbd>endkey</kbd> parameters are nice and speedy, but there are times when I&#8217;d kill for a <kbd>keycontains</kbd> parameter.</p>
<p>More to the point, I think the course is teaching great skills.  Not only do students get to play with a variety of databases<sup>1</sup>, but they also get to see how easy it is to decouple layers of an application.  It&#8217;s nice that they get to muck around in Map/Reduce and REST APIs and what not, but the architectural and problem-solving lessons will take them so much further.</p>
<p>Oh, and just to head anyone off at the pass, the exam is done in PHP because working with MongoDB in PHP is stupid easy, while in ColdFusion it&#8217;s not for the faint of heart<sup>2</sup>.  The underlying Java library is usable, but requires a whole lot of syntactic icing.  That is, a metric ton of <kbd>javaCast</kbd> calls and type paranoia.  While that might be great for the students to encounter on a take-home assignment, it&#8217;s not something they need to be tripping over on a timed exam.  And yes, there are some great MongoDB libraries available for ColdFusion, but the point of the exam is to have the students show that they can do it themselves.</p>
<hr/>
<ol>
<li>
<p>If I had another 3 hours on the exam I would totally make the students add in layers for Sqlite and XML.</p>
</li>
<li>
<p>JSON-related quirks aside, using CouchDB requires an equivalent effort level from both PHP and ColdFusion.  Yay REST API.</p>
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://rickosborne.org/blog/2011/03/because-no-one-in-web-dev-uses-interfaces/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>PHP-FW/1</title>
		<link>http://rickosborne.org/blog/2011/02/php-fw1/</link>
		<comments>http://rickosborne.org/blog/2011/02/php-fw1/#comments</comments>
		<pubDate>Tue, 08 Feb 2011 21:36:18 +0000</pubDate>
		<dc:creator>Rick Osborne</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[fw/1]]></category>
		<category><![CDATA[php]]></category>
		<guid isPermaLink="false">http://rickosborne.org/blog/?p=1302</guid>
		<description><![CDATA[Short version: I ported FW/1 to PHP. Long version: I&#8217;ve been using Sean Corfield&#8217;s Framework/1 as a teaching tool for ~18 months. It&#8217;s been going well, as I find FW/1 is one of the few frameworks that doesn&#8217;t suck. It&#8217;s easy to set up, easy to configure, and it mostly stays out of your way. [...]]]></description>
			<content:encoded><![CDATA[<p>Short version: <a href="https://github.com/rickosborne/php-fw1">I ported FW/1 to PHP.</a></p>
<p>Long version:</p>
<p>I&#8217;ve been using <a href="https://github.com/seancorfield/fw1/" rel="external" target="_blank">Sean Corfield&#8217;s Framework/1</a> as a teaching tool for ~18 months.  It&#8217;s been going well, as I find <a href="/blog/2009/12/coldfusion-fw1-mvc-framework/">FW/1 is one of the few frameworks that doesn&#8217;t suck</a>.  It&#8217;s easy to set up, easy to configure, and it mostly stays out of your way.</p>
<p>This month, we switched things around a bit at the University.  The server-side classes have been, well, rotated.  Instead of one term of in-depth PHP followed by one term of in-depth ColdFusion, we now teach one term of entry-level PHP and ColdFusion, followed by one term of advanced PHP, ColdFusion, and other server-side languages and frameworks.  Long story short, I needed a good MVC framework to use to show off the PHP side of things.</p>
<p>Unfortunately, it seems like most PHP MVC frameworks are big, lumbering beasts.  (To be fair, so are most CF MVC frameworks.)  CodeIgniter, for example, is a couple hundred files.<sup>1</sup>  It may be an awesome framework, but I can&#8217;t very well spend more class time installing and configuring the thing than actually building something with it.</p>
<p>I also needed to sharpen my PHP skills, as I haven&#8217;t done any <em>serious</em> PHP work in years.  So, as an exercise, I started porting FW/1 to PHP.  I thought I would eventually hit a wall, but I didn&#8217;t.  It turns out that FW/1 is simple enough that even my rusty PHP skills could make it work.</p>
<p>The code has now undergone enough revisions, and I&#8217;m using it in a couple of internal projects, such that I feel it can be released.  I&#8217;ve set up a GitHub repo here:</p>
<p><a href="https://github.com/rickosborne/php-fw1">https://github.com/rickosborne/php-fw1</a></p>
<p>There are a few minor changes, mostly owing to nitpicking language differences, and a few big ones, such as the lack of subsystem code.<sup>2</sup>  But it works, and I think it works surprisingly well. YMMV, of course.</p>
<p>-R</p>
<hr/>
<ol>
<li>
<p>An install of Cake is almost 1000 files.  WTF?  Seriously?</p>
</li>
<li>
<p>There&#8217;s nothing bad about the subsystem code in the original version, I just didn&#8217;t need it.</p>
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://rickosborne.org/blog/2011/02/php-fw1/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

