tag:blogger.com,1999:blog-60142555067998809922024-03-05T19:14:22.846-08:00PragdaveDave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.comBlogger150125tag:blogger.com,1999:blog-6014255506799880992.post-69288093377942306552014-01-28T12:29:00.000-08:002014-01-30T13:02:41.528-08:00Class factories in Coffeescript<div class="markdown-here-wrapper" data-md-original="%3Cdiv%3E%3Cp%3EThere%E2%80%99s%20a%20neat%20trick%20for%20dynamically%20constructing%20heterogeneous%20classes%20using%20a%20single%20factory%20function%20in%20CoffeeScript.%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E(This%20is%20probably%20a%20common%20pattern%20among%20Coffeescript%20cognoscenti%2C%20but%20I%20hadn%E2%80%99t%20bumped%20into%20it%2C%20so%20I%20thought%20it%20was%20worth%20jotting%20down.)%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EI%E2%80%99m%20in%20the%20middle%20of%20writing%20a%20CoffeeScript%20application%20which%20handles%20a%20variety%20of%20related%20but%20different%20user%20interface%20widgets.%20I%E2%80%99d%20normally%20treat%20each%20as%20an%20independent%20class%2C%20and%20use%20mixins%20for%20the%20common%20functionality.%20But%20in%20this%20particular%20app%2C%20it%20turns%20out%20to%20be%20incredibly%20convenient%20to%20have%20a%20single%20factory%20method%20that%20takes%20a%20DOM%20element%20and%20uses%20a%20data-type%20attribute%20to%20generate%20an%20object%20of%20the%20correct%20class.%20That%20is%2C%20given%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E%60%60%60%20html%3C%2Fp%3E%3Cpre%3E%3Ccode%20class%3D%22language-html%22%3E%26lt%3Barticle%20class%3D%22widget%22%20data-type%3D%22Wibble%22%26gt%3B%0A%20%20%20%20%E2%80%A6%0A%26lt%3B%2Farticle%26gt%3B%3C%2Fcode%3E%3C%2Fpre%3E%3Cp%3E%60%60%60%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EI%E2%80%99d%20want%20an%20object%20of%20class%20%3Ccode%3EWibble%3C%2Fcode%3E%2C%20and%20given%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E%60%60%60%20html%3C%2Fp%3E%3Cp%3E%26lt%3Barticle%20class%3D%22widget%22%20data-type%3D%22Wobble%22%26gt%3B%3C%2Fp%3E%3Cpre%3E%3Ccode%20class%3D%22language-html%22%3E%20%20%20%20%E2%80%A6%0A%26lt%3B%2Farticle%26gt%3B%3C%2Fcode%3E%3C%2Fpre%3E%3Cp%3E%60%60%60%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EI%E2%80%99d%20want%20a%20%3Ccode%3EWobble%3C%2Fcode%3E%20object.%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EThe%20initialization%20code%20to%20create%20these%20objects%20will%20look%20something%20like%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E%60%60%60%20javascript%3C%2Fp%3E%3Cpre%3E%3Ccode%20class%3D%22language-javascript%22%3E%24(%3Cfont%20class%3D%22string%22%3E%22.widget%22%3C%2Ffont%3E).map(%3Cfont%20class%3D%22function%22%3E%3Cfont%20class%3D%22keyword%22%3Efunction%3C%2Ffont%3E%20%3Cfont%20class%3D%22params%22%3E(_%2Cel)%3C%2Ffont%3E%20%7B%3C%2Ffont%3E%20%0A%3Cfont%20class%3D%22keyword%22%3E%20%20%20%20return%3C%2Ffont%3E%20Widget.for_element(%24(el))%0A%7D)%3C%2Fcode%3E%3C%2Fpre%3E%3Cp%3E%60%60%60%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EHere%E2%80%99s%20what%20I%20came%20up%20with%20for%20the%20%3Ccode%3Efor_element%3C%2Fcode%3E%20factory%20method.%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3E%60%60%60%20coffeescript%3C%2Fp%3E%3Cpre%3E%3Ccode%20class%3D%22language-coffeescript%22%3E%3Cfont%20class%3D%22class%22%3E%3Cfont%20class%3D%22keyword%22%3Eclass%3C%2Ffont%3E%20%3Cfont%20class%3D%22title%22%3EWidget%3C%2Ffont%3E%3C%2Ffont%3E%0A%20%20%20%20%3Cfont%20class%3D%22property%22%3E%40for_element%3C%2Ffont%3E%3A%20%3Cfont%20class%3D%22function%22%3E%3Cfont%20class%3D%22params%22%3E(el)%3C%2Ffont%3E%20-%26gt%3B%3C%2Ffont%3E%0A%20%20%20%20%20%20%20%20type%20%3D%20el.data(%3Cfont%20class%3D%22string%22%3E%22type%22%3C%2Ffont%3E)%0A%20%20%20%20%20%20%20%20%3Cfont%20class%3D%22keyword%22%3Enew%3C%2Ffont%3E%20%40%5Btype%5D(el)%0A%0A%20%20%20%20%3Cfont%20class%3D%22attribute%22%3Econstructor%3C%2Ffont%3E%3A%20%3Cfont%20class%3D%22function%22%3E%3Cfont%20class%3D%22params%22%3E(%3Cfont%20class%3D%22property%22%3E%40el%3C%2Ffont%3E)%3C%2Ffont%3E%20-%26gt%3B%3C%2Ffont%3E%0A%0A%3Cfont%20class%3D%22class%22%3E%3Cfont%20class%3D%22keyword%22%3Eclass%3C%2Ffont%3E%20%3Cfont%20class%3D%22title%22%3EWidget%3C%2Ffont%3E.%3Cfont%20class%3D%22title%22%3EWibble%3C%2Ffont%3E%20%3Cfont%20class%3D%22keyword%22%3Eextends%3C%2Ffont%3E%20%3Cfont%20class%3D%22title%22%3EWidget%3C%2Ffont%3E%3C%2Ffont%3E%0A%20%20%20%20%3Cfont%20class%3D%22attribute%22%3Econstructor%3C%2Ffont%3E%3A%20%3Cfont%20class%3D%22function%22%3E%3Cfont%20class%3D%22params%22%3E(el)%3C%2Ffont%3E%20-%26gt%3B%3C%2Ffont%3E%0A%20%20%20%20%20%20%20%20%3Cfont%20class%3D%22comment%22%3E%23%20subclass-specific%20stuff%3C%2Ffont%3E%0A%20%20%20%20%20%20%20%20%3Cfont%20class%3D%22keyword%22%3Esuper%3C%2Ffont%3E%0A%0A%3Cfont%20class%3D%22class%22%3E%3Cfont%20class%3D%22keyword%22%3Eclass%3C%2Ffont%3E%20%3Cfont%20class%3D%22title%22%3EWidget%3C%2Ffont%3E.%3Cfont%20class%3D%22title%22%3EWobble%3C%2Ffont%3E%20%3Cfont%20class%3D%22keyword%22%3Eextends%3C%2Ffont%3E%20%3Cfont%20class%3D%22title%22%3EWidget%3C%2Ffont%3E%3C%2Ffont%3E%0A%20%20%20%20%3Cfont%20class%3D%22attribute%22%3Econstructor%3C%2Ffont%3E%3A%20%3Cfont%20class%3D%22function%22%3E%3Cfont%20class%3D%22params%22%3E(el)%3C%2Ffont%3E%20-%26gt%3B%3C%2Ffont%3E%0A%20%20%20%20%20%20%20%20%3Cfont%20class%3D%22comment%22%3E%23%20subclass-specific%20stuff%3C%2Ffont%3E%0A%20%20%20%20%20%20%20%20%3Cfont%20class%3D%22keyword%22%3Esuper%3C%2Ffont%3E%3C%2Fcode%3E%3C%2Fpre%3E%3Cp%3E%60%60%60%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3Cp%3EThe%20fun%20part%20of%20this%20is%20that%20by%20namespacing%20the%20individual%20widget%20subclasses%20in%20the%20parent%20%3Ccode%3EWidget%3C%2Fcode%3E%20class%2C%20I%20can%20use%20%3Ccode%3Enew%20%40%5Btype%5D(el)%3C%2Fcode%3E%20to%20look%20up%20the%20subclass%20in%20the%20factory%2C%20and%20then%20instantiate%20the%20object.%3C%2Fp%3E%3Cp%3E%3Cbr%3E%3C%2Fp%3E%3C%2Fdiv%3E" data-md-url="https://www.blogger.com/blogger.g?blogID=6014255506799880992#editor/target=post;postID=6928809337794230655;onPublishedMenu=allposts;onClosedMenu=allposts;postNum=0;src=postname" id="markdown-here-wrapper-819820">
<div style="margin: 1.2em 0px !important;">
There’s a neat trick for dynamically constructing heterogeneous classes using a single factory function in CoffeeScript.</div>
<div style="margin: 1.2em 0px !important;">
(This is probably a common pattern among Coffeescript cognoscenti, but I hadn’t bumped into it, so I thought it was worth jotting down.)</div>
<div style="margin: 1.2em 0px !important;">
I’m in the middle of writing a CoffeeScript application which handles a variety of related but different user interface widgets. I’d normally treat each as an independent class, and use mixins for the common functionality. But in this particular app, it turns out to be incredibly convenient to have a single factory method that takes a DOM element and uses a data-type attribute to generate an object of the correct class. That is, given</div>
<pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; font-size: 1em; line-height: 1.2em; margin: 1.2em 0px; overflow: auto;"><code class="language-html" style="background-color: #f8f8f8; background-color: ghostwhite; background-position: initial initial; background-repeat: initial initial; border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); border: 1px solid rgb(234, 234, 234); color: #333333; display: block; display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0.5em 0.7em; padding: 0.5em; padding: 0px 0.3em; white-space: nowrap; white-space: pre;">
<article class="widget" data-type="Wibble"> … </article>
</code></pre>
<div style="margin: 1.2em 0px !important;">
I’d want an object of class Wibble, and given</div>
<pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; font-size: 1em; line-height: 1.2em; margin: 1.2em 0px; overflow: auto;"><code class="language-html" style="background-color: #f8f8f8; background-color: ghostwhite; background-position: initial initial; background-repeat: initial initial; border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); border: 1px solid rgb(234, 234, 234); color: #333333; display: block; display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0.5em 0.7em; padding: 0.5em; padding: 0px 0.3em; white-space: nowrap; white-space: pre;"><article class="widget" data-type="Wobble">
… </article>
</code></pre>
<div style="margin: 1.2em 0px !important;">
I’d want a Wobble object.</div>
<div style="margin: 1.2em 0px !important;">
The initialization code to create these objects will look something like</div>
<pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; font-size: 1em; line-height: 1.2em; margin: 1.2em 0px; overflow: auto;"><code class="language-javascript" style="background-color: #f8f8f8; background-color: ghostwhite; background-position: initial initial; background-repeat: initial initial; border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); border: 1px solid rgb(234, 234, 234); color: #333333; display: block; display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0.5em 0.7em; padding: 0.5em; padding: 0px 0.3em; white-space: nowrap; white-space: pre;">
$(<span class="string" style="color: #dd1144;">".widget"</span>).map(<span class="function"><span class="keyword" style="color: #333333; font-weight: bold;">function</span> <span class="params">(_,el)</span> {</span> <span class="keyword" style="color: #333333; font-weight: bold;">return</span> Widget.for_element($(el)) })
</code></pre>
<div style="margin: 1.2em 0px !important;">
Here’s what I came up with for the for_element factory method.</div>
<pre style="font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; font-size: 1em; line-height: 1.2em; margin: 1.2em 0px; overflow: auto;"><code class="language-coffeescript" style="background-color: #f8f8f8; background-color: ghostwhite; background-position: initial initial; background-repeat: initial initial; border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; border-top-left-radius: 3px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-top-right-radius: 3px; border: 1px solid rgb(204, 204, 204); border: 1px solid rgb(234, 234, 234); color: #333333; display: block; display: inline; font-family: Consolas, Inconsolata, Courier, monospace; font-size: 0.85em; margin: 0px 0.15em; padding: 0.5em 0.7em; padding: 0.5em; padding: 0px 0.3em; white-space: nowrap; white-space: pre;">
<span class="class" style="color: #445588; font-weight: bold;"><span class="keyword" style="color: #333333; font-weight: bold;">class</span> <span class="title" style="color: #445588; color: #990000; font-weight: bold; font-weight: bold;">Widget</span> @<span class="title" style="color: #445588; color: #990000; font-weight: bold; font-weight: bold;">for_element</span>:</span> <span class="function"><span class="params">(el)</span> -></span> type = el.data<span class="function"><span class="params">(<span class="string" style="color: #dd1144;">"type"</span>)</span> <span class="title" style="color: #990000; font-weight: bold;">new</span> @[<span class="title" style="color: #990000; font-weight: bold;">type</span>]<span class="params">(el)</span> <span class="title" style="color: #990000; font-weight: bold;">constructor</span>: <span class="params">(<span class="property">@el</span>)</span> -></span> <span class="class" style="color: #445588; font-weight: bold;"><span class="keyword" style="color: #333333; font-weight: bold;">class</span> <span class="title" style="color: #445588; color: #990000; font-weight: bold; font-weight: bold;">Widget</span>.<span class="title" style="color: #445588; color: #990000; font-weight: bold; font-weight: bold;">Wibble</span> <span class="keyword" style="color: #333333; font-weight: bold;">extends</span> <span class="title" style="color: #445588; color: #990000; font-weight: bold; font-weight: bold;">Widget</span> <span class="title" style="color: #445588; color: #990000; font-weight: bold; font-weight: bold;">constructor</span>:</span> <span class="function"><span class="params">(el)</span> -></span> <span class="comment" style="color: #999988; font-style: italic;"># subclass-specific stuff super class Widget.Wobble extends Widget constructor: (el) -> # subclass-specific stuff super</span>
</code></pre>
<div style="margin: 1.2em 0px !important;">
The fun part of this is that by namespacing the individual widget subclasses in the parent Widget class, I can use new @<a href="http://el/">type</a> to look up the subclass in the factory, and then instantiate the object.</div>
</div>
Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com1tag:blogger.com,1999:blog-6014255506799880992.post-39893941426555713462014-01-12T15:41:00.000-08:002014-01-30T12:50:13.852-08:00Room for one more<div class="figure">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjoSXy4XxVF8K5cPvbq_9lCWgsZ3-Jd0E1-PFVnJaxczD7isxh2yFQQkfdRfezRvQCgWkTGSIjfnwzNqDuwJEgn8nh5P3ndJzyPerrgPcw-l1pMloCOfoLSgcpG9ehlX2Kt-nw0bVKaFM/s1600/room-for-one-more.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjoSXy4XxVF8K5cPvbq_9lCWgsZ3-Jd0E1-PFVnJaxczD7isxh2yFQQkfdRfezRvQCgWkTGSIjfnwzNqDuwJEgn8nh5P3ndJzyPerrgPcw-l1pMloCOfoLSgcpG9ehlX2Kt-nw0bVKaFM/s1600/room-for-one-more.png" height="412" width="640" /></a></div>
</div>
Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-65679925306318137012014-01-09T13:47:00.000-08:002014-01-30T12:53:16.987-08:00Moon over Midway<div class="figure">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga9K60n7dAPina2CNd6q-8mMmY75X5wSD8BxsrEgMg5VbGWe9mJugZBnycfFK_MbysVYKdSOxRgcBmWv8V9Y56mIDah7SPkeIzLz4c5du350CizG5OlZcAax-EWHFCzdXDJn28EJ1lDjs/s1600/moon_over_midway.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga9K60n7dAPina2CNd6q-8mMmY75X5wSD8BxsrEgMg5VbGWe9mJugZBnycfFK_MbysVYKdSOxRgcBmWv8V9Y56mIDah7SPkeIzLz4c5du350CizG5OlZcAax-EWHFCzdXDJn28EJ1lDjs/s1600/moon_over_midway.jpg" height="640" width="360" /></a></div>
<figure><br /></figure></div>
<div dir="ltr">
<br /></div>
Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-39494854993181802232014-01-09T00:53:00.000-08:002014-01-30T12:37:37.050-08:00Just used a cool regexp trick in Ruby<p><pre>consonant =-> (ch) { <span>/\A[a-z&&[^aeiou]]\z/</span> =~ ch }</pre></p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-14635528822090428522014-01-06T13:06:00.000-08:002014-01-30T12:37:37.059-08:00I'm sick of site spam<p><p dir="ltr">Is this a way of fighting back?</p><br/><p dir="ltr">The pragprog.com site tries to make it easy for our readers. We don’t want them to have to jump through hoops to register an account, post to forums, or note an erratum. We don’t want to ban external links—they are useful when people want to reference some resource or gist.</p><br/><p dir="ltr">And, of course, that means we attract out share of spammers, adding links to external sites and products. </p><br/><p dir="ltr">I spend a bit of time each week searching this out and deleting it. But I sometimes miss things, particularly when it is a site link in a user’s profile.</p><br/><p dir="ltr">But Google notices, and it complains. Not to me, but to the owner of the site the links reference. That’s fair—the site owner paid someone to spam us, and Google complains to them, threatening to put their page rank in the crapper unless they remove the spam link.</p><br/><p dir="ltr">But they can’t remove it, because it was added by some kid in link factory somewhere.</p><br/><p dir="ltr">So instead they write to us. Here’s a typical email. </p><br/><p dir="ltr"><font color="#888888">from: Mr Woc <webmaster@worldofchat.co.uk></font></p><br/><p dir="ltr"><font color="#888888">Hi,</font></p><br/><p dir="ltr"><font color="#888888">I work for the company touchlineban.co.uk.</font></p><br/><p dir="ltr"><font color="#888888">Your web page:</font></p><br/><p dir="ltr"><font color="#888888"><font color="#4c4c4c"><a href="http://forums.pragprog.com/users/73905"><a href="http://forums.pragprog.com/users/73905">http://forums.pragprog.com/users/73905</a></a></font></font></p><br/><p dir="ltr"><font color="#888888">is linking to our domain and we have been given an email from Google regarding our linking habits!</font></p><br/><p dir="ltr"><font color="#888888">Since this letter from Google our site is suffering very badly, I need to get this link removed.</font></p><br/><p dir="ltr"><font color="#888888">Therefore I politely request that you remove the link to our site touchlineban.co.uk immediately or as soon as is possible.</font></p><br/><p dir="ltr"><font color="#888888">Many thanks for your cooperation in advance.</font></p><br/><p dir="ltr"><font color="#888888">If you have any questions please contact me here:</font></p><br/><p dir="ltr"><font color="#888888">webmaster@touchlineban.co.uk</font></p><br/><p dir="ltr"><font color="#888888">Also if you have any other domain linking to us please can these links be removed too?</font></p><br/><p dir="ltr"><font color="#888888">Kind regards</font><br/></p><br/><p dir="ltr">I get these emails quite frequently.</p><br/><p dir="ltr">So, this time I responded:</p><br/><p dir="ltr"><font color="#888888">I will remove the link if you give me the name of the company you employed to add it in the first place.</font><br/></p><br/><p dir="ltr">I got a wonderful response:</p><br/><p dir="ltr"><font color="#888888">from: Woccy <webmaster@touchlineban.co.uk></font><br/><br/></p><br/><p dir="ltr"><font color="#888888">It was a long long time ago i have no idea sorry, ive got thousands of links and hired 100s of people over the years.</font></p><br/><p dir="ltr"><font color="#888888">Far easier for you to remove them otherwise i just have to put the url on a disavow file, which is never good for any site, as I have to get rid of the links one way or another</font></p><br/><p dir="ltr"><font color="#888888">Ive replied from the touchlineban email too so you know its my site.</font></p><br/><p dir="ltr"><font color="#888888">Many thanks</font></p><br/><p dir="ltr"><font color="#888888">Jc</font><br/></p><br/><p dir="ltr">Oh, my heart bleeds. The poor fellow. He’s hired 100s of people to spam sites like ours, and has polluted the web with thousands of links to his football management site. He can’t be expected to remember any details.</p><br/><p dir="ltr">So, here’s my thinking. What would happen if I create a page on our site where I collect every single spam link I find, and leave those links active forever?</p><br/><p dir="ltr">Would this cause some pain to the folks who spammed us in the first place?</p><br/><p dir="ltr">And would it hurt our own page rank? Is there a way to let Google know what we’re doing?</p></p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-87040265516963383972014-01-04T11:08:00.000-08:002014-01-30T12:37:37.071-08:00Reactive systems have no top<p>Back when I used to consult into projects in trouble, there was a trick that always worked, Look for classes or modules named <code>XxxManager</code>. These puppies would always be at the epicenter of the structural spaghetti. Invariably they’d be doing too much, with lots of conditional code and a fair amount of poking into the business of the things they were supposed to be managing.</p><br/><p>So we’d pick them apart, split out functionality, and see if there was a way to either eliminate them, or turn them into something less coupled (my favorite approach when appropriate would be to turn each into a state machine).</p><br/><p>But, as they say, the cobbler’s children have no shoes. I fell into the trap myself this week.</p><br/><p>Over the Christmas break, I’ve been amusing myself by writing a terminal emulator in Coffeescript. Part of the intent is to allow me to record and then play back interactive sessions. The playback will have a bunch of bells and whistles (including fast forward, rewind, step-by-step and so on).</p><br/><p><img alt="image" src="https://31.media.tumblr.com/c3dfec2870757b0cbbb66e70d2f05d86/tumblr_inline_mywwumUvgn1rgo2z9.png"/></p><br/><p>To manage all this (yes, there’s that word) I wrote a class called <code>Driver.</code></p><br/><p>Perhaps it was the eggnog, but the usual alarm bells were muted. I happily coded away for half a day, hacking more and more stuff into the driver. We had events, callbacks, a little RxJS, and lots of asking other objects for status.</p><br/><p>And it bogged down. Every change got more difficult. Every test harder to write. And it wasn’t fun.</p><br/><p>So I took the dog for a walk, and the dog told me I was being stupid. I’d written a manager class. It wasn’t called <code>PlaybackManager</code>—that would have been a giveaway. I’d called it <code>Driver</code>. That kind of pathetically meaningless name should also have been a giveaway, but until the dog pointed it out, I’d kinda spaced it out.</p><br/><p>So I got back, gave the dog a treat, rolled back the code to the start of day, and looked for a good name for a class that would drive the playback. I ended up with <code>VcrControls</code>. What did it control? A class called <code>Player</code>. The <code>Player</code> class had methods such as <code>play()</code>, <code>rewind()</code>, and <code>step()</code>. The <code>VcrControls</code> object sat between the UI and the player. And the code just fell into place.</p><br/><p>In a way, this is a variant of the “tell, don’t ask” rule. </p><br/><p>Reactive systems have no top—they are lots of components that transform data and events. There’s no place for anything called a manager in such a system. And careful naming (cf <code>Driver</code>…) is a quick way of working out when you break the rule.</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-31321441669557482622014-01-01T09:55:00.000-08:002014-01-30T12:37:37.079-08:00<div class="figure"><figure><br/> <img src="http://31.media.tumblr.com/bd3cf568bf6be140b3c367bf65751dda/tumblr_myyth9rW6M1s6q3fbo1_1280.jpg" alt=""><br/></figure></div><br/><br/> <p>Water tower</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-36797944369249711672013-12-30T00:19:00.000-08:002014-01-30T12:37:37.087-08:00<div class="figure"><figure><br/> <img src="http://31.media.tumblr.com/fbbb0710f1f14fab0a7194d8665e20bd/tumblr_myytdqABF71s6q3fbo1_400.png" alt=""><br/></figure></div><br/><br/> <p>Elixir Wordl from Ganesan Janarthanam</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-86003963006113775932013-12-24T14:00:00.000-08:002014-01-30T12:37:37.095-08:00<div class="figure"><figure><br/> <img src="http://25.media.tumblr.com/732a3f8b634809d1f4e8dee3e2cd896f/tumblr_myytbysbAP1s6q3fbo1_1280.jpg" alt=""><br/></figure></div><br/><br/> <p>Oft repeated, rarely heeded…</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-21368785602018440102013-12-20T06:06:00.000-08:002014-01-30T12:37:37.102-08:00Deploying Elixir<div class="post_title">When any serious app is 100% done, there’s another 50% left to do, and that 50% is deployment. For complicated or large apps, there’s no easy way to do this.</div><br/><div class="post_body"><br/><p>A reader asked me about Elixir and deployment:</p><br/><blockquote><br/><p>There is definitely a lot of excitement around Elixir and I like it. What I am concerned with is are their any production deployment issues with Elixir? I have not don’t one myself but Elixir depends a lot on Erlang and Erlang libraries which have some kind of unique release process or so I have been told. I am not sure if I understood it correctly but I believe Erlang is released in such a away that it is self reliant and doesn’t depend on any external dependencies. How would Elixir behave if the system Erlang version moves ahead?</p><br/></blockquote><br/><p>And I responded:</p><br/><p>Elixir is just Erlang, as far as Erlang is concerned. This means that Elixir code can be deployed alongside Erlang code—the two coexist.</p><br/><p>However, you have to be careful when looking at Erlang deployments. Up until now, these have tended to be large-scale, distributed, and highly redundant systems. The goal has been seriously high reliability. Now no system like this can be deployed just by pushing a button—there’s a lot of planning, and a lot of configuration and scripting.</p><br/><p>As a result, a “classical” Erlang deploy can be a big beast. Your Elixir code can join in this fun if it wants to.</p><br/><p>But Elixir also offers simpler options. For example, deploying an Erlixir web app to Heroku is just about as easy as deploying any app to Heroku—just push to a repository.</p><br/><p>So the short answer is that deployment in any language is not just one topic—it varies greatly depending on the application’s characteristics. At the large scale end, Erlang (and by extension Elixir) has a great story—it is mature and proven. At the small scale, deployments such as Heroku make it easy. And in the middle—well, that’s where the interesting stuff will happen.</p><br/></div>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-28011494615022251112013-11-01T12:00:00.000-07:002014-01-30T12:37:37.109-08:00Pragmatic Royalties—2013 Edition<p>Back in 2009, I posted a summary of the<a href="http://pragdave.tumblr.com/post/68440628303/pragmatic-bookshelf-royalty-rates"> breakdo</a><a href="http://pragdave.tumblr.com/post/68440628303/pragmatic-bookshelf-royalty-rates">wn of the royalties</a> we paid on our titles. Susannah, our managing editor, has been suggesting for a while that I should update it. I was surprised by what I found.</p><br/><p>Here are the 2009 numbers:</p><br/><p><img alt="image" src="https://31.media.tumblr.com/bf3f91aab2dfab0a30a28630c2b966af/tumblr_inline_my1dt39C4Y1rgo2z9.png"/></p><br/><br/><p>Compare with 2013:</p><br/><p><img alt="image" src="https://31.media.tumblr.com/ba431a0884256752c728d64fc2e2f6e4/tumblr_inline_my1dtfrZGh1rgo2z9.png"/></p><br/><br/><p>Below $10k, the numbers are about the same. That’s not surprising—mostly they reflect the vanity titles that were around in 2009. But above the $10k mark, things are a little different.</p><br/><p>In 2009, 70% of titles made more than $25k. By 2013, that number has grown to 74%.</p><br/><p>In 2009, 41% of titles made over $50k. By 2013, it’s 46%.</p><br/><p>And while roughly the same percentage of titles made between $75k and $100k (12% in 2009, 13% now), there’s a big increase in the $100–$200k wedge, up from 4% to 12%. The only drop at the top is the >$400k wedge, and that simply reflects that we haven’t had a title as big as the Rails and Ruby books recently, while the overall number of titles has grown.</p><br/><p>These numbers were pleasantly surprising. I know that as a business we are insulated from the plummeting fortunes of more conventional publishers. But I hadn’t realized that were were even more attractive to authors now than back in 2009.</p><br/><p>Maybe it’s time for you to consider <a href="http://pragprog.com/write-for-us" target="_self">writing a book</a>…</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com1tag:blogger.com,1999:blog-6014255506799880992.post-3885619309692485332012-02-01T11:00:00.000-08:002014-01-30T12:37:37.118-08:00Smart Constants<p>I’ve been really enjoying James Edward Gray II’s <a href="http://subinterest.com/rubies-in-the-rough" target="_self">Rubies in the Rough</a> articles. Every couple of weeks, he publishes something that is guaranteed to get me thinking about some aspect of coding I hadn’t considered before.</p><br/><p>His<a href="http://subinterest.com/rubies-in-the-rough/10-test-driving-an-algorithm-part-1" target="_self"> latest article</a> is part I of an exploration of an algorithm for the <a href="http://puzzlenode.com/puzzles/11-hitting-rock-bottom" target="_self">Hitting Rock Bottom</a> problem posed by by Gregory Brown & Andrea Singh. At its core, the problem asks you to simulate pouring water into a 2D container, filling it using a simple set of rules.</p><br/><p>As I was coding up my solution, I found I had code like</p><br/><pre><code>case <br/> when cave.cell_below == " " then cave.move_down<br/> when cave.cell_to_the_right == " " then cave.move_right<br/> # ...<br/> else<br/> cave.move_up<br/> cave.move_left until cave.cell == "~"<br/> # ...</code></pre><br/><p>Here ” “ is a cell containing air, and ”~” a watery cell. So clearly we should create some named constants for that:</p><br/><pre><code>AIR = " "<br/>WATER = "~"<br/><br/>case <br/> when cave.cell_below == AIR then cave.move_down<br/> when cave.cell_to_the_right == AIR then cave.move_right<br/> # ...<br/> else<br/> cave.move_up<br/> cave.move_left until cave.cell == WATER<br/> # ...</code></pre><br/><p>But it occurred to me that we could use Ruby’s singleton methods to give AIR and WATER a little smarts:</p><br/><pre><code>WATER = "~"<br/>AIR = " "<br/>[WATER, AIR].each do |content|<br/> def content.in?(cell)<br/> cell == self<br/> end<br/>end<br/><br/># ...<br/>case <br/>when AIR.in?(cave.cell_below) then cave.move_down<br/>when AIR.in?(cave.cell_to_the_right) then cave.move_right<br/># ...<br/>else<br/> # ...<br/> cave.move_left until WATER.in?(cave.cell) if AIR.in?(cave.cell)</code></pre><br/><p>Now you could argue that the cave object should do this: cave.watery?, or that the individual elements in the cave should be objects that know their moisture content, rather than simply characters. I don’t agree with the first (simply because the cave is the container, and the water/air is the separate stuff that goes into that container). I have a lot of sympathy for the second, and I’d probably end up there given a sufficiently large nudge during a refactoring. </p><br/><pre><code>WATER = "~"<br/>AIR = " "<br/>[WATER, AIR].each do |content|<br/> def content.in?(cell)<br/> cell == self<br/> end<br/>end<br/><br/># ...<br/>case <br/>when AIR.in?(cave.cell_below) then cave.move_down<br/>when AIR.in?(cave.cell_to_the_right) then cave.move_right<br/># ...<br/>else<br/> # ...<br/> cave.move_left until WATER.in?(cave.cell) if AIR.in?(cave.cell) </code></pre><br/><p>But, for the problem at hand, simply decorating the two constants with a domain method seems to result in code that is a lot more readable. It isn’t a technique I’d used before, so I thought I’d share.</p><br/><p>(And remember to check out <a href="http://subinterest.com/rubies-in-the-rough" target="_self">Rubies in the Rough</a>…)</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-33900597871776649992011-11-12T11:00:00.000-08:002014-01-30T12:37:37.127-08:00Followup to my EMail experiment<p>So the Hacker News folks are having a <a href="http://news.ycombinator.com/item?id=3230233" title="discussion" target="_self">discussion</a> about my <a href="http://pragdave.pragprog.com/post/70458845533/so-im-trying-an-email-experiment">email experiment</a> last April. Many interesting points were raised. One fair question is “how did the experiment work out?” </p><br/><p>In short, it worked incredibly well.</p><br/><p>I was mostly worried about annoying the folks sending me email. But the only feedback I got was positive. </p><br/><p>I was also a little worried about folks abusing the [urgent] flag. But that didn’t happen, either. I had perhaps 5 or 6 urgent emails, and they were indeed things I needed to handle when I got back. Maybe I’m just lucky when it comes to the people who correspond with me.</p><br/><p>The experiment had two positive effects on my life. First, the vacation was genuinely a lot nicer not having to worry about the sacks full of mail piling up for me when I got back. Was that selfish of me? Perhaps a little. </p><br/><p>I wasn’t expecting the other side effect. Since I returned from vacation, the quality of email I receive has improved, and the quantity I receive has dropped. I still enjoy interacting with all the people I need to interact with, and I still get to answer all the questions that need answering. It just seems that my inbox is somehow more focussed.</p><br/><p>I have a theory. I think that, during the course of the preceding few years, I’d become something of a slave to my email. I’d answer stuff as it arrived. And those rapid responses would in turn trigger another round of email, and another. There was almost an adreneline rush to it.</p><br/><p>So my vacation broke that cycle. And now things are sane (or at least closer to sane).</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-10393856758273549272011-04-14T12:00:00.000-07:002014-01-30T12:37:37.135-08:00So I'm trying an email experiment<p>For the next 2 weeks, here’s my vacation message:</p><br/><br/><blockquote><br/><p>Subject: <strong>I’m on vacation, and I’ve deleted your message—really</strong></p><br/><p>I know this sounds brutal, but here’s the deal.</p><br/><p>I can’t remember the last time I took a vacation where I didn’t actually end up working a few hours each day handling e-mail. I felt I had to, because if I didn’t, the Inbox would just grow and grow, waiting for me when I got back—the idea that I’d be flying home to 5,000 messages would always be nagging at me, detracting from my holiday. So I worked (which also detracted from the holiday).</p><br/><p> This time, I’m taking a different approach. I’m asking for your help to make my break more enjoyable.</p><br/><p> I’m going to be discarding email I receive. That’s right—your email will be recycled into warm, fluffy bit-jackets for underprivileged children. I won’t see it.</p><br/><p>If it’s something you think I really, really need to know, you can bypass this brutality by putting “urgent” in the subject line. But before you do:</p><br/><ul><li>if it is something that can be handled by the wonderful Pragprog support folk, could you send your message to <a href="mailto:support@pragprog.com">support@pragprog.com</a></li><br/><li>if it can wait until I get back on April 25, please resend your message then.</li><br/></ul><br/><p>It’s an experiment. Bon voyage à moi!</p><br/></blockquote><br/><br/><p>Dave</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-50562553957629374432009-10-19T12:00:00.000-07:002014-01-30T12:37:37.147-08:00<div class="figure"><figure><br/> <img src="http://25.media.tumblr.com/bf3f91aab2dfab0a30a28630c2b966af/tumblr_myyt4s4fIX1s6q3fbo1_1280.png" alt=""><br/></figure></div><br/><br/> <p>When we started the <a href="http://pragprog.com" title="The Pragmatic Bookshelf" target="_blank">Bookshelf</a>, we wanted our authors to share in the success of their books, so we set our royalty rates to between 40% and 50%. That is, an author will receive between 40% and 50% of whatever gross profit we make on a book. We felt back then, and we still feel, that this is the highest overall royalty offered by any technical publisher (most publishers offer something in the 10–18% range).</p><br/><p>But it isn’t always easy to compare different publishers, because the definitions of gross profit (or whatever they use) differ wildly. Our definition is that we take whatever money we receive from the sale of a book (in whatever form), deduct the direct cost of production (which is zero for eBooks, and a couple of dollars for paper books), and then split what’s left according to the royalty rate. We also account for our costs of copy edit, indexing, and typesetting by splitting them (again according to the royalty rate) between the author and us. So if a book costs $5,000 to copy edit, index, and typeset, and we’re paying 50% royalties, then the author’s royalty account starts with a $2,500 negative balance.</p><br/><p>We don’t pay advances, but we do pay royalties quarterly. If a book enters our beta program, the author starts receiving the royalties at the end of the quarter.</p><br/><p>In the last few years, we’re had a number of prospective authors tell us that other publishers woo them by saying that our 40–50% royalties are somehow illusory—that by the time the author gets a payment the figures have somehow been shaved down to the point where we pay the same as everyone else. And that’s just <a href="http://en.wikipedia.org/wiki/Fear,_uncertainty_and_doubt" title="Fear, uncertainty, and doubt">FUD</a>.</p><br/><p>So, in order to help people compare, attached is a chart. It shows the royalties we’ve paid so far on our titles that have been in print for at least a year. Eight percent of the titles have earned less than $10k. Several of these are vanity titles we produced on behalf of private companies, the others are books that sold into very specific, narrow niches (because we felt someone should do it, and even at these low volumes we can do so profitably). Ninety-two percent of our titles paid more than $10k in royalties, and forty-two percent paid more than $50k. Twelve percent earned into six figures.</p><br/><p>I’d welcome publishers who talk down our royalty payment schedules to publish their figures. I know many will have some titles that earn a lot more than $400k. But I’d be most interested in the distribution—how much does a typical author make? I’m proud of the fact that we’ve set up an environment where authors of good books can earn back at least a reasonable portion of the investment they made in writing.</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-17329469981916397492009-06-11T12:00:00.000-07:002014-01-30T12:37:37.161-08:00<audio controls src="https%3A%2F%2Fwww.tumblr.com%2Faudio_file%2Fpragdave%2F72411571364%2Ftumblr_myyt1oVTij1s6q3fb"><a href="https%3A%2F%2Fwww.tumblr.com%2Faudio_file%2Fpragdave%2F72411571364%2Ftumblr_myyt1oVTij1s6q3fb">Audio</a></audio><br/><br/> <p>Here’s another piece of music I wrote. This one I started over a year ago, but then put down for a while. I think it really wants to be a lot longer piece—maybe one day.</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-6086955697318326342009-05-11T12:00:00.000-07:002014-01-30T12:37:37.181-08:00<audio controls src="https%3A%2F%2Fwww.tumblr.com%2Faudio_file%2Fpragdave%2F72411405985%2Ftumblr_myysyweAEA1s6q3fb"><a href="https%3A%2F%2Fwww.tumblr.com%2Faudio_file%2Fpragdave%2F72411405985%2Ftumblr_myysyweAEA1s6q3fb">Audio</a></audio><br/><br/> <p>In my ongoing attempt to keep myself honest, here’s another piece I wrote, again played by Mike Springer. I’m not sure how to categorize this one—I wanted to play around with 7/8, and ended up with what I think are some interesting patterns. </p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-23453254219319370602009-05-03T12:00:00.000-07:002014-01-30T12:37:37.189-08:00<div class="figure"><figure><br/> <img src="http://25.media.tumblr.com/8a10aab6d2002f4bd2e0a2ba0e22c310/tumblr_myyswqQLos1s6q3fbo1_1280.jpg" alt=""><br/></figure></div><br/><br/> <p>I’ve known Chad Fowler for almost ten years. He’s a seriously good guy: musician, developer, leader, and friend. So when he came to me some years ago with an idea for a book, I jumped at it. I was hoping for something good, but what we got was something truly great.</p><br/><p>Andy and I wrote <em>The Pragmatic Programmer</em> over 10 years ago. It was a book full of advice on the job of programming, from low-level coding to teams and projects.</p><br/><p>Well, Chad had written the companion book. Where our book looked outward at the job you were doing, <a href="http://pragprog.com/titles/cfcar2/the-passionate-programmer">The Passionate Programmer</a> looked inward at the person doing the work. It’s a book about finding fulfillment in what you do. It’s a book about rekindling the fires that you felt when you first entered the profession. It’s a book about creating a career, rather than turning up for a job.</p><br/><p>I was blown away.</p><br/><p>And then I did something really stupid. The book came out about 5 years ago, and outsourcing was big on everyone’s mind. So I thought “let’s make a jokey title that’ll grab people’s attention.” I called the book <em>My Job Went to India (And All I Got Was This Lousy book)</em>. I’ve already <a href="http://pragdave.blogs.pragprog.com/pragdave/2007/07/the-joy-of-titl.html">blogged</a> about how stupid that was—it was probably the single dumbest thing I’ve done since I got into publishing. The title put people off; it gave them the wrong idea. The book was really nothing to do with outsourcing, but you wouldn’t know it from the cover. This book deserved so much better</p><br/><p>So, four years later, we revisited the book. Chad’s given it a spring cleaning, revising and updating it. And we gave it a new title and a new cover, both of which do a better job of conveying the energy and enthusiasm that lie within.</p><br/><p>I’m not into selling: my philosophy with our books is “if they’re good, people will buy them.” But this book is different. I really think it can make a difference. So I’d love for you to <a href="http://pragprog.com/titles/cfcar2/the-passionate-programmer">read the extracts</a> and maybe take this book home with you. I honestly think you’ll thank me (and, most importantly, Chad) if you do.</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-77360222959059578782009-04-08T12:00:00.000-07:002014-01-30T12:37:37.198-08:00Twitter Should Move Away from Ruby<p>Oh dear. The chattering classes are at it, talking about how the Twitter folks are dissing Ruby by announcing the replacement of some Ruby code with Scala code.</p><br/><div>Please stop.</div><br/><p>At the kinds of volumes that Twitter handles (and with what I assume is a somewhat scary growth curve), Twitter needs to improve concurrency—it needs an environment/language with low memory overhead, incredible performance, and super-efficient threading. I don’t know if Scala fits that particular bill, but I know that current Ruby implementations don’t. It isn’t what Ruby’s intended to be. So the move away is just sound thinking. (I suspect it also took some courage.) I applaud Alex and the team for this.</p><br/><p>Instead of defending Ruby when it’s clearly not an appropriate solution, let’s think about things the other way around.</p><br/><p>The good folks at Twitter started off with Ruby because they wanted to get something running quickly, and they wanted to experiment. And Ruby gave them that. And, what’s more, Ruby saw them through at least two rounds of phenomenal growth. Could they have done it in another language? Sure. But I suspect Ruby, despite the occasional headache, helped them get where they are now. </p><br/><p>And now they’ve reached the status of world-wide wunderkind, it’s time to move on. </p><br/><p>I for one wish them luck. I look forward to the day when our online store reaches the kind of size where we have to move away from Rails. I’ll tweet the fact with a tear in my eye, while my yacht sails me off to the sunset.</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-5173847909201969562008-12-25T11:00:00.000-08:002014-01-30T12:37:37.207-08:00<audio controls src="https%3A%2F%2Fwww.tumblr.com%2Faudio_file%2Fpragdave%2F72411079283%2Ftumblr_myystcnez21s6q3fb"><a href="https%3A%2F%2Fwww.tumblr.com%2Faudio_file%2Fpragdave%2F72411079283%2Ftumblr_myystcnez21s6q3fb">Audio</a></audio><br/><br/> <p>I decided a while back to publish the music I’m writing, if nothing else as a way of keeping myself honest. So, here’s a little piece of fluff I wrote just to play with time signatures—alternating 5/8 and 6/8 has a nice drive to it. It’s played by my music teacher.</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-88237868758101115212008-12-20T11:00:00.000-08:002014-01-30T12:37:37.217-08:00<div class="figure"><figure><br/> <img src="http://24.media.tumblr.com/ac2effbd48ca2b9ba9643c27c7a3367e/tumblr_myysq7h5L21s6q3fbo1_400.jpg" alt=""><br/></figure></div><br/><br/> <p>Like the rest of our publishing business, I like to keep our covers simple and easy. But now I realize that these covers fail to capture the true epic nature of our books. <span class="author vcard fn">Joey deVilla posted some <a href="http://www.globalnerdy.com/2007/09/14/reimagining-programming-book-covers/" title="Rworking some book covers" target="_blank">reworkings</a> of book covers last year, but I only came across them today. I’m inspired…<br/><br/>The strange thing is: I’m not sure where he got hold of the image. After we posed for the picture, DHH and I thought better of it. We thought we had destroyed all the copies…</span></p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-79024914138534497992008-12-16T11:00:00.000-08:002014-01-30T12:37:37.228-08:00Ruby 1.9 can check your indentation<p>All Ruby programmers regularly encounter the mystical error “syntax error, unexpected $end, expecting keyword_end.” We know what it means: we left off an end somewhere in the code. As Ruby compiled our source, it keeps track of nesting, and when it reached the end of file ($end), it was expecting to see one more end keyword, and none was there.</p><br/><p>So, we trundle back through the source, and after a while discover we’d deleted just one too many lines during that last edit.</p><br/><p>Ruby 1.9 makes that easier. For example, here’s a source file:</p><br/><p><strong>class</strong> Example<br/> <strong>def</strong> meth1<br/> <strong>if</strong> Time.now.hours > 12<br/> puts “Afternoon”<br/> <strong>end</strong><strong><br/></strong><strong> def</strong> meth2<br/> # …<br/> <strong>end</strong><strong><br/>end</strong></p><br/><p>Run it through Ruby 1.9, and you’ll get the same old error message:</p><br/><p>dave[RUBY3/Book 8:26:48*] <strong>ruby t.rb</strong> <br/>t.rb:10: syntax error, unexpected $end, expecting keyword_end</p><br/><p>But add the -w flag, and things get more interesting.</p><br/><p>dave[RUBY3/Book 8:26:51*] <strong>ruby -w t.rb</strong><br/>t.rb:5: warning: mismatched indentations at ‘end’ with ‘if’ at 3<br/>t.rb:9: warning: mismatched indentations at ‘end’ with ‘def’ at 2<br/>t.rb:10: syntax error, unexpected $end, expecting keyword_end</p><br/><p>It’s the small things in life…</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-55781278919990489332008-12-01T11:00:00.000-08:002014-01-30T12:37:37.249-08:00Forking Ruby—my RubyConf Keynote is now upLink: <a href="http://rubyconf2008.confreaks.com/keynote.html">Forking Ruby—my RubyConf Keynote is now up</a><br/><br/> <p>There’s a sound that no presenter wants to hear, and that’s dead silence. And that’s what greeted me when I made the suggestion in my RubyConf keynote that the community should fork the Ruby language. I think by the end of the talk, though, most people were convinced.</p><br/><p>Am I anti Ruby? no.</p><br/><p>Am I suggesting Matz is doing a bad job? Not in the least.</p><br/><p>But I do think the complexity of the current language inhibits experimentation with language features. Want to implement parallel Ruby? If you do it with the current syntax and semantics, you’ll be struggling with the integration of global variables, the non-threadsafe nature of require, continuations, and so on, and so on. So before starting these kinds of experimental projects, I’m saying we should fork the language. Produce variants that let us focus in on the aspects under test. Make the new language a rich-enough subset that you can do useful work with it. Then let people play with it. Maybe the ideas are stellar, in which case we can all talk about integrating the changes back into the mainline language. And maybe the idea didn’t pan out, in which case we can quietly forget it, and we’ve done no damage to the language itself.</p><br/><p>A mutation is an altered fork of the original. And mutations are essential to the diversity and strength of a genetic line over time. Let’s not be afraid to create Ruby mutants and let them compete.</p><br/><p>The keynote is available from <a href="http://rubyconf2008.confreaks.com/keynote.html" title="RubyConf 2008 keynote" target="_blank">Confreaks</a>.</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-73815466562213854172008-11-29T11:00:00.000-08:002014-01-30T12:37:37.265-08:00See Rails request paths in 'top'<p>During our sale, we had one particular request that came in and wedged the application: every time it hit, the mongrel process size zoomed steadily up to 500Mb, so we had to kill it. But finding out which request was doing this was tricky. The log files didn’t help—with the amount of traffic we were getting, it was a small needle and a large haystack.</p><br/><div>Eventually, we found the culprit. But it would have been a lot easier if I’d thought of this hack on Friday, and not after the sale ended.</div><br/><p>If you put this into your application controller:</p><br/><pre><code>before_filter :set_process_name_from_request<br/><br/>def set_process_name_from_request<br/> $0 = request.path[0,16]<br/>end<br/><br/>after_filter :unset_process_name_from_request<br/><br/>def unset_process_name_from_request<br/> $0 = request.path[0,15] + "*"<br/>end</code></pre><br/><p>then Ruby will set the cmd field in your process control block to the first 16 characters of the request path. You can then use top to see what request is being handled by each mongrel.</p><br/><div><img alt="image" src="https://31.media.tumblr.com/28ac6f40c9115c64702b0bd7383f06c4/tumblr_inline_my1bogZBkM1rgo2z9.jpg"/><br/></div><br/><div>Once the request has been handled, an asterisk sign is appended, so you can see the last URL when a mongrel becomes idle. </div><br/><div></div><br/><div><img alt="image" src="https://31.media.tumblr.com/2cbaaaf73b2cdf827c0d0f7be90b88b7/tumblr_inline_my1bq7OMLl1rgo2z9.jpg"/><p></p><br/></div><br/><div>If your version of top doesn’t show the short command by default, use the c keyboard command to see it.</div><br/><div></div><br/><div>This is probably common knowledge, but I thought it was cool.</div>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0tag:blogger.com,1999:blog-6014255506799880992.post-2358221999619105142008-10-15T12:00:00.000-07:002014-01-30T12:37:37.274-08:00Fun with Ruby 1.9 Regular Expressions<p>I’ve reorganized the regular expression content in the new Programming Ruby, and added some cool new advanced examples. This one’s fairly straightforward, but I love the fact that I can now start refactoring my more complex patterns, removing duplication.</p><br/><p>The stuff below is an extract from the unedited update. It’ll appear in the next beta. It follows a discussion of named groups, <code>\k</code> and related stuff.</p><br/><hr><div class="from-book"><br/><p>There’s a trick which allows us to write subroutines inside regular expressions. Recall that we can invoke a named group using <code>\g<name></code>, and we define the group using <code>(?<name>...)</code>. Normally, the definition of the group is itself matched as part of executing the pattern. However, if you add the suffix <code>{0}</code> to the group, it means “zero matches of this group,” so the group is not executed when first encountered.</p><br/><pre>sentence = %r{ <br/> (?<subject> cat | dog | gerbil ){0} <br/> (?<verb> eats | drinks| generates ){0} <br/> (?<object> water | bones | PDFs ){0} <br/> (?<adjective> big | small | smelly ){0} <br/><br/> (?<opt_adj> (\g<adjective>\s)? ){0} <br/><br/> The\s\g<opt_adj>\g<subject>\s\g<verb>\s\g<opt_adj>\g<object> <br/>}x<br/><br/>md = sentence.match("The cat drinks water") <br/>puts "The subject is #{md[:subject]} and the verb is #{md[:verb]}"<br/> <br/>md = sentence.match("The big dog eats smelly bones") <br/>puts "The adjective in the second sentence is #{md[:adjective]}" <br/><br/>sentence =~ "The gerbil generates big PDFs" <br/>puts "And the object in the last is #{$~[:object]}" <br/></pre><br/><p><em>produces:</em></p><br/><pre>The subject is cat and the verb is drinks <br/>The adjective in the second sentence is smelly <br/>And the object in the last is PDFs <br/></pre><br/></div><br/><hr><p>Cool, eh?</p>Dave Thomashttp://www.blogger.com/profile/17391903659506284188noreply@blogger.com0