<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    <title>Software Voices - Programming</title>
    <link>http://www.softwarevoices.com/</link>
    <description>Perspectives from commercial developers of consumer software</description>
    <dc:language>en</dc:language>
    <generator>Serendipity 1.0 - http://www.s9y.org/</generator>
    <pubDate>Fri, 14 Mar 2008 18:19:54 GMT</pubDate>

    <image>
        <url>http://www.softwarevoices.com/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: Software Voices - Programming - Perspectives from commercial developers of consumer software</title>
        <link>http://www.softwarevoices.com/</link>
        <width>100</width>
        <height>21</height>
    </image>

<item>
    <title>ssh tunnel to Amazon EC2 as a temporary web proxy for privacy and security</title>
    <link>http://www.softwarevoices.com/archives/54-ssh-tunnel-to-Amazon-EC2-as-a-temporary-web-proxy-for-privacy-and-security.html</link>
            <category>Programming</category>
    
    <comments>http://www.softwarevoices.com/archives/54-ssh-tunnel-to-Amazon-EC2-as-a-temporary-web-proxy-for-privacy-and-security.html#comments</comments>
    <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=2.0&amp;type=comments&amp;cid=54</wfw:commentRss>
    

    <author>nospam@example.com (Eric Hammond)</author>
    <content:encoded>
    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 &lt;a href=&quot;http://aws.amazon.com/ec2&quot;&gt;Amazon EC2&lt;/a&gt; instance.  With an &lt;a href=&quot;http://en.wikipedia.org/wiki/SSH_tunnel&quot; &gt;ssh tunnel&lt;/a&gt; from my laptop to &lt;a href=&quot;http://www.squid-cache.org/&quot; &gt;squid&lt;/a&gt; running on the the EC2 instance, my HTTP traffic was encrypted over the wifi and local network, then went out as normal from Amazon&#039;s networks to the target web servers.&lt;br /&gt;
&lt;br /&gt;
I started by firing up an instance of &lt;a href=&quot;http://ec2gutsy.notlong.com/&quot;&gt;ec2gutsy.notlong.com&lt;/a&gt;, 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&#039;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.&lt;div style=&quot;padding-left: 15px; font-size: 12px;&quot;&gt;&lt;pre style=&quot;line-height:75%&quot;&gt;&lt;code&gt;ec2-run-instances -k KEYPAIR ami-b111f4d8&lt;br /&gt;
ec2-describe-instances INSTANCEID&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;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.&lt;br /&gt;
&lt;div style=&quot;padding-left: 15px; font-size: 12px;&quot;&gt;&lt;pre style=&quot;line-height:75%&quot;&gt;&lt;code&gt;ssh -i SSHIDENTITY root@HOSTNAME &quot;apt-get -y install squid&quot;&lt;br /&gt;
ssh -i SSHIDENTITY -f -N -L3128:localhost:3128 root@HOSTNAME&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Now all that&#039;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&lt;br /&gt;
&lt;br /&gt;
Set the HTTP Proxy to &quot;localhost&quot; port &quot;3128&quot;.&lt;br /&gt;
&lt;br /&gt;
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:&lt;div style=&quot;padding-left: 15px; font-size: 12px;&quot;&gt;&lt;pre style=&quot;line-height:75%&quot;&gt;&lt;code&gt;tail -f /var/log/squid/access.log&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;I thought that paying 10 cents an hour (EC2 fee) to protect my privacy and security was a pretty good bargain, but don&#039;t forget to terminate the instance when you&#039;re done with it and reset your browser proxy settings.&lt;br /&gt;
&lt;br /&gt;
[Edited 2008-03-14 to update AMI ID]&lt;br /&gt;
 
    </content:encoded>

    <pubDate>Fri, 09 Nov 2007 16:40:57 -0600</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/54-guid.html</guid>
    <category>ec2</category>
<category>http</category>
<category>privacy</category>
<category>proxy</category>
<category>security</category>
<category>squid</category>
<category>ssh</category>
<category>ubuntu</category>
<category>wifi</category>

</item>
<item>
    <title>Only seeing 3GB of RAM on Ubuntu 7.04 Feisty when 4GB are installed? [SOLUTION]</title>
    <link>http://www.softwarevoices.com/archives/53-Only-seeing-3GB-of-RAM-on-Ubuntu-7.04-Feisty-when-4GB-are-installed-SOLUTION.html</link>
            <category>Programming</category>
    
    <comments>http://www.softwarevoices.com/archives/53-Only-seeing-3GB-of-RAM-on-Ubuntu-7.04-Feisty-when-4GB-are-installed-SOLUTION.html#comments</comments>
    <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=2.0&amp;type=comments&amp;cid=53</wfw:commentRss>
    

    <author>nospam@example.com (Eric Hammond)</author>
    <content:encoded>
    I&#039;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.&lt;br /&gt;
&lt;div style=&quot;padding-left: 15px; font-size: 12px;&quot;&gt;&lt;pre style=&quot;line-height:75%&quot;&gt;&lt;code&gt;$ free&lt;br /&gt;
             total       used       free     shared    buffers     cached&lt;br /&gt;
Mem:       &lt;font color=&quot;green&quot;&gt;3106764&lt;/font&gt;    2960304     146460          0     129636    1046552&lt;br /&gt;
-/+ buffers/cache:    1784116    1322648&lt;br /&gt;
Swap:            0          0          0&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
This seems to be a fairly &lt;a href=&quot;http://www.google.com/search?q=ubuntu%203GB%204GB&quot;&gt;common problem&lt;/a&gt;.  I and some Ubuntu friends suffered for many months thinking that this just wasn&#039;t solvable, waiting patiently for the good Ubuntu folks to magically make it work again in a future version. &lt;br /&gt;
&lt;br /&gt;
Then, one day I installed Ubuntu Feisty on a server at &lt;a href=&quot;http://www.johncompanies.com/&quot;&gt;JohnCompanies&lt;/a&gt;, and I noticed that I could see all 4GB of RAM there.&lt;br /&gt;
 &lt;br /&gt;&lt;a href=&quot;http://www.softwarevoices.com/archives/53-Only-seeing-3GB-of-RAM-on-Ubuntu-7.04-Feisty-when-4GB-are-installed-SOLUTION.html#extended&quot;&gt;Continue reading &quot;Only seeing 3GB of RAM on Ubuntu 7.04 Feisty when 4GB are installed? [SOLUTION]&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Tue, 17 Jul 2007 17:59:42 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/53-guid.html</guid>
    <category>feisty</category>
<category>linux</category>
<category>ram</category>
<category>ubuntu</category>

</item>
<item>
    <title>Convenient svn-ignore script for Subversion</title>
    <link>http://www.softwarevoices.com/archives/51-Convenient-svn-ignore-script-for-Subversion.html</link>
            <category>Programming</category>
    
    <comments>http://www.softwarevoices.com/archives/51-Convenient-svn-ignore-script-for-Subversion.html#comments</comments>
    <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=2.0&amp;type=comments&amp;cid=51</wfw:commentRss>
    

    <author>nospam@example.com (Eric Hammond)</author>
    <content:encoded>
    Subversion allows you to specify certain filenames that it will ignore when performing certain operations (like &quot;svn status&quot;).  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 &quot;.cvsignore&quot; that you could edit.&lt;br /&gt;
&lt;br /&gt;
With Subversion, however, I have to remember and type the following correctly and then use vi to add the name:&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;padding-left: 15px; font-size: 12px;&quot;&gt;&lt;pre style=&quot;line-height:75%&quot;&gt;&lt;code&gt;svn propedit svn:ignore DIRECTORY&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
It looks simple, but it was so unintuitive it took me months to memorize it correctly and I still think it&#039;s ugly. Plus, I&#039;m not particularly in love with vi, though I&#039;ve been using it for over 20 years.  I would much rather type something direct like:&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;padding-left: 15px; font-size: 12px;&quot;&gt;&lt;pre style=&quot;line-height:75%&quot;&gt;&lt;code&gt;svn-ignore DIRECTORY/FILENAME&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
so I wrote the following shell script which lets me do just that:&lt;br /&gt;
 &lt;br /&gt;&lt;a href=&quot;http://www.softwarevoices.com/archives/51-Convenient-svn-ignore-script-for-Subversion.html#extended&quot;&gt;Continue reading &quot;Convenient svn-ignore script for Subversion&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Fri, 03 Nov 2006 08:21:27 -0600</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/51-guid.html</guid>
    <category>.cvsignore</category>
<category>bash</category>
<category>cvs</category>
<category>ignore</category>
<category>propedit</category>
<category>revision control</category>
<category>subversion</category>
<category>svn</category>
<category>svn:ignore</category>

</item>
<item>
    <title>Steve Kelley Heart Model-to-model Transforms ... Not</title>
    <link>http://www.softwarevoices.com/archives/49-Steve-Kelley-Heart-Model-to-model-Transforms-...-Not.html</link>
            <category>Generative programming</category>
    
    <comments>http://www.softwarevoices.com/archives/49-Steve-Kelley-Heart-Model-to-model-Transforms-...-Not.html#comments</comments>
    <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=2.0&amp;type=comments&amp;cid=49</wfw:commentRss>
    

    <author>nospam@example.com (Jollymorphic)</author>
    <content:encoded>
    A short while ago, I posted an &lt;a href=&quot;http://www.softwarevoices.com/archives/42-Out-of-one-tyranny,-into-the-next.html&quot;&gt;article&lt;/a&gt; here arguing that model-to-model transformations (or rather, modularity features based on them) are necessary to escape a new &quot;tyranny of the dominant decomposition&quot; in model-driven programming.  Well, what should arrive in my electronic mailbox a few days ago but a newsletter from &lt;a href=&quot;http://www.metacase.com/&quot;&gt;MetaCase&lt;/a&gt; wherein the first big headline reads, provocatively, &quot;Model-To-Model Transformations: A Recipe for Trouble.&quot;  Oh my!&lt;br /&gt;
&lt;p&gt;The newsletter links to an &lt;a href=&quot;http://www.codegeneration.net/tiki-read_article.php?articleId=81&amp;PHPSESSID=0e57f1674ef1623769492bd0accd26c7&quot;&gt;article&lt;/a&gt; posted a couple of months ago by &lt;a href=&quot;http://www.metacase.com/blogs/stevek/blogView&quot;&gt;Steve Kelley&lt;/a&gt; on the &lt;a href=&quot;http://www.codegeneration.net/tiki-index.php&quot;&gt;Code Generation Network&lt;/a&gt; site.  In a nutshell, Kelley argues &quot;[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.&quot;  He has a lot more to say than this, of course, and the whole editorial is definitely worth your time.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The Whole Article&lt;/h3&gt;&lt;br /&gt;
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 &quot;the payback may be little greater than the effort required to automate&quot;).  And he explains why a UML-based approach, or one based on any &quot;general-purpose design language&quot; for that matter, is doomed to the same fate as those products of yesteryear that have &quot;taught many developers to look at code generators with suspicion.&quot;  He argues that only domain-specific languages created by a product line&#039;s architects themselves can appropriately model features of the domain and serve as a basis for handcraft-quality code generation:&lt;br /&gt;
&lt;blockquote&gt;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&#039;t know enough about an organization&#039;s specific requirements to generate ideal code, so it is not surprising that many have found generated code unsatisfactory.&lt;/blockquote&gt;Kelley then advocates simplicity as a central principle in the development of code generators based on domain-specific models.  &quot;The simpler they are to start with, the simpler it will be to make changes to them later.&quot;  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 &quot;a good reference implementation&quot; 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.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Night and Day&lt;/h3&gt;&lt;br /&gt;
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&#039;s talking about a different way of automating software development than I am.  He&#039;s talking about a user-modified, bidirectional train wreck that we both find repugnant, and for the same reasons:&lt;br /&gt;
&lt;blockquote&gt;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&#039;s say 2 pieces).&lt;/blockquote&gt;We&#039;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&#039;ve enjoyed in OOP languages, which have allowed me to gracefully model relationships that are horizontal, vertical, and everything &quot;in between.&quot;&lt;br /&gt;
&lt;blockquote&gt;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.&lt;br /&gt;&lt;br /&gt;
Often people say next &quot;and we want to be able to change the high-level models still, and have those changes reflected in the low level models&quot;. 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. &quot;Correctly&quot; 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&#039;s name has now been changed).&lt;/blockquote&gt;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, &quot;A DSM generator[&#039;s] output will not normally be edited  or even checked  by hand.&quot;  So, of course, he finds such approaches untenable, as do I.&lt;br /&gt;
&lt;p&gt;If this reflects, as Kelley suggests, the current state of the art in model-to-model transformations, I&#039;d be sad but not surprised.  But I&#039;m also hopeful and eager for the long-term potential presented by some of the technologies currently being nurtured academically.&lt;br /&gt;
&lt;p&gt;And lest you thought Mr. Kelley&#039;s customers stopped there, &lt;em&gt;there&#039;s more...&lt;/em&gt;&lt;br /&gt;
&lt;blockquote&gt;And next, people say &quot;and we want to be able to change the low-level models, and have the high-level models update&quot;. This is even harder.&lt;/blockquote&gt;&lt;strong&gt;I&#039;LL SAY IT IS!&lt;/strong&gt;  Now my earlier sadness has shifted focus from the model business to its customers.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;br /&gt;
Obviously, Kelley and I are talking about different things.  He&#039;s looking at current practice, particularly people who &lt;em&gt;think&lt;/em&gt; they want &quot;model-to-model transformations,&quot; and he&#039;s rightly turning up his nose.  What I&#039;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&#039;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&#039;t use them like code generators.  Rather, they generate &quot;intermediate build products&quot; (in terms of current tooling nomenclature) that are inherently inviolate and of interest only to the development software itself, not to humans.&lt;br /&gt;
&lt;p&gt;The only other way in which Kelley&#039;s post can be said to clash with mine is in his emphasis on &quot;[k]eep[ing] it simple&quot; 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 &quot;gives a good impression, as it looks familiar, follows the required programming mode, includes appropriate comments and follows the local standards for coding style.&quot;  And this emphasis leads straight to simple, reference-implementation-based transformations.  Naturally!&lt;br /&gt;
&lt;p&gt;But I&#039;m focused on the wider, future potential offered by this new abstraction layer, and the types of modularization of models I&#039;ve &lt;em&gt;already&lt;/em&gt; 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&#039;m even willing to sacrifice a little quality in the code that&#039;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 &lt;a href=&quot;http://en.wikipedia.org/wiki/Just_In_Time_compilation&quot;&gt;JIT&lt;/a&gt;s, but now &lt;a href=&quot;http://channel9.msdn.com/Showpost.aspx?postid=20487&quot;&gt;everything&#039;s copacetic&lt;/a&gt;.  The problems that need to be solved may be more abstract than those that came before, but I think they&#039;re tractable, and I look forward to seeing how people do it. 
    </content:encoded>

    <pubDate>Tue, 15 Aug 2006 01:04:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/49-guid.html</guid>
    
</item>
<item>
    <title>URL design: making sure your urls are clickable in plain text emails</title>
    <link>http://www.softwarevoices.com/archives/45-URL-design-making-sure-your-urls-are-clickable-in-plain-text-emails.html</link>
            <category>Programming</category>
    
    <comments>http://www.softwarevoices.com/archives/45-URL-design-making-sure-your-urls-are-clickable-in-plain-text-emails.html#comments</comments>
    <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=2.0&amp;type=comments&amp;cid=45</wfw:commentRss>
    

    <author>nospam@example.com (Craig Ogg)</author>
    <content:encoded>
    One of my fellow bloggers, Eric Hammond, makes the point that  &lt;a href=&quot;http://www.softwarevoices.com/archives/41-Securityprivacy-problem-with-dropping-the-www.-from-your-web-site-URL.html&quot; &gt;dropping the www from your site name may be unwise&lt;/a&gt; for security and privacy reasons.  Another problem with it is that it may make your urls unclickable in emails.&lt;br /&gt;
&lt;br /&gt;
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&#039;t.  In addition it has to make guesses and when the url is &quot;finished.&quot;&lt;br /&gt;
&lt;br /&gt;
Virtually software will only turn text into a link if it starts with &lt;i&gt;www&lt;/i&gt; or &lt;i&gt;http://&lt;/i&gt;.  So dropping the &lt;i&gt;www&lt;/i&gt; to shorten an url actually means having to prefix it with &lt;i&gt;http://&lt;/i&gt; instead --  a net loss.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Here is how some urls are interpreted by the Thunderbird email client:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;#&quot;&gt;http://www.example.com/index.cfm&lt;/a&gt;?param=1 (query parameters dropped)&lt;br /&gt;
&lt;a href=&quot;#&quot;&gt;http://www.example.com/test&lt;/a&gt;! (exclamation dropped from urll)&lt;br /&gt;
&lt;br /&gt;
It is worth the time to test the various email clients to see if your url structure is compatible. 
    </content:encoded>

    <pubDate>Fri, 04 Aug 2006 10:48:02 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/45-guid.html</guid>
    <category>email</category>
<category>urls</category>
<category>usability</category>
<category>www</category>

</item>
<item>
    <title>Out of one tyranny, into the next</title>
    <link>http://www.softwarevoices.com/archives/42-Out-of-one-tyranny,-into-the-next.html</link>
            <category>Generative programming</category>
    
    <comments>http://www.softwarevoices.com/archives/42-Out-of-one-tyranny,-into-the-next.html#comments</comments>
    <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=2.0&amp;type=comments&amp;cid=42</wfw:commentRss>
    

    <author>nospam@example.com (Jollymorphic)</author>
    <content:encoded>
    Among the papers related to generative and model-driven programming I&#039;ve read over the last couple of years, one old favorite is &lt;a href=&quot;http://www.sciencedirect.com/science?_ob=ArticleURL&amp;_udi=B75H1-4FW5VYY-3&amp;_coverDate=04%2F11%2F2005&amp;_alid=421277399&amp;_rdoc=1&amp;_fmt=&amp;_orig=search&amp;_qd=1&amp;_cdi=13109&amp;_sort=d&amp;view=c&amp;_acct=C000050221&amp;_version=1&amp;_urlVersion=0&amp;_userid=10&amp;md5=97f312f268c78d6d9f49bfca1b4bf72d&quot;&gt;The Side Transformation Pattern - making transforms modular and re-usable&lt;/a&gt; by Edward Willink (the &lt;a href=&quot;http://www.computing.surrey.ac.uk/research/dsrg/fog/&quot;&gt;FOG&lt;/a&gt; guy) and Phillip Harris.  The full text is no longer available for free on-line, unfortunately, so I&#039;ll attempt to summarize, quoting the authors:&lt;br /&gt;
&lt;blockquote&gt;Transformation is often presented as a complete activity.  This impression is particularly prevalent in today&#039;s &quot;MDA-compliant&quot; tools, which perform a one-stage rewrite of source ... concepts.  Such an approach ... offers little opportunity for evolution through progressive transformation.&lt;br /&gt;&lt;br /&gt;Where a single stage approach satisfies the user&#039;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.&lt;/blockquote&gt;They may be talking about &lt;a href=&quot;http://en.wikipedia.org/wiki/Model-driven_architecture&quot;&gt;MDA&lt;/a&gt;, but what they&#039;re saying applies equally to almost every tool in this field and most of the projects in development.  The &lt;a href=&quot;http://www.metacase.com/&quot;&gt;commercial&lt;/a&gt; &lt;a href=&quot;http://msdn.microsoft.com/vstudio/teamsystem/workshop/sf/default.aspx&quot;&gt;tools&lt;/a&gt;, 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&#039;re lucky, they may incorporate some other rudimentary features, like model validation and repositories.&lt;br /&gt;
&lt;p&gt;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&#039;s a &lt;em&gt;pattern paper&lt;/em&gt;.  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&#039;m aware of.&lt;br /&gt;
&lt;blockquote&gt;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.&lt;/blockquote&gt;They&#039;re talking about leverage in the implementation of the application development tools themselves, here (the &quot;factory,&quot; in Microsoft&#039;s lingo), not just the applications they produce.  And they&#039;re achieving it through modularity and &lt;a href=&quot;http://en.wikipedia.org/wiki/Aspect_%28computer_science%29&quot;&gt;aspectual decomposition&lt;/a&gt;.&lt;br /&gt;
&lt;p&gt;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.&lt;br /&gt;
&lt;p&gt;Are these guys (and some other folks I&#039;ll get to) onto something?  Is &quot;separation of different concerns[,] ... flexibility and visibility&quot; valuable enough to invest so much in transformation?  More after the fold. &lt;br /&gt;&lt;a href=&quot;http://www.softwarevoices.com/archives/42-Out-of-one-tyranny,-into-the-next.html#extended&quot;&gt;Continue reading &quot;Out of one tyranny, into the next&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Fri, 28 Jul 2006 05:50:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/42-guid.html</guid>
    <category>transformation</category>

</item>
<item>
    <title>Showing Implementation Details in URLs (Example from Google)</title>
    <link>http://www.softwarevoices.com/archives/44-Showing-Implementation-Details-in-URLs-Example-from-Google.html</link>
            <category>Programming</category>
    
    <comments>http://www.softwarevoices.com/archives/44-Showing-Implementation-Details-in-URLs-Example-from-Google.html#comments</comments>
    <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=2.0&amp;type=comments&amp;cid=44</wfw:commentRss>
    

    <author>nospam@example.com (Eric Hammond)</author>
    <content:encoded>
    Google&#039;s official blog &lt;a href=&quot;http://googleblog.blogspot.com/2006/07/roadmap-for-google-help.html&quot;&gt; annouced the location of a new help page&lt;/a&gt; today.  Here&#039;s the link to the new page (which I haven&#039;t even gone to see):&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://www.google.com/support/bin/static.py?page=alpha_index.html&quot;&gt;http://www.google.com/support/bin/static.py?page=alpha_index.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
This is a good example of a poor URL and it&#039;s coming from Google.  Breaking it down we see...&lt;br /&gt;
 &lt;br /&gt;&lt;a href=&quot;http://www.softwarevoices.com/archives/44-Showing-Implementation-Details-in-URLs-Example-from-Google.html#extended&quot;&gt;Continue reading &quot;Showing Implementation Details in URLs (Example from Google)&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Thu, 27 Jul 2006 10:10:31 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/44-guid.html</guid>
    <category>google</category>
<category>urls</category>
<category>usability</category>

</item>
<item>
    <title>Security/privacy problem with dropping the &quot;www.&quot; from your web site URL</title>
    <link>http://www.softwarevoices.com/archives/41-Securityprivacy-problem-with-dropping-the-www.-from-your-web-site-URL.html</link>
            <category>Programming</category>
    
    <comments>http://www.softwarevoices.com/archives/41-Securityprivacy-problem-with-dropping-the-www.-from-your-web-site-URL.html#comments</comments>
    <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=2.0&amp;type=comments&amp;cid=41</wfw:commentRss>
    

    <author>nospam@example.com (Eric Hammond)</author>
    <content:encoded>
    Given today&#039;s state of DNS, smart firewalls/routers/load balancers, and the popularity of the web, it hardly seems necessary to include the &quot;www.&quot; on the front of the URL for your web site.&lt;br /&gt;
&lt;br /&gt;
It is very tempting to drop the &quot;www.&quot; so that when folks visit your site they are browsing &quot;example.com&quot; instead of &quot;www.example.com&quot;.  In fact, I did this with &lt;a href=&quot;http://notlong.com/&quot;&gt;http://notlong.com&lt;/a&gt; and I&#039;m happy with the results there.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s the situation:&lt;br /&gt;
 &lt;br /&gt;&lt;a href=&quot;http://www.softwarevoices.com/archives/41-Securityprivacy-problem-with-dropping-the-www.-from-your-web-site-URL.html#extended&quot;&gt;Continue reading &quot;Security/privacy problem with dropping the &amp;quot;www.&amp;quot; from your web site URL&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Mon, 03 Jul 2006 12:00:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/41-guid.html</guid>
    <category>cookies</category>
<category>dns</category>
<category>feedburner</category>
<category>firefox</category>
<category>internet explorer</category>
<category>privacy</category>
<category>security</category>
<category>squarespace</category>
<category>subdomains</category>
<category>typepad</category>
<category>www</category>

</item>
<item>
    <title>standardCreateElement - the mystery function no one talks about but everyone uses</title>
    <link>http://www.softwarevoices.com/archives/40-standardCreateElement-the-mystery-function-no-one-talks-about-but-everyone-uses.html</link>
            <category>Programming</category>
    
    <comments>http://www.softwarevoices.com/archives/40-standardCreateElement-the-mystery-function-no-one-talks-about-but-everyone-uses.html#comments</comments>
    <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=2.0&amp;type=comments&amp;cid=40</wfw:commentRss>
    

    <author>nospam@example.com (Craig Ogg)</author>
    <content:encoded>
    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&#039;s bookmarklet (aka favelet).  You&#039;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.&lt;br /&gt;
&lt;br /&gt;
It is an eBay specific hack.  Here is the code eBay uses to try to stop bookmarklets and other active content from working:&lt;br /&gt;
&lt;div style=&quot;padding-left: 15px; font-size: 12px;&quot;&gt;&lt;pre style=&quot;line-height:75%&quot;&gt;&lt;code&gt;function EbayBlockActiveContent(pParent,pName)&lt;br /&gt;
{&lt;br /&gt;
  ...&lt;br /&gt;
  document.standardWrite=document.write;&lt;br /&gt;
  this.documentWrite=function(pStr)...&lt;br /&gt;
  document.standardWriteln=document.writeln;&lt;br /&gt;
  this.documentWriteln=function(pStr)...&lt;br /&gt;
  &lt;b&gt;document.standardCreateElement=document.createElement;&lt;br /&gt;
  this.createElement=function(pStr)...&lt;/b&gt;&lt;br /&gt;
  document.write=c.documentWrite;&lt;br /&gt;
  document.writeln=c.documentWriteln;&lt;br /&gt;
  document.createElement=c.createElement;&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
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 &lt;code&gt;standardOLDNAME&lt;/code&gt;.  Sneaky. 
    </content:encoded>

    <pubDate>Mon, 03 Jul 2006 00:05:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/40-guid.html</guid>
    <category>bookmarklet</category>
<category>ebay</category>
<category>javascript</category>

</item>
<item>
    <title>Book Review:  Joe Celko's Trees and Hierarchies</title>
    <link>http://www.softwarevoices.com/archives/39-Book-Review-Joe-Celkos-Trees-and-Hierarchies.html</link>
            <category>Database development</category>
    
    <comments>http://www.softwarevoices.com/archives/39-Book-Review-Joe-Celkos-Trees-and-Hierarchies.html#comments</comments>
    <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=2.0&amp;type=comments&amp;cid=39</wfw:commentRss>
    

    <author>nospam@example.com (Glenn Crowe)</author>
    <content:encoded>
    This is a book review of Joe Celko&#039;s book titled &quot;Joe Celko&#039;s Trees and Hierarchies in SQL for Smarties&quot;  ISBN: 1558609202&lt;br /&gt;
&lt;br /&gt;
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 &quot;&lt;b&gt;yes&lt;/b&gt;.&quot;  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.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;The Good News&lt;/h3&gt; &lt;br /&gt;&lt;a href=&quot;http://www.softwarevoices.com/archives/39-Book-Review-Joe-Celkos-Trees-and-Hierarchies.html#extended&quot;&gt;Continue reading &quot;Book Review:  Joe Celko&#039;s Trees and Hierarchies&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Thu, 25 May 2006 22:22:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/39-guid.html</guid>
    <category>binary trees</category>
<category>book review</category>
<category>joe celko</category>
<category>sql</category>
<category>trees and hierarchies in sql for smarties</category>

</item>
<item>
    <title>Counting nodes in a tree:  A bottom-up approach</title>
    <link>http://www.softwarevoices.com/archives/32-Counting-nodes-in-a-tree-A-bottom-up-approach.html</link>
            <category>Database development</category>
    
    <comments>http://www.softwarevoices.com/archives/32-Counting-nodes-in-a-tree-A-bottom-up-approach.html#comments</comments>
    <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=2.0&amp;type=comments&amp;cid=32</wfw:commentRss>
    

    <author>nospam@example.com (Glenn Crowe)</author>
    <content:encoded>
    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.&lt;br /&gt;
&lt;br /&gt;
For clarity I will point out that the organization is a tree where each employee represents a node.&lt;br /&gt;
&lt;br /&gt;
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:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Create table #tEmployeeTree &lt;br /&gt;
( EmployeeID int, ManagerID int, PassNumber int )&lt;br /&gt;
&lt;br /&gt;
Declare @Pass int, @RowCount int, @EmpIDParam int&lt;br /&gt;
Select  @Pass = 1, @RowCount = 0, @EmpIDParam = 12&lt;br /&gt;
Insert #tEmployeeTree ( EmployeeID, ManagerID, PassNumber )&lt;br /&gt;
Select EmployeeID, ManagerID, @Pass &lt;br /&gt;
  from HumanResources.Employee a&lt;br /&gt;
 where  ManagerID = @EmpIDParam&lt;br /&gt;
&lt;br /&gt;
Select @RowCount = @@RowCount, @Pass = @Pass + 1&lt;br /&gt;
&lt;br /&gt;
While ( @RowCount != 0 )&lt;br /&gt;
begin&lt;br /&gt;
&lt;br /&gt;
    Insert #tEmployeeTree &lt;br /&gt;
    ( EmployeeID, ManagerID, PassNumber )&lt;br /&gt;
    Select&lt;br /&gt;
          b.EmployeeID&lt;br /&gt;
         ,b.ManagerID&lt;br /&gt;
         ,@Pass&lt;br /&gt;
      from  #tEmployeeTree a&lt;br /&gt;
       join HumanResources.Employee b on a.EmployeeID = b.ManagerID&lt;br /&gt;
     where a.PassNumber = @Pass -1&lt;br /&gt;
&lt;br /&gt;
    Select @RowCount = @@RowCount, @Pass = @Pass + 1&lt;br /&gt;
end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;At this point you can be confident that the number of records in the #tEmployeeTree table represents the correct answer.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;&lt;a href=&quot;http://www.softwarevoices.com/archives/32-Counting-nodes-in-a-tree-A-bottom-up-approach.html#extended&quot;&gt;Continue reading &quot;Counting nodes in a tree:  A bottom-up approach&quot;&lt;/a&gt;
    </content:encoded>

    <pubDate>Tue, 25 Apr 2006 23:43:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/32-guid.html</guid>
    <category>graph</category>
<category>hierarchy</category>
<category>sql</category>
<category>sql2005</category>
<category>stored procedures</category>
<category>transact sql</category>
<category>tree</category>

</item>
<item>
    <title>Subclassing DBI when using Class::DBI</title>
    <link>http://www.softwarevoices.com/archives/36-Subclassing-DBI-when-using-ClassDBI.html</link>
            <category>Programming</category>
    
    <comments>http://www.softwarevoices.com/archives/36-Subclassing-DBI-when-using-ClassDBI.html#comments</comments>
    <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=2.0&amp;type=comments&amp;cid=36</wfw:commentRss>
    

    <author>nospam@example.com (Eric Hammond)</author>
    <content:encoded>
    [Update: I&#039;ve been informed that you should be using DBIx::Class instead of Class::DBI because the latter is no longer supported, but I haven&#039;t had time to switch yet.]&lt;br /&gt;
&lt;br /&gt;
The &lt;a href=&quot;http://search.cpan.org/~timb/DBI/DBI.pm&quot;&gt;DBI manpage&lt;/a&gt; describes &lt;a href=&quot;http://search.cpan.org/~timb/DBI/DBI.pm#Subclassing_the_DBI&quot;&gt;how to subclass DBI&lt;/a&gt; to override certain methods on database and statement handles (search for MySubDBI in the DBI manpage).  If you are using &lt;a href=&quot;http://search.cpan.org/~tmtm/Class-DBI/lib/Class/DBI.pm&quot;&gt;Class::DBI&lt;/a&gt;, however, the instructions there won&#039;t work and it won&#039;t be obvious why.&lt;br /&gt;
&lt;br /&gt;
The secret to being able to override DBI methods when using Class::DBI (and subclasses like &lt;a href=&quot;http://search.cpan.org/~tmtm/Class-DBI-mysql/lib/Class/DBI/mysql.pm&quot;&gt;Class::DBI::mysql&lt;/a&gt;) is to instead subclass &lt;a href=&quot;http://search.cpan.org/~tmtm/DBIx-ContextualFetch/lib/DBIx/ContextualFetch.pm&quot;&gt;DBIx::ContextualFetch&lt;/a&gt;.  That class is used by &lt;a href=&quot;http://search.cpan.org/~tmtm/Ima-DBI/lib/Ima/DBI.pm&quot;&gt;Ima::DBI&lt;/a&gt; (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-&gt;connect().&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a sample following the naming conventions in the DBI manpage.  Note that the &quot;connected&quot; 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.&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
package MySubDBI;&lt;br /&gt;
use strict;&lt;br /&gt;
use base &#039;DBIx::ContextualFetch&#039;;&lt;br /&gt;
&lt;br /&gt;
package MySubDBI::db;&lt;br /&gt;
use base &#039;DBIx::ContextualFetch::db&#039;;&lt;br /&gt;
&lt;br /&gt;
# Override methods for the database handle here. (Sample provided)&lt;br /&gt;
sub connected {&lt;br /&gt;
  my $dbh = shift;&lt;br /&gt;
  my ($dsn, $user, $pass, $attr) = @_;&lt;br /&gt;
  warn &quot;Connected to $dsn as $user&quot;;&lt;br /&gt;
  return $dbh-&gt;SUPER::connected($dsn, $user, $pass, $attr);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
package MySubDBI::st;&lt;br /&gt;
use base &#039;DBIx::ContextualFetch::st&#039;;&lt;br /&gt;
&lt;br /&gt;
# Override methods for the statement handle here.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;b&gt;Important:&lt;/b&gt; When opening the database handle for your Class::DBI objects, you need to specify the following attribute in the &lt;i&gt;DSN string&lt;/i&gt;: &quot;RootClass=MySubDBI&quot; (where MySubDBI is the name of your subclass above). For example the DSN might look like:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&quot;DBI:mysql(RootClass=MySubDBI):host=localhost;database=dbname&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;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&#039;t spend a lot of time trying to figure out exactly why.&lt;br /&gt;
 
    </content:encoded>

    <pubDate>Wed, 05 Apr 2006 16:52:35 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/36-guid.html</guid>
    <category>Class::DBI</category>
<category>DBI</category>
<category>Perl</category>

</item>
<item>
    <title>Debugging Character Set Problems (aka, how to fix smart quotes that turn into diamonds)</title>
    <link>http://www.softwarevoices.com/archives/35-Debugging-Character-Set-Problems-aka,-how-to-fix-smart-quotes-that-turn-into-diamonds.html</link>
            <category>Programming</category>
    
    <comments>http://www.softwarevoices.com/archives/35-Debugging-Character-Set-Problems-aka,-how-to-fix-smart-quotes-that-turn-into-diamonds.html#comments</comments>
    <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=35</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=2.0&amp;type=comments&amp;cid=35</wfw:commentRss>
    

    <author>nospam@example.com (Craig Ogg)</author>
    <content:encoded>
    It all started with a simple bug report:  when the user pastes a registered trademark symbol (&amp;reg;) into a textarea is &quot;having children&quot; when it is displayed -- multiple characters are appearing where there was only one before. Many hours later I concluded that my attempts at quick fixes weren&#039;t going to work -- I was getting different results from Firefox on Linux than from IE on Windows XP.&lt;br /&gt;
&lt;br /&gt;
My comments below are my experience in Perl on Linux, but much of the advice should be language and platform independent.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;30 Second Guide to Character Sets&lt;sup&gt;1&lt;/sup&gt;&lt;/b&gt;&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Strings are stored as a sequence of bytes.&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;What characters these bytes represent is completely arbitrary, but it is dictated by what the software &lt;i&gt;believes&lt;/i&gt; the character set encoding is.&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Every piece of software the touches the string has an opportunity to screw it up if it believes wrong.&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;If English is your primary language, you won&#039;t notice it is screwed up until you get to unusual characters (registered trademark, smart quotes, foreign language character).&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Fixing it once it is screwed up will be painful.&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Once you fix it, it will break again every time there is new software that touches the string.&lt;/li&gt;&lt;br /&gt;
&lt;/ol&gt;Fortunately it is relatively straightforward to debug if you follow:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Ogg&#039;s Rules for Debugging Character Set Problems&lt;/b&gt;&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;&lt;b&gt;Never&lt;/b&gt; waste your time debugging by printing the strings to the terminal or to a file.  Your screen driver or editor is software.  Its interpretation of the character set just introduces more variables into the equation.&lt;sup&gt;2&lt;/sup&gt;&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;&lt;b&gt;Always&lt;/b&gt; print the bytes as hex or use another reliable mechanism for determine what bytes actually make up the string.  For Perl, this is &lt;code&gt;Devel::Peek::Dump&lt;/code&gt;.&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Check the values before and after any operation that modifies the string.&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;For languages like Perl that attempt to transparently handle both ASCII and Unicode, check what the language believes the string is before and after any operation that modifies the string.&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;Don&#039;t use string literals that have characters that aren&#039;t 7-bit safe (their ASCII value is &lt; 128), instead specify them with the character set appropriate numeric value.  In Perl, always use the Unicode value for this.&lt;sup&gt;3&lt;/sup&gt;&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;If a web page says it is using ISO-8859-1 encoding or Latin-1 encoding, assume they are actually using Windows-1252 encoding instead.  This is what the browsers assume, so you might as well (this primarily affects the &amp;trade; symbol).&lt;/li&gt;&lt;br /&gt;
&lt;li&gt;If you don&#039;t know what encoding the input is in, you really have no chance of actually knowing what the bytes mean.  For an HTML input form this means using a hidden field named &lt;code&gt;&amp;#95;charset_&lt;/code&gt;.  You are using one in every form, right? (See this &lt;a href=&#039;https://bugzilla.mozilla.org/show_bug.cgi?id=18643&#039;&gt;Mozilla bug report&lt;/a&gt; for details)&lt;/li&gt;&lt;br /&gt;
&lt;/ol&gt;&lt;br /&gt;
&lt;sup&gt;1&lt;/sup&gt;Read &lt;a href=&#039;http://www.amazon.com/exec/obidos/ASIN/0596004567&#039;&gt;Advanced Perl Programming&lt;/a&gt; for more in depth coverage.&lt;br /&gt;
&lt;br /&gt;
&lt;sup&gt;2&lt;/sup&gt;For example, if you output a Perl string that is not marked as utf8 to UTF-8 terminal as you normally would, it will print correctly (even though it is wrong). If the string is correctly marked as utf8, it will print as if it is screwed up. If you correctly set STDOUT to utf8 (&lt;code&gt;binmode(STDOUT, &quot;:utf8&quot;)&lt;/code&gt;), the results will be reversed.  Do you even know what character set your terminal uses?&lt;br /&gt;
&lt;br /&gt;
&lt;sup&gt;3&lt;/sup&gt;If you ignore this advice and are using string constants anywhere in your code and those constants have non-English or special characters, make sure you know what character set your language is going to think the file is in (which, of course, is probably unrelated to what character set your OS thinks the file is in).  For Perl, if you have &lt;code&gt;use utf8;&lt;/code&gt; at the top of your file, the file will be assumed to be in the UTF-8 encoding.  If you use &lt;code&gt;use encoding &quot;latin-1&quot;;&lt;/code&gt; then Perl will assume your file is in Latin-1.  See &lt;code&gt;perldoc utf8&lt;/code&gt;. 
    </content:encoded>

    <pubDate>Tue, 04 Apr 2006 16:16:00 -0500</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/35-guid.html</guid>
    <category>charset</category>
<category>forms</category>
<category>html</category>
<category>perl</category>
<category>unicode</category>
<category>utf-8</category>

</item>
<item>
    <title>Passing n parameters to a Stored Procedure in a single call</title>
    <link>http://www.softwarevoices.com/archives/27-Passing-n-parameters-to-a-Stored-Procedure-in-a-single-call.html</link>
            <category>Database development</category>
    
    <comments>http://www.softwarevoices.com/archives/27-Passing-n-parameters-to-a-Stored-Procedure-in-a-single-call.html#comments</comments>
    <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=27</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=2.0&amp;type=comments&amp;cid=27</wfw:commentRss>
    

    <author>nospam@example.com (Glenn Crowe)</author>
    <content:encoded>
    Application developers have long lamented the seemingly delinquent support for passing an unbounded number of parameters to a SQL Server stored procedure.  Such support has always existed, but the mechanism has never been entirely intuitive.&lt;br /&gt;
&lt;br /&gt;
Observe a stored procedure defined thusly:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;Create proc sp_AsManyAsYouLike as&lt;br /&gt;
set nocount on Select myInt * 1000 from #tempParam&lt;br /&gt;
go&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Now I bring all of my Perl programming skills to bear:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;$cmd-&gt;{ActiveConnection} = $conn;&lt;br /&gt;
$cmd-&gt;{CommandType} = 1;&lt;br /&gt;
$cmd-&gt;{CommandText} = &quot;set nocount on Create table #tempParam (MyInt int)\n&quot;;&lt;br /&gt;
$cmd-&gt;{CommandText} = $cmd-&gt;{CommandText} . &quot;Insert #tempParam Select 1\n&quot;;&lt;br /&gt;
$cmd-&gt;{CommandText} = $cmd-&gt;{CommandText} . &quot;Insert #tempParam Select 2\n&quot;;&lt;br /&gt;
$cmd-&gt;{CommandText} = $cmd-&gt;{CommandText} . &quot;Exec sp_AsManyAsYouLike&quot;;&lt;br /&gt;
&lt;br /&gt;
$WScript-&gt;Echo($cmd-&gt;CommandText . &quot;\n&quot;);&lt;br /&gt;
    &lt;br /&gt;
$RS = $cmd-&gt;Execute();&lt;br /&gt;
&lt;br /&gt;
while(!$RS-&gt;EOF){&lt;br /&gt;
$WScript-&gt;Echo($RS-&gt;Fields(0)-&gt;value);&lt;br /&gt;
$RS-&gt;MoveNext;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Which yeilds the following:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;set nocount on Create table #tempParam (MyInt int)&lt;br /&gt;
Insert #tempParam Select 1&lt;br /&gt;
Insert #tempParam Select 2&lt;br /&gt;
Exec sp_AsManyAsYouLike&lt;br /&gt;
&lt;br /&gt;
1000&lt;br /&gt;
2000&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
My example above is simplistic, but you can extend this model to pass all sorts of complex structures to a stored procedure.  I don&#039;t offer this solution as a brilliant design.  It is merely more palatable, and more flexible, than parsing strings with Transact SQL.   
    </content:encoded>

    <pubDate>Wed, 01 Mar 2006 00:03:00 -0600</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/27-guid.html</guid>
    <category>ado</category>
<category>database</category>
<category>parameters</category>
<category>perl</category>
<category>sql</category>
<category>sql2005</category>
<category>sql2k</category>
<category>stored procedures</category>
<category>transact sql</category>
<category>variable parameters</category>

</item>
<item>
    <title>Code Review:  OUTPUT parameters and transactions</title>
    <link>http://www.softwarevoices.com/archives/26-Code-Review-OUTPUT-parameters-and-transactions.html</link>
            <category>Database development</category>
    
    <comments>http://www.softwarevoices.com/archives/26-Code-Review-OUTPUT-parameters-and-transactions.html#comments</comments>
    <wfw:comment>http://www.softwarevoices.com/wfwcomment.php?cid=26</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.softwarevoices.com/rss.php?version=2.0&amp;type=comments&amp;cid=26</wfw:commentRss>
    

    <author>nospam@example.com (Glenn Crowe)</author>
    <content:encoded>
    File this one away for the next time you code review a SQL Server stored procedure.  Those OUTPUT parameters arent bound to your transactions in any way.&lt;br /&gt;
&lt;br /&gt;
Observe:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Create proc sp_OutputMyIdent (@myOutputIdent int output)&lt;br /&gt;
as&lt;br /&gt;
set nocount on&lt;br /&gt;
Begin transaction &lt;br /&gt;
    Insert myIdentTable Select &#039;foo&#039;&lt;br /&gt;
    Select @myOutputIdent = @@Identity&lt;br /&gt;
&lt;b&gt;rollback transaction&lt;/b&gt;&lt;br /&gt;
go&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Now a little ADO from JScript:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
myCommand.CommandText = &quot;sp_OutputMyIdent&quot;;&lt;br /&gt;
myCommand.CommandType = adCmdStoredProc;&lt;br /&gt;
myCommand.ActiveConnection = myConnection;        &lt;br /&gt;
myCommand.Parameters(&quot;@myOutputIdent&quot;) = 0;        &lt;br /&gt;
WScript.Echo(&quot;Before:  &quot; + myCommand.Parameters(&quot;@myOutputIdent&quot;));&lt;br /&gt;
myCommand.Execute();        &lt;br /&gt;
WScript.Echo(&quot;After:  &quot; + myCommand.Parameters(&quot;@myOutputIdent&quot;));&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Which yields the following:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Before:  0&lt;br /&gt;
&lt;b&gt;After:  1&lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Errors dont alter this behavior at all.  Any reasonably competent scripting programmer can trap and then disregard your error.&lt;br /&gt;
&lt;br /&gt;
Observe:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Create proc sp_OutputMyIdent (@myOutputIdent int output)&lt;br /&gt;
as&lt;br /&gt;
set nocount on&lt;br /&gt;
Begin transaction &lt;br /&gt;
    Insert myIdentTable Select &#039;foo&#039;&lt;br /&gt;
    Select @myLocalVar = @@Identity&lt;br /&gt;
    &lt;b&gt;RaisError ( N&#039;Uh Oh!&#039;, 16, 1 )&lt;/b&gt;&lt;br /&gt;
rollback transaction &lt;br /&gt;
go&lt;br /&gt;
&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
myCommand.CommandText = &quot;sp_OutputMyIdent&quot;;&lt;br /&gt;
myCommand.CommandType = adCmdStoredProc;&lt;br /&gt;
myCommand.ActiveConnection = myConnection;        &lt;br /&gt;
myCommand.Parameters(&quot;@myOutputIdent&quot;) = 0;        &lt;br /&gt;
WScript.Echo(&quot;Before:  &quot; + myCommand.Parameters(&quot;@myOutputIdent&quot;));&lt;br /&gt;
myCommand.Execute();&lt;br /&gt;
}&lt;br /&gt;
catch(e){ WScript.Echo(e.description) }&lt;br /&gt;
WScript.Echo(&quot;After: &quot; + myCommand.Parameters(&quot;@myOutputIdent&quot;));&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
Which yields the following:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Before:  0&lt;br /&gt;
Uh Oh!&lt;br /&gt;
&lt;b&gt;After:  2&lt;/b&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
The best thing to do is to keep your progress private until you know you are done:&lt;div style=&quot;padding-left: 15px&quot;&gt;&lt;pre style=&quot;line-height:50%; color:black; font-size:10pt&quot;&gt;&lt;code&gt;&lt;br /&gt;
Create proc sp_OutputMyIdent (@myOutputIdent int output)&lt;br /&gt;
as&lt;br /&gt;
set nocount on&lt;br /&gt;
Declare @myLocalVar int&lt;br /&gt;
Begin transaction &lt;br /&gt;
    Insert myIdentTable Select &#039;foo&#039;&lt;br /&gt;
    Select @myLocalVar = @@Identity&lt;br /&gt;
    RaisError ( N&#039;Uh Oh!&#039;, 16, 1 )&lt;br /&gt;
&lt;b&gt;commit transaction &lt;/b&gt;&lt;br /&gt;
Select &lt;b&gt;@myOutputIdent &lt;/b&gt;= @myLocalVar&lt;br /&gt;
go&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt; 
    </content:encoded>

    <pubDate>Thu, 16 Feb 2006 23:47:03 -0600</pubDate>
    <guid isPermaLink="false">http://www.softwarevoices.com/archives/26-guid.html</guid>
    <category>database</category>
<category>output parameters</category>
<category>sql</category>
<category>sql2005</category>
<category>sql2k</category>
<category>stored procedures</category>

</item>

</channel>
</rss>