<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>David Cassel</title>
	
	<link>http://blog.davidcassel.net</link>
	<description>on Software Development and Entrepreneurism</description>
	<lastBuildDate>Tue, 24 Apr 2012 14:26:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/DavidCassel" /><feedburner:info uri="davidcassel" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Converting CSV to XML</title>
		<link>http://feedproxy.google.com/~r/DavidCassel/~3/MAjJh7LsbRo/</link>
		<comments>http://blog.davidcassel.net/2012/04/converting-csv-to-xml/#comments</comments>
		<pubDate>Tue, 24 Apr 2012 02:48:08 +0000</pubDate>
		<dc:creator>Dave Cassel</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[csv]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[marklogic]]></category>
		<category><![CDATA[xquery]]></category>

		<guid isPermaLink="false">http://blog.davidcassel.net/?p=399</guid>
		<description><![CDATA[I just published an XQuery library to GitHub to convert lines of Comma Separated Value data to XML. That can probably be done more simply if you don&#8217;t care what the XML looks like, but I wanted to build templates so that I could get good structure. I also built in an action mechanism, so that [...]]]></description>
			<content:encoded><![CDATA[<p>I just <a href="https://github.com/dmcassel/blog-code">published an XQuery library to GitHub</a> to convert lines of Comma Separated Value data to XML. That can probably be done more simply if you don&#8217;t care what the XML looks like, but I wanted to build templates so that I could get good structure. I also built in an action mechanism, so that you can apply functions as the XML gets built. That makes it easy to format dates nicely, do geocoding, or whatever you need.</p>
<p>My GitHub repo has the library in the context of <a href="https://github.com/marklogic/roxy">a Roxy framework</a> so that I could write some unit tests. Those tests not only give me confidence that the code works, they also show you how to use the code. Here&#8217;s an example template I used in a unit test:</p>
<pre>&lt;curio:item&gt;
  &lt;curio:type src="1"/&gt;
  &lt;curio:name src="2"/&gt;
  &lt;curio:location&gt;
    &lt;curio:label src="3"/&gt;
  &lt;/curio:location&gt;
  &lt;curio:acquired-date&gt;
    &lt;curio:start src="4" ns="http://davidcassel.net/csv" action="reformat-date"/&gt;
    &lt;curio:end src="5" ns="http://davidcassel.net/csv" action="reformat-date"/&gt;
  &lt;/curio:acquired-date&gt;
  &lt;curio:description src="6"/&gt;
  &lt;curio:notes src="7"/&gt;
  &lt;curio:owner src="8"/&gt;
&lt;/curio:item&gt;</pre>
<p>As you can see, a lot of the elements have a &#8220;src&#8221; attribute. The number corresponds to a field position in the CSV line. If the corresponding value is empty, the element gets skipped. The &#8220;ns&#8221; and &#8220;action&#8221; attributes specify a function that you want to run on an element after it has values put in. (At some point, I&#8217;ll try to add an &#8220;at&#8221; attribute so you can specify the library module; right now it&#8217;s assumed to be in csv-lib.xqy.) Although my examples have the action attribute on leaf nodes, it can be higher up the chain.</p>
<p>Here&#8217;s an example CSV line:</p>
<pre>pin,Pilatus,"Pilatus mountain",7/1/1984,7/31/1984,,"a word, and another",dcassel</pre>
<p>The library will handle commas embedded in quoted strings. And for completeness, here&#8217;s the generated XML:</p>
<pre>&lt;curio:item xmlns:curio="http://davidcassel.net/curio"&gt;
  &lt;curio:type&gt;pin&lt;/curio:type&gt;
  &lt;curio:name&gt;Pilatus&lt;/curio:name&gt;
  &lt;curio:location&gt;
    &lt;curio:label&gt;Pilatus mountain&lt;/curio:label&gt;
  &lt;/curio:location&gt;
  &lt;curio:acquired-date&gt;
    &lt;curio:start&gt;1984-07-01&lt;/curio:start&gt;
    &lt;curio:end&gt;1984-07-31&lt;/curio:end&gt;
  &lt;/curio:acquired-date&gt;
  &lt;curio:notes&gt;a word, and another&lt;/curio:notes&gt;
  &lt;curio:owner&gt;dcassel&lt;/curio:owner&gt;
&lt;/curio:item&gt;</pre>
<p>After you&#8217;ve downloaded the repo, here are the steps for you to be able to run the unit tests:</p>
<ol>
<li>Check whether the ports I&#8217;m using conflict with any app servers you already have set up. You&#8217;ll find them in deploy/build.properties (app-port, test-port, xcc-port)</li>
<li>./ml local bootstrap  &lt;&#8211; use ml.bat if you&#8217;re on Windows</li>
<li>./ml local restart  &lt;&#8211; if necessary &#8212; output from step 1 will tell you if you need to restart</li>
<li>./ml local deploy modules</li>
</ol>
<p>Assuming all went well, you should now be able to point your browser to http://localhost:8022/test/ and run the csv-lib unit tests.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/11_a9_290Gg9zPKT-gWy7yaIF8E/0/da"><img src="http://feedads.g.doubleclick.net/~a/11_a9_290Gg9zPKT-gWy7yaIF8E/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/11_a9_290Gg9zPKT-gWy7yaIF8E/1/da"><img src="http://feedads.g.doubleclick.net/~a/11_a9_290Gg9zPKT-gWy7yaIF8E/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DavidCassel/~4/MAjJh7LsbRo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.davidcassel.net/2012/04/converting-csv-to-xml/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.davidcassel.net/2012/04/converting-csv-to-xml/</feedburner:origLink></item>
		<item>
		<title>Priority Task Spawning in MarkLogic 5</title>
		<link>http://feedproxy.google.com/~r/DavidCassel/~3/jdjEFGKCFLM/</link>
		<comments>http://blog.davidcassel.net/2012/02/priority-task-spawning-in-marklogic-5/#comments</comments>
		<pubDate>Thu, 01 Mar 2012 01:22:21 +0000</pubDate>
		<dc:creator>Dave Cassel</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[marklogic]]></category>
		<category><![CDATA[new feature]]></category>
		<category><![CDATA[xquery]]></category>

		<guid isPermaLink="false">http://blog.davidcassel.net/?p=390</guid>
		<description><![CDATA[MarkLogic has long had the ability to spawn tasks, consisting of a module, a set of variables and some options. Those tasks go into the task queue and get worked off by the configured number of threads. A new feature in MarkLogic 5 gives a new option: higher priority tasks. Let&#8217;s take a look at [...]]]></description>
			<content:encoded><![CDATA[<p>MarkLogic has long had the ability to spawn tasks, consisting of a module, a set of variables and some options. Those tasks go into the task queue and get worked off by the configured number of threads. A new feature in MarkLogic 5 gives a new option: higher priority tasks. Let&#8217;s take a look at how that works.</p>
<p>My local instance of MarkLogic is configured for 16 task server threads, which I can see by going to Configure -&gt; Groups -&gt; Default -&gt; Task Server in the Admin UI. By clicking on the Status tab here, I&#8217;ll be able to watch the tasks get worked off.</p>
<h2>Normal Priority</h2>
<p>To play with the queue, I&#8217;ll start by setting up a simple module to simulate a long running task. I&#8217;ll call this write-log.xqy:</p>
<pre>xquery version "1.0-ml";

declare variable $priority external;
declare variable $id external;

xdmp:sleep(5000),
xdmp:log(fn:concat("task priority: ", $priority, "; id=", $id))</pre>
<p>Sleep for 5 seconds, then write out the parameters. Very simple. Now I&#8217;ll fire up Query Console and spawn a bunch of these tasks:</p>
<pre>for $i in (1 to 500)
let $priority := "normal"
return
  xdmp:spawn(
    "/write-log.xqy",
    (xs:QName("priority"), $priority,
     xs:QName("id"), $i),
    &lt;options xmlns="xdmp:eval"&gt;&lt;priority&gt;{$priority}&lt;/priority&gt;&lt;/options&gt;
  )</pre>
<p>I spawn 500 tasks with &#8220;normal&#8221; priority. After running this, I can refresh the Task Server Status page and see a bunch of tasks in the queue, getting worked off by the 16 threads. Watching the log file, I see 16 of the log messages bunched together as the threads wrap up around the same time; then 5 seconds later, another group of 16.</p>
<h2>Higher Priority</h2>
<p>The new option in MarkLogic 5 is to choose between &#8220;normal&#8221; and &#8220;higher&#8221; priority. Let&#8217;s see what happens when they mix. We&#8217;ll use the same write-log.xqy as before, but we&#8217;ll change what we do in Query Console:</p>
<pre>for $i in (1 to 500)
let $priority := if ($i &lt;= 250) then "normal" else "higher"
return
  xdmp:spawn(
    "/write-log.xqy",
    (xs:QName("priority"), $priority,
     xs:QName("id"), $i),
    &lt;options xmlns="xdmp:eval"&gt;&lt;priority&gt;{$priority}&lt;/priority&gt;&lt;/options&gt;
  )</pre>
<p>We launch 250 normal priority tasks followed by 250 higher priority tasks. Higher priority tasks get a separate queue and their own batch of threads. That means that both sets of tasks can proceed in parallel. We see this when we look at the Task Server Status page and see 32 running threads, and in the log file where we see 32 of the log messages bunched together. Tasks 1-16 and tasks 251-266 complete around the same time; about five seconds later, we see tasks 17-32 and tasks 267-282.</p>
<h2>Using Priorities</h2>
<p>From the way this works, an application can have most tasks running as normal priority, but when higher priority tasks come along, they&#8217;ll get to run without interrupting the normal ones. If you make heavy use of the higher priority tasks, be conscious of the extra threads that will be run on your behalf.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/QfFFhnDU8x_ag2LcZeGjihXGXu8/0/da"><img src="http://feedads.g.doubleclick.net/~a/QfFFhnDU8x_ag2LcZeGjihXGXu8/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/QfFFhnDU8x_ag2LcZeGjihXGXu8/1/da"><img src="http://feedads.g.doubleclick.net/~a/QfFFhnDU8x_ag2LcZeGjihXGXu8/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DavidCassel/~4/jdjEFGKCFLM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.davidcassel.net/2012/02/priority-task-spawning-in-marklogic-5/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.davidcassel.net/2012/02/priority-task-spawning-in-marklogic-5/</feedburner:origLink></item>
		<item>
		<title>Range Indexes and Empty Elements</title>
		<link>http://feedproxy.google.com/~r/DavidCassel/~3/h_EQ97cfuP4/</link>
		<comments>http://blog.davidcassel.net/2012/02/range-indexes-and-empty-elements/#comments</comments>
		<pubDate>Thu, 23 Feb 2012 01:11:06 +0000</pubDate>
		<dc:creator>Dave Cassel</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[marklogic]]></category>
		<category><![CDATA[xquery]]></category>

		<guid isPermaLink="false">http://blog.davidcassel.net/?p=387</guid>
		<description><![CDATA[I&#8217;ve started a couple posts lately, only to find them more complex than expected. So to get myself back on the board, tonight you get a pretty simple one, based on an error one of my colleagues encountered recently. Suppose we have an int range element index set up on &#60;count/&#62; in our MarkLogic database. xdmp:document-insert( [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve started a couple posts lately, only to find them more complex than expected. So to get myself back on the board, tonight you get a pretty simple one, based on an error one of my colleagues encountered recently. Suppose we have an int range element index set up on &lt;count/&gt; in our MarkLogic database.</p>
<pre>xdmp:document-insert(
  "/test.xml",
  &lt;doc&gt;
    &lt;count/&gt;
  &lt;/doc&gt;
)</pre>
<p>This triggers an error:</p>
<p>[1.0-ml] XDMP-RANGEINDEX: xdmp:eval(&#8220;xdmp:document-insert(&amp;#10; &amp;quot;/test.xml&amp;quot;,&amp;#10; &lt;doc&gt;&amp;#&#8230;&#8221;, (), &lt;options xmlns=&#8221;xdmp:eval&#8221;&gt;&lt;database&gt;13528717381355350321&lt;/database&gt;&lt;root&gt;/Users/dcassel/gi&#8230;&lt;/options&gt;) &#8212; Range index error: int fn:doc(&#8220;/test.xml&#8221;)/doc/count: XDMP-CAST: (err:FORG0001) Invalid cast: xs:untypedAtomic(&#8220;&#8221;) cast as xs:int</p>
<p>So what&#8217;s going on? When you set up a range index on an element, MarkLogic will add any new values to the index. The value of the &lt;count/&gt; element above is &#8220;&#8221; (empty string), which has no valid interpretation as a number. You&#8217;ll encounter the same problem with any non-string element or attribute range index (I see it a lot with dates that don&#8217;t match the required format).</p>
<h2>The Solution</h2>
<p>There are basically two choices if you don&#8217;t have an actual value to put in an element. The first is to assume a sensible default. For an element called count, that&#8217;s probably zero. The other approach is to skip the element altogether. While that can be simple for the insert, it does make an update a little more complex, as you need to check whether you will insert a element or replace an existing one:</p>
<pre>declare function local:update-count($doc, $new-ct)
{
  if (fn:exists($doc/count)) then
    xdmp:node-replace($doc/count, &lt;count&gt;{$new-ct}&lt;/count&gt;)
  else
    xdmp:node-insert-child($doc, &lt;count&gt;{$new-ct}&lt;/count&gt;)
};</pre>
<p>Besides complexity, the other factor to consider is whether a missing value is likely to be provided later. If the value might never be provided (for instance, you have a lot of possible elements, but only a few usually get filled), then you&#8217;re better off skipping them &#8212; the empty elements don&#8217;t server a purpose. If it is likely that an element will get a value, then populating it with a reasonable default keeps your code a little simpler.</p>
<p>&nbsp;</p>

<p><a href="http://feedads.g.doubleclick.net/~a/kMrF7mlffRVkrondW0yqI-SHe3M/0/da"><img src="http://feedads.g.doubleclick.net/~a/kMrF7mlffRVkrondW0yqI-SHe3M/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/kMrF7mlffRVkrondW0yqI-SHe3M/1/da"><img src="http://feedads.g.doubleclick.net/~a/kMrF7mlffRVkrondW0yqI-SHe3M/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DavidCassel/~4/h_EQ97cfuP4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.davidcassel.net/2012/02/range-indexes-and-empty-elements/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.davidcassel.net/2012/02/range-indexes-and-empty-elements/</feedburner:origLink></item>
		<item>
		<title>Sneak Peak: ImageMagick in MarkLogic</title>
		<link>http://feedproxy.google.com/~r/DavidCassel/~3/QSpqnzkLhPY/</link>
		<comments>http://blog.davidcassel.net/2012/01/sneak-peak-imagemagick-in-marklogic/#comments</comments>
		<pubDate>Thu, 12 Jan 2012 19:38:49 +0000</pubDate>
		<dc:creator>Dave Cassel</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[CurioVault]]></category>
		<category><![CDATA[image magick]]></category>
		<category><![CDATA[marklogic]]></category>
		<category><![CDATA[sneak peak]]></category>
		<category><![CDATA[xquery]]></category>

		<guid isPermaLink="false">http://blog.davidcassel.net/?p=380</guid>
		<description><![CDATA[Today I get to give you a sneak peak into a feature that's not yet officially present, but you'll find if you know where to look: XQuery-level integration with ImageMagick! In this post I demonstrate automatically scaling down large images for CurioVault.com. ]]></description>
			<content:encoded><![CDATA[<p>Today I get to give you a sneak peak into a feature that&#8217;s not yet officially present, but you&#8217;ll find if you know where to look: XQuery-level integration with ImageMagick!</p>
<p>Before we go any further, let&#8217;s be clear that this is neither documented nor supported in the current version &#8212; and if it becomes official, the interface with the feature may very well change. If you are interested in this feature, please contact <a href="mailto:Stephen.Buxton@marklogic.com">Stephen Buxton</a> in Product Management and let him know.</p>
<p>With all that out of the way, let&#8217;s take a look.</p>
<p><a href="http://www.imagemagick.org/script/index.php" target="_blank">ImageMagick</a> is &#8220;a software suite to create, edit, compose or convert bitmap images&#8221;, as stated on its web site. If you have ImageMagick installed on your server when MarkLogic 5 starts up, you&#8217;ll see something like this line slide by in your ErrorLog.txt:</p>
<blockquote>
<pre>2012-01-09 17:10:41.557 Info: ImageMagick 6.7.4-4 2012-01-09 Q16 http://www.imagemagick.org</pre>
</blockquote>
<p>If you don&#8217;t have it installed, you&#8217;ll still see some reference to ImageMagick, but it will be a message indicating that it was not able to load ImageMagick.</p>
<p>Regular readers will have seen that I&#8217;m now running a site with the MarkLogic Express license: <a title="CurioVault" href="http://www.curiovault.com" target="_blank">CurioVault.com</a>. The site lets users upload information about collectibles they have, including when and where they got the item, an interesting story connected to it, and a picture of it. CurioVault is more about the stories than the pictures. It&#8217;s not Flickr &#8212; I don&#8217;t want the site to get bogged down with a bunch of multi-megabyte images. So, I set up the code so that I can specify a maximum size for an image in bytes, and automatically scale down any uploaded images that exceed that size. I also set up a maximum image dimension (in pixels) to use when scaling. Here&#8217;s the code that does it:</p>
<pre>declare function item:scale-image($img as binary()) as binary()
{
  if (xdmp:binary-size($img) &gt; $MAX-IMG-SIZE) then
    let $wand := <a href="http://www.imagemagick.org/api/magick-image.php#MagickReadImageBlob" target="_blank">magick:read-image</a>(<a href="http://www.imagemagick.org/api/magick-wand.php#NewMagickWand" target="_blank">magick:wand()</a>, $img)
    let $height := <a href="http://www.imagemagick.org/api/magick-image.php#MagickGetImageHeight" target="_blank">magick:get-image-height</a>($wand)
    let $width := <a href="http://www.imagemagick.org/api/magick-image.php#MagickGetImageWidth" target="_blank">magick:get-image-width</a>($wand)
    let $wand :=
      <a href="http://www.imagemagick.org/api/magick-image.php#MagickScaleImage" target="_blank">magick:scale-image</a>(
        $wand,
        fn:min((fn:ceiling($width * $MAX-IMG-DIM div $height), $MAX-IMG-DIM)),
        fn:min((fn:ceiling($height * $MAX-IMG-DIM div $width), $MAX-IMG-DIM)))
    return <a href="http://www.imagemagick.org/api/magick-image.php#MagickGetImageBlob" target="_blank">magick:write-image</a>($wand)
  else
    $img
};</pre>
<p>The trickery with the 2nd and 3rd parameters to magick:scale-image() is to make sure the aspect ratio remains the same, while setting a maximum for either dimension. But simple as that, I pass in binary image that a user uploaded and when it comes back, I know that it won&#8217;t be huge. (People who do a lot of image manipulation may have suggestions for a better approach; such comments are welcome, but don&#8217;t let that distract you from celebrating this feature!) Previously, to accomplish this would have required calls out to MLJAM or a service.</p>
<p>This integration is so new that even the internal documentation is mostly references to <a href="http://www.imagemagick.org/api/magick-wand.php" target="_blank">ImageMagick&#8217;s documentation</a> at this point. If you want to play around a bit, you can map the code above to the corresponding functions on ImageMagick&#8217;s documentation and probably figure out how to make some other kinds of calls.</p>
<p>Be sure to let Stephen know what you think.</p>
<p>Next up for CurioVault: letting users crop images at upload time.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/vjOKEJ0vwMR4Pfmuw4gZ-07Jy5E/0/da"><img src="http://feedads.g.doubleclick.net/~a/vjOKEJ0vwMR4Pfmuw4gZ-07Jy5E/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/vjOKEJ0vwMR4Pfmuw4gZ-07Jy5E/1/da"><img src="http://feedads.g.doubleclick.net/~a/vjOKEJ0vwMR4Pfmuw4gZ-07Jy5E/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DavidCassel/~4/QSpqnzkLhPY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.davidcassel.net/2012/01/sneak-peak-imagemagick-in-marklogic/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.davidcassel.net/2012/01/sneak-peak-imagemagick-in-marklogic/</feedburner:origLink></item>
		<item>
		<title>CurioVault: putting the Express License to work</title>
		<link>http://feedproxy.google.com/~r/DavidCassel/~3/JO8U1dVNcuc/</link>
		<comments>http://blog.davidcassel.net/2012/01/curiovault-putting-the-express-license-to-work/#comments</comments>
		<pubDate>Sat, 07 Jan 2012 20:15:23 +0000</pubDate>
		<dc:creator>Dave Cassel</dc:creator>
				<category><![CDATA[Entrepreneurism]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[CurioVault]]></category>
		<category><![CDATA[express]]></category>
		<category><![CDATA[marklogic]]></category>

		<guid isPermaLink="false">http://blog.davidcassel.net/?p=374</guid>
		<description><![CDATA[MarkLogic 5 includes the Express license, which allows for small production deployments. I decided to take advantage of that to put onto the web a little hobby site I&#8217;ve had in prototype mode for a year or so. I&#8217;ve collected lapel pins since 1984. In that time, I&#8217;ve gotten more than 150 and I&#8217;ve started [...]]]></description>
			<content:encoded><![CDATA[<p>MarkLogic 5 includes the Express license, which allows for small production deployments. I decided to take advantage of that to put onto the web a little hobby site I&#8217;ve had in prototype mode for a year or so.</p>
<p>I&#8217;ve collected lapel pins since 1984. In that time, I&#8217;ve gotten more than 150 and I&#8217;ve started to forget when I got some of them, where I got them, and the stories that went with them. Hence <a href="http://www.curiovault.com" target="_blank">CurioVault.com</a>. Give it a look!</p>
<p>The site runs on a computer I bought for $150 on Amazon Marketplace &#8212; a used box with Intel Core 2 Duo, 2GB of RAM (upgradable to 4GB) and a 500 GB hard drive. Not a very hefty machine, but good enough to get a small site online. </p>
<p>I&#8217;ve seen many examples of MarkLogic being a great solution for huge data sets. But the productivity advantages apply just as well when dealing with a small site. Great tools help on big jobs and little. Throw in the hope that a small site will one day grow up to be a big one, and I&#8217;m excited to be building a site for myself on MarkLogic.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/OVbt6qCplASDNISm7Dnotdh_b8U/0/da"><img src="http://feedads.g.doubleclick.net/~a/OVbt6qCplASDNISm7Dnotdh_b8U/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/OVbt6qCplASDNISm7Dnotdh_b8U/1/da"><img src="http://feedads.g.doubleclick.net/~a/OVbt6qCplASDNISm7Dnotdh_b8U/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DavidCassel/~4/JO8U1dVNcuc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.davidcassel.net/2012/01/curiovault-putting-the-express-license-to-work/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.davidcassel.net/2012/01/curiovault-putting-the-express-license-to-work/</feedburner:origLink></item>
		<item>
		<title>Models in XQuery</title>
		<link>http://feedproxy.google.com/~r/DavidCassel/~3/4QkfzU1Rg-c/</link>
		<comments>http://blog.davidcassel.net/2011/12/models-in-xquery/#comments</comments>
		<pubDate>Thu, 08 Dec 2011 03:49:38 +0000</pubDate>
		<dc:creator>Dave Cassel</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[marklogic]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[xquery]]></category>

		<guid isPermaLink="false">http://blog.davidcassel.net/?p=369</guid>
		<description><![CDATA[At MarkLogic, I work on a team that is charged with building Proof-of-Concept systems quickly and building them well enough that the developers who take over later will have a good starting point. I&#8217;d like to talk more about the framework that we&#8217;ve built to help us with those goals in future posts, but for [...]]]></description>
			<content:encoded><![CDATA[<p>At MarkLogic, I work on a team that is charged with building Proof-of-Concept systems quickly and building them well enough that the developers who take over later will have a good starting point. I&#8217;d like to talk more about the framework that we&#8217;ve built to help us with those goals in future posts, but for today, I&#8217;ll limit myself to the fact that this framework uses MVC as the major design pattern.</p>
<p>Yes, we&#8217;re talking about Model-View-Controller. I&#8217;ve had a number of conversations with people about whether MVC makes sense in an XQuery world, and I wanted to share my reasons for thinking it does.</p>
<p>The conversation typically centers on the Model part of MVC. The argument against MVC in XQuery points out that a big part of the Model&#8217;s job is to get rid of the impedance mismatch between the way data is stored (perhaps rows and columns in a relational database) and the way it is used (perhaps Java objects). In XQuery, data is both stored and used in XML, so there is no mismatch, ergo a Model is overkill. That&#8217;s a valid point as far as it goes &#8212; after all, that is one of the benefits of working with XQuery in general and MarkLogic in particular.</p>
<p>When we started with our framework, we took a VC approach &#8212; we used Views to separate out the presentation logic, and we used Controllers to handle request inputs. However, we still used library modules to do the work of taking those request inputs and turning them into some data to present. We wanted to isolate that logic so that we could write unit tests. Before long, we recognized that we were, in fact, building Models.</p>
<p>So what role does a model play in XQuery? A simpler one. Once you leave the impedance mismatch problem behind, the benefit you are left with is encapsulation. Many of our applications need functions to register, log in, and log out users, along with updating passwords and identifying the current user. Each of these is a function that we store together in a library module, which we write unit tests for and can easily pull out of one project and put into another. That&#8217;s our user model. Likewise, many applications have some central concepts to them that lend themselves to building a model, even though there is no corresponding table, as we would have in the relational world.</p>
<p>Yes, this is a thinner version of how people think of a Model in the relational world. But there are benefits to having divisions between the parts of your application, and MVC is an approach that is familiar and (when used properly) has been useful.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/tCM5uv3Y03HRXf8IFSV1JMs7NIo/0/da"><img src="http://feedads.g.doubleclick.net/~a/tCM5uv3Y03HRXf8IFSV1JMs7NIo/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/tCM5uv3Y03HRXf8IFSV1JMs7NIo/1/da"><img src="http://feedads.g.doubleclick.net/~a/tCM5uv3Y03HRXf8IFSV1JMs7NIo/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DavidCassel/~4/4QkfzU1Rg-c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.davidcassel.net/2011/12/models-in-xquery/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.davidcassel.net/2011/12/models-in-xquery/</feedburner:origLink></item>
		<item>
		<title>MarkLogic on $40 per month</title>
		<link>http://feedproxy.google.com/~r/DavidCassel/~3/YeC47YK8UZU/</link>
		<comments>http://blog.davidcassel.net/2011/11/marklogic-on-40-per-month/#comments</comments>
		<pubDate>Mon, 14 Nov 2011 13:00:18 +0000</pubDate>
		<dc:creator>Dave Cassel</dc:creator>
				<category><![CDATA[Entrepreneurism]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[ec2]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[marklogic]]></category>
		<category><![CDATA[startup]]></category>

		<guid isPermaLink="false">http://blog.davidcassel.net/?p=358</guid>
		<description><![CDATA[Update (8 Mar 2012): Amazon has changed their prices again. Let&#8217;s see what the math tells us now. These numbers assume you want to run a web site 24&#215;7, using the Heavy Utilization pricing on Reserved instances: Small: ($195 + $0.016/hour * 8760 hours/year) / 12 months = $27.93 per month Large: ($780 + $0.064/hour * 8760 [...]]]></description>
			<content:encoded><![CDATA[<p><em>Update (8 Mar 2012): Amazon has changed their prices again. Let&#8217;s see what the math tells us now. These numbers assume you want to run a web site 24&#215;7, using the Heavy Utilization pricing on Reserved instances:</em></p>
<div>
<ul>
<li><em>Small: ($195 + $0.016/hour * 8760 hours/year) / 12 months = $27.93 per month</em></li>
<li><em>Large: ($780 + $0.064/hour * 8760 hours/year) / 12 months = $111.72 per month</em></li>
<li><em>Large for 3 years: <em>($1200 + $0.052/hour * 8760 hours/year * 3 years) / 36 months = $71.29 per month</em></em></li>
</ul>
</div>
<p>You may have heard about the recent release of MarkLogic 5. We at MarkLogic are excited about lots of great improvements in this release, which have been written about in other places. I&#8217;m pretty stoked about the <a title="MarkLogic's License options" href="http://developer.marklogic.com/licensing" target="_blank">Express License</a>. Express is similar to the old Community License in that it&#8217;s available for anyone to use, but the big change is that you&#8217;re now allowed to go into production. There are some limits, as you might guess: 40 GB of data and 2 cores.</p>
<p>I found myself wondering how little one could spend and put something out there.</p>
<h2>Hosting Options</h2>
<p>There are a number of options when it comes to putting your software creation out there. There are basic web hosting (like this site), Virtual Private Hosts, Dedicated Hosts, colocation, using your own data center, and then there&#8217;s Amazon&#8217;s EC2. Ramping a VPS or above up to a good amount of memory pushes the other options above the cost of an EC2 instance. Even getting FIOS Small Business Internet would start at $70/month. Let&#8217;s take a look at what we could do with EC2.</p>
<h2>Amazon EC2 Standard Small Instance</h2>
<p>The Express License is limited to 2 CPUs, so we&#8217;ll be looking at <a title="Amazon EC2 instance types" href="http://aws.amazon.com/ec2/instance-types/" target="_blank">the small instance</a>. If we go with Linux, the cost per hour is $0.085 per hour. There are 24 * 365 = 8760 hours in a year, or 730 hours per month. Amazon will charge you for each hour in which your instance is busy working. Let&#8217;s take the worst case and say that we&#8217;re running at 100% (after all, we&#8217;re hoping people will show and use your site, right?). In that case, <a title="Amazon EC2 pricing" href="http://aws.amazon.com/ec2/pricing/" target="_blank">Amazon will charge you</a> $0.085/hour * 730 hours = $62.05 per month. Not too shabby.</p>
<h2>Amazon EC2 Reserved Small Instance</h2>
<p>Amazon also offers reserved instances, where you pay a fixed fee for 1 or 3 years, getting you a reduced hourly rate. If you decide to go with one year of a Reserved Small Instance, you&#8217;ll pay a one-time fee of $227.50, plus just $0.03 per hour. Averaging that out, we get ($227/year + $0.03/hour * 8760 hours/year) / 12 months = $40.86 per month.</p>
<p>Okay, that&#8217;s slightly above the title $40/month, but &#8220;MarkLogic on $40.86 per month&#8221; just doesn&#8217;t have the same ring to it, does it?</p>
<p>Oh, if you go with the 3-year term, it looks like it&#8217;s ($350/3 years + $0.03/hour * 8760 hours/year * 3 years) / 36 months = $31.62 per month, but three years seems like a long commitment for this level of service. Hopefully, you&#8217;ll be raking in the revenue and upgrading before that time is up.</p>
<h2>Garage Stage</h2>
<p>Lots of startups begin with big dreams and small bank accounts. I know, I&#8217;ve been there. But I think it&#8217;s fair to say that someone who&#8217;s looking to start a business can handle $40 per month in exchange for the productivity and performance they&#8217;ll get from MarkLogic. (If not, I humbly suggest you may be working on a hobby rather than a business.) If I&#8217;d had MarkLogic <a title="Beginning with an End" href="http://blog.davidcassel.net/2009/08/beginning-with-an-end/">when I started Trovz</a>&#8230;.</p>
<h2>Keeping It Real</h2>
<p>Okay, let&#8217;s face it &#8212; there are some caveats on this approach. You&#8217;ve got the data limit of 40 GB. That should hold you for a while. There&#8217;s a limit of 2 CPUs, which will keep you from upgrading to a bigger EC2 instance. Truth be told, you won&#8217;t get the same performance this way that you would on a dedicated server with more CPUs and more RAM. But that costs more. All things considered, this looks like a real opportunity, especially considering that the cost estimates above assume that the server is busy 24&#215;7 &#8212; in practice, I don&#8217;t know what utilization percentage is likely (that would vary project to project), but I would guess it&#8217;s going to be less than 100%. I have a project that I may launch this way at some point.</p>
<p>Here&#8217;s the bottom line: Express License + Amazon EC2 offers a cheap way to make use of some mighty powerful software. It may be enough to get you started. And when you outgrow what Express gives you, MarkLogic will be there to help you grow.</p>
<p><em>Final caveat: I haven&#8217;t set up an instance myself, just looked at Amazon&#8217;s documentation. Take the time to check out their documentation yourself before you launch. Also, I haven&#8217;t factored in the cost of bandwidth or EBS Volumes, although those costs appear minimal to me. Do your own due diligence, but I think you&#8217;ll like what you find. </em></p>
<p>&nbsp;</p>

<p><a href="http://feedads.g.doubleclick.net/~a/Pu40JmlOunALsWkuQCFQW78M2gc/0/da"><img src="http://feedads.g.doubleclick.net/~a/Pu40JmlOunALsWkuQCFQW78M2gc/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/Pu40JmlOunALsWkuQCFQW78M2gc/1/da"><img src="http://feedads.g.doubleclick.net/~a/Pu40JmlOunALsWkuQCFQW78M2gc/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DavidCassel/~4/YeC47YK8UZU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.davidcassel.net/2011/11/marklogic-on-40-per-month/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.davidcassel.net/2011/11/marklogic-on-40-per-month/</feedburner:origLink></item>
		<item>
		<title>Modules databases versus the file system</title>
		<link>http://feedproxy.google.com/~r/DavidCassel/~3/Xn4XiVHlGW8/</link>
		<comments>http://blog.davidcassel.net/2011/11/modules-databases-versus-the-file-system/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 13:00:57 +0000</pubDate>
		<dc:creator>Dave Cassel</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[marklogic]]></category>

		<guid isPermaLink="false">http://blog.davidcassel.net/?p=344</guid>
		<description><![CDATA[When you point a MarkLogic application server to some source code, that code can either reside on the file system or in a modules database. Here are some reasons why you might pick one of those over the other. Modules Database Deploying code is a transactional update &#8212; there&#8217;s no need to worry that the [...]]]></description>
			<content:encoded><![CDATA[<p>When you point a MarkLogic application server to some source code, that code can either reside on the file system or in a modules database. Here are some reasons why you might pick one of those over the other.</p>
<h2>Modules Database</h2>
<ol>
<li>Deploying code is a transactional update &#8212; there&#8217;s no need to worry that the server will be reading your source files while you&#8217;re in the middle of updating them.</li>
<li>Related to #1, if you&#8217;re working in a cluster and an application server is present on multiple instances, deploying to a modules database that spans those instances will let the application server on all instances update to the new code at the same time.</li>
<li>When you&#8217;re migrating an application from one server to another, you can use <a href="http://developer.marklogic.com/code/xqsync" target="_blank">XQSync</a> to move the source code as well as the data.</li>
<li>Using a modules database is actually required for CPF. In a database where you set up content processing, check the Configure tab for the domain &#8212; the evaluation context has to be a database.</li>
</ol>
<h2>File System</h2>
<ol>
<li>When you make a change in your code, there&#8217;s no deploy step. Just hit save and then refresh your browser (or however you are accessing results). Very simple.</li>
<li>You&#8217;ve got your code in a version control system like SVN or GIT (right?), and those expect to live on the file system. I guess you could set up WebDAV and do an &#8220;svn checkout &#8230;&#8221; right into a modules database, but that feels a little weird to me. Your code probably lives in a file system directory somewhere, and you interact with the version control system from there.</li>
<li>When deploying to an integration or production server, I&#8217;ve sometimes pointed the application server to a soft link, then update the soft link on the file system after setting up a directory with the new code. I think that addresses point #1 under Module Databases, but not #2 unless you do it on a volume that is visible to all instances.</li>
</ol>
<h2>What Do I Do?</h2>
<p>Common practice among my colleagues seems to be use the file system while developing on your local box, then deploy to a modules database for integration or production servers. I&#8217;ve actually been using a modules database even for local work lately, because I&#8217;ve got an ant script that makes it simple and fast. Even with that, every now and then I forget to deploy.</p>
<p>Where does your code live? Any reasons I haven&#8217;t covered?</p>

<p><a href="http://feedads.g.doubleclick.net/~a/gquf9AhDWXJ4TiyEX87EhiAB67A/0/da"><img src="http://feedads.g.doubleclick.net/~a/gquf9AhDWXJ4TiyEX87EhiAB67A/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/gquf9AhDWXJ4TiyEX87EhiAB67A/1/da"><img src="http://feedads.g.doubleclick.net/~a/gquf9AhDWXJ4TiyEX87EhiAB67A/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DavidCassel/~4/Xn4XiVHlGW8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.davidcassel.net/2011/11/modules-databases-versus-the-file-system/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.davidcassel.net/2011/11/modules-databases-versus-the-file-system/</feedburner:origLink></item>
		<item>
		<title>Element constructors: computed and direct</title>
		<link>http://feedproxy.google.com/~r/DavidCassel/~3/7qfPc5j5TF8/</link>
		<comments>http://blog.davidcassel.net/2011/10/element-constructors-computed-and-direct/#comments</comments>
		<pubDate>Mon, 31 Oct 2011 15:30:47 +0000</pubDate>
		<dc:creator>Dave Cassel</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[techniques]]></category>
		<category><![CDATA[xquery]]></category>

		<guid isPermaLink="false">http://blog.davidcassel.net/?p=334</guid>
		<description><![CDATA[In XQuery, you can build an element one of two ways: computed or direct. Direct This is the simpler case, so I&#8217;ll take it first. Direct means that your XQuery code has the XML you want to build: declare namespace blog = "http://davidcassel.net/blog"; &#60;blog:example simple="true"&#62;   &#60;blog:pointless/&#62; &#60;/blog:example&#62; XML is a natural data structure for [...]]]></description>
			<content:encoded><![CDATA[<p>In XQuery, you can build an element one of two ways: computed or direct.</p>
<h2>Direct</h2>
<p>This is the simpler case, so I&#8217;ll take it first. Direct means that your XQuery code has the XML you want to build:</p>
<pre>declare namespace blog = "http://davidcassel.net/blog";</pre>
<pre>&lt;blog:example simple="true"&gt;
  &lt;blog:pointless/&gt;
&lt;/blog:example&gt;</pre>
<p>XML is a natural data structure for XQuery and this is a very simple way to construct it.</p>
<h2>Computed</h2>
<p>A computed element is less direct, but it has its benefits. Let&#8217;s take a look:</p>
<pre>declare namespace blog = "http://davidcassel.net/blog";

element { xs:QName("blog:example") } {
  attribute simple { "true" },
  element { xs:QName("blog:pointless") } { }
}</pre>
<h2>Benefits</h2>
<p>The direct method is more concise, so why would we use the computed? There are two reasons why I typically end up using them.</p>
<h3>A Conditional Attribute</h3>
<p>Sometimes you want to include an attribute only under certain circumstances. The trick is, this doesn&#8217;t work:</p>
<pre>&lt;blog:example { if ($condition) then simple="true" else () }/&gt;</pre>
<p>That&#8217;s not valid syntax &#8212; the attribute either has to be there or not, though its value can be the result of an XQuery expression. One way we can conditionally include an attribute is to build the element different in the if and else branches of the condition:</p>
<pre>if ($condition) then
  &lt;blog:example simple="true"/&gt;
else
  &lt;blog:example/&gt;</pre>
<p>As you can imagine, that can be a lousy way to go if the element has some complexity to it, for instance if it has a lot of attributes. This is one place where computed construction makes your life easier:</p>
<pre>declare namespace blog = "http://davidcassel.net/blog";

element { xs:QName("blog:example") } {
  if ($condition) then attribute simple { "true" } else (),
  element { xs:QName("blog:pointless") } { }
}</pre>
<h3>Computing the Name</h3>
<p>Another case where the computed version comes in handy is when the name of the element itself will be the result of a computation. Let&#8217;s suppose you have a map that you want to turn into a set of elements.</p>
<pre>&lt;root&gt;{
  for $key in map:keys($map)
  return element { $key } { map:get($map, $key) }
}&lt;/root&gt;</pre>
<p>There&#8217;s really no other way to do this case, but it&#8217;s simple to do this way.</p>
<p>Any other cases you can think of where computed elements are the easier way to go?</p>

<p><a href="http://feedads.g.doubleclick.net/~a/oVZV_Y87zQ32db6gb4vGMUqZAzg/0/da"><img src="http://feedads.g.doubleclick.net/~a/oVZV_Y87zQ32db6gb4vGMUqZAzg/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/oVZV_Y87zQ32db6gb4vGMUqZAzg/1/da"><img src="http://feedads.g.doubleclick.net/~a/oVZV_Y87zQ32db6gb4vGMUqZAzg/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DavidCassel/~4/7qfPc5j5TF8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.davidcassel.net/2011/10/element-constructors-computed-and-direct/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.davidcassel.net/2011/10/element-constructors-computed-and-direct/</feedburner:origLink></item>
		<item>
		<title>Douglas Crockford on coding standards</title>
		<link>http://feedproxy.google.com/~r/DavidCassel/~3/3aeEIZLEMgs/</link>
		<comments>http://blog.davidcassel.net/2011/10/douglas-crockford-on-coding-standards/#comments</comments>
		<pubDate>Wed, 26 Oct 2011 23:29:54 +0000</pubDate>
		<dc:creator>Dave Cassel</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[standards]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://blog.davidcassel.net/?p=316</guid>
		<description><![CDATA[The team I&#8217;m working recently put together a set of coding standards for our XQuery work. This team was generally happy to do so and we came to agreement on a set of standards pretty quickly. The exercise brought to mind a time at a previous company where two of us started discussing aloud whether [...]]]></description>
			<content:encoded><![CDATA[<p>The team I&#8217;m working recently put together a set of coding standards for our XQuery work. This team was generally happy to do so and we came to agreement on a set of standards pretty quickly. The exercise brought to mind a time at a previous company where two of us started discussing aloud whether some coding standards would be helpful for that group. One member of the team overheard us and chimed in with an emphatic: NO! It was pretty funny in a way, because in the 2+ years I worked with him, I think that was the only time I saw him get excited about something. He was a very calm kind of guy.</p>
<p>Anyway, as we set up our XQuery standards, we chose to rely on Douglas Crockford&#8217;s <a href="http://jslint.com/">JSLint</a> to set the standards for our JavaScript code. I found the quote below in <a href="https://github.com/douglascrockford/JSLint">a README file</a> as part of JSLint and I thought it was worth sharing.</p>
<blockquote><p>The place to express yourself in programming is in the quality of your ideas,and the efficiency of execution. The role of style is the same as in literature. A great writer doesn&#8217;t express himself by putting the spaces before his commas instead of after, or by putting extra spaces inside his parentheses. A great writer will slavishly conform to some rules of style, and that in no way constrains his power to express himself creatively. See for example William Strunk&#8217;s The Elements of Style [<a href="http://www.crockford.com/wrrrld/style.html">http://www.crockford.com/wrrrld/style.html</a>].</p>
<p>This applies to programming as well. Conforming to a consistent style improves readability, and frees you to express yourself in ways that matter. JSLint here plays the part of a stern but benevolent editor, helping you to get the style right so that you can focus your creative energy where it is most needed.</p></blockquote>
<p>As someone who writes both code and prose, I could relate well to both aspects of what he was saying. I keep my copy of Strunk pretty close at handy.</p>

<p><a href="http://feedads.g.doubleclick.net/~a/GGa3Jv8nFV1OG5oVbC5uWZJGtlk/0/da"><img src="http://feedads.g.doubleclick.net/~a/GGa3Jv8nFV1OG5oVbC5uWZJGtlk/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/GGa3Jv8nFV1OG5oVbC5uWZJGtlk/1/da"><img src="http://feedads.g.doubleclick.net/~a/GGa3Jv8nFV1OG5oVbC5uWZJGtlk/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/DavidCassel/~4/3aeEIZLEMgs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.davidcassel.net/2011/10/douglas-crockford-on-coding-standards/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.davidcassel.net/2011/10/douglas-crockford-on-coding-standards/</feedburner:origLink></item>
	</channel>
</rss>

