<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="/templates/default/atom.css" type="text/css" ?>

<feed 
   xmlns="http://www.w3.org/2005/Atom"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/">
    <link href="http://www.softwarevoices.com/feeds/atom.xml" rel="self" title="Software Voices" type="application/atom+xml" />
    <link href="http://www.softwarevoices.com/"                        rel="alternate"    title="Software Voices" type="text/html" />
    <link href="http://www.softwarevoices.com/rss.php?version=2.0"     rel="alternate"    title="Software Voices" type="application/rss+xml" />
    <title type="html">Software Voices</title>
    <subtitle type="html">Perspectives from commercial developers of consumer software</subtitle>
    <icon>http://www.softwarevoices.com/templates/default/img/s9y_banner_small.png</icon>
    <id>http://www.softwarevoices.com/</id>
    <updated>2008-03-14T18:19:54Z</updated>
    <generator uri="http://www.s9y.org/" version="1.0">Serendipity 1.0 - http://www.s9y.org/</generator>
    <dc:language>en</dc:language>

    <entry>
        <link href="http://www.softwarevoices.com/archives/54-ssh-tunnel-to-Amazon-EC2-as-a-temporary-web-proxy-for-privacy-and-security.html" rel="alternate" title="ssh tunnel to Amazon EC2 as a temporary web proxy for privacy and security" />
        <author>
            <name>Eric Hammond</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2007-11-09T22:40:57Z</published>
        <updated>2008-03-14T18:19:54Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=54</wfw:comment>
    
        <slash:comments>3</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=54</wfw:commentRss>
    
            <category scheme="http://www.softwarevoices.com/categories/4-Programming" label="Programming" term="Programming" />
    
        <id>http://www.softwarevoices.com/archives/54-guid.html</id>
        <title type="html">ssh tunnel to Amazon EC2 as a temporary web proxy for privacy and security</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                I was recently using a public wifi connection in a situation where I trusted neither the network operators nor the other wifi users around me.  In order to protect my privacy and the security of my data passed over HTTP, I set up a web proxy using a temporary <a href="http://aws.amazon.com/ec2">Amazon EC2</a> instance.  With an <a href="http://en.wikipedia.org/wiki/SSH_tunnel" >ssh tunnel</a> from my laptop to <a href="http://www.squid-cache.org/" >squid</a> running on the the EC2 instance, my HTTP traffic was encrypted over the wifi and local network, then went out as normal from Amazon's networks to the target web servers.<br />
<br />
I started by firing up an instance of <a href="http://ec2gutsy.notlong.com/">ec2gutsy.notlong.com</a>, a base Ubuntu 7.14 Gutsy server install which I previously built, registered, and made public.  Feel free to use it yourself, though this basic approach would work with pretty much any AMI as long as you can install squid.  You'll obviously need to have previously set up an Amazon AWS/EC2 account and have configured and installed some sort of client (command line, web, extension) to start up instances.<div style="padding-left: 15px; font-size: 12px;"><pre style="line-height:75%"><code>ec2-run-instances -k KEYPAIR ami-b111f4d8<br />
ec2-describe-instances INSTANCEID</code></pre></div>Install the squid proxy server (default config works just fine) and set up an ssh tunnel from port 3128 on the local computer to the squid port on the EC2 instance.<br />
<div style="padding-left: 15px; font-size: 12px;"><pre style="line-height:75%"><code>ssh -i SSHIDENTITY root@HOSTNAME "apt-get -y install squid"<br />
ssh -i SSHIDENTITY -f -N -L3128:localhost:3128 root@HOSTNAME</code></pre></div>Now all that's left is to configure the web browser to use the ssh tunnel to the squid proxy.  In Firefox this is under: Edit / Preferences / Advanced / Network / Settings... / [X] Manual proxy configuration<br />
<br />
Set the HTTP Proxy to "localhost" port "3128".<br />
<br />
You can confirm that the network traffic is going through the Amazon EC2 instance by watching the squid log file on that instance while you browse:<div style="padding-left: 15px; font-size: 12px;"><pre style="line-height:75%"><code>tail -f /var/log/squid/access.log</code></pre></div>I thought that paying 10 cents an hour (EC2 fee) to protect my privacy and security was a pretty good bargain, but don't forget to terminate the instance when you're done with it and reset your browser proxy settings.<br />
<br />
[Edited 2008-03-14 to update AMI ID]<br />
 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/53-Only-seeing-3GB-of-RAM-on-Ubuntu-7.04-Feisty-when-4GB-are-installed-SOLUTION.html" rel="alternate" title="Only seeing 3GB of RAM on Ubuntu 7.04 Feisty when 4GB are installed? [SOLUTION]" />
        <author>
            <name>Eric Hammond</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2007-07-17T22:59:42Z</published>
        <updated>2007-11-10T00:05:01Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=53</wfw:comment>
    
        <slash:comments>1</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=53</wfw:commentRss>
    
            <category scheme="http://www.softwarevoices.com/categories/4-Programming" label="Programming" term="Programming" />
    
        <id>http://www.softwarevoices.com/archives/53-guid.html</id>
        <title type="html">Only seeing 3GB of RAM on Ubuntu 7.04 Feisty when 4GB are installed? [SOLUTION]</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                I've been using Ubuntu Linux for a number of versions now.  My Dell system has 4GB of memory (as verified by checking the BIOS at boot time) but after one of the upgrades it started to report that it could only see 3GB.<br />
<div style="padding-left: 15px; font-size: 12px;"><pre style="line-height:75%"><code>$ free<br />
             total       used       free     shared    buffers     cached<br />
Mem:       <font color="green">3106764</font>    2960304     146460          0     129636    1046552<br />
-/+ buffers/cache:    1784116    1322648<br />
Swap:            0          0          0</code></pre></div><br />
This seems to be a fairly <a href="http://www.google.com/search?q=ubuntu%203GB%204GB">common problem</a>.  I and some Ubuntu friends suffered for many months thinking that this just wasn't solvable, waiting patiently for the good Ubuntu folks to magically make it work again in a future version. <br />
<br />
Then, one day I installed Ubuntu Feisty on a server at <a href="http://www.johncompanies.com/">JohnCompanies</a>, and I noticed that I could see all 4GB of RAM there.<br />
 <br /><a href="http://www.softwarevoices.com/archives/53-Only-seeing-3GB-of-RAM-on-Ubuntu-7.04-Feisty-when-4GB-are-installed-SOLUTION.html#extended">Continue reading "Only seeing 3GB of RAM on Ubuntu 7.04 Feisty when 4GB are installed? [SOLUTION]"</a>
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/52-pflogsumm-summarize-Postfix-email-log-stats-on-Ubuntu.html" rel="alternate" title="pflogsumm - summarize Postfix email log stats on Ubuntu" />
        <author>
            <name>Eric Hammond</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2007-06-25T17:44:13Z</published>
        <updated>2007-07-17T23:46:32Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=52</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=52</wfw:commentRss>
    
    
        <id>http://www.softwarevoices.com/archives/52-guid.html</id>
        <title type="html">pflogsumm - summarize Postfix email log stats on Ubuntu</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                I just discovered <a href="http://jimsun.linxnet.com/postfix_contrib.html">pflogsumm</a>, a convenient way to see what's going on with email on your Ubuntu Linux system running Postfix.<br />
<br />
To install on Ubuntu:<br />
<br />
<div style="padding-left: 15px; font-size: 12px;"><pre style="line-height:75%"><code>sudo apt-get install pflogsumm</code></pre></div><br />
A simple way to run (see manpage for more info):<br />
<br />
<div style="padding-left: 15px; font-size: 12px;"><pre style="line-height:75%"><code>pflogsumm -d yesterday /var/log/mail.log | less</code></pre></div> <br /><a href="http://www.softwarevoices.com/archives/52-pflogsumm-summarize-Postfix-email-log-stats-on-Ubuntu.html#extended">Continue reading "pflogsumm - summarize Postfix email log stats on Ubuntu"</a>
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/51-Convenient-svn-ignore-script-for-Subversion.html" rel="alternate" title="Convenient svn-ignore script for Subversion" />
        <author>
            <name>Eric Hammond</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2006-11-03T14:21:27Z</published>
        <updated>2007-07-17T23:46:52Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=51</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=51</wfw:commentRss>
    
            <category scheme="http://www.softwarevoices.com/categories/4-Programming" label="Programming" term="Programming" />
    
        <id>http://www.softwarevoices.com/archives/51-guid.html</id>
        <title type="html">Convenient svn-ignore script for Subversion</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Subversion allows you to specify certain filenames that it will ignore when performing certain operations (like "svn status").  These are often temporary files that you do not want to have under revision control.  Back in the CVS days this was fairly easy with a simple file named ".cvsignore" that you could edit.<br />
<br />
With Subversion, however, I have to remember and type the following correctly and then use vi to add the name:<br />
<br />
<div style="padding-left: 15px; font-size: 12px;"><pre style="line-height:75%"><code>svn propedit svn:ignore DIRECTORY</code></pre></div><br />
It looks simple, but it was so unintuitive it took me months to memorize it correctly and I still think it's ugly. Plus, I'm not particularly in love with vi, though I've been using it for over 20 years.  I would much rather type something direct like:<br />
<br />
<div style="padding-left: 15px; font-size: 12px;"><pre style="line-height:75%"><code>svn-ignore DIRECTORY/FILENAME</code></pre></div><br />
so I wrote the following shell script which lets me do just that:<br />
 <br /><a href="http://www.softwarevoices.com/archives/51-Convenient-svn-ignore-script-for-Subversion.html#extended">Continue reading "Convenient svn-ignore script for Subversion"</a>
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/49-Steve-Kelley-Heart-Model-to-model-Transforms-...-Not.html" rel="alternate" title="Steve Kelley Heart Model-to-model Transforms ... Not" />
        <author>
            <name>Jollymorphic</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2006-08-15T06:04:00Z</published>
        <updated>2006-08-15T18:38:41Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=49</wfw:comment>
    
        <slash:comments>3</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=49</wfw:commentRss>
    
            <category scheme="http://www.softwarevoices.com/categories/3-Generative-programming" label="Generative programming" term="Generative programming" />
    
        <id>http://www.softwarevoices.com/archives/49-guid.html</id>
        <title type="html">Steve Kelley Heart Model-to-model Transforms ... Not</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                A short while ago, I posted an <a href="http://www.softwarevoices.com/archives/42-Out-of-one-tyranny,-into-the-next.html">article</a> here arguing that model-to-model transformations (or rather, modularity features based on them) are necessary to escape a new "tyranny of the dominant decomposition" in model-driven programming.  Well, what should arrive in my electronic mailbox a few days ago but a newsletter from <a href="http://www.metacase.com/">MetaCase</a> wherein the first big headline reads, provocatively, "Model-To-Model Transformations: A Recipe for Trouble."  Oh my!<br />
<p>The newsletter links to an <a href="http://www.codegeneration.net/tiki-read_article.php?articleId=81&PHPSESSID=0e57f1674ef1623769492bd0accd26c7">article</a> posted a couple of months ago by <a href="http://www.metacase.com/blogs/stevek/blogView">Steve Kelley</a> on the <a href="http://www.codegeneration.net/tiki-index.php">Code Generation Network</a> site.  In a nutshell, Kelley argues "[o]ur experience is that it is better that generators produce code directly, rather than producing intermediate models that you need to extend during the development process."  He has a lot more to say than this, of course, and the whole editorial is definitely worth your time.<br /><br /><h3>The Whole Article</h3><br />
He spends some time laying out the benefits of code generation for product line development (though he distinguishes this from a one-off project, where "the payback may be little greater than the effort required to automate").  And he explains why a UML-based approach, or one based on any "general-purpose design language" for that matter, is doomed to the same fate as those products of yesteryear that have "taught many developers to look at code generators with suspicion."  He argues that only domain-specific languages created by a product line's architects themselves can appropriately model features of the domain and serve as a basis for handcraft-quality code generation:<br />
<blockquote>If we wish to raise the abstraction level beyond code, yet still be able to generate fully working code, going domain-specific is the only alternative....  Despite the existence of multiple ways to write code for a certain behavior, vendors usually choose just one of them, which is unlikely the ideal candidate for your specific contingency....  Third-party generators often don't know enough about an organization's specific requirements to generate ideal code, so it is not surprising that many have found generated code unsatisfactory.</blockquote>Kelley then advocates simplicity as a central principle in the development of code generators based on domain-specific models.  "The simpler they are to start with, the simpler it will be to make changes to them later."  He discusses ways of keeping generators simple (depend on model validation rather than validating input, isolate repeating code patterns into libraries), and he prescribes the use of "a good reference implementation" as a starting point for implementing any model-to-code transformation.  All of this is quite useful and appropriate advice for those using the current generation of tools, and there are many people exploring or working in this blossoming field who would doubtless benefit greatly from it.<br /><br /><h3>Night and Day</h3><br />
As it turns out, though, our seemingly conflicting points of view amount to apples and oranges.  Because when Kelley talks about model-to-model transformations, he's talking about a different way of automating software development than I am.  He's talking about a user-modified, bidirectional train wreck that we both find repugnant, and for the same reasons:<br />
<blockquote>Normally, the idea of model-to-model transformation is that each piece of data in the high-level language gets transformed to more than one piece of data in the lower-level language (let's say 2 pieces).</blockquote>We've already parted ways here, by the way, as this passage describes the primary purpose of model-to-model transformations as the generation of lower-level models; a strictly downward-directed process.  The kinds of technologies I highlight in my post are concerned with transformations in any direction, and most of the examples are horizontal, not vertical.  I want a modularity strategy for transformations to be just as general as the modularity I've enjoyed in OOP languages, which have allowed me to gracefully model relationships that are horizontal, vertical, and everything "in between."<br />
<blockquote>This is fine if you never (or rarely) look at the low-level language, and never (or very rarely) edit it. But if you decide to edit it, you are then working with two pieces of data, but clearly they are not totally independent, since they could be produced from one piece. The result of this is that any changes to the higher level would need to map those changes back to lower levels too.<br /><br />
Often people say next "and we want to be able to change the high-level models still, and have those changes reflected in the low level models". That means you are working with 1+2 pieces of information, plus that you need to come up with some way to propagate the changes down to the low-level models correctly. "Correctly" here means: without destroying information manually added to those low-level models; updating the automatically generated parts; creating new generated parts; updating manually added parts to reflect changes in the top-level models (e.g. if the manually added part refers to the name of an element originally from the high level model, and that element's name has now been changed).</blockquote>Horrors, indeed!  A setup like this violates a critical characteristic of successful generative methods: the inviolate nature of generated artifacts.  Kelley briefly mentions an example of this characteristic elsewhere in his article, saying, "A DSM generator['s] output will not normally be edited  or even checked  by hand."  So, of course, he finds such approaches untenable, as do I.<br />
<p>If this reflects, as Kelley suggests, the current state of the art in model-to-model transformations, I'd be sad but not surprised.  But I'm also hopeful and eager for the long-term potential presented by some of the technologies currently being nurtured academically.<br />
<p>And lest you thought Mr. Kelley's customers stopped there, <em>there's more...</em><br />
<blockquote>And next, people say "and we want to be able to change the low-level models, and have the high-level models update". This is even harder.</blockquote><strong>I'LL SAY IT IS!</strong>  Now my earlier sadness has shifted focus from the model business to its customers.<br /><br /><h3>Conclusion</h3><br />
Obviously, Kelley and I are talking about different things.  He's looking at current practice, particularly people who <em>think</em> they want "model-to-model transformations," and he's rightly turning up his nose.  What I'm interested in, on the other hand, are ways of modularizing this new abstraction layer bestowed upon us by generative and model-driven programming, so as to achieve leverage in ways analogous to those with which I've been successful using currently popular programming methods.  I think the best way to do this in the new world is the same as the best way in the old: separation of concerns.  And I think those concerns have to be realized in a way that cross-cuts implementations.  The kinds of designs that can accomplish this tend to use model-to-model transformations, but they don't use them like code generators.  Rather, they generate "intermediate build products" (in terms of current tooling nomenclature) that are inherently inviolate and of interest only to the development software itself, not to humans.<br />
<p>The only other way in which Kelley's post can be said to clash with mine is in his emphasis on "[k]eep[ing] it simple" when it comes to transformations in general.  He and I agree that small, domain-specific models yield the best results.  But because of his (and our) bad experiences with CASE technologies and their putrid generated code, he emphasizes the simulation of handcraft as a dominant theme in the design of transformations, proclaiming that ideal generated code "gives a good impression, as it looks familiar, follows the required programming mode, includes appropriate comments and follows the local standards for coding style."  And this emphasis leads straight to simple, reference-implementation-based transformations.  Naturally!<br />
<p>But I'm focused on the wider, future potential offered by this new abstraction layer, and the types of modularization of models I've <em>already</em> found that I need, and I see way more powerful ways to automate than the methods undertaken by the people Kelley is talking to.  I'm even willing to sacrifice a little quality in the code that's ultimately generated, at least in the short term, to get there.  Some may argue that more than a little quality loss must inherently follow from such flights of abstraction, but I disagree.  Sure, we went through an era of Visual BASIC p-code before arriving at <a href="http://en.wikipedia.org/wiki/Just_In_Time_compilation">JIT</a>s, but now <a href="http://channel9.msdn.com/Showpost.aspx?postid=20487">everything's copacetic</a>.  The problems that need to be solved may be more abstract than those that came before, but I think they're tractable, and I look forward to seeing how people do it. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/45-URL-design-making-sure-your-urls-are-clickable-in-plain-text-emails.html" rel="alternate" title="URL design: making sure your urls are clickable in plain text emails" />
        <author>
            <name>Craig Ogg</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2006-08-04T15:48:02Z</published>
        <updated>2006-08-04T16:31:09Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=45</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=45</wfw:commentRss>
    
            <category scheme="http://www.softwarevoices.com/categories/4-Programming" label="Programming" term="Programming" />
    
        <id>http://www.softwarevoices.com/archives/45-guid.html</id>
        <title type="html">URL design: making sure your urls are clickable in plain text emails</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                One of my fellow bloggers, Eric Hammond, makes the point that  <a href="http://www.softwarevoices.com/archives/41-Securityprivacy-problem-with-dropping-the-www.-from-your-web-site-URL.html" >dropping the www from your site name may be unwise</a> for security and privacy reasons.  Another problem with it is that it may make your urls unclickable in emails.<br />
<br />
While some designers will aim for short urls to make them not break in an email, real email-friendliness is rarely considered when designing urls.  Unfortunately ignoring it can have a negative impact on how easy it is for word of your site to travel.  Most modern software (email clients, word processors, spreadsheets, file explorers, etc.) attempt to auto-recognize urls and turn them into clickable links.  In order for this to work, the software has to make guesses on what an url is and isn't.  In addition it has to make guesses and when the url is "finished."<br />
<br />
Virtually software will only turn text into a link if it starts with <i>www</i> or <i>http://</i>.  So dropping the <i>www</i> to shorten an url actually means having to prefix it with <i>http://</i> instead --  a net loss.<br />
<br />
Determining where it ends is even harder for the client software because links often appear at the end of sentences.  This means that punctuation in an url will often cause the client to end the link early.<br />
<br />
Here is how some urls are interpreted by the Thunderbird email client:<br />
<br />
<a href="#">http://www.example.com/index.cfm</a>?param=1 (query parameters dropped)<br />
<a href="#">http://www.example.com/test</a>! (exclamation dropped from urll)<br />
<br />
It is worth the time to test the various email clients to see if your url structure is compatible. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/42-Out-of-one-tyranny,-into-the-next.html" rel="alternate" title="Out of one tyranny, into the next" />
        <author>
            <name>Jollymorphic</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2006-07-28T10:50:00Z</published>
        <updated>2006-08-10T06:00:34Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=42</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=42</wfw:commentRss>
    
            <category scheme="http://www.softwarevoices.com/categories/3-Generative-programming" label="Generative programming" term="Generative programming" />
    
        <id>http://www.softwarevoices.com/archives/42-guid.html</id>
        <title type="html">Out of one tyranny, into the next</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Among the papers related to generative and model-driven programming I've read over the last couple of years, one old favorite is <a href="http://www.sciencedirect.com/science?_ob=ArticleURL&_udi=B75H1-4FW5VYY-3&_coverDate=04%2F11%2F2005&_alid=421277399&_rdoc=1&_fmt=&_orig=search&_qd=1&_cdi=13109&_sort=d&view=c&_acct=C000050221&_version=1&_urlVersion=0&_userid=10&md5=97f312f268c78d6d9f49bfca1b4bf72d">The Side Transformation Pattern - making transforms modular and re-usable</a> by Edward Willink (the <a href="http://www.computing.surrey.ac.uk/research/dsrg/fog/">FOG</a> guy) and Phillip Harris.  The full text is no longer available for free on-line, unfortunately, so I'll attempt to summarize, quoting the authors:<br />
<blockquote>Transformation is often presented as a complete activity.  This impression is particularly prevalent in today's "MDA-compliant" tools, which perform a one-stage rewrite of source ... concepts.  Such an approach ... offers little opportunity for evolution through progressive transformation.<br /><br />Where a single stage approach satisfies the user's requirements, it can offer dramatic improvements in productivity, for example in code generator templates that produce Java or C++ source text directly from UML graphical models. Too often however, the one-stage approach inhibits a proper separation of different programming concerns.  The result is a lack of flexibility and visibility in the transformation process, leading to poor opportunities for enhancement or re-use.</blockquote>They may be talking about <a href="http://en.wikipedia.org/wiki/Model-driven_architecture">MDA</a>, but what they're saying applies equally to almost every tool in this field and most of the projects in development.  The <a href="http://www.metacase.com/">commercial</a> <a href="http://msdn.microsoft.com/vstudio/teamsystem/workshop/sf/default.aspx">tools</a>, in particular, seem to concentrate most of their design efforts on graphical model editors, and they treat the actual generation of artifacts as a simple, one-stage process, usually taking the form of text template languages.  If you're lucky, they may incorporate some other rudimentary features, like model validation and repositories.<br />
<p>This insight into the inadequacy of current approaches is valuable enough on its own, but the really beautiful thing about this paper is that it's a <em>pattern paper</em>.  It presents a solution (or, at least, a part of a solution) in the form of an easily understood, straightforwardly replicated design pattern.  How many pattern papers do you see for implementors of these kinds of tools?  This is the only one I'm aware of.<br />
<blockquote>We therefore look to an approach that involves many small transformations, each dealing with a single aspect of the problem, such that relevant transformations extracted from a large library of re-usable transformations can be exploited to build an apparently custom composite with few truly custom contributions.</blockquote>They're talking about leverage in the implementation of the application development tools themselves, here (the "factory," in Microsoft's lingo), not just the applications they produce.  And they're achieving it through modularity and <a href="http://en.wikipedia.org/wiki/Aspect_%28computer_science%29">aspectual decomposition</a>.<br />
<p>The authors go on to propose a pattern for the modularization of transforms involving forking and merging models, and they demonstrate the pattern in a few credible examples, including the addition of type inference constraints to a model and the insertion of synchronization barriers in a flow graph.  The examples are concrete.  The benefit they convey is tangible.<br />
<p>Are these guys (and some other folks I'll get to) onto something?  Is "separation of different concerns[,] ... flexibility and visibility" valuable enough to invest so much in transformation?  More after the fold. <br /><a href="http://www.softwarevoices.com/archives/42-Out-of-one-tyranny,-into-the-next.html#extended">Continue reading "Out of one tyranny, into the next"</a>
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/44-Showing-Implementation-Details-in-URLs-Example-from-Google.html" rel="alternate" title="Showing Implementation Details in URLs (Example from Google)" />
        <author>
            <name>Eric Hammond</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2006-07-27T15:10:31Z</published>
        <updated>2006-07-28T15:58:00Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=44</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=44</wfw:commentRss>
    
            <category scheme="http://www.softwarevoices.com/categories/4-Programming" label="Programming" term="Programming" />
    
        <id>http://www.softwarevoices.com/archives/44-guid.html</id>
        <title type="html">Showing Implementation Details in URLs (Example from Google)</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Google's official blog <a href="http://googleblog.blogspot.com/2006/07/roadmap-for-google-help.html"> annouced the location of a new help page</a> today.  Here's the link to the new page (which I haven't even gone to see):<br />
<br />
<a href="http://www.google.com/support/bin/static.py?page=alpha_index.html">http://www.google.com/support/bin/static.py?page=alpha_index.html</a><br />
<br />
This is a good example of a poor URL and it's coming from Google.  Breaking it down we see...<br />
 <br /><a href="http://www.softwarevoices.com/archives/44-Showing-Implementation-Details-in-URLs-Example-from-Google.html#extended">Continue reading "Showing Implementation Details in URLs (Example from Google)"</a>
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/43-Escaping-From-lines-in-the-content-of-email-messages-in-mbox-format.html" rel="alternate" title="Escaping &quot;From &quot; lines in the content of email messages in mbox format" />
        <author>
            <name>Eric Hammond</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2006-07-13T16:02:26Z</published>
        <updated>2006-07-14T00:47:33Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=43</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=43</wfw:commentRss>
    
    
        <id>http://www.softwarevoices.com/archives/43-guid.html</id>
        <title type="html">Escaping &quot;From &quot; lines in the content of email messages in mbox format</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <a href="http://diveintomark.org/">Mark Pilgrim</a> has been blogging about his success in converting from the Mac to Ubuntu Linux and occassionally some problems he has run into during the process.<br />
<br />
In [<a href="http://diveintomark.org/archives/2006/07/13/mail-checks-in">Mail.app's "Save as" is broken</a>] Mark talks about how Apple's Mail.app doesn't save valid mbox format files because it does not quote lines starting with "From " (From followed by a space).  I sent him this to try:<br />
<br />
Make sure you have the "procmail" package installed (it contains the program "formail"):<br />
<code><br />
sudo apt-get install procmail<br />
</code><br />
Use the "formail" command to split up the mbox into individual email messages and have it invoke itself where it's default behavior is to escape "From " lines:<br />
<code><br />
formail -s formail < bad.mbox > good.mbox<br />
</code><br />
This might not escape "From " lines that are inside messages that have a Content-Length: header, but your mail reader should be able to handle those messages correctly anyway. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/41-Securityprivacy-problem-with-dropping-the-www.-from-your-web-site-URL.html" rel="alternate" title="Security/privacy problem with dropping the &quot;www.&quot; from your web site URL" />
        <author>
            <name>Eric Hammond</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2006-07-03T17:00:00Z</published>
        <updated>2006-07-03T17:13:10Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=41</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=41</wfw:commentRss>
    
            <category scheme="http://www.softwarevoices.com/categories/4-Programming" label="Programming" term="Programming" />
    
        <id>http://www.softwarevoices.com/archives/41-guid.html</id>
        <title type="html">Security/privacy problem with dropping the &quot;www.&quot; from your web site URL</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Given today's state of DNS, smart firewalls/routers/load balancers, and the popularity of the web, it hardly seems necessary to include the "www." on the front of the URL for your web site.<br />
<br />
It is very tempting to drop the "www." so that when folks visit your site they are browsing "example.com" instead of "www.example.com".  In fact, I did this with <a href="http://notlong.com/">http://notlong.com</a> and I'm happy with the results there.<br />
<br />
However, there is a security/privacy issue with doing this that I have not seen discussed elsewhere.  It comes about from a combination of factors which will not apply to everybody, but which are more likely to hit large, serious web sites that use third party services for part of their functionality.<br />
<br />
Here's the situation:<br />
 <br /><a href="http://www.softwarevoices.com/archives/41-Securityprivacy-problem-with-dropping-the-www.-from-your-web-site-URL.html#extended">Continue reading "Security/privacy problem with dropping the &quot;www.&quot; from your web site URL"</a>
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/40-standardCreateElement-the-mystery-function-no-one-talks-about-but-everyone-uses.html" rel="alternate" title="standardCreateElement - the mystery function no one talks about but everyone uses" />
        <author>
            <name>Craig Ogg</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2006-07-03T05:05:00Z</published>
        <updated>2006-07-08T06:06:08Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=40</wfw:comment>
    
        <slash:comments>1</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=40</wfw:commentRss>
    
            <category scheme="http://www.softwarevoices.com/categories/4-Programming" label="Programming" term="Programming" />
    
        <id>http://www.softwarevoices.com/archives/40-guid.html</id>
        <title type="html">standardCreateElement - the mystery function no one talks about but everyone uses</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Do a quick Google search on standardCreateElement() and you will get a large number of results that all match a piece of Javascript code in someone's bookmarklet (aka favelet).  You'll never get a page that tells you what the function does or why it is necessary.  This drove me crazy for quite some time, but I finally figured out what was going on.<br />
<br />
It is an eBay specific hack.  Here is the code eBay uses to try to stop bookmarklets and other active content from working:<br />
<div style="padding-left: 15px; font-size: 12px;"><pre style="line-height:75%"><code>function EbayBlockActiveContent(pParent,pName)<br />
{<br />
  ...<br />
  document.standardWrite=document.write;<br />
  this.documentWrite=function(pStr)...<br />
  document.standardWriteln=document.writeln;<br />
  this.documentWriteln=function(pStr)...<br />
  <b>document.standardCreateElement=document.createElement;<br />
  this.createElement=function(pStr)...</b><br />
  document.write=c.documentWrite;<br />
  document.writeln=c.documentWriteln;<br />
  document.createElement=c.createElement;<br />
  ...<br />
}</code></pre></div><br />
For those readers that may be somewhat new to Javascript, what this function does is redefine a few of the standard methods on the document object so that they call new eBay defined methods and rename the old methods <code>standardOLDNAME</code>.  Sneaky. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/39-Book-Review-Joe-Celkos-Trees-and-Hierarchies.html" rel="alternate" title="Book Review:  Joe Celko's Trees and Hierarchies" />
        <author>
            <name>Glenn Crowe</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2006-05-26T03:22:00Z</published>
        <updated>2006-05-26T03:22:37Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=39</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=39</wfw:commentRss>
    
            <category scheme="http://www.softwarevoices.com/categories/2-Database-development" label="Database development" term="Database development" />
    
        <id>http://www.softwarevoices.com/archives/39-guid.html</id>
        <title type="html">Book Review:  Joe Celko's Trees and Hierarchies</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                This is a book review of Joe Celko's book titled "Joe Celko's Trees and Hierarchies in SQL for Smarties"  ISBN: 1558609202<br />
<br />
Should you read this book?  This, it seems to me, is the point a book review must inevitably resolve.  Ill go ahead and kill the suspense by saying "<b>yes</b>."  If you are involved with the development of SQL systems at any level and wish to read some productive material you can safely turn to this book.  This isnt a perfect book by any means.  It disappoints in some key ways.  However, I am hard pressed to find fault enough to justify not recommending the book.<br />
<br />
<h3>The Good News</h3> <br /><a href="http://www.softwarevoices.com/archives/39-Book-Review-Joe-Celkos-Trees-and-Hierarchies.html#extended">Continue reading "Book Review:  Joe Celko's Trees and Hierarchies"</a>
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/38-Apache-Symbolic-link-not-allowed-error.html" rel="alternate" title="Apache: &quot;Symbolic link not allowed&quot; error" />
        <author>
            <name>Eric Hammond</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2006-05-03T19:28:29Z</published>
        <updated>2006-08-14T22:14:51Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=38</wfw:comment>
    
        <slash:comments>4</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=38</wfw:commentRss>
    
    
        <id>http://www.softwarevoices.com/archives/38-guid.html</id>
        <title type="html">Apache: &quot;Symbolic link not allowed&quot; error</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                You're running Apache 2.x and you are getting a "Forbidden" error in the browser.  The error log states "Symbolic link not allowed: /path/to/file".  You make sure that you put the "Options FollowSymLinks" in the right place in your Apache config file and it's still reporting the same error.<br />
<br />
It turns out that Apache reports this same "Symbolic link not allowed" error if symbolic links <i>are</i> allowed but the symbolic link is pointing to a non-existent file.<br />
<br />
I obviously wouldn't make this basic mistake, but I thought I might save somebody else 30 minutes of debugging down the wrong path.  Because (I imagine) this would really be frustrating.<br />
 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/32-Counting-nodes-in-a-tree-A-bottom-up-approach.html" rel="alternate" title="Counting nodes in a tree:  A bottom-up approach" />
        <author>
            <name>Glenn Crowe</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2006-04-26T04:43:00Z</published>
        <updated>2006-04-27T02:40:53Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=32</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=32</wfw:commentRss>
    
            <category scheme="http://www.softwarevoices.com/categories/2-Database-development" label="Database development" term="Database development" />
    
        <id>http://www.softwarevoices.com/archives/32-guid.html</id>
        <title type="html">Counting nodes in a tree:  A bottom-up approach</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                A popular interview question for SQL Developers goes something like the following:  Given an employee table where ManagerID is an attribute of the Employee record, write a stored procedure which counts the total number of employees which report to the passed employee.<br />
<br />
For clarity I will point out that the organization is a tree where each employee represents a node.<br />
<br />
There is a simple answer which you should probably stick to in the context of an interview.  A top down approach (without the sproc wrapper) would look like this:<div style="padding-left: 15px"><pre style="line-height:50%; color:black; font-size:10pt"><code><br />
Create table #tEmployeeTree <br />
( EmployeeID int, ManagerID int, PassNumber int )<br />
<br />
Declare @Pass int, @RowCount int, @EmpIDParam int<br />
Select  @Pass = 1, @RowCount = 0, @EmpIDParam = 12<br />
Insert #tEmployeeTree ( EmployeeID, ManagerID, PassNumber )<br />
Select EmployeeID, ManagerID, @Pass <br />
  from HumanResources.Employee a<br />
 where  ManagerID = @EmpIDParam<br />
<br />
Select @RowCount = @@RowCount, @Pass = @Pass + 1<br />
<br />
While ( @RowCount != 0 )<br />
begin<br />
<br />
    Insert #tEmployeeTree <br />
    ( EmployeeID, ManagerID, PassNumber )<br />
    Select<br />
          b.EmployeeID<br />
         ,b.ManagerID<br />
         ,@Pass<br />
      from  #tEmployeeTree a<br />
       join HumanResources.Employee b on a.EmployeeID = b.ManagerID<br />
     where a.PassNumber = @Pass -1<br />
<br />
    Select @RowCount = @@RowCount, @Pass = @Pass + 1<br />
end</code></pre></div>At this point you can be confident that the number of records in the #tEmployeeTree table represents the correct answer.<br />
<br />
Now, there is an embellishment to this question which can lead to some interesting discussion.  An executive would like to know which of his or her direct subordinates has the most number of employees in their organization.<br />
<br />
<br />
 <br /><a href="http://www.softwarevoices.com/archives/32-Counting-nodes-in-a-tree-A-bottom-up-approach.html#extended">Continue reading "Counting nodes in a tree:  A bottom-up approach"</a>
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.softwarevoices.com/archives/36-Subclassing-DBI-when-using-ClassDBI.html" rel="alternate" title="Subclassing DBI when using Class::DBI" />
        <author>
            <name>Eric Hammond</name>
            <email>nospam@example.com</email>
        </author>
    
        <published>2006-04-05T21:52:35Z</published>
        <updated>2006-07-03T18:43:10Z</updated>
        <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=36</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=atom1.0&amp;type=comments&amp;cid=36</wfw:commentRss>
    
            <category scheme="http://www.softwarevoices.com/categories/4-Programming" label="Programming" term="Programming" />
    
        <id>http://www.softwarevoices.com/archives/36-guid.html</id>
        <title type="html">Subclassing DBI when using Class::DBI</title>
        <content type="xhtml" xml:base="http://www.softwarevoices.com/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                [Update: I've been informed that you should be using DBIx::Class instead of Class::DBI because the latter is no longer supported, but I haven't had time to switch yet.]<br />
<br />
The <a href="http://search.cpan.org/~timb/DBI/DBI.pm">DBI manpage</a> describes <a href="http://search.cpan.org/~timb/DBI/DBI.pm#Subclassing_the_DBI">how to subclass DBI</a> to override certain methods on database and statement handles (search for MySubDBI in the DBI manpage).  If you are using <a href="http://search.cpan.org/~tmtm/Class-DBI/lib/Class/DBI.pm">Class::DBI</a>, however, the instructions there won't work and it won't be obvious why.<br />
<br />
The secret to being able to override DBI methods when using Class::DBI (and subclasses like <a href="http://search.cpan.org/~tmtm/Class-DBI-mysql/lib/Class/DBI/mysql.pm">Class::DBI::mysql</a>) is to instead subclass <a href="http://search.cpan.org/~tmtm/DBIx-ContextualFetch/lib/DBIx/ContextualFetch.pm">DBIx::ContextualFetch</a>.  That class is used by <a href="http://search.cpan.org/~tmtm/Ima-DBI/lib/Ima/DBI.pm">Ima::DBI</a> (a parent of Class::DBI) to add functionality to the database handles and statement handles even if you or Class::DBI thought your code was directly calling DBI->connect().<br />
<br />
Here's a sample following the naming conventions in the DBI manpage.  Note that the "connected" sub is not needed and is only provided as a sample which can be used to make sure that the subclassing is actually working for you.<div style="padding-left: 15px"><pre style="line-height:50%; color:black; font-size:10pt"><code><br />
package MySubDBI;<br />
use strict;<br />
use base 'DBIx::ContextualFetch';<br />
<br />
package MySubDBI::db;<br />
use base 'DBIx::ContextualFetch::db';<br />
<br />
# Override methods for the database handle here. (Sample provided)<br />
sub connected {<br />
  my $dbh = shift;<br />
  my ($dsn, $user, $pass, $attr) = @_;<br />
  warn "Connected to $dsn as $user";<br />
  return $dbh->SUPER::connected($dsn, $user, $pass, $attr);<br />
}<br />
<br />
package MySubDBI::st;<br />
use base 'DBIx::ContextualFetch::st';<br />
<br />
# Override methods for the statement handle here.</code></pre></div><b>Important:</b> When opening the database handle for your Class::DBI objects, you need to specify the following attribute in the <i>DSN string</i>: "RootClass=MySubDBI" (where MySubDBI is the name of your subclass above). For example the DSN might look like:<div style="padding-left: 15px"><pre style="line-height:50%; color:black; font-size:10pt"><code>"DBI:mysql(RootClass=MySubDBI):host=localhost;database=dbname"</code></pre></div>Specifying RootClass in the %attr hash does not seem to be sufficient, possibly due to the way that DBIx::ContenxtualFetch overrides the attributes and tries to insert its own RootClass, but I didn't spend a lot of time trying to figure out exactly why.<br />
 
            </div>
        </content>
        
    </entry>

</feed>