<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.asp.net/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Alex Papadimoulis' .NET Blog</title><subtitle type="html">Alex's musings about .NET and other Microsoft technologies</subtitle><id>http://weblogs.asp.net/alex_papadimoulis/atom.aspx</id><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/default.aspx" /><link rel="self" type="application/atom+xml" href="http://weblogs.asp.net/alex_papadimoulis/atom.aspx" /><generator uri="http://communityserver.org" version="3.0.20510.895">Community Server</generator><updated>2005-04-22T14:06:00Z</updated><entry><title>ScriptOnly - The Opposite of a NOSCRIPT</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2008/02/21/scriptonly-the-opposite-of-a-noscript.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2008/02/21/scriptonly-the-opposite-of-a-noscript.aspx</id><published>2008-02-21T18:07:00Z</published><updated>2008-02-21T18:07:00Z</updated><content type="html">&lt;P&gt;Despite all of the advances in client-side scripting, the wonderful JavaScript libraries like &lt;A href="http://www.prototypejs.org/" mce_href="http://www.prototypejs.org/"&gt;Prototype&lt;/A&gt; and &lt;A href="http://script.aculo.us/" mce_href="http://script.aculo.us/"&gt;Scriptaculous&lt;/A&gt;, and the ease of writing AJAXy code in ASP.NET, there’s still one aspect of modern web development that can be a complete pain in the butt: accessibility for users without JavaScript. If you’re lucky – perhaps you’re developing an Intranet application, or the like – a simple &amp;lt;noscript&amp;gt;Error: This application requires JavaScript enabled&amp;lt;/noscript&amp;gt; is all it takes. But other times, you need to take that extra step and make it work for those with and without JavaScript enabled. 
&lt;P&gt;There’s a lot of ways that this can be accomplished, but one of the more popular ways is with the SCRIPT/NOSCRIPT combo... &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;script&lt;/SPAN&gt; &lt;SPAN class=attr&gt;type&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="text/javascript"&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
    document.write(&lt;SPAN class=str&gt;'Only users with JavaScript will see me.'&lt;/SPAN&gt;);    
&lt;SPAN class=kwrd&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN class=html&gt;script&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;noscript&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
    Only users without JavaScript will see me.
&lt;SPAN class=kwrd&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN class=html&gt;noscript&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;While this works fine in a lot of scenarios, it can get especially tricky when you want to put server-side controls on the SCRIPT side of things. A lot of developers resort to something like this... &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;div&lt;/SPAN&gt; &lt;SPAN class=attr&gt;id&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="javaScriptOnly"&lt;/SPAN&gt; &lt;SPAN class=attr&gt;style&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="display:none"&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
    Only users with JavaScript will see me.
    &lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;asp:LinkButton&lt;/SPAN&gt; &lt;SPAN class=attr&gt;runat&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="server"&lt;/SPAN&gt; ... &lt;SPAN class=kwrd&gt;/&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN class=html&gt;div&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;div&lt;/SPAN&gt; &lt;SPAN class=attr&gt;id&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="noJavaScript"&lt;/SPAN&gt; &lt;SPAN class=attr&gt;style&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="display:block"&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
    Only users without JavaScript will see me.
    &lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;asp:Button&lt;/SPAN&gt; &lt;SPAN class=attr&gt;runat&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="server"&lt;/SPAN&gt; ... &lt;SPAN class=kwrd&gt;/&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN class=html&gt;div&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;script&lt;/SPAN&gt; &lt;SPAN class=attr&gt;type&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="text/javascript"&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
    document.getElementById(&lt;SPAN class=str&gt;'javaScriptOnly'&lt;/SPAN&gt;).style.display = &lt;SPAN class=str&gt;'block'&lt;/SPAN&gt;;
    document.getElementById(&lt;SPAN class=str&gt;'noJavaScript'&lt;/SPAN&gt;).style.display = &lt;SPAN class=str&gt;'none'&lt;/SPAN&gt;;
&lt;SPAN class=kwrd&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN class=html&gt;script&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;... and of course, things quickly get much uglier once you do this in the real world. 
&lt;P&gt;One solution that I use is a simple, custom-control called ScriptOnly. It works just like this... &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;inedo:ScriptOnly&lt;/SPAN&gt; &lt;SPAN class=attr&gt;runat&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="server"&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
    Only users with JavaScript will see me.
    &lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;asp:LinkButton&lt;/SPAN&gt; &lt;SPAN class=attr&gt;runat&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="server"&lt;/SPAN&gt; &lt;SPAN class=attr&gt;onClick&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="doSomething"&lt;/SPAN&gt; ... &lt;SPAN class=kwrd&gt;/&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN class=html&gt;inedo:ScriptOnly&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;noscript&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
    Only users without JavaScript will see me.
    &lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;asp:Button&lt;/SPAN&gt; &lt;SPAN class=attr&gt;runat&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="server"&lt;/SPAN&gt; &lt;SPAN class=attr&gt;onClick&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="doSomething"&lt;/SPAN&gt; ... &lt;SPAN class=kwrd&gt;/&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN class=html&gt;noscript&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;JavaScript users see a LinkButton, while non-JavaScript users see a plain old submit button. What’s neat about this technique is that you can put any type of content - server-controls, html, script tags, etc - and that content will only be displayed for JavaScript users. In essense, it works like a reverse NOSCRIPT tag. 
&lt;P&gt;Behind the scenes, ScriptOnly is a very simple control... &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;[ParseChildren(&lt;SPAN class=kwrd&gt;false&lt;/SPAN&gt;)]
&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;class&lt;/SPAN&gt; ScriptOnly : Control
{
    &lt;SPAN class=kwrd&gt;protected&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;override&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; Render(HtmlTextWriter writer)
    {
        &lt;SPAN class=rem&gt;//Render contents to a StringWriter&lt;/SPAN&gt;
        StringWriter renderedContents = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; StringWriter();
        &lt;SPAN class=kwrd&gt;base&lt;/SPAN&gt;.Render(&lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; HtmlTextWriter(renderedContents));

        &lt;SPAN class=rem&gt;//write out the contents, line by line&lt;/SPAN&gt;
        writer.WriteLine(&lt;SPAN class=str&gt;"&amp;lt;script type=\"text/javascript\"&amp;gt;"&lt;/SPAN&gt;);
        StringReader sr = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; StringReader(renderedContents.ToString());
        &lt;SPAN class=kwrd&gt;while&lt;/SPAN&gt; (sr.Peek() &amp;gt;= 0)
        {
            &lt;SPAN class=rem&gt;// This could be optimized to write on one line; but&lt;/SPAN&gt;
            &lt;SPAN class=rem&gt;// I've found this makes it easier to debug when&lt;/SPAN&gt;
            &lt;SPAN class=rem&gt;// looking at a page's source&lt;/SPAN&gt;
            writer.WriteLine(
                &lt;SPAN class=str&gt;"document.writeln('{0}');"&lt;/SPAN&gt;,
                jsEscapeText(sr.ReadLine()).Trim());
        }
        writer.WriteLine(&lt;SPAN class=str&gt;"&amp;lt;/script&amp;gt;"&lt;/SPAN&gt;);
    }

    &lt;SPAN class=kwrd&gt;private&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; jsEscapeText(&lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;value&lt;/SPAN&gt;)
    {
        &lt;SPAN class=kwrd&gt;if&lt;/SPAN&gt; (&lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt;.IsNullOrEmpty(&lt;SPAN class=kwrd&gt;value&lt;/SPAN&gt;)) &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;value&lt;/SPAN&gt;;

        &lt;SPAN class=rem&gt;// This, too, could be optimzied to replace character&lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;// by character; but this gives you an idea of&lt;/SPAN&gt;
        &lt;SPAN class=rem&gt;// what to escape out&lt;/SPAN&gt;
        &lt;SPAN class=kwrd&gt;return&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;value&lt;/SPAN&gt;
            &lt;SPAN class=rem&gt;/*  \ --&amp;gt; \\ */&lt;/SPAN&gt;
            .Replace(&lt;SPAN class=str&gt;"\\", "&lt;/SPAN&gt;\\\\&lt;SPAN class=str&gt;")
            /*  ' --&amp;gt; \' */
            .Replace("&lt;/SPAN&gt;&lt;SPAN class=str&gt;'", "\\'")
            /*  " --&amp;gt; \" */
            .Replace("\"", "\\\"")
            /*  (newline) --&amp;gt; \n */
            .Replace("\n", "\\n")
            /*  (creturn) --&amp;gt; \r */
            .Replace("\r", "\\r")
            /* &amp;lt;/script&amp;gt; string */
            .Replace("&amp;lt;/script&amp;gt;", "&amp;lt;/scri'&lt;/SPAN&gt;+'pt&amp;gt;");
    }
}&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;When "pre-reistered" in your web.config, it works just as well as the NOSCRIPT tag.&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5836416" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>A Workaround For VirtualPath Weirdness With Custom VirtualPathProviders</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2008/01/11/a-workaround-for-virtualpath-weirdness-with-custom-virtualpathproviders.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2008/01/11/a-workaround-for-virtualpath-weirdness-with-custom-virtualpathproviders.aspx</id><published>2008-01-11T23:16:00Z</published><updated>2008-01-11T23:16:00Z</updated><content type="html">&lt;P&gt;[[ &lt;EM&gt;Meta-blogging: as you may have noticed from the name/description change (and of course, this article) I’ve decided to shift the focus of this blog back to the “front lines” of Microsoft/.NET development technologies. All other rants and ramblings will go to &lt;/EM&gt;&lt;A href="http://thedailywtf.com/Series/Alex_0x27_s_Soapbox.aspx" mce_href="http://thedailywtf.com/Series/Alex_0x27_s_Soapbox.aspx"&gt;&lt;EM&gt;Alex's Soapbox&lt;/EM&gt;&lt;/A&gt;&lt;EM&gt; over at &lt;A class="" href="http://thedailywtf.com/" mce_href="http://thedailywtf.com"&gt;WTF&lt;/A&gt; &lt;/EM&gt;]] &lt;/P&gt;
&lt;P&gt;If you've ever come across this error... 
&lt;BLOCKQUOTE&gt;The VirtualPathProvider returned a VirtualFile object with VirtualPath set to '/global/initrode/embeddedControl.ascx' instead of the expected '//global/initrode/embeddedControl.ascx'&lt;/BLOCKQUOTE&gt;
&lt;P&gt;... then chances are you're implementing VirtualPathProvider in order to serve up embedded Page/Control resources or something fun like that. Let's just hope your not &lt;A href="http://msdn2.microsoft.com/en-us/library/aa479502.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa479502.aspx"&gt;serving pages from a ZIP file&lt;/A&gt;. And if you have no idea what a VirtualPathProvider is, then do check out that MSDN article I linked to get an idea. 
&lt;P&gt;The reason behind this error is identified in Microsoft Bug #&lt;A href="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=307978" mce_href="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=307978"&gt;307978&lt;/A&gt;: ASP.NET is erroneously replacing page compilation errors with the bad virtual path error. While ensuring that your virtual-pathed page will compile is a sure-fire way to fix the error, finding the compilation errors can be a bit of pain. 
&lt;P&gt;Fortunately, there's a pretty easy workaround that will let you see some of the compilation errors. First, make sure that your custom VirtualPathProvider has a static method that can determine if given virtualPath is on disk or is virtualized (e.g. an embedded resource). Next, create an IHandlerFactory that inherits PageHandlerFactory, overrides the GetHandler method, and has a try/catch around a call to base.GetHandler(). In the event that an exception occurs, simply determine if the request's virtual path is "virtual" (through that static method) and, if so, rethrow the exception with only the error message. In other words, &lt;PRE&gt;public class MyPageHandlerFactory : PageHandlerFactory
    {
        public override IHttpHandler GetHandler(HttpContext context, string requestType, string virtualPath, string path)
        {
            try
            {
                return base.GetHandler(context, requestType, virtualPath, pathTranslated);
            }
            catch (Exception ex)
            {
                //TODO: ASP.NET 2.0 Bug Workaround
                // There is an error generating a stack trace for VirtualPathed files, so 
                // we have to give up our stack trace if it's a resource file

                if (EmbeddedResourceVirtualPathProvider.IsResourcePath(virtualPath))
                    throw new Exception(ex.Message);
                else
                    throw ex;
            }
        }
    }&lt;/PRE&gt;
&lt;P&gt;Since we're only wrapping the GetHandler method (as opposed to the IHttpHandler's ProcessRequest method), the only errors you'll see wrapped like this are pre-ProcessRequest errors (e.g. compilation errors). And while this won't give you the full stack trace, at least you'll see something like this instead: 
&lt;BLOCKQUOTE&gt;http://server//global/initrode/embeddedControl.ascx(5): error CS1002: ; expected &lt;/BLOCKQUOTE&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5591595" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>Coghead: Web Applications for Dummies by Dummies</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2006/09/25/Coghead_3A00_-Web-Applications-for-Dummies-by-Dummies.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2006/09/25/Coghead_3A00_-Web-Applications-for-Dummies-by-Dummies.aspx</id><published>2006-09-25T22:53:00Z</published><updated>2006-09-25T22:53:00Z</updated><content type="html">&lt;p&gt;&lt;img style="width: 192px; height: 106px" src="http://thedailywtf.com/images/alexp/coghead02.gif" alt="" width="192" height="106" align="right" /&gt;There&amp;#39;s been a buzz going around about a new web startup called Coghead.&amp;nbsp; Heralded by Business 2.0 as one of the &amp;quot;innovations that could reorder entire industries,&amp;quot; Coghead is lead by former Red Hat executive Paul McNamara and Extricity founder Greg Olsen. El Dorado Ventures, a Venture Capitalist firm, recently invested $2.3M in the company. According to McNamara,&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;Coghead will enable nonprogrammers to rapidly create their own custom business software&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;In other words, Coghead is the b*stard child of 4GL and Web 2.0; it&amp;#39;s the end result of a careful mixture of myth and buzzword; and, I&amp;#39;m sure, it will play an important part in several upcoming The Daily WTF articles. Before we get into the details of Coghead, let&amp;#39;s take a look back at the world of 4GL.&lt;/p&gt;&lt;p&gt;There&amp;#39;s a bit of ambiguity surrounding what is and isn&amp;#39;t a 4GL (Fourth Generation Language), so I&amp;#39;ll stick with James Martin&amp;#39;s characterization from his 1982 book, &lt;em&gt;Application Development Without Programmers&lt;/em&gt;. The book&amp;#39;s title should give you a good enough understanding of the goal of a 4GL: the ability to develop complex custom business software through the use of simple-to-use tools.&lt;/p&gt;&lt;p&gt;In the quarter-century since &lt;em&gt;Application Development Without Programmers&lt;/em&gt; debuted, let&amp;#39;s consider how far we&amp;#39;ve come on this goal: dBase, Clipper, FileMaker, and Access. It&amp;#39;s a pretty far cry from what James Martin and the other 4GL dreamers had in mind. Sure, Jane in Accounting could easily use Microsoft Access to create custom software to manage her music collection, but ask her to develop the General Ledger in Access and you&amp;#39;ll find your books in worse shape than Enron&amp;#39;s and Tyco&amp;#39;s combined.&lt;/p&gt;&lt;p&gt;There&amp;#39;s a simple, common-sense reason why custom business software will always require programmers. It&amp;#39;s the same reason that brickwork will always require a mason and why woodwork will always require a carpenter. No matter how complex and versatile a tool is, an experienced builder is always required to create something unique.&lt;/p&gt;&lt;p&gt;Like many other common-sense principles, the &amp;quot;software machine&amp;quot; is one that some programmers don&amp;#39;t get. Be it with The Tool or The Customer Friendly System, these programmers believe they are so clever and so intelligent that they can program even themselves into obsolescence.&lt;/p&gt;&lt;p&gt;Some businesses don&amp;#39;t get it, either. But they will eventually pay the price: the &amp;quot;mission critical&amp;quot; software they developed for themselves in Microsoft Access will become their albatross, costing time, opportunity, and, eventually, lots of money for real programmers to fix their mess. &lt;/p&gt;&lt;p&gt;And this is where we return to Coghead. You see, Coghead is merely another example of this arrogant ignorance, but this time it&amp;#39;s web-based and enterprisey. That&amp;#39;s right; unlike its desktop counterparts, Coghead is targeted towards big businesses, not small businesses and hobbyists: &lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;&amp;quot;anyone who can code a simple Excel macro should have little trouble using Coghead to create even sophisticated enterprise apps like logistics trackers, CRM programs, or project management systems.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Even with a liberal application of AJAX, the fact that Coghead is web-based means that it&amp;#39;s less functional and offers a poorer experience than its desktop equivalent. Not only that, but all data and business logic are left in the hands of a third party. That, in and of itself, is a good enough reason to avoid Coghead.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;img src="http://thedailywtf.com/images/alexp/coghead01.gif" alt="" width="554" height="391" /&gt;&lt;br /&gt;&lt;em&gt;the Coghead web IDE&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Twenty years ago, if you developed a dBase application, you &amp;quot;owned&amp;quot; it and knew that so long as you could find a MS-DOS 2.0 disk, your data and business logic were safe. If you developed a Coghead application, what would happen if Coghead went out of business? What if they upgrade their system and it breaks your application? What if you forget to pay the subscription fee and they delete your application? It just isn&amp;#39;t worth the risk.&lt;/p&gt;&lt;p&gt;Some might argue that this negative analysis is a knee-jerk reaction to a threat. After all, Business 2.0 claims that Coghead will be a disruptor for &amp;quot;initially, custom software developers, but potentially almost all software-tool makers.&amp;quot; But I&amp;#39;m not threatened by Coghead; I&amp;#39;m disappointed. &lt;/p&gt;&lt;p&gt;We&amp;#39;ve come a long way with software development in the past twenty-five years, from automated build processes to advanced integrated development environments. We&amp;#39;ve developed effective techniques for communicating with users and bringing them closer to the development process. Perpetuating the myth that programmers are an unnecessary part of the software development process does nothing but alienate users and frustrate them when the (programmer-developed) &amp;Uuml;berTool fails to deliver the results it promised.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=582002" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author><category term="General Software Development" scheme="http://weblogs.asp.net/alex_papadimoulis/archive/tags/General+Software+Development/default.aspx" /></entry><entry><title>Stop Using Enterprise Manager! (Use DDL Instead)</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2006/05/03/stop-using-enterprise-manager-use-ddl-instead.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2006/05/03/stop-using-enterprise-manager-use-ddl-instead.aspx</id><published>2006-05-03T20:43:00Z</published><updated>2006-05-03T20:43:00Z</updated><content type="html">&lt;P&gt;Of all the tools that ship with SQL Server, Enterprise Manager is by far the most feature-packed and widely-used. Nearly every SQL Server developer is familiar with Enterprise Manager. They are comfortable using the wizards and GUI to do everything from creating a new table to adding a schedule job. But as a project grows to encompass more developers and environments, Enterprise Manager becomes a detriment to the development process.&lt;/P&gt;
&lt;P&gt;Most applications exist in at least two different environments: a development environment and a production environment. Promoting changes to code from a lower level (development) to a higher level (production) is trivial. You just copy the executable code to the desired environment. &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Click on the desired database. &lt;/LI&gt;
&lt;LI&gt;Click on Action, New, then Table. &lt;/LI&gt;
&lt;LI&gt;Add a column named "Shipper_Id" with a Data Type "char", give it a length of 5, and uncheck the "Allow Nulls" box. &lt;/LI&gt;
&lt;LI&gt;In the toolbar, click on the "Set Primary Key" icon. Then you skip 22 steps. &lt;/LI&gt;
&lt;LI&gt;In the toolbar, click on the "Manage Relationships…" button. &lt;/LI&gt;
&lt;LI&gt;Click on the New button, and then select "Shippers" as the Foreign key table. &lt;/LI&gt;
&lt;LI&gt;Select "Shipper_Id" on the left column and "Shipper_Id" on the right column. Skip the remaining steps. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Not only is this process tedious, but you're prone to making errors and omissions when using it. Such errors and omissions leave the higher-level and lower-level databases out of sync. &lt;/P&gt;
&lt;P&gt;Fortunately, you can use an easier method to maintain changes between databases: Data Definition Language (DDL). The change described in the previous example can be developed in a lower-level environment and migrated to a higher-level environment with this simple script: &lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE&gt;CREATE TABLE Shippers (
  Shipper_Id CHAR(5) NOT NULL 
    CONSTRAINT PK_Shippers PRIMARY KEY,
  Shipper_Name VARCHAR(75) NOT NULL,
  Active_Indicator CHAR(1) NOT NULL 
    CONSTRAINT CK_Shippers_Indicator 
      CHECK (Active_Indicator IN ('Y','N'))
)
ALTER TABLE Orders
  ADD Shipper_Id CHAR(5) NULL,
  ADD CONSTRAINT FK_Orders_Shippers
    FOREIGN KEY (Shipper_Id)
    REFERENCES Shippers(Shipper_Id)
&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;You can manage all the DDL scripts with a variety of different techniques and technologies, ranging from network drives to source control. Once a system is put in place to manage DDL scripts, you can use an automated deployment process to migrate your changes. This process is as simple as clicking the "Deploy Changes" button. &lt;/P&gt;
&lt;P&gt;The perceived difficulty of switching changes from Enterprise Manager to DDL scripts is one of the biggest hurdles for developers. The Books Online don't help change this perception. A quick look at the syntax for the CREATE TABLE statement is enough to discourage most developers from using DDL. &lt;/P&gt;
&lt;P&gt;Enterprise Manager helps you with this transition. Before making database changes, Enterprise Manager generates its own DDL script to run against the database. With the "Save Change Script" button, you can copy the generated DDL script to disk, instead of running it against the database. &lt;/P&gt;
&lt;P&gt;But as with any code generator, your resulting T-SQL script is far from ideal. For example, having Enterprise Manager generate the DDL required for the change described in the example involves six different ill-formatted statements. What do you do now? You can add a bit of refactoring to the generated script, and the result looks almost identical to the example script I showed earlier. After a few more rounds of generating and refactoring, you'll want to transition straight to DDL, and never look back at tiresome database development within Enterprise Manager. &lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=444973" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>Holy Crap: I'm an Official MVP for MS Paint</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/11/13/430478.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2005/11/13/430478.aspx</id><published>2005-11-14T03:47:00Z</published><updated>2005-11-14T03:47:00Z</updated><content type="html">&lt;p&gt;&lt;img style="FLOAT: left" src="http://www.devcampus.com/paintmvp.jpg" /&gt; &lt;p&gt;There are few emails that one will receive in his lifetime that will render him completely speechless. This past weekend, I received one such email. Its subject read &lt;i&gt;Congratulations on your MVP Award!&lt;/i&gt; &lt;p&gt;I struggle with the words to describe how elated I am to be chosen for this award. Sure, I’ve worked my butt off in &lt;font color="#0000ff"&gt;&lt;u&gt;microsoft.public.accessories.paint&lt;/u&gt;&lt;/font&gt;, helping both newbies and vets solve their problems. But I never expected this. For me, it’s always been about my love of the Paint, and sharing my knowledge and expertise of Paint with the world. &lt;p&gt;I don’t want to bore you with me patting my self on the back, so I’ll just use the rest of this space to share my top three tips and tricks. I’ve got plenty more, so if you ever need some help with Paint, don’t hesitate to ask this MVP! &lt;hr /&gt; &lt;p&gt;&lt;b&gt;Why are some of my edges jagged?&lt;/b&gt;&lt;br /&gt;You’ve discovered one of the dark secrets of digital art: pixilation. Because everything in your Paint image is made of small square blocks, the only way to make a diagonal line or a curve is to arrange the pixels in “steps;” these very steps give the image that ugly, jagged appearance. &lt;p&gt;&lt;img src="http://thedailywtf.com/forums/50486/PostAttachment.aspx" /&gt; &lt;p&gt;Fortunately, we can help smooth out the jagged edges with a technique called anti-aliasing. The trick is to make the jagged edge an in-between color of the two bodies of colors. For our red circle and white background, all we need is pink, applied with the spray paint can tool. &lt;p&gt;&lt;img src="http://thedailywtf.com/forums/50485/PostAttachment.aspx" /&gt; &lt;p&gt;And like magic, the jagged edge is no more! &lt;p&gt;&lt;b&gt;How do I do shadows?&lt;/b&gt;&lt;br /&gt;Shadows in Paint are incredibly easy to do:&lt;br /&gt;1) Draw the shape you want to draw, but instead use black&lt;br /&gt;2) Draw the shape you want to draw, using the colors you really want to use, but draw it at an angle slightly away from the black shape &lt;p&gt;&lt;img src="http://thedailywtf.com/forums/50487/PostAttachment.aspx" /&gt; &lt;p&gt;Look ma, a shadow! &lt;p&gt;&lt;b&gt;How can I make realistic looking Hair?&lt;/b&gt;&lt;br /&gt;This is one of the more difficult things to accomplish in Paint. But it’s certainly doable. First, you need to figure out what hair style you want to use. Once you figure that out, it’s just a matter of using the right tool. &lt;p&gt;&lt;i&gt;Curl&lt;/i&gt;&lt;br /&gt;&lt;img src="http://thedailywtf.com/forums/50489/PostAttachment.aspx" /&gt;&lt;br /&gt;Believe it or not, this is a simple matter of using the wonderfully handy spray can tool. Just pick the hair color, and go crazy!!! &lt;p&gt;&lt;i&gt;Baldy&lt;/i&gt;&lt;br /&gt;&lt;img src="http://thedailywtf.com/forums/50488/PostAttachment.aspx" /&gt;&lt;br /&gt;This hairstyle is so ridiculously simple you’ll wonder why more cartoons characters aren’t bald. Simply apply the ellipse tool twice, above each ear, and you’ve got yourself a bald guy! &lt;p&gt;&lt;i&gt;Side Part&lt;/i&gt;&lt;br /&gt;&lt;img src="http://thedailywtf.com/forums/50490/PostAttachment.aspx" /&gt;&lt;br /&gt;When you want to make your character look neat and orderly, only the polygon tool will do. Here’s something funny: I like to part my own hair on the left, but draw it parted on the right. Funny, see, I told you! &lt;p&gt;&lt;i&gt;Bed Head&lt;/i&gt;&lt;br /&gt;&lt;img src="http://thedailywtf.com/forums/50491/PostAttachment.aspx" /&gt;&lt;br /&gt;Oh no, caught red handed without a comb! You can easily achieve this look with the use of the paint brush tool. Don’t go too crazy, it’s pretty easy to slip and go through an eye. &lt;hr /&gt; &lt;p&gt;Be sure to congratulate Jason Mauss as well. He was &lt;A href="http://weblogs.asp.net/jamauss/archive/2005/11/12/430429.aspx"&gt;awarded&lt;/a&gt; this year’s MSN Messenger MVP.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=430478" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>Express Agent for SQL Server Express: Jobs, Jobs, Jobs, and Mail</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/11/10/Express-Agent-for-SQL-Server-Express_3A00_-Jobs_2C00_-Jobs_2C00_-Jobs_2C00_-and-Mail.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2005/11/10/Express-Agent-for-SQL-Server-Express_3A00_-Jobs_2C00_-Jobs_2C00_-Jobs_2C00_-and-Mail.aspx</id><published>2005-11-10T15:52:00Z</published><updated>2005-11-10T15:52:00Z</updated><content type="html">&lt;P&gt;UPDATE:&amp;nbsp;My&amp;nbsp;appologies, but with the advent of relatively inexpensive commercial solutions avaiable, I've decided to suspend this project indefinitely. If I do need a solution for myself, I may take it up again. But until then, I would recommend getting a commercial version (&lt;A href="http://www.valesoftware.com/products-express-agent.php" mce_href="http://www.valesoftware.com/products-express-agent.php"&gt;&lt;STRIKE&gt;http://www.valesoftware.com/products-express-agent.php&lt;/STRIKE&gt;&lt;/A&gt;&lt;STRIKE&gt;&amp;nbsp;is one source&lt;/STRIKE&gt;) or using the Windows Task Manager to run batch files. &lt;/P&gt;
&lt;P&gt;UPDATE 2: I no longer "officially" recommend Vale's agent; though I've used the product for well over a year, they were completely non responsive (via phone or&amp;nbsp;email) to a showstopper bug in their product (stopped working after 24 hours when a job was set to run every 5 minutes). My workaround was to have a Windows Task stop then start VAle's SQL Agent service. Also, as a commenter noted, a free version (&lt;A href="http://www.lazycoding.com/products.aspx"&gt;http://www.lazycoding.com/products.aspx&lt;/A&gt;) is out there - I have not used this, however.&lt;/P&gt;
&lt;P&gt;I was pretty excited to learn about &lt;A href="http://www.microsoft.com/sql/editions/express/default.mspx" mce_href="http://www.microsoft.com/sql/editions/express/default.mspx"&gt;SQL Server: Express Edition&lt;/A&gt;. It is a stripped-down of version of SQL Server that is free to get, free to use, and free to distribute. This is great news if you're in the business of building small- and mid-sized database applications but not in a position to fork over five grand for the full edition. &lt;/P&gt;
&lt;P&gt;A free, stripped-down version of SQL Server is nothing new; afterall, MSDE filled this niche for the previous version of SQL Server. One thing that sets SQL Server Express apart is its branding and accessiblity. Not only does Express "feel" like SQL Server, it's easy to install, use, and administer. MSDE did not have these qualities, which kept it out of the reach of many would-be database developers. &lt;/P&gt;
&lt;P&gt;The limitations imposed by SQL Server Express do not hinder most small- and mid-sized applications. A single processor and a gigabyte of RAM is enough to run most of these applications and it certainly takes a *lot* of data to fill a database up to four gigabytes. One thing that makes Express a deal-killer is the lack of SQL Agent, which runs scheduled jobs and automates backups. That's important in just about all-sizes of applications. &lt;/P&gt;
&lt;P&gt;I'm developing an application that will fill this functionality gap: Express Agent. I was hoping to have this complete before the launch of SQL Server Express, but other priorities prevented this from happening. Express Agent strives to replace and improve upon the SQL Agent that was left out. &lt;/P&gt;
&lt;P&gt;Like the SQL Agent, Express Agent runs as a service. However, Express Agent can also be "plugged in" to a hosted web-application as a HttpHandler. This allows Express Agent agent to run as background thread, running jobs and sending email as needed. &lt;/P&gt;
&lt;P&gt;The jobs are modeled in a similar fashion to the way SQL Server handles them. A job contains a number of tasks (SQL Scripts) that are run depending on whether the previous task was successful (no errors) or successful (errors). Jobs can also be scheduled on a one-time, idle, start-up, and recurring basis. The recurring schedule is handled much the same way SQL Server handles jobs as well. &lt;/P&gt;
&lt;P&gt;Express Agent also adds database-email capability to Express Edition. Though not as complex as SQL Server's implemntation, this should cover just about any emailing you'd need to do from within your stored procedures. The mail feature is used to send success/failure notifications after jobs have been run. &lt;/P&gt;
&lt;P&gt;It's difficult for me to show progress, since much of the work I've done is the "behind the scenes" stuff. I'm still working out the UI, HttpHandler, and some other issues, but so far it works great on it's own, so long as jobs are added via the stored procedures. No less, here's a few screen shots from the Jobs Manager UI ... &lt;/P&gt;
&lt;P&gt;&lt;IMG height=332 alt="" src="http://www.thedailywtf.com/forums/50234/PostAttachment.aspx" width=464 mce_src="http://www.thedailywtf.com/forums/50234/PostAttachment.aspx"&gt; &lt;/P&gt;
&lt;P&gt;&lt;IMG height=415 alt="" src="http://www.thedailywtf.com/forums/50235/PostAttachment.aspx" width=480 mce_src="http://www.thedailywtf.com/forums/50235/PostAttachment.aspx"&gt; &lt;/P&gt;
&lt;P&gt;&lt;IMG height=476 alt="" src="http://www.thedailywtf.com/forums/50236/PostAttachment.aspx" width=490 mce_src="http://www.thedailywtf.com/forums/50236/PostAttachment.aspx"&gt; &lt;/P&gt;
&lt;P&gt;If this app looks like it may be of interest to you, I'd appreciate your feedback. If you're interested in lending a hand with some of the remaining portions, I'd really appreciate that, too. I plan on offering this completed product for free, but most likely not open source.&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=430203" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>Gettin' Down in Detroit: The 2005 Launch Party</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/11/09/gettin-down-in-detroit-the-2005-launch-party.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2005/11/09/gettin-down-in-detroit-the-2005-launch-party.aspx</id><published>2005-11-09T18:46:00Z</published><updated>2005-11-09T18:46:00Z</updated><content type="html">&lt;p&gt;I saw that Jason Mauss wrote about &lt;a href="http://weblogs.asp.net/jamauss/archive/2005/11/09/430034.aspx"&gt;his experience&lt;/a&gt; at the San Fransisco 2005 Launch Party, so I thought I&amp;#39;d share my experience at the Detroit venue. Because it wasn&amp;#39;t the &amp;quot;real&amp;quot; Launch Party, we didn&amp;#39;t have anything fancy like a speech from Steve Balmer, songs performed by AC/DC, or appearances by the guys from Orange County Choppers. But it was still a good time. Please bare with my lack of actual photographs, as I did not have the foresight to bring a camera. &lt;/p&gt;&lt;p&gt;Although the &amp;quot;doors&amp;quot; to the event opened at 7:30AM, the insatiable desire for inexpensive liquor required a stop at the duty-free shop first. I loaded up on Courvoisier, Chambord Royale, and many other fine spirits, saving easily $80 - $100. The US Customs agent even waived the &amp;quot;required&amp;quot; $2.85 duty per liter. He was surprisingly much nicer than the Canadian Customs agent, who demanded a birth certificate, a certificate certifying the birth certificate, the presence of my parents to certify the certified birth certificate, and a certificate certifying my parents are really my parents. Either that or a passport. &lt;/p&gt;&lt;blockquote&gt;&lt;table border="0"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;img height="200" src="http://www.dutyfreetunnel.com/images/products/alcohol/courvoisier.jpg" width="200" /&gt;&lt;/td&gt;&lt;td&gt;&lt;img height="203" src="http://www.sean-o-meter.com/archives/Chambord_lge.jpg" width="164" /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td colspan="2"&gt;Tax-free Booze&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/blockquote&gt;&lt;p&gt;The event was at the Renaissance Center, located in the heart of downtown. Despite being the tallest building in 100-square miles, it was surprisngly difficult to find, especially if you&amp;#39;re unfamiliar Detroitonese, the language of the locals. They call it the &amp;quot;Ren Cen&amp;quot; and I&amp;#39;m surprised that any out-of-towner would find it. &lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;img height="368" src="http://www.urbanoptions.org/RenewableEnergy/images/EnergyEfficiencySuccessStories2.jpg" style="width: 292px; height: 368px" width="292" /&gt;&lt;br /&gt;The Ren Cen&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Arriving there at 8:30, it was a bit disappointing to have to shell out $12.00 for parking. But such a high price does offer us protection from the Linux Crashers, who have a hard enough time getting a car to go downtown, let alone money to pay for parking. You know who I&amp;#39;m talking about, right? Those basement-dwelling fanboys who go to Microsoft conferences armed with Ubuntoo discs and try to dissuade people from attending because the carpet is not open source. They actually used to protest the building being &amp;quot;closed source,&amp;quot; until someone pointed them to the city planning department for architectural diagrams. &lt;/p&gt;&lt;p&gt;Coming in so late offered one other large disadvantage: missing out on many of the cooler freebies given out by the vendors. Here&amp;#39;s a quick classification/rarity guide on the Detroit Launch Event vendor free stuff: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Laser Pen&lt;/strong&gt; (Rare) - Offered by Berbee, this was by far the coolest give-away. Only a few lucky attendies scored this combination pen/laser pointer. Surprisingly, no one abused these devices during the sessions. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Blinking Yo-yo&lt;/strong&gt; (Rare) - I somehow managed to get one of these. It was really cool until I realized it was not a &amp;quot;sleeper&amp;quot; yo-yo, so I gave it away to a colleague. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Blinking HP Necklace&lt;/strong&gt; (Uncommon) - About a third of the attendees had these, leading to two simultaneous yet conflicting feelings: &amp;quot;those are incredibly tacky&amp;quot; and &amp;quot;I wish I had one.&amp;quot; &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Quest Software Weeble&lt;/strong&gt; (Uncommon) - I don&amp;#39;t know what these were called actually, but it was just a yellow cotton ball with paper feet and plastic eyes glued on. Despite having an uncommon rarity, no one really wanted these. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Intel Mints&lt;/strong&gt; (Uncommon) - These were in a neat, small metal container. They are borderline rare, mostly because you had to actually talk to the rep to get one. They were not just lying out like everything else. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Pens&lt;/strong&gt; (Common) - A handful of vendors were giving these away, giving to a good variety of pens. All however were cheap and plastic. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Post-It Pads&lt;/strong&gt; (Common) - Surprisingly, only one vendor was giving these away. Probably a good thing, just one less thing to end up in the landfill after the event. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Fortunately, there was plenty of free continental breakfast food. A good variety of bagels, danishes, and other pastries. The most notable thing from breakfast (and possibly even the day) was the itsy-bitsy jars of honey. They are about half the size of the mini-jars of jelly, and a fourth the size of baby-food containers. I was left speechless at the absolute adorableness of these mini-jars. I think I ended up with 12 of these. &lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;img height="298" src="http://www.cudge.net/images/honey3large.jpg" width="410" /&gt;&lt;br /&gt;Too cute to eat&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;After breakfast, there was the keynote speech and then a technical session. Not quite sure if there&amp;#39;s anything more I can say about those. &lt;/p&gt;&lt;p&gt;Lunch time was absolutely incredible. There were tables and tables *stacked* with boxed lunches. I felt bad that they ordered so many more lunches than attendees, so I took three. My colleague was a bit less generous and had two. We also snapped up a highly-treasured premium: seats at a table. That&amp;#39;s right, we were actually sitting down for lunch. I probably would have considering trading the seat for a blinking pendant and two pens, though. The boxed lunches were pretty good, too. I was only able to eat one, the others went in my already-overstuffed bags of goodies. &lt;/p&gt;&lt;p&gt;After lunch, they had another technical session. &lt;/p&gt;&lt;p&gt;I was &amp;quot;wowed&amp;quot; yet again after the second technical session. The community area was filled with lots of snacks: peanuts, pretzels, white-cheddar popcorn, etc. They even had this awful-tasting energy drink called Rockstar. Tried as I might, I was only able to down half of it. I was really hoping I&amp;#39;d like it, too, because there were a whole lot of them available. I did consider taking home a few, but I just couldn&amp;#39;t imagine ever getting desperate enough to drink one of those again. &lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;img height="384" src="http://www.40ouncebeer.com/pictsenergydrinks/rockstarcans6.jpg" width="640" /&gt;&lt;br /&gt;Gives you the energy to throw it away&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;My colleague and I decided to turn in the evaluation forms early and get the T-Shirt and SQL-Server/VS.NET/BizTalk software before there was a rush. And wow, let me tell you, that was quite a moment. It&amp;#39;s one thing to experience Visual Studio 2005 through your buddy&amp;#39;s work&amp;#39;s MSDN subscription, but you really feel alive having your own, fully-licensed copy of the software. I&amp;#39;m still buzzing from that. &lt;/p&gt;&lt;p&gt;Things went a bit down hill from there. I was a bit disappointed at the next break between sessions three and four. It was very bleak. There were hordes of developers, all hungry and thirsty, scavenging through the remaining pop, water, and Rockstar drinks from the previous breaks. I felt bad for them; some were so desperate that they had to buy drinks the vending machines. Thankfully, I had about a weeks-worth of snacks and beverages saved up from the other breaks, so I was good to go. &lt;/p&gt;&lt;p&gt;All in all, it was a fun event. If you weren&amp;#39;t able to make it, make sure to catch the &amp;quot;Best Of&amp;quot; tour starting next month. There probably won&amp;#39;t be any vendors set up, and I doubt you&amp;#39;ll see much free food, but you&amp;#39;ll get the software. It&amp;#39;s so worth it for that. If anyone is planning on attending the Brooklyn, Ohio &amp;quot;best of&amp;quot; event, I&amp;#39;ll see you there!&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=430091" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>MySQL 5.0: Still A "Toy" RDBMS</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/10/26/428527.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2005/10/26/428527.aspx</id><published>2005-10-26T14:30:00Z</published><updated>2005-10-26T14:30:00Z</updated><content type="html">&lt;p&gt;"Ha," an email from a colleague started, "I think you can finally admit that MySQL is ready to compete with the big boys!" I rolled my eyes and let out a skeptical "uh huh." His email continued, "Check out Version 5. They now have views, stored procedures, and triggers." &lt;p&gt;My colleague has been a MySQL fan since day one. He loves the fact that it's free and open source and could never quite understand why anyone would spend tens of thousands of dollars on something else. But then again, he has never really had an interest in understanding; data management just isn't his "thing." Thankfully, he readily admits this and stays far, far away from anything to do with databases, leaving all of that "stuff" to the experts. No less, he'll still&amp;nbsp;cheers whenever there's a MySQL "victory." it is, after all, free and open source. &lt;p&gt;Data professionals&amp;nbsp;have traditionally relegated MySQL as a "toy" relational database management system (RDBMS). Don't get me wrong, it's perfectly suitable for blogs, message boards, and similar applications. But despite what its proponents claim, it has always been a non-choice for data management in an information-system. This is not a criticism of the "free open source" aspect of the product, but of its creators. &lt;p&gt;The MySQL developers claim to have built a reliable RDBMS yet seem to lack a thorough understanding of RDBMS fundamentals, namely data integrity. Furthermore, they will often surrogate their ignorance with arrogance. Consider, for example, their documentation on &lt;a href="http://dev.mysql.com/doc/refman/5.0/en/constraint-invalid-data.html"&gt;invalid data&lt;/a&gt; [emphasis added]: &lt;blockquote&gt; &lt;p&gt;MySQL allows you to store certain incorrect date values into DATE and DATETIME columns (such as '2000-02-31' or '2000-02-00'). The idea is that &lt;b&gt;it's not the job of the SQL server [sic] to validate dates&lt;/b&gt;.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Wait a minute. It's not the job of the RDBMS to ensure data are valid?!? One of the greatest revelations in information systems is that applications are not good at managing their data: they change too frequently are too-bug prone. It just doesn't work. That's the whole &lt;em&gt;point&lt;/em&gt; of a DBMS; it ensures that data are typed and valid according to business rules (i.e. an employee can't have -65 dependents). &lt;p&gt;But I digress. This is the 5.0 release. They've added views. They've added stored procedures. They've added triggers. Maybe things have changed. &lt;p&gt;I thought I'd check out MySQL 5.0 first hand, so I visited their website and downloaded the product. I have to say, the installation process was painless. It even defaulted to and recommended "strict mode," which apparently disallows the invalid dates as seen above. This is certainly progress! &lt;p&gt;After it installed, I fired up the MySQL prompt and started hackin' around. &lt;p&gt; &lt;div dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p dir="ltr" style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;font size="2"&gt; mysql&amp;gt; CREATE DATABASE ALEXP; Query OK, 1 row affected (0.00 sec) &lt;br /&gt; mysql&amp;gt; USE ALEXP; Database changed &lt;br /&gt; mysql&amp;gt; CREATE TABLE HELLO ( &lt;br /&gt; -&amp;gt; WORLD VARCHAR(15) NOT NULL PRIMARY KEY, &lt;br /&gt; -&amp;gt; CONSTRAINT CK_HELLO CHECK (WORLD = 'Hello World') &lt;br /&gt; -&amp;gt; ); &lt;br /&gt; Query OK, 0 rows affected (0.14 sec)&lt;/font&gt;&lt;/pre&gt; &lt;p&gt;&lt;/p&gt;&lt;/div&gt; &lt;p&gt;Wow! I'm impressed! MySQL 5.0 has check constraints! Maybe I was wrong about these guys ... &lt;p&gt; &lt;div dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p dir="ltr" style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;font size="2"&gt; mysql&amp;gt; INSERT INTO HELLO(WORLD) VALUES('Hi World'); &lt;br /&gt; Query OK, 1 row affected (0.05 sec)&lt;/font&gt;&lt;/pre&gt; &lt;p&gt;&lt;/p&gt;&lt;/div&gt; &lt;p&gt;Err … umm … wait a minute. You did just see me put that check constraint on the HELLO table, right? It's not a very complicated check, maybe, I did it wrong? &lt;p&gt; &lt;div dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p dir="ltr" style="MARGIN-RIGHT: 0px"&gt;&lt;pre&gt;&lt;font size="2"&gt; mysql&amp;gt; SELECT * FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS&lt;br /&gt; -&amp;gt; WHERE TABLE_NAME='HELLO'; &lt;br /&gt; +--------------------+-------------------+-----------------+--------------+------------+-----------------+ &lt;br /&gt; | CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | TABLE_SCHEMA | TABLE_NAME | CONSTRAINT_TYPE | &lt;br /&gt; +--------------------+-------------------+-----------------+--------------+------------+-----------------+ &lt;br /&gt; | NULL | alexp | PRIMARY | alexp | hello | PRIMARY KEY | &lt;br /&gt; +--------------------+-------------------+-----------------+--------------+------------+-----------------+ &lt;br /&gt; 1 row in set (0.01 sec)&lt;/font&gt;&lt;/pre&gt; &lt;p&gt;&lt;/p&gt;&lt;/div&gt; &lt;p&gt;Well how about that. It didn't actually add the constraint. Of course, had I done my research before hand, I would have known that MySQL 5.0 does not support check constraints. Apparently, in the MySQL world, one can buy a negative number of items and can be hired long before being born. &lt;p&gt;Alas, maybe I'm being too harsh; I suppose we could implement data validation logic in triggers. After all, this is often required in other RDBMS when CHECK constraints do not allow cross-table tests (e.g., making sure items cannot be added to a shipped order). So, why not just do it here? &lt;blockquote&gt; &lt;p&gt;The trigger cannot use statements that explicitly or implicitly begin or end a transaction such as START TRANSACTION, COMMIT, or ROLLBACK. &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Oh that's just lovely. Leave it to MySQL to drop the most important use of triggers (complex data validation) and encourage their most obnoxious use (difficult to maintain business logic). &lt;p&gt;As far as other features added in MySQL, I think they are definitely a step in the right direction. Stored Procedures are a key component in creating a clean interface with strong-cohesion to the data layer (see, &lt;a href="http://www.thedailywtf.com/forums/47424/PostAttachment.aspx"&gt;Strong vs Weak cohesion&lt;/a&gt;). Views (virtual tables) are absolutely essential for creating an effective and maintainable data model. &lt;p&gt;However, the new features do very little to budge MySQL's position as a "toy" RDBMS. As I mentioned before, this does not preclude MySQL from being an excellent tool for niche applications. But without mechanisms to ensure data are valid, MySQL will remain a non-choice for information systems. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=428527" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>"When Should I Use SQL-Server CLR User Definied Types (UDT)?"</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/10/20/428014.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2005/10/20/428014.aspx</id><published>2005-10-20T15:26:00Z</published><updated>2005-10-20T15:26:00Z</updated><content type="html">&lt;p&gt;No one has asked me that question just yet, but with the release of SQL Server 2005 just around the corner, I'm sure a handful of people will. Unlike regular &lt;A href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/10/07/426930.aspx"&gt;User Defined Types&lt;/a&gt;, CLR UDTs are a new feature of SQL Server 2005 that allows one to create a .NET class and use it as a column datatype. As long as a &lt;a href="http://msdn2.microsoft.com/en-us/library/ms131082"&gt;few requirements&lt;/a&gt; are followed, one can create any class with any number of properties and methods and use that class as a CLR UDT. &lt;p&gt;Generally, when a new feature is introduced with a product, it can be a bit of a challenge to know when and how to use that feature. Fortunately, with SQL Server's CLR UDTs, knowing when to use them is pretty clear: &lt;p&gt;&lt;b&gt;Never.&lt;/b&gt; &lt;p&gt;Let me repeat that. Never. You should never use SQL Server CLR User Defined Types. I'm pretty sure that this answer will just lead to more questions, so allow me to answer a few follow-up questions I'd anticipate. &lt;p&gt;&lt;u&gt;Why Not?&lt;/u&gt;&lt;br /&gt;CLR UDTs violate a fundamental principle of relational databases: a relationship's underlying domains must contain only atomic values. In other words, the columns on a table can contain only scalar values. No arrays. No sub-tables. And, most certainly, no classes or structures. Remember all the different levels of normalization? This is the first normal form, you know, the "duh" one. &lt;p&gt;This is a big thing. One can't just go and fudge a tried-and-true, mathematically-validated, theoretically-sound concept and "add and change stuff to it 'cause it'll be cool." Think of how much your car would love driving on a road made of stained glass blocks three years after it was built by an engineer who thought it'd look better. &lt;p&gt;Deviating so grossly from the relational model will bring as much joy as a dilapidated glass road. Take Oracle's foray into relational abuse: nested tables. I don't believe that there has ever been a single, successful implementation of that abomination. Sure, it may work out of the box, but after a year or two of use and maintenance, it decays into a tangled mess of redundancy and "synch" procedures -- both completely unnecessary with a normalized relational model. &lt;p&gt;And if that doesn't convince you, just think of having to change that CLR UDT. How easy do you think it would be to add a property to the class representing a few million rows of binary-serialized objects? And, trust me, it won't be nearly as easy as you think. &lt;p&gt;&lt;u&gt;But wouldn't I want to share my .NET code so I don't have to duplicate logic?&lt;/u&gt;&lt;br /&gt;This is always a novel goal, but an impossible one. A good system (remember, good means maintainable by other people) has no choice but to duplicate, triplicate, or even-more-licate business logic. Validation is the best example of this. If "Account Number" is a seven-digit required field, it should be declared as CHAR(7) NOT NULL in the database &lt;i&gt;and&lt;/i&gt; have some client-side code to validate it was entered as&amp;nbsp;seven digits. If the system allows data entry in other places, by other means, that means more duplication of the "Account Number" logic. &lt;p&gt;By trying to share business logic between all of the tiers of the application, you end up with a tangled mess of a system. I have illustrated this in the diagram below. &lt;blockquote&gt; &lt;p&gt;&lt;img src="http://www.thedailywtf.com/forums/47424/PostAttachment.aspx" /&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;As you can see, the diagram on the right is a nicely structure three-tier architecture. The system on the right is the result of someone trying to share business logic between tiers, making a horribly tangled mess. One can expect to end up with the latter system by using CLR UDTs. &lt;p&gt;&lt;u&gt;Never?!? How can there never, ever be an application of CLR UDTs?&lt;/u&gt;&lt;br /&gt;Though I may not live by the cliché "never say never," I do follow the "never say 'never, ever'" rule. The only possible time where one might possibly want to use this feature is for developing non-data applications. But therein lies the crux: why would one develop a non-data application using SQL Server? There are certainly better tools out there for what the non-data application needs to accomplish. If you can come up with an appropriate use of a CLR UDT in an information system, I'll&amp;nbsp;buy you a&amp;nbsp;&lt;a href="http://www.cafepress.com/thedailywtf"&gt;t-shirt or a mug&lt;/a&gt;. &lt;p&gt;&lt;u&gt;But what about the &lt;a href="http://msdn2.microsoft.com/en-us/library/ms160894"&gt;samples&lt;/a&gt; provided? That's a use, right there!&lt;/u&gt;&lt;br /&gt;Allow me to address these ... &lt;p&gt;&lt;i&gt;Supplementary-Aware String Manipulation / UTF8 String User-Defined Data Type&lt;/i&gt;&lt;br /&gt;Both of these samples have to do with UTF-8 character encoding. Without getting into the &lt;a href="http://www.joconner.com/javai18n/articles/UTF8.html"&gt;details&lt;/a&gt;, UTF-8 encodes characters as one, two, three, or four 8-bit bytes, meaning you can not do anything with characters in the string (length, substring, etc) unless you read it byte-by-byte. This works great for preserving "funny characters" while transmitting data but is a poor choice for storage. UCS-2 uses a fixed-size character format of 16-bits per character and is what should be used for storing character data. &lt;p&gt;&lt;i&gt;Calendar-Aware Date/Time UDTs&lt;/i&gt;&lt;br /&gt;Let's think about this. A point in time is a point in time; how it's described varies by culture ("Monday", "Lunes"), time zone (+6:00 GMT, -3:00GMT), calendar (Gregorian, Aztek), and format (2005-08, Aug '05). Describing a point in time properly is essential when interfacing with people or other systems. The keyword in that last sentence was "interface;" such description is best done in the "interface" tier of a system, not in the data tier. Doing this makes as much sense as putting currency conversion and language translation in the database. &lt;p&gt;&lt;i&gt;Multi-dimensional Points and Latitude/Longitude&lt;/i&gt;&lt;br /&gt;A geospatial location is described with Latitude &lt;i&gt;and&lt;/i&gt; Longitude. Not Lati-longi-tude. These are two separate attributes and putting them in the same column violates First Normal Form. The same goes for points and other "array-like" structures. &lt;p&gt;&lt;i&gt;Imaginary Numbers&lt;/i&gt;&lt;br /&gt;Seriously? Correct me if I'm wrong, but the only actual use for imaginary numbers is in solving of differential equations. If you're not sure why this invalidates the example, say these two phrases aloud: "solving differential equations" and "relational database." Didn't that feel just like saying "drilling a hole" and "hacksaw?" &lt;p&gt;&lt;i&gt;But what about if I want to put down "SQL CLR UDTs" on my resume?&lt;/i&gt;&lt;br /&gt;What's stopping you now? By reading this article, you know everything you will ever need to about CLR UDTs. With this on your resume, you will be able to use your expert knowledge on the topic to never use CLR UDT. &lt;p&gt;I hope that clears things up about CLR UDT. Hopefully now you look forward to not using them and strongly opposing anyone who suggests it. Oh, and I really am serious about sending The Daily WTF swag to whoever can come up with a use for these things. So think about a use; you may just get a free t-shirt. &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=428014" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>"What's the Point of [SQL Server] User-Defined Types?"</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/10/07/426930.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2005/10/07/426930.aspx</id><published>2005-10-07T19:57:00Z</published><updated>2005-10-07T19:57:00Z</updated><content type="html">&lt;p&gt;I'm asked that question every now and then from other developers who've played around in SQL Server Enterprise Manager and noticed the "User Defined Data Types" tab under their database. UDT seem a bit strange and pointless because they do not allow one to define (as one might expect) a data structure with more than one related data element. A UDT consists simply of a name and a base type (INT, VARCHAR(6), etc). &lt;/p&gt; &lt;p&gt;So why then would one use a UDT? It all has to do with a fundamental concept of data known as "domains." I'm not referring to a dot-com type domain, but a domain in the mathematical sense of restricting the value of a particular value. For example, the domain of x for "f(x) = 1/x" is "!=0". &lt;/p&gt; &lt;p&gt;We don't get domains in C++ / C# / VB / etc; all we have are types (integer, date, string, etc). But we're used to not having this; everyone knows you need to check if "x != 0" before trying to divide by x.&amp;nbsp; Imagine how much less coding (and related bugs) we'd have if trying to assign "0" to "x" threw an exception from the start, instead of in the middle. That's exactly what you can (and should) be doing with your databases.&amp;nbsp; &lt;/p&gt; &lt;p&gt;When I start on this same explanation to others, it turns out a lot don't quite understand what check constraints are. Basically, check constraints are used to define the domain of a column to ensure that a row can only contain valid data according to the business rules. For example, your Products table should have a check constraint on the Price column, requiring it to be greater than zero (this would cause an exception to be raised if you tried to update the price to zero). Here's another example of some code:&lt;/p&gt; &lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p&gt;&lt;font face="Courier New" size="2"&gt;CREATE TABLE [Transactions] (&lt;br /&gt;&amp;nbsp; [Transaction_Id] INT IDENTITY(1,1) PRIMARY KEY NOT NULL,&lt;br /&gt;&amp;nbsp; [Transaction_Type] VARCHAR(5) NOT NULL &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CHECK ([Transaction_Type] IN ('Debit','Credit','Escrow')),&lt;br /&gt;&amp;nbsp; [Transaction_Amount] DECIMAL(4,2) NOT NULL&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CHECK ([Transaction_Amount] &amp;lt;&amp;gt; 0),&lt;br /&gt;&amp;nbsp; [Reference_Code] CHAR(5)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CHECK ([Reference_Code] LIKE '[A-Z][ A-Z][A-Z][A-Z][A-Z]'))&lt;br /&gt;)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Get the idea? Each column has a constraint to ensure only valid data is allowed in the table. This way, there is no way that [Reference_Code] could contain anything but a five character string of upper case letters. No need to write code to test it, no need to ever validate it (except maybe on the data entry form so that the user doesn't see an ugly exception message), and no need to assume that it will be anything but that.&lt;/p&gt; &lt;p&gt;Now, immagine that you wanted to have the same [Reference_Code] attribute throughout your database. You'd have to define that check constraint time and time again. If the rules ever changed, you'd need to change it in every place. That's where UDTs come into place. UDTs are the SQL Server imlementation of domains.&lt;/p&gt; &lt;p&gt;If you have a common data element that will be used throughout the system, then it should be a UDT. Account number, Username, Order Number, etc; all should be UDT. When you define these types, you can easily apply rules (which are essentially just check constraints that apply whenever the type is used) to the type, and have it automatically enforced throughout the system.&lt;/p&gt; &lt;p&gt;It's really easy to do. I'll use the SQL 2005 syntax, but you can do the same things in 2000 using sp_addtype and sp_addrule:&lt;/p&gt; &lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p&gt;&lt;font face="Courier New" size="2"&gt;CREATE TYPE USERNAME FROM VARCHAR(20)&lt;br /&gt;GO&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" size="2"&gt;CREATE RULE USERNAME_Domain&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AS @Username = LTRIM(RTRIM(@Username))&lt;br /&gt;&amp;nbsp;&amp;nbsp; AND LOWER(@Username) NOT IN ('admin','administrator','guest')&lt;br /&gt;GO&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="Courier New" size="2"&gt;EXEC sp_bindrule 'USERNAME_Domain', 'USERNAME'&lt;br /&gt;GO&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;And that's it. Now you can use the type throughout the database just as you normally would, and you'll never need to check or verify to make sure that someone slipped in an invalid value ...&lt;/p&gt; &lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p&gt;&lt;font face="Courier New" size="2"&gt;CREATE TABLE [User_Logons] (&lt;br /&gt;&amp;nbsp; [Username] USERNAME NOT NULL,&lt;br /&gt;&amp;nbsp; [Logon_Date] DATETIME NOT NULL,&lt;br /&gt;&amp;nbsp; [Success_Indicator] CHAR(1) NOT NULL&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CHECK ([Success_Indicator] IN ('Y','N')),&lt;br /&gt;&amp;nbsp; PRIMARY KEY ([Username],[Logon_Date])&lt;br /&gt;)&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=426930" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>Pounding A Nail: Old Shoe or Glass Bottle?</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/05/25/408925.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2005/05/25/408925.aspx</id><published>2005-05-25T21:03:00Z</published><updated>2005-05-25T21:03:00Z</updated><content type="html">&lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p dir="ltr" style="MARGIN-RIGHT: 0px"&gt;"A client has asked me to build and install a custom shelving system. I'm at the point where I need to nail it, but I'm not sure what to use to pound the nails in. Should I use an old shoe or a glass bottle?&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;How would you answer the question?&lt;/p&gt; &lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p&gt;a) It depends. If you are looking to pound a small (20lb) nail in something like drywall, you'll find it much easier to use the bottle, especially if the shoe is dirty. However, if you are trying to drive a heavy nail into some wood, go with the shoe: the bottle with shatter in your hand.&lt;/p&gt; &lt;p&gt;b) There is something fundamentally wrong with the way you are building; you need to use real tools. Yes, it may involve a trip to the toolbox (or even to the hardware store), but doing it the right way is going to save a lot of time, money, and aggravation through the lifecycle of your product. You need to stop building things for money until you understand the basics of construction.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I would hope that just about any sane person would choose something close to (b). Sure, it may seem a bit harsh, but think about it from the customer prospective: how would you feel if your carpenter asked such a question?&lt;/p&gt; &lt;p&gt;I find it a bit disturbing, however, that this attitude is not prevalent in software development. In fact, from what I can tell, it seems to be discouraged.&amp;nbsp; &lt;/p&gt; &lt;p&gt;I've been participating in Usenet/forums/lists for a decade now, asking programming questions and helping out others who have questions of their own. If some one asks a question that demonstrates the complete absurdity of their design, I'll generally reply with my (quite candid) opinion on their design. To give you an idea what I'm talking about, here's something I remember seeing a while back (from memory).&lt;/p&gt; &lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p&gt;&lt;strong&gt;Subject: Aggregates Help&lt;br /&gt;&lt;/strong&gt;I have a table that stores test results for milling machines. Each test consists of N-runs conducted by a measurer going M-trials each. I have this information represented in a varchar column in the following format: "44:1,5,4;23:2,4,9;14:1,4,3".&amp;nbsp; When the column is read into the class, it is converted into a jagged array: ( (44,(1,5,4)), (23,(2,4,9)), (14,(1,4,3)) ) of runs (3 of them) and measurers(Ids of 44,23,14) and trials (1,5,4 and 2,4,9 and 1,4,3). &lt;/p&gt; &lt;p&gt;One of the reports I have is a deficiency report, which predicts which machines may fail. To run this, I have a report class that loads up the appropriate tests and processes the information. However, this is taking longer and longer to run. I'm thinking that running it in a stored procedure will be quicker.&lt;/p&gt; &lt;p&gt;I can figure out how to get an "array" in SQL with a table variable, but how do I make a jagged array? Any ideas?&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Some of the folks on in the list took it as a fun challenge, going back and forth with how deficiencies are calculated, and providing some incredibly brilliant ways of solving this problem. &lt;/p&gt; &lt;p&gt;Not I, though. My response was something to the effect of …&lt;/p&gt; &lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p&gt;This is quite possibly the worst way you could store this data in a database. No, seriously. They had better ways of doing this over thirty years ago. You have created a horrible problem that is only starting to rear its ugly head. It will only continue to get horribly worse, costing your company more and more money to maintain.&lt;/p&gt; &lt;p&gt;You need to drop everything your doing right now and take a trip to your bookstore to get a database book. I recommend INTRODUCTION TO DATABASE SYSTEMS by DATE, but at this point anything should do. For the sake of everyone who will maintain your future code, don't touch a database until you understand how big of a mess you've created.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;How do you think you would have responded to that post? Would you have taken the challenge to think about how to solve the problem or just take the opportunity to school the poster? &lt;/p&gt; &lt;p&gt;If you say the former, then you probably think I'm a grumpy curmudgeon (more likely, less family-friendly words though). My appeal to you is to think back to the carpenter. How is this any different? How fair is this to person paying him to develop software, or, more importantly, the poor sap that will have to come in and not only understand the mess, but maintain it. That poor sap could be you one day!&lt;/p&gt; &lt;p&gt;If you say you'd go with the latter, harsher reply, then I ask, why aren't you out there participating in the newsgroups/forums/lists? We need more people like you out there: there are too many of the people who tell people exactly how to apply the duct tape without giving the poster a firm scolding.&amp;nbsp; &lt;/p&gt; &lt;p&gt;But I think the problem is worse than not having enough grumpy curmudgeons: in my experience, forum moderators actively delete critical posts that don't solve the problem, keeping only the hacks that solve the hacks. When new users come to read the posts in the future, they may actually think, "hey, I could use this to solve my problem."&lt;/p&gt; &lt;p&gt;Am I on the wrong side in this? Should we actively be encouraging new programmers to use their horrific techniques? Or am I just looking at this the totally wrong way?&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=408925" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>DNA, XP, SOA, ESB, ETC Are Dead; FAD is the Future</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/05/05/405747.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2005/05/05/405747.aspx</id><published>2005-05-05T14:35:00Z</published><updated>2005-05-05T14:35:00Z</updated><content type="html">&lt;p&gt;I've come across a truly revolutionary software development methodology called &lt;strong&gt;Front Ahead Design (FAD)&lt;/strong&gt;. Essentially, it's a fundamental paradigm shift over "traditional" and "neo" ways of building software. Not only does it surpass every software development methodology out there, it solves every problem there is to building software (and then some). But don't take my word for it, here are the Top Five fundamentals ...&lt;/p&gt; &lt;p&gt;&lt;strong&gt;I. Front Ahead Design&lt;br /&gt;&lt;/strong&gt;The essence of FAD is conveyed directly in its name: design your front-end/user-interface first, ahead of everything else. The customer could care less what's behind the scenes, so long as it looks good and does what its supposed to. Deliver a working front-end first and then &lt;em&gt;Do What It Takes&lt;/em&gt; to fill in the functionality gaps.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;II. Do What It Takes&lt;br /&gt;&lt;/strong&gt;Other methodologies are great at delivering excuses. How many times have you heard (or have been told) "we can't do that here because it could throw off the whole design?"&amp;nbsp; In FAD, you just do it (that would have been the bullet point, but Nike has it trademarked). To get it done, you &lt;em&gt;Do What It Takes&lt;/em&gt;. Your customer will love you.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;III. Code Light, Not "Right"&lt;br /&gt;&lt;/strong&gt;A traditional methodology calls a complex framework with layer after layer of objects. In those ways, adding a simple value to a form can be a monumental task, requiring it to be added to every single layer. Does that sound right? Proponents of the other methodologies will tell you it is, but what about your customer? With FAD, you just &lt;em&gt;Do What It Takes&lt;/em&gt; to add the functionality to your interface. No more.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;IV. "Throw Away" Diagrams&lt;/strong&gt;&lt;br /&gt;Think of all the Visio diagrams you've drawn over the years. Sequence diagrams, context diagrams, flow charts, and so on. Was that really productive? Did your customer ever see any of those? Were those diagrams even relevant after the system was finally developed? Didn't think so.&lt;/p&gt; &lt;p&gt;In FAD, all diagrams are made on a disposable medium. Whiteboards, napkins, even your forearms work. And there is no formal modeling language to battle with: just &lt;em&gt;Do What It Takes&lt;/em&gt; to draw and explain your design to other developers.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;V. Life Is Short (a.k.a. Patchwork)&lt;/strong&gt;&lt;br /&gt;The average software system has a life expectancy of seven years. No matter how "properly" the system is designed from the start, within the first year of its life, maintenance programmers unfamiliar with the complex architecture (and having no help from out-of-date documentation) will turn the system into a complete mess with bug fixes and change requests. &lt;/p&gt; &lt;p&gt;In FAD, this isn't even a concern. We know the short life span of a system and develop every feature (from the interface) as a patch. Maintenance programmers can come in and &lt;em&gt;Do What It Takes&lt;/em&gt; to add their patches. In FAD, we don't even try to stop the aging process. We encourage it.&lt;/p&gt; &lt;hr /&gt; &lt;p&gt;There's quite a few more fundamentals, but that's all I've got time for today. I'm incredibly busy trying to finish a book on the topic (halfway through it!!). Hopefully, it'll make it as the first FAD book. I hear some other big names are in the first FAD book race, too.&lt;/p&gt; &lt;p&gt;I also came across some community sites:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;FADblogs.com&lt;/strong&gt; - .TEXT blogging site, open for anyone to blog about FAD&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;FADisIn.com&lt;/strong&gt; - general informational site with articles, help, discussion, and tools&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;strong&gt;ItsAFAD.com&lt;/strong&gt; - gallery of successful projects (from small business to enterprise) that have successfully used FAD&lt;/p&gt; &lt;p&gt;They're all under construction, but I'm helping a lot with the FADblogs.com, so let me know if you'd like to be one of the FAD bloggers. &lt;/p&gt; &lt;p&gt;Next article: a comparison of the FAD design tools, including H/YPe and nFAD.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=405747" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>Comicality Inflation</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/05/03/405535.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2005/05/03/405535.aspx</id><published>2005-05-03T23:27:00Z</published><updated>2005-05-03T23:27:00Z</updated><content type="html">&lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;My post the other day (&lt;A href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/04/29/405078.aspx"&gt;Computer Programmer Inflation&lt;/a&gt;) got me thinking of another type of inflation that I've observed over the years: Comicality Inflation. Like other types of inflation, it's not as if things have gotten funnier, it’s just the terms we use to describe them.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Back in the day (and I'm talking &lt;em&gt;the &lt;/em&gt;day; as in, before electricity and all that), if a friend sent us a letter that we found entertaining, we would simply compliment it when we penned our reply: &lt;em&gt;Archibald, I must concede your quip about poor &lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:place w:st="on"&gt;Rutherford&lt;/st1:place&gt;’s embarrassing gaffe was quite witty and remarkably entertaining&lt;/em&gt;. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Thankfully, those days are long gone, replaced by the ever-so-simple (though dreadfully less elegant) onomatopoeic interjection "haha" (and it's cousins, "hehe", "hoho", etc). One of the great features of "haha" is that it is an expandojective: the intensity of its meaning is proportional to its length.&lt;/p&gt; &lt;ul&gt; &lt;li&gt; &lt;div class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;ha&lt;/strong&gt; - mildly amusing, possibly causing a very soft chuckle&lt;/div&gt;&lt;/li&gt; &lt;li&gt; &lt;div class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;haha&lt;/strong&gt; - funny, causing at a minimum a chuckle, but most likely a snort &lt;/div&gt;&lt;/li&gt; &lt;li&gt; &lt;div class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;...&lt;/div&gt;&lt;/li&gt; &lt;li&gt; &lt;div class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;a-hahahahahaha&lt;/strong&gt; - busting out in full-blown laughter requiring a pre-laughter breath (hence, the "a-")&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;By the way, if anyone knows the proper term for such a word, please advise. It's not as if "haha" is the only expandojective. There’s "aaagh", "aarrg", "reeeaaaaly", "zzz", and so on. These magical fantastic words truly need their own category. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;Anyway, it would seem that "haha" would be the perfect way of indicating the comicality of something you read.&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;After all, it expands as things get funnier and it even has lots of room for personalization ("ho-ha-ha","teehehe",etc). Alas, it is not; some one had to come along and create the acronym "LOL". &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;On its own, I don't think that LOL (Laugh Out Loud) is a terrible thing. After all, there's no official "ha" scale and it's quite hard to tell if "hahaha" means "I laughed out loud" or "I had a series of snickers."&lt;span style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/span&gt;It's the abuse and extension of LOL that really offends me.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;First, let’s consider the abuse. How many times have you seen people reply with "LOL" and you know, for a fact, that what you wrote wasn’t possibly that funny? And if you think exaggerative flattery is excusable, consider the typical teenage instant message conversation:&lt;/p&gt; &lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;princessGurl1924&lt;/font&gt;&lt;/strong&gt;: heya becca, hows it goin, lol&lt;br /&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;angelKitty77&lt;/font&gt;&lt;/strong&gt;: omg, lol it's goin pretty good lol. u??&lt;br /&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;princessGurl1924&lt;/strong&gt;&lt;/font&gt;: lol good good!~!!&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;If I knew anyone who laughed that much in real life, I would suggest that they have some serious mental disorder. Or that they are high on some cocktail of illicit narcotics. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;I know that I'm not alone in this observation. I've noticed that quite a few people have started to differentiate between LOL-funny and Laugh-Out-Loud-funny by replacing the latter with the absurdly redundant "LLOL" (Literally Laugh Out Loud). I swear, if we ever begin to figuratively LLOL, I will have no choice but to become a Luddite. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;I’d have to say that the extensions of LOL offend me the most. Let's consider the most prevalent:&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;blockquote dir="ltr" style="MARGIN-RIGHT: 0px"&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;ROFL (Rolling On the Floor Laughing)&lt;/strong&gt; - I've seen a lot of funny stuff in my day, and, let me tell you, I'm a laugher. But I have never seen anything that was so funny that I dropped to the floor in a fit of uncontrollable laughter. And if you ever have, it certainly wasn’t while reading something on the internet.&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;LMAO (Laughing My Ass Off)&lt;/strong&gt; - Some might say that this is not fair game because the colloquialism "laughing my ass off" had existed prior to the Internet. No less, I still consider the acronymization to be a direct result of LOL. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;ROFLMAO (Rolling On the Floor Laughing My Ass Off)&lt;/strong&gt; - A total unnecessary expansion of an expansion. Since when was an uncontrollable fit of laughter causing one to drop to the floor *not* the most extreme reaction to humor possible? And what, precisely, is the difference between laughing while rolling on the floor and laughing your ass off while rolling on the floor? How possibly could one distinguish between the two?&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;ROFLOL (Rolling On the Floor Laughing Out Loud) &lt;/strong&gt;- I'm guessing this falls somewhere between ROFL and ROLFMAO. But it’s just another pointless expansion. We already know that there is no difference between ROFL and ROFLMAO, but think about what ROFLOL implies. Someone who is rolling on the floor in laughter isn't doing so audibly, just quietly rolling around on the floor, laughing to themselves. &lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;strong&gt;LOLOLOL (???) &lt;/strong&gt;- I don't even know what this is. Laugh Out Loud Out Loud Out Loud? Laugh Out Laugh Out Loud Out Loud? How exactly did an acronym become an expandojective? It's "words" like this that make me long the good-ole-days before "haha" was created.&lt;/p&gt;&lt;/blockquote&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/p&gt; &lt;p class="MsoNormal" style="MARGIN: 0in 0in 0pt"&gt;I know we've all used these new-aged acronyms (except LOLOLOL, I hope). And I know we probably won't stop. But, at least consider this rant next time you reply with ROFLMAO; it just may just enhance your fits of laughter while you're rolling around on the floor.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=405535" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>Computer Programmer Inflation</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/04/29/405078.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2005/04/29/405078.aspx</id><published>2005-04-29T18:17:00Z</published><updated>2005-04-29T18:17:00Z</updated><content type="html">&lt;p&gt;I was thinking the other day about the changes over the years in what we call people who write computer programs. Back in the day, we called these folks &lt;i&gt;computer programmers&lt;/i&gt;. A rather fitting title, one would suppose, for a person who programs computers. But one would suppose wrong. &lt;p&gt;Shortly after &lt;i&gt;computer programmer&lt;/i&gt; became the "official" title, someone, somewhere, somehow decided that it wasn't enough. After all, computer programmers do more then program, they &lt;i&gt;analyze&lt;/i&gt; a problem and &lt;i&gt;then&lt;/i&gt; write a program. They should, therefore, be titled &lt;i&gt;programmer/analysts&lt;/i&gt;. One would suppose that such analysis is an implicit part of the job, much like how writers need to &lt;i&gt;think&lt;/i&gt; about something before they actually write it. But one would suppose wrong. &lt;p&gt;Unlike the &lt;i&gt;computer programmer&lt;/i&gt; title, &lt;i&gt;programmer/analyst&lt;/i&gt; seemed to stick around for quite a while. In fact, it was only fairly recently that we all became &lt;i&gt;software developers&lt;/i&gt; (or, &lt;i&gt;developers&lt;/i&gt; for short). The change this time around was all about image; you gotta admit how much sexier &lt;i&gt;developer&lt;/i&gt; sounds over &lt;i&gt;programmer&lt;/i&gt;. Certainly&amp;nbsp;one would suppose it's pretty hard to "sex up" an industry whose Steves out number its women (see the &lt;A href="http://weblogs.asp.net/alex_papadimoulis"&gt;Steve Rule&lt;/a&gt;). But one would suppose wrong. &lt;p&gt;Believe it or not, &lt;i&gt;developer&lt;/i&gt; is on its way out and we're in the middle of yet another title change. If you think about it, the problem with &lt;i&gt;developer&lt;/i&gt; is that, if any one asked what a "developer" is, you'd have to expand it to &lt;i&gt;software developer&lt;/i&gt;. Software == Computers == Programming == Nerdy. We can't have that! &lt;p&gt;This is where the title &lt;i&gt;solution developer&lt;/i&gt; comes in. We're the guys who you call when you have a problem. Doesn't matter what the problem is, we will &lt;i&gt;develop&lt;/i&gt; a &lt;i&gt;solution&lt;/i&gt;. Heck, we can even develop solutions (by programming a computer) for problems that don't exist. We're that good. &lt;p&gt;But where do we go from here? First, we need to reach the maximum level of ambiguity possible. I'm not an expert at coming up with job titles, but I suspect &lt;i&gt;solution specialist&lt;/i&gt; is a step in the right direction. Of course, once we've gone all the way to one side, the only place we can really go is to other extreme: a way more overblown/descriptive/nerdy sounding name than needed. When &lt;i&gt;solution specialist&lt;/i&gt; (or whatever) expires, I really hope the replacement will end with -ologist. I would really like to be an -ologist of some sort. You know you'd like it, too.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=405078" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry><entry><title>The "Steve Rule" Proved True Again</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/alex_papadimoulis/archive/2005/04/22/403889.aspx" /><id>http://weblogs.asp.net/alex_papadimoulis/archive/2005/04/22/403889.aspx</id><published>2005-04-22T18:06:00Z</published><updated>2005-04-22T18:06:00Z</updated><content type="html">&lt;p&gt;Yesterday on &lt;a href="http://www.thedailywtf.com/"&gt;The Daily WTF&lt;/a&gt;, I &lt;a href="http://www.thedailywtf.com/forums/33107/ShowPost.aspx"&gt;mentioned&lt;/a&gt; something I called the &lt;strong&gt;Steve Rule&lt;/strong&gt;: &lt;em&gt;in a random sample of programmers, there will be more named Steve then there will be females&lt;/em&gt;. &lt;/p&gt; &lt;p&gt;What's ironic is that I didn't mean that as a joke. In my personal experience, every group of programmers with fifteen or more always had more guys with the same name than women.&amp;nbsp;No, it's not always&amp;nbsp;Steve, but&amp;nbsp;that&amp;nbsp;was&amp;nbsp;the name&amp;nbsp;when I first made the observation (three Steves, one woman).&lt;/p&gt; &lt;p&gt;I thought I'd test the "Steve Rule" once again using the &lt;a href=""&gt;Weblogs.Asp.Net&lt;/a&gt; bloggers. To do this, I looked at the &lt;A href="http://weblogs.asp.net/Opml.aspx"&gt;OPML&lt;/a&gt;&amp;nbsp;[XML], and used the title of 258 blogs. There were 139 I skipped because either I couldn't tell the gender (no offense, &lt;A href="http://weblogs.asp.net/SBehera/"&gt;Suresh Behera&lt;/a&gt;, et al.) or the title didn't have a name (e.g. &lt;A href="http://weblogs.asp.net/randerson"&gt;Models and Hacks&lt;/a&gt;).&lt;/p&gt; &lt;p&gt;Of the blogs, I found six female bloggers:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;A href="http://weblogs.asp.net/g_zierdt/"&gt;Gwen Zierdt&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;A href="http://weblogs.asp.net/jlerman/"&gt;Julia Lerman&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;A href="http://weblogs.asp.net/kristianrickard/"&gt;Kristian Rickard&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;A href="http://weblogs.asp.net/datagridgirl/"&gt;Datagrid Girl (Marcie)&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;A href="http://weblogs.asp.net/rreese"&gt;Racheal Reese&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;A href="http://weblogs.asp.net/swarren"&gt;Susan Warren&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;For the guys, I was only able to find four different Steves. But,&amp;nbsp;there were &lt;strong&gt;seven&lt;/strong&gt; different names (with slight variations) that outnumbered the girls&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Andrew (7)&lt;/li&gt; &lt;li&gt;Chris (7)&lt;/li&gt; &lt;li&gt;Dave (7)&lt;/li&gt; &lt;li&gt;Jason (7)&lt;/li&gt; &lt;li&gt;John (7)&lt;/li&gt; &lt;li&gt;Robert (7)&lt;/li&gt; &lt;li&gt;Scott (9).&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;So, for us Weblogs.Asp.Net bloggers, it looks like we are goverened by the "Scott Rule."&amp;nbsp;How about that?&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=403889" width="1" height="1"&gt;</content><author><name>Alex Papadimoulis</name><uri>http://weblogs.asp.net/members/Alex-Papadimoulis.aspx</uri></author></entry></feed>