<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-25574505</id><updated>2012-01-25T07:10:16.968-08:00</updated><category term='silverlight bar chart graph wizard'/><category term='WPF Wizard'/><category term='showPopup'/><category term='User Control'/><category term='Repeater'/><category term='&quot;Visual Studio Tools for Office&quot;'/><category term='wpf xaml mvvc'/><category term='ajax'/><category term='PopupControlExtender'/><title type='text'>Confessions of a Code Monkey</title><subtitle type='html'>In the beginning was the code.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>55</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-25574505.post-5647961690418687382</id><published>2012-01-25T06:50:00.000-08:00</published><updated>2012-01-25T07:10:16.980-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wpf xaml mvvc'/><title type='text'>WPF Mapping / Association Control</title><content type='html'>When importing data from one store to another, many applications allow visual "mapping" of source fields to destination fields where lines are drawn to connect the two.&lt;br /&gt;I tried in vain to find some kind of WPF/Xaml control that would do that, so I created one:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/-u8VkJZzkXOk/TyAZE_L1wGI/AAAAAAAAAB4/NlRvhsD8-1c/s1600/Mapping.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 400px; height: 400px;" src="http://3.bp.blogspot.com/-u8VkJZzkXOk/TyAZE_L1wGI/AAAAAAAAAB4/NlRvhsD8-1c/s400/Mapping.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5701584701722312802" /&gt;&lt;/a&gt;The control (regular user control) would be useful for any kind of association between two sets of data.  The user creates associations by dragging from source to destination.  It has a mode for one-to-one (a source item can only be mapped to one destination item) and one-to-many.  Moving the scroll bars of the lists redraws the association lines appropriately.  It's done MVVC style with models for the control as a whole and for the lists that hold the fields.&lt;br /&gt;&lt;br /&gt;I was amazed at how easy this was to do with Xaml.  I'm only a recent Xaml user, and when I use it I'm so pleased and dismayed at the same time.  Pleased because it's such a rich, well thought out technology.  Dismayed because MS has been forced to essentially abandon it in favor of the tyranny of HTML.  I wonder how much more difficult this same thing would be to do using HTML5.&lt;br /&gt;&lt;br /&gt;Source code &lt;a href="http://www.puretolerance.com/Mapping.zip"&gt;here&lt;/a&gt;.  Hope someone else can make use of it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-5647961690418687382?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/5647961690418687382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=5647961690418687382' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/5647961690418687382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/5647961690418687382'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2012/01/wpf-mapping-association-control.html' title='WPF Mapping / Association Control'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-u8VkJZzkXOk/TyAZE_L1wGI/AAAAAAAAAB4/NlRvhsD8-1c/s72-c/Mapping.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-2994170137556012879</id><published>2011-11-28T11:23:00.000-08:00</published><updated>2011-11-28T11:27:38.218-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF Wizard'/><title type='text'>WPF Wizard Control</title><content type='html'>There doesn't seem to really be anything in the way of a wizard control for WPF.  Developer Express has one for Winforms, but when it came to WPF, their recent advice is to look at &lt;a href="http://www.codeproject.com/KB/WPF/InternationalizedWizard.aspx"&gt;this project&lt;/a&gt; until they create one.&lt;br /&gt;&lt;br /&gt;I took that project (not a control; merely an example of a wizard implementation) and made it into a reusable user control.  It's &lt;a href="http://wpfwizard.codeplex.com/"&gt;available on codeplex&lt;/a&gt;.  Just as with my last post, I hope someone can make use of it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-2994170137556012879?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/2994170137556012879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=2994170137556012879' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/2994170137556012879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/2994170137556012879'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2011/11/wpf-wizard-control.html' title='WPF Wizard Control'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-1744102605646221724</id><published>2011-11-03T10:29:00.000-07:00</published><updated>2011-11-03T10:33:08.226-07:00</updated><title type='text'>Programmatically Creating SSIS Packages</title><content type='html'>The last post was specific; this one very general.&lt;br /&gt;&lt;br /&gt;I created a &lt;a href="http://ssis.codeplex.com/"&gt;project on codeplex&lt;/a&gt; that is a functional import system using the SSIS runtime.  If you are heading down the road of using the SSIS API, the project may be very helpful in helping to figure out just how.&lt;br /&gt;&lt;br /&gt;I sure hope it saves somebody a bunch of time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-1744102605646221724?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/1744102605646221724/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=1744102605646221724' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/1744102605646221724'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/1744102605646221724'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2011/11/programmatically-creating-ssis-packages.html' title='Programmatically Creating SSIS Packages'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-7599702878290905311</id><published>2011-10-13T06:33:00.000-07:00</published><updated>2011-11-03T10:29:24.317-07:00</updated><title type='text'>Programmatically Creating an SSIS Package with a Flat File Connection Source</title><content type='html'>I'm using the SSIS API to programmatically create (and execute) a package.  The requirement for the first package is to get .csv data from a flat file into a SQL Server table.  So I start checking into the MS docs, looks easy enough.  Not so fast.  When it comes to a flat file connection, there seems to be holes in the API.  I ended up having to use one class that (according to the docs) I shouldn't be referencing in my code, but there doesn't seem to be any other way to make the flat file connection work because it simply won't load column metadata from the file.  Won't do it.&lt;br /&gt;&lt;br /&gt;I found exactly one other sample of doing this (which was helpful), but that sample's method of reading the flat file's columns seemed less than optimal.&lt;br /&gt;&lt;br /&gt;Following is a working sample.  Sorry for formatting; I simply don't know any way to prevent the software from stripping out my formatting...&lt;br /&gt;&lt;br /&gt;The data file looks like the following.  Column names in first row.&lt;br /&gt;"this","that"&lt;br /&gt;"data","more data"&lt;br /&gt;"other data","you get the point"&lt;br /&gt;&lt;br /&gt;The SQL table is like yay:&lt;br /&gt;CREATE TABLE [dbo].[bubba](&lt;br /&gt; [this] [varchar](max) NULL,&lt;br /&gt; [that] [varchar](max) NULL&lt;br /&gt;) ON [PRIMARY]&lt;br /&gt;&lt;br /&gt;The method below uses this helper class which makes use of the TextFieldParser class which seems very useful.  I have no idea why it's in the Microsoft.VisualBasic.FileIO namespace, but whatever works:&lt;br /&gt;&lt;br /&gt;&lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt;&lt;br /&gt;&lt;div style="background-color: #d9d9df; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap"&gt;&lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;FlatFileColumnReader&lt;/span&gt;&lt;br&gt;&lt;br /&gt;{&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:#0000ff"&gt;string&lt;/span&gt;&amp;gt; Columns( &lt;span style="color:#0000ff"&gt;string&lt;/span&gt; path, &lt;span style="color:#0000ff"&gt;char&lt;/span&gt; delimiter, &lt;span style="color:#2b91af"&gt;FieldType&lt;/span&gt; ft )&lt;br&gt;&lt;br /&gt;    {&lt;br&gt;&lt;br /&gt;        &lt;span style="color:#0000ff"&gt;var&lt;/span&gt; tfp = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;TextFieldParser&lt;/span&gt;( path )&lt;br&gt;&lt;br /&gt;        {&lt;br&gt;&lt;br /&gt;            TextFieldType = ft&lt;br&gt;&lt;br /&gt;        };&lt;br&gt;&lt;br /&gt;        tfp.Delimiters = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#0000ff"&gt;string&lt;/span&gt;[] {delimiter.ToString()};&lt;br&gt;&lt;br /&gt;        &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; tfp.ReadFields().ToList();&lt;br&gt;&lt;br /&gt;    }&lt;br&gt;&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Here is the (big fat, but working) method.  Requires following usings.  The referenced assemblies were found on my machine in C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies.  Note that they're in the x86 dir.  Thus, my application is set to target x86.&lt;br /&gt;using System.Data.Common;&lt;br /&gt;using Microsoft.SqlServer.Dts.Runtime;&lt;br /&gt;using Microsoft.SqlServer.Dts.Runtime.Wrapper;&lt;br /&gt;using Microsoft.SqlServer.Dts.Pipeline.Wrapper;&lt;br /&gt;using Microsoft.VisualBasic.FileIO;&lt;br /&gt;&lt;br /&gt;&lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt;&lt;br /&gt;&lt;div style="background-color: #d9d9df; max-height: 300px; overflow: auto; padding: 2px 5px; white-space: nowrap"&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; Microsoft.SqlServer.Dts.Runtime.&lt;span style="color:#2b91af"&gt;Package&lt;/span&gt; Generate( Microsoft.SqlServer.Dts.Runtime.&lt;span style="color:#2b91af"&gt;Application&lt;/span&gt; app )&lt;br&gt;&lt;br /&gt;{&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; Objects&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    Microsoft.SqlServer.Dts.Runtime.&lt;span style="color:#2b91af"&gt;Package&lt;/span&gt; _package;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#2b91af"&gt;Executable&lt;/span&gt; _dataFlowTask;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#2b91af"&gt;IDTSComponentMetaData100&lt;/span&gt; _dataSource;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#2b91af"&gt;IDTSComponentMetaData100&lt;/span&gt; _dataDest;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#2b91af"&gt;CManagedComponentWrapper&lt;/span&gt; _sourceInstance;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#2b91af"&gt;CManagedComponentWrapper&lt;/span&gt; _destinationInstance;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#2b91af"&gt;ConnectionManager&lt;/span&gt; _conMgrSource;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#2b91af"&gt;ConnectionManager&lt;/span&gt; _conMgrDest;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; Create package and data flow task&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    _package = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; Microsoft.SqlServer.Dts.Runtime.&lt;span style="color:#2b91af"&gt;Package&lt;/span&gt;();&lt;br&gt;&lt;br /&gt;    _package.DelayValidation = &lt;span style="color:#0000ff"&gt;true&lt;/span&gt;;&lt;br&gt;&lt;br /&gt;    _dataFlowTask = _package.Executables.Add( &lt;span style="color:#a31515"&gt;&amp;quot;STOCK:PipelineTask&amp;quot;&lt;/span&gt; );  &lt;span style="color:#008000"&gt;// PipelineTask is a DataFlowTask ??&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#0000ff"&gt;var&lt;/span&gt; pipe = (&lt;span style="color:#2b91af"&gt;MainPipe&lt;/span&gt;)( (Microsoft.SqlServer.Dts.Runtime.&lt;span style="color:#2b91af"&gt;TaskHost&lt;/span&gt;)_dataFlowTask ).InnerObject;&lt;br&gt;&lt;br /&gt;    pipe.Events = &lt;span style="color:#2b91af"&gt;DtsConvert&lt;/span&gt;.GetExtendedInterface( &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;ComponentEvents&lt;/span&gt;() &lt;span style="color:#0000ff"&gt;as&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IDTSComponentEvents&lt;/span&gt; );  &lt;span style="color:#008000"&gt;// my ComponentEvents() just writes some stuff to debug for now&lt;/span&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; Create connections&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    _conMgrSource = _package.Connections.Add( &lt;span style="color:#a31515"&gt;&amp;quot;FLATFILE&amp;quot;&lt;/span&gt; );&lt;br&gt;&lt;br /&gt;    _conMgrSource.Properties[&lt;span style="color:#a31515"&gt;&amp;quot;Format&amp;quot;&lt;/span&gt;].SetValue( _conMgrSource, &lt;span style="color:#a31515"&gt;&amp;quot;Delimited&amp;quot;&lt;/span&gt; );&lt;br&gt;&lt;br /&gt;    _conMgrSource.Properties[&lt;span style="color:#a31515"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;].SetValue( _conMgrSource, &lt;span style="color:#a31515"&gt;&amp;quot;Flat File Connection&amp;quot;&lt;/span&gt; );&lt;br&gt;&lt;br /&gt;    _conMgrSource.Properties[&lt;span style="color:#a31515"&gt;&amp;quot;ConnectionString&amp;quot;&lt;/span&gt;].SetValue( _conMgrSource, &lt;span style="color:#a31515"&gt;@&amp;quot;C:&amp;#92;temp&amp;#92;Eeemport&amp;#92;bubba.txt&amp;quot;&lt;/span&gt; );&lt;br&gt;&lt;br /&gt;    _conMgrSource.Properties[&lt;span style="color:#a31515"&gt;&amp;quot;ColumnNamesInFirstDataRow&amp;quot;&lt;/span&gt;].SetValue( _conMgrSource, &lt;span style="color:#0000ff"&gt;true&lt;/span&gt; );&lt;br&gt;&lt;br /&gt;    _conMgrSource.Properties[&lt;span style="color:#a31515"&gt;&amp;quot;HeaderRowDelimiter&amp;quot;&lt;/span&gt;].SetValue( _conMgrSource, &lt;span style="color:#a31515"&gt;&amp;quot;&amp;#92;r&amp;#92;n&amp;quot;&lt;/span&gt; );&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; If you set the delimiter like this, it&amp;#39;ll look correct if you open the resulting package in the UI, but it won&amp;#39;t execute (unless you click &amp;quot;Reset Columns&amp;quot;)&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#008000"&gt;//_conMgrSource.Properties[&amp;quot;RowDelimiter&amp;quot;].SetValue( _conMgrSource, &amp;quot;{CR}{LF}&amp;quot; );&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    _conMgrSource.Properties[&lt;span style="color:#a31515"&gt;&amp;quot;TextQualifier&amp;quot;&lt;/span&gt;].SetValue( _conMgrSource, &lt;span style="color:#a31515"&gt;&amp;quot;&amp;#92;&amp;quot;&amp;quot;&lt;/span&gt; );&lt;br&gt;&lt;br /&gt;    _conMgrSource.Properties[&lt;span style="color:#a31515"&gt;&amp;quot;DataRowsToSkip&amp;quot;&lt;/span&gt;].SetValue( _conMgrSource, 0 );&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    _conMgrDest = _package.Connections.Add( &lt;span style="color:#a31515"&gt;&amp;quot;OLEDB&amp;quot;&lt;/span&gt; );&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#008000"&gt;// This provider wouldn&amp;#39;t work&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#008000"&gt;//_conMgrDest.ConnectionString = @&amp;quot;Provider=Native OLE DB&amp;#92;SQL Server Native Client 10.0;Data Source=.&amp;#92;SQLEXPRESS;Initial Catalog=FASClient;Integrated Security=True&amp;quot;;&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    _conMgrDest.ConnectionString = &lt;span style="color:#a31515"&gt;@&amp;quot;Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=FASClient;Data Source=.&amp;#92;SQLEXPRESS&amp;quot;&lt;/span&gt;;&lt;br&gt;&lt;br /&gt;    _conMgrDest.Name = &lt;span style="color:#a31515"&gt;&amp;quot;OLE DB Connection&amp;quot;&lt;/span&gt;;&lt;br&gt;&lt;br /&gt;    _conMgrDest.Description = &lt;span style="color:#a31515"&gt;&amp;quot;OLE DB Connection&amp;quot;&lt;/span&gt;;&lt;br&gt;&lt;br /&gt;    _conMgrDest.Properties[&lt;span style="color:#a31515"&gt;&amp;quot;RetainSameConnection&amp;quot;&lt;/span&gt;].SetValue( _conMgrDest, &lt;span style="color:#0000ff"&gt;true&lt;/span&gt; );&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; Create the columns in the flat file connection&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#0000ff"&gt;var&lt;/span&gt; flatFileConnection = _conMgrSource.InnerObject &lt;span style="color:#0000ff"&gt;as&lt;/span&gt; &lt;span style="color:#2b91af"&gt;IDTSConnectionManagerFlatFile100&lt;/span&gt;;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#0000ff"&gt;var&lt;/span&gt; fileColumns = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;FlatFileColumnReader&lt;/span&gt;().Columns( &lt;span style="color:#a31515"&gt;@&amp;quot;C:&amp;#92;temp&amp;#92;Eeemport&amp;#92;bubba.txt&amp;quot;&lt;/span&gt;, &lt;span style="color:#a31515"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;, &lt;span style="color:#2b91af"&gt;FieldType&lt;/span&gt;.Delimited );&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#0000ff"&gt;for&lt;/span&gt; ( &lt;span style="color:#0000ff"&gt;int&lt;/span&gt; i = 0; i &amp;lt; fileColumns.Count; i++ )&lt;br&gt;&lt;br /&gt;    {&lt;br&gt;&lt;br /&gt;        &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; This object (IDTSConnectionManagerFlatFileColumn100) is not supposed to be referenced by my code according to doc:&lt;/span&gt;&lt;br&gt;&lt;br /&gt;        &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.dts.runtime.wrapper.idtsconnectionmanagerflatfilecolumn100.aspx&lt;/span&gt;&lt;br&gt;&lt;br /&gt;        &lt;span style="color:#0000ff"&gt;var&lt;/span&gt; column = flatFileConnection.Columns.Add();&lt;br&gt;&lt;br /&gt;        &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; Last column delimiter must be newline.&lt;/span&gt;&lt;br&gt;&lt;br /&gt;        &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; If you select &amp;quot;,&amp;quot; for the column delimiter in the designer for a Flat File Connection, and the row delimiter is newline, it does this same thing...&lt;/span&gt;&lt;br&gt;&lt;br /&gt;        column.ColumnDelimiter = ( i == fileColumns.Count - 1 ) ? &lt;span style="color:#a31515"&gt;&amp;quot;&amp;#92;r&amp;#92;n&amp;quot;&lt;/span&gt; : &lt;span style="color:#a31515"&gt;&amp;quot;,&amp;quot;&lt;/span&gt;; &lt;br&gt;&lt;br /&gt;        column.TextQualified = &lt;span style="color:#0000ff"&gt;true&lt;/span&gt;;&lt;br&gt;&lt;br /&gt;        column.ColumnType = &lt;span style="color:#a31515"&gt;&amp;quot;Delimited&amp;quot;&lt;/span&gt;;&lt;br&gt;&lt;br /&gt;        &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; Here&amp;#39;s one benefit of creating my own columns:&lt;/span&gt;&lt;br&gt;&lt;br /&gt;        &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; My destination column in Sql Server is varchar.  The columns seem to be defaulted to DT_WSTR which won&amp;#39;t go into a varchar column w/o being&lt;/span&gt;&lt;br&gt;&lt;br /&gt;        &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; manually changed or run through a data converter component.&lt;/span&gt;&lt;br&gt;&lt;br /&gt;        column.DataType = &lt;span style="color:#2b91af"&gt;DataType&lt;/span&gt;.DT_TEXT;&lt;br&gt;&lt;br /&gt;        column.DataPrecision = 0;&lt;br&gt;&lt;br /&gt;        column.DataScale = 0;&lt;br&gt;&lt;br /&gt;        ( (&lt;span style="color:#2b91af"&gt;IDTSName100&lt;/span&gt;)column ).Name = fileColumns[i];&lt;br&gt;&lt;br /&gt;    }&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; Create Data Flow Components&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    _dataSource = pipe.ComponentMetaDataCollection.New();&lt;br&gt;&lt;br /&gt;    _dataSource.Name = &lt;span style="color:#a31515"&gt;&amp;quot;Flat File Source&amp;quot;&lt;/span&gt;;&lt;br&gt;&lt;br /&gt;    _dataSource.ComponentClassID = app.PipelineComponentInfos[&lt;span style="color:#a31515"&gt;&amp;quot;Flat File Source&amp;quot;&lt;/span&gt;].CreationName;&lt;br&gt;&lt;br /&gt;    _dataSource.ValidateExternalMetadata = &lt;span style="color:#0000ff"&gt;false&lt;/span&gt;;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    _dataDest = pipe.ComponentMetaDataCollection.New();&lt;br&gt;&lt;br /&gt;    _dataDest.Name = &lt;span style="color:#a31515"&gt;&amp;quot;Sql Server Destination&amp;quot;&lt;/span&gt;;&lt;br&gt;&lt;br /&gt;    _dataDest.ComponentClassID = app.PipelineComponentInfos[&lt;span style="color:#a31515"&gt;&amp;quot;SQL Server Destination&amp;quot;&lt;/span&gt;].CreationName;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#008000"&gt;///// Create design instances&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    _sourceInstance = _dataSource.Instantiate();&lt;br&gt;&lt;br /&gt;    _sourceInstance.ProvideComponentProperties();&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; I think this junk must come after ProvideComponentProperties() above&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    _dataSource.RuntimeConnectionCollection[0].ConnectionManager = &lt;span style="color:#2b91af"&gt;DtsConvert&lt;/span&gt;.GetExtendedInterface( _conMgrSource );&lt;br&gt;&lt;br /&gt;    _dataSource.RuntimeConnectionCollection[0].ConnectionManagerID = _conMgrSource.ID;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    _sourceInstance.AcquireConnections( &lt;span style="color:#0000ff"&gt;null&lt;/span&gt; );  &lt;span style="color:#008000"&gt;// do we need to do this since we created our own columns?&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    _sourceInstance.ReinitializeMetaData();&lt;br&gt;&lt;br /&gt;    _sourceInstance.ReleaseConnections();&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    _destinationInstance = _dataDest.Instantiate();&lt;br&gt;&lt;br /&gt;    _destinationInstance.ProvideComponentProperties();&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; I know SetComponentProperty can only be called after ProvideComponentProperties()&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; To see available component properties, open an existing package (the XML) with an existing component of that type&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    _destinationInstance.SetComponentProperty( &lt;span style="color:#a31515"&gt;&amp;quot;BulkInsertTableName&amp;quot;&lt;/span&gt;, &lt;span style="color:#a31515"&gt;&amp;quot;[dbo].[bubba]&amp;quot;&lt;/span&gt; );&lt;br&gt;&lt;br /&gt;    _dataDest.RuntimeConnectionCollection[0].ConnectionManager = &lt;span style="color:#2b91af"&gt;DtsConvert&lt;/span&gt;.GetExtendedInterface( _conMgrDest );&lt;br&gt;&lt;br /&gt;    _dataDest.RuntimeConnectionCollection[0].ConnectionManagerID = _conMgrDest.ID;&lt;br&gt;&lt;br /&gt;    _destinationInstance.AcquireConnections( &lt;span style="color:#0000ff"&gt;null&lt;/span&gt; );&lt;br&gt;&lt;br /&gt;    _destinationInstance.ReinitializeMetaData();&lt;br&gt;&lt;br /&gt;    _destinationInstance.ReleaseConnections();&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#008000"&gt;//// Hook the path from source to dest&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#0000ff"&gt;var&lt;/span&gt; path = pipe.PathCollection.New();&lt;br&gt;&lt;br /&gt;    path.AttachPathAndPropagateNotifications( _dataSource.OutputCollection[0], _dataDest.InputCollection[0] );&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; Do stuff with the virtual input (whatever the @#$% that is)&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#0000ff"&gt;var&lt;/span&gt; virtualInput = _dataDest.InputCollection[0].GetVirtualInput();&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#0000ff"&gt;foreach&lt;/span&gt; ( &lt;span style="color:#2b91af"&gt;IDTSVirtualInputColumn100&lt;/span&gt; column &lt;span style="color:#0000ff"&gt;in&lt;/span&gt; virtualInput.VirtualInputColumnCollection )&lt;br&gt;&lt;br /&gt;    {&lt;br&gt;&lt;br /&gt;        _destinationInstance.SetUsageType( _dataDest.InputCollection[0].ID, virtualInput, column.LineageID, &lt;span style="color:#2b91af"&gt;DTSUsageType&lt;/span&gt;.UT_READONLY );&lt;br&gt;&lt;br /&gt;    }&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#808080"&gt;///&lt;/span&gt;&lt;span style="color:#008000"&gt; MapColumns();&lt;/span&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#0000ff"&gt;foreach&lt;/span&gt; ( &lt;span style="color:#2b91af"&gt;IDTSInputColumn100&lt;/span&gt; inputColumn &lt;span style="color:#0000ff"&gt;in&lt;/span&gt; _dataDest.InputCollection[0].InputColumnCollection )&lt;br&gt;&lt;br /&gt;    {&lt;br&gt;&lt;br /&gt;        &lt;span style="color:#0000ff"&gt;var&lt;/span&gt; outputColumn = _dataDest.InputCollection[0].ExternalMetadataColumnCollection[inputColumn.Name];&lt;br&gt;&lt;br /&gt;        outputColumn.Name = inputColumn.Name;&lt;br&gt;&lt;br /&gt;        _destinationInstance.MapInputColumn( _dataDest.InputCollection[0].ID, inputColumn.ID, outputColumn.ID );&lt;br&gt;&lt;br /&gt;    }&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#008000"&gt;//_package.Validate( _package.Connections, null, null, null );&lt;/span&gt;&lt;br&gt;&lt;br /&gt;&lt;br&gt;&lt;br /&gt;    &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; _package;&lt;br&gt;&lt;br /&gt;}&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-7599702878290905311?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/7599702878290905311/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=7599702878290905311' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/7599702878290905311'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/7599702878290905311'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2011/10/programmatically-creating-ssis-package.html' title='Programmatically Creating an SSIS Package with a Flat File Connection Source'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-3466399913445489932</id><published>2011-05-06T06:53:00.000-07:00</published><updated>2011-05-16T20:47:57.839-07:00</updated><title type='text'>File or Folder Delete Utility</title><content type='html'>I originally put this utility together for one very specific purpose: to delete all files in a given folder whose name started with a number (cleaning up after other processes).  It has since been used for other purposes, so I made it easier to extend by using the "pipeline" pattern just like is commonly done with data filtering.  File or folder names from the requested directory are passed through filters (Filters.cs).  Those meeting filter requirements are processed (either logged or deleted).&lt;br /&gt;&lt;br /&gt;The currently implemented filters are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Date (always taken into account)&lt;/li&gt;&lt;li&gt;Starts with numeric&lt;/li&gt;&lt;li&gt;Name is a guid&lt;/li&gt;&lt;/ul&gt;It will target either files or folders.  Launch the utility with no parameters to see instructions.&lt;br /&gt;&lt;br /&gt;To extend with another filter:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Add methods to Filters.cs following same pattern as existing (returns IEnumerable of FileInfo for files; IEnumerable of string for folders).&lt;/li&gt;&lt;li&gt;Add parameter metadata for the new filter parameter in AppParams.cs.PARAM_STRINGS&lt;/li&gt;&lt;li&gt;Add a "mode" property for the new filter in AppParams.cs (Like existing NumericMode).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add a method to read the new param from the command line and set the new property you created above (like existing SetNumericMode).&lt;/li&gt;&lt;li&gt;Update the help text that prints when no params or bad params are passed to the utility in Program.cs&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Test before using, of course, but I hope it's of use to somebody.  If you just want the utility, get it &lt;a href="http://www.puretolerance.com/DeleteUtility/Deleter.exe"&gt;here&lt;/a&gt;; if you want the code, it's &lt;a href="http://www.puretolerance.com/DeleteUtility/DeleterSolution.zip"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-3466399913445489932?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/3466399913445489932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=3466399913445489932' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/3466399913445489932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/3466399913445489932'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2011/05/file-or-folder-delete-utility.html' title='File or Folder Delete Utility'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-1859298715641105280</id><published>2010-12-22T10:43:00.000-08:00</published><updated>2011-01-20T09:25:32.154-08:00</updated><title type='text'>C# Decimal to English Money Converter</title><content type='html'>&lt;style type="text/css"&gt;&lt;br /&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: Consolas, "Courier New", Courier, Monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt &lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; &lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;I needed a way to convert a money value (decimal) into the kind of English text that appears on a legal document (like a check or a contract), e.g., 1245.36 becomes "One Thousand Two Hundred Forty Five and 36/100 Dollars."&lt;br /&gt;After searching for awhile, I couldn't find anything.  Maybe somebody else will make use of this (took a bit longer than I estimated).  Has a limitation on millions (I'm not working on a government contract), but this can easily be changed.  Requires .Net 4 (uses Tuples).&lt;br /&gt;&lt;br /&gt;Sorry for poor code formatting.&lt;br /&gt;&lt;br /&gt;First the decimal extension class that contains a method used by the actual converter class and also has a method to call the converter itself:&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; DecimalExtension&lt;br /&gt;    {&lt;br /&gt;    &lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Evaluates just the portion of the value to the right of the decimal place and returns it as a 2 character string.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Returns 00 if the value is a whole number.&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;The value to the right of the decimal place. Returns 0 if the value is a whole number.&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetDecimalNumbers( &lt;span class="kwrd"&gt;this&lt;/span&gt; &lt;span class="kwrd"&gt;decimal&lt;/span&gt; number )&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;int&lt;/span&gt; divint = Convert.ToInt32( Decimal.Floor( number ) );&lt;br /&gt;            &lt;span class="kwrd"&gt;decimal&lt;/span&gt; decValue = number - divint;&lt;br /&gt;&lt;br /&gt;            var result = decValue.ToString();&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; ( result.Length &amp;gt; 1 )&lt;br /&gt;            {&lt;br /&gt;                result = result.Substring( 2 );&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; ( result.Length &amp;gt; 2 )&lt;br /&gt;                {&lt;br /&gt;                    result = result.Substring( 0, 2 );&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; ( result.Length &amp;lt; 2 )&lt;br /&gt;                {&lt;br /&gt;                    result += &lt;span class="str"&gt;"0"&lt;/span&gt;;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                result = &lt;span class="str"&gt;"00"&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ToEnglishMoney( &lt;span class="kwrd"&gt;this&lt;/span&gt; &lt;span class="kwrd"&gt;decimal&lt;/span&gt; d )&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; DecimalToEnglishMoney( d ).ToString();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;Now for the actual converter class:&lt;br /&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; DecimalToEnglishMoney&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;enum&lt;/span&gt; DigitPlace&lt;br /&gt;        {&lt;br /&gt;            Ones = 0,&lt;br /&gt;            Tens = 1,&lt;br /&gt;            Hundreds = 2&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _result;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; DecimalToEnglishMoney( &lt;span class="kwrd"&gt;decimal&lt;/span&gt; d )&lt;br /&gt;        {&lt;br /&gt;            _result = FormatWholePortion( d );&lt;br /&gt;            _result += FormatDecimalPortion( d );&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; ToString()&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; _result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FormatDecimalPortion( &lt;span class="kwrd"&gt;decimal&lt;/span&gt; d )&lt;br /&gt;        {&lt;br /&gt;            var result = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty;&lt;br /&gt;            var decimalPortion = d.GetDecimalNumbers();&lt;br /&gt;            result += &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format( &lt;span class="str"&gt;" and {0}/100 Dollars"&lt;/span&gt;, decimalPortion );&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FormatWholePortion( &lt;span class="kwrd"&gt;decimal&lt;/span&gt; d )&lt;br /&gt;        {&lt;br /&gt;            var result = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty;&lt;br /&gt;            var wholePortion = (&lt;span class="kwrd"&gt;int&lt;/span&gt;)Math.Floor( (&lt;span class="kwrd"&gt;double&lt;/span&gt;)d );&lt;br /&gt;            var groups = FormatToNumberGroups( wholePortion );&lt;br /&gt;            groups.ForEach( g =&amp;gt;&lt;br /&gt;            {&lt;br /&gt;                result += (result == &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : &lt;span class="str"&gt;" "&lt;/span&gt;;&lt;br /&gt;                var formattedChunk = FormatChunkToEnglish( g.Item2 );&lt;br /&gt;                var amountDescriptor = (g.Item1 == &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : &lt;span class="str"&gt;" "&lt;/span&gt; + g.Item1;  &lt;span class="rem"&gt;// "Thousand"&lt;/span&gt;&lt;br /&gt;                result += formattedChunk;&lt;br /&gt;                result += (amountDescriptor == &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : amountDescriptor;&lt;br /&gt;            } );&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Returns the chunk name (blank, Thousand, Million) and the chunk number&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="i"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;"Million" "NNN"&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; List&amp;lt;Tuple&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;&amp;gt; FormatToNumberGroups( &lt;span class="kwrd"&gt;int&lt;/span&gt; i )&lt;br /&gt;        {&lt;br /&gt;            var result = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Tuple&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;&amp;gt;();&lt;br /&gt;            var asString = i.ToString();&lt;br /&gt;            var count = 1;&lt;br /&gt;            &lt;span class="kwrd"&gt;while&lt;/span&gt; ( asString.Length &amp;gt; 0 )&lt;br /&gt;            {&lt;br /&gt;                var chunkStartPos = (asString.Length &amp;lt; 3) ? 0 : asString.Length - 3;&lt;br /&gt;                var chunkLength = (asString.Length &amp;lt; 3) ? asString.Length : 3;&lt;br /&gt;                var chunk = asString.Substring( chunkStartPos, chunkLength );&lt;br /&gt;                &lt;span class="kwrd"&gt;switch&lt;/span&gt; ( count )&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;case&lt;/span&gt; 2:&lt;br /&gt;                        result.Add( &lt;span class="kwrd"&gt;new&lt;/span&gt; Tuple&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;( &lt;span class="str"&gt;"Thousand"&lt;/span&gt;, chunk ) );&lt;br /&gt;                        &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                    &lt;span class="kwrd"&gt;case&lt;/span&gt; 3:&lt;br /&gt;                        result.Add( &lt;span class="kwrd"&gt;new&lt;/span&gt; Tuple&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;( &lt;span class="str"&gt;"Million"&lt;/span&gt;, chunk ) );&lt;br /&gt;                        &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                    &lt;span class="kwrd"&gt;default&lt;/span&gt;:&lt;br /&gt;                        &lt;span class="rem"&gt;/// First chunk is blank and we're not expecting anything &amp;gt; than million&lt;/span&gt;&lt;br /&gt;                        result.Add( &lt;span class="kwrd"&gt;new&lt;/span&gt; Tuple&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;( &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty, chunk ) );&lt;br /&gt;                        &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                }&lt;br /&gt;                count++;&lt;br /&gt;                asString = (asString.Length &amp;gt; 3) ? asString.Substring( 0, asString.Length - 3 ) : &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty;&lt;br /&gt;            }&lt;br /&gt;            result.Reverse();&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FormatChunkToEnglish( &lt;span class="kwrd"&gt;string&lt;/span&gt; chunk )&lt;br /&gt;        {&lt;br /&gt;            Debug.Assert( (chunk.Length &amp;lt;= 3) &amp;amp;&amp;amp; (chunk.Length &amp;gt;= 1), &lt;span class="str"&gt;"Expecting 1-3 digit portion of a number to format to english."&lt;/span&gt; );&lt;br /&gt;            &lt;br /&gt;            var onesDigit = OnesDigit( chunk );&lt;br /&gt;            var tensDigit = TensDigit( chunk );&lt;br /&gt;            var hundredsDigit = HundredsDigit( chunk );&lt;br /&gt;            &lt;br /&gt;            var onesDigitFormatted = FormatDigit( onesDigit, DigitPlace.Ones, chunk );&lt;br /&gt;            var tensDigitFormatted = (tensDigit == &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : FormatDigit( tensDigit, DigitPlace.Tens, chunk );&lt;br /&gt;            var hundredsDigitFormatted = (hundredsDigit == &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : FormatDigit( hundredsDigit, DigitPlace.Hundreds, chunk );&lt;br /&gt;            &lt;br /&gt;            var result = onesDigitFormatted;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; ( tensDigitFormatted != &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty )&lt;br /&gt;            {&lt;br /&gt;                result = ( result == &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty ) ? tensDigitFormatted : &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format( &lt;span class="str"&gt;"{0} {1}"&lt;/span&gt;, tensDigitFormatted, result );&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; ( hundredsDigitFormatted != &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty )&lt;br /&gt;            {&lt;br /&gt;                result = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format( &lt;span class="str"&gt;"{0} {1}"&lt;/span&gt;, hundredsDigitFormatted, result );&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; These all deal with the 1-3 digit chunks&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; HundredsDigit( &lt;span class="kwrd"&gt;string&lt;/span&gt; chunk )&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; (chunk.Length &amp;gt; 2) ? chunk.Substring( chunk.Length - 3, 1 ) : &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; TensDigit( &lt;span class="kwrd"&gt;string&lt;/span&gt; chunk )&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; (chunk.Length &amp;gt; 1) ? chunk.Substring( chunk.Length - 2, 1 ) : &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; OnesDigit( &lt;span class="kwrd"&gt;string&lt;/span&gt; chunk )&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; chunk.Substring( chunk.Length - 1 );&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; ContainsTeen( &lt;span class="kwrd"&gt;string&lt;/span&gt; allDigits )&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; TensDigit( allDigits ) == &lt;span class="str"&gt;"1"&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FormatDigit( &lt;span class="kwrd"&gt;string&lt;/span&gt; digit, DigitPlace digitPlace, &lt;span class="kwrd"&gt;string&lt;/span&gt; allDigits )&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="rem"&gt;/// Param must be string due to the way it's constructed&lt;/span&gt;&lt;br /&gt;            Debug.Assert( digit.Length == 1, &lt;span class="str"&gt;"Expecting to format single digit while converting number to english, but received multiple digits"&lt;/span&gt; );&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;switch&lt;/span&gt; ( digit )&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"0"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"1"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;switch&lt;/span&gt; ( digitPlace )&lt;br /&gt;                    {&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Ones:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; ContainsTeen(allDigits) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : &lt;span class="str"&gt;"One"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Tens:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; FormatTeen(allDigits);&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Hundreds:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"One Hundred"&lt;/span&gt;;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"2"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;switch&lt;/span&gt; ( digitPlace )&lt;br /&gt;                    {&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Ones:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; ContainsTeen(allDigits) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : &lt;span class="str"&gt;"Two"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Tens:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Twenty"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Hundreds:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Two Hundred"&lt;/span&gt;;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"3"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;switch&lt;/span&gt; ( digitPlace )&lt;br /&gt;                    {&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Ones:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; ContainsTeen(allDigits) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : &lt;span class="str"&gt;"Three"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Tens:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Thirty"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Hundreds:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Three Hundred"&lt;/span&gt;;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"4"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;switch&lt;/span&gt; ( digitPlace )&lt;br /&gt;                    {&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Ones:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; ContainsTeen(allDigits) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : &lt;span class="str"&gt;"Four"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Tens:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Forty"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Hundreds:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Four Hundred"&lt;/span&gt;;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"5"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;switch&lt;/span&gt; ( digitPlace )&lt;br /&gt;                    {&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Ones:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; ContainsTeen(allDigits) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : &lt;span class="str"&gt;"Five"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Tens:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Fifty"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Hundreds:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Five Hundred"&lt;/span&gt;;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"6"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;switch&lt;/span&gt; ( digitPlace )&lt;br /&gt;                    {&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Ones:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; ContainsTeen(allDigits) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : &lt;span class="str"&gt;"Six"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Tens:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Sixty"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Hundreds:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Six Hundred"&lt;/span&gt;;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"7"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;switch&lt;/span&gt; ( digitPlace )&lt;br /&gt;                    {&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Ones:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; ContainsTeen(allDigits) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : &lt;span class="str"&gt;"Seven"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Tens:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Seventy"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Hundreds:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Seven Hundred"&lt;/span&gt;;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"8"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;switch&lt;/span&gt; ( digitPlace )&lt;br /&gt;                    {&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Ones:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; ContainsTeen(allDigits) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : &lt;span class="str"&gt;"Eight"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Tens:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Eighty"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Hundreds:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Eight Hundred"&lt;/span&gt;;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"9"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;switch&lt;/span&gt; ( digitPlace )&lt;br /&gt;                    {&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Ones:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; ContainsTeen(allDigits) ? &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : &lt;span class="str"&gt;"Nine"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Tens:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Ninety"&lt;/span&gt;;&lt;br /&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; DigitPlace.Hundreds:&lt;br /&gt;                            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Nine Hundred"&lt;/span&gt;;&lt;br /&gt;                    }&lt;br /&gt;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;default&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty;  &lt;span class="rem"&gt;// not a good sign when you have to add code just to make it compile&lt;/span&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="allDigits"&amp;gt;Either 2 or 3 characters long and the tens digit is a one&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FormatTeen( &lt;span class="kwrd"&gt;string&lt;/span&gt; allDigits )&lt;br /&gt;        {&lt;br /&gt;            Debug.Assert( (allDigits.Length == 2) || (allDigits.Length == 3) );&lt;br /&gt;            &lt;span class="kwrd"&gt;switch&lt;/span&gt; ( OnesDigit(allDigits) )&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"0"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Ten"&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"1"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Eleven"&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"2"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Twelve"&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"3"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Thirteen"&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"4"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Fourteen"&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"5"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Fifteen"&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"6"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Sixteen"&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"7"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Seventeen"&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"8"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Eighteen"&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;case&lt;/span&gt; &lt;span class="str"&gt;"9"&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="str"&gt;"Nineteen"&lt;/span&gt;;&lt;br /&gt;                &lt;span class="kwrd"&gt;default&lt;/span&gt;:&lt;br /&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-1859298715641105280?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/1859298715641105280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=1859298715641105280' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/1859298715641105280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/1859298715641105280'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2010/12/c-decimal-to-english-money-converter.html' title='C# Decimal to English Money Converter'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-8305405206553578646</id><published>2010-09-08T06:36:00.001-07:00</published><updated>2010-09-08T07:14:27.586-07:00</updated><title type='text'>Implementing Session Timeout Check in MVC</title><content type='html'>&lt;span style="font-size:85%;"&gt;This took me awhile to get right; hope it saves some time for somebody else.  I simply want to decorate a given controller (at the class level) with an attribute that will cause a redirect to login page (with a session timeout message) on session timeout while using forms authentication.&lt;br /&gt;&lt;br /&gt;Here's the attribute:&lt;/span&gt;&lt;br /&gt; &lt;div style="color:black;overflow:auto;width:99.5%;"&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt;     &lt;span style="color:#0000ff"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:#0000ff"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af"&gt;CheckSessionAttribute&lt;/span&gt;&amp;nbsp;: &lt;span style="color:#2b91af"&gt;ActionFilterAttribute&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt;     &lt;span style="color:#000000"&gt;{&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt;         &lt;span style="color:#0000ff"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:#0000ff"&gt;override&lt;/span&gt;&amp;nbsp;&lt;span style="color:#0000ff"&gt;void&lt;/span&gt;&amp;nbsp;OnActionExecuting( &lt;span style="color:#2b91af"&gt;ActionExecutingContext&lt;/span&gt;&amp;nbsp;filterContext )&lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt;         &lt;span style="color:#000000"&gt;{&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt;             &lt;span style="color:#0000ff"&gt;if&lt;/span&gt;&amp;nbsp;( filterContext.HttpContext.Session.IsNewSession )&lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt;             &lt;span style="color:#000000"&gt;{&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt;                 &lt;span style="color:#2b91af"&gt;FormsAuthentication&lt;/span&gt;.SignOut();&lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt;                 filterContext.Controller.TempData[&lt;span style="color:#2b91af"&gt;Constants&lt;/span&gt;&amp;nbsp;.&lt;span style="color:#2b91af"&gt;TEMPDATA_KEYS&lt;/span&gt;&amp;nbsp;.TIMEOUT] = &lt;span style="color:#a31515"&gt;&amp;quot;Your session has timed out.  Please login again to continue.&amp;quot;&lt;/span&gt;&amp;nbsp;;&lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt;                 filterContext.Result = &lt;span style="color:#0000ff"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af"&gt;RedirectResult&lt;/span&gt;&amp;nbsp;( &lt;span style="color:#a31515"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&amp;nbsp;);&lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt;             &lt;span style="color:#000000"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt;         &lt;span style="color:#000000"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt;     &lt;span style="color:#000000"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt; &lt;/pre&gt;&lt;br /&gt; &lt;pre style="margin:0em;"&gt; &lt;/pre&gt;&lt;br /&gt; &lt;/div&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Now you need only check the presence of that TempData key on your logon view in order to show a proper timeout message instead of the standard login message.&lt;br /&gt;Note the use of RedirectResult.  The old Response.Redirect will do a proper redirect, but won't terminate the original request (even with the overload containing the parameter that tells it to do so).  Response.Redirect should really raise an error when used in an MVC app.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-8305405206553578646?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/8305405206553578646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=8305405206553578646' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/8305405206553578646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/8305405206553578646'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2010/09/implementing-session-timeout-check-in.html' title='Implementing Session Timeout Check in MVC'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-2967288609190974582</id><published>2010-08-12T07:43:00.000-07:00</published><updated>2010-08-12T07:51:38.655-07:00</updated><title type='text'>Fix for Extremely Slow Development Browser Performance</title><content type='html'>I'm running Windows 7 with Visual Studio 2010.  When I would debug web applications (where VS would use Cassini, the development web server), browser performance was &lt;span style="font-style:italic;"&gt;extremely&lt;/span&gt; slow.  We're talking almost a second for retrieval of every image (all on my local machine).  Most of the time it seemed like IE didn't experience the problem, but something changed and it too seemed to stop working.&lt;br /&gt;After coming across &lt;a href="http://weblogs.asp.net/dwahlin/archive/2007/06/17/fixing-firefox-slowness-with-localhost-on-vista.aspx"&gt;this post&lt;/a&gt; and doing what it recommended, the problem went away.  I've no idea why that configuration change in Firefox would affect IE, but all my problems vanished.&lt;br /&gt;Maybe this will help some other poor chap; it got to the point where I just couldn't work at all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-2967288609190974582?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/2967288609190974582/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=2967288609190974582' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/2967288609190974582'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/2967288609190974582'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2010/08/fix-for-extremely-slow-development.html' title='Fix for Extremely Slow Development Browser Performance'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-8119120278222032264</id><published>2010-04-23T10:56:00.001-07:00</published><updated>2010-06-17T08:58:59.811-07:00</updated><title type='text'>Detecting Session Timeout in ASP.Net WebForms</title><content type='html'>[Edit]&lt;br /&gt;Disregard all this crap.  It's simply not possible to detect session timeout using cookieless sessions.  Detecting a post with a redirect does in fact trigger the condition in Application_EndRequest below (in my defense, it seemed to work in a test project and was deceiving).&lt;br /&gt;[/Edit]&lt;br /&gt;&lt;br /&gt;Everyone is starting new projects with MVC these days, but for all those maintenance projects in ASP.Net WebForms, here is what I've settled on as the best way to detect session timeout.  I've had 1 or 2 other methods in production that didn't cause problems, but were not quite correct.&lt;br /&gt;&lt;br /&gt;I was quite surprised when initially investigating this issue to see how many ways people had come up with to do it.&lt;br /&gt;&lt;br /&gt;I had a completely different version of this up on this post for quite awhile that didn't work when using cookieless sessions.&lt;br /&gt;&lt;br /&gt;Here's the assumption: if a user's session has timed out, but they've issued an HTTP POST, that indicates a session timeout. If you're not using cookieless sessions, that's all there is to it; check this somewhere in a page base class:&lt;br /&gt;&lt;div style="text-align: center;"&gt;Request.HttpMethod.Equals( "POST" ) &amp;amp;&amp;amp; (Session.IsNewSession)&lt;br /&gt;&lt;/div&gt;The problem with cookieless sessions is, you never get to that condition on a page.  In either case, Session.IsNewSession by itself is completely useless because that may be true on an initial GET (not a session timeout condition).  With cookieless sessions, sometimes it &lt;span style="font-style: italic;"&gt;will be true&lt;/span&gt; and the &lt;span style="font-style: italic;"&gt;request will be a GET&lt;/span&gt; (by the time it gets to your page) when the user posts after a session timeout.&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;This is what happens when using cookieless sessions&lt;/span&gt;&lt;/span&gt;: the user posts up, ASP.Net detects a session timeout and issues a 302 telling the browser to go to the same place, but use GET.  Thus, on any page, &lt;span style="font-style: italic;"&gt;there is absolutely no way to know whether a timeout condition has occurred&lt;/span&gt;.&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Consequently, the way I handled this problem is by detecting the above stated condition (user's session has timed out, current request is a post) in Global.asax.  A Response.Redirect or Server.Transfer works fine with this.  The problem that will occur with this approach is that the flag for session timeout will be set, but before the user with the timeout round trips back to the server with a GET, another user will hit Session_Start and receive an incorrect session timeout condition.  Also, the user who timed out might, for whatever reason, not make the round trip back to the server.  In this case, again, a user issuing his first request will see a session timeout.  I'm willing to accept that, on rare occasion, this happens.  Knowing users, he will simply try again, get the page he requested, and think little of it.&lt;br /&gt;&lt;div   style="overflow: auto; width: 99.5%;font-size:small;background-color:white;"&gt;&lt;br /&gt;Global.asax  code:&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;     &lt;span style="color: rgb(0, 0, 255);"&gt;public&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  &lt;span style="color: rgb(43, 145, 175);"&gt;Global&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  : System.Web.&lt;span style="color: rgb(43, 145, 175);"&gt;HttpApplication&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;     &lt;span style="color: rgb(0, 0, 0);"&gt;{&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt; &lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;bool&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  _sessionTimedOutCookieless = &lt;span style="color: rgb(0, 0, 255);"&gt;false&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; ;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt; &lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  Application_EndRequest( &lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  sender, &lt;span style="color: rgb(43, 145, 175);"&gt;EventArgs&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  e )&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 0);"&gt;{&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(128, 128, 128);"&gt;///&lt;span style="color: rgb(0, 128, 0);"&gt; This condition occurs when using cookieless sessions (but perhaps not with "AutoDetect" - that mode is evil)&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(128, 128, 128);"&gt;///&lt;span style="color: rgb(0, 128, 0);"&gt; The redirect will occur within the context of this same application instance, so the private variable will still&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(128, 128, 128);"&gt;///&lt;span style="color: rgb(0, 128, 0);"&gt; be alive.&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  ( Request.HttpMethod.Equals( &lt;span style="color: rgb(163, 21, 21);"&gt;"POST"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  ) &amp;amp;&amp;amp; (Response.StatusCode == 302) )&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(0, 0, 0);"&gt;{&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;                 _sessionTimedOutCookieless = &lt;span style="color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; ;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(0, 0, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt; &lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  Session_Start( &lt;span style="color: rgb(0, 0, 255);"&gt;object&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  sender, &lt;span style="color: rgb(43, 145, 175);"&gt;EventArgs&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  e )&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 0);"&gt;{&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  ( _sessionTimedOutCookieless || (SessionTimedOutWithCookies()) )&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(0, 0, 0);"&gt;{&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;                 _sessionTimedOutCookieless = &lt;span style="color: rgb(0, 0, 255);"&gt;false&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; ;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;                 Session.Add( &lt;span style="color: rgb(163, 21, 21);"&gt;"timeout"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; , &lt;span style="color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  );&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(0, 0, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt; &lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;private&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;bool&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  SessionTimedOutWithCookies()&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 0);"&gt;{&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(0, 0, 255);"&gt;return&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  Request.HttpMethod.Equals( &lt;span style="color: rgb(163, 21, 21);"&gt;"POST"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  ) &amp;amp;&amp;amp; (Session.IsNewSession);&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt; &lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;     &lt;span style="color: rgb(0, 0, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt; &lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt; &lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- End block --&gt;&lt;br /&gt;&lt;br /&gt;In a base page class:&lt;br /&gt;&lt;div   style="overflow: auto; width: 99.5%;font-size:small;background-color:white;"&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 255);"&gt;protected&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  &lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  Page_PreInit()&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 0);"&gt;{&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  ( Session[&lt;span style="color: rgb(163, 21, 21);"&gt;"timeout"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; ] != &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  )&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(0, 0, 0);"&gt;{&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;                 _timedout = &lt;span style="color: rgb(0, 0, 255);"&gt;true&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; ; &lt;span style="color: rgb(0, 128, 0);"&gt;// do something about this wherever&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;                 Session.Remove( &lt;span style="color: rgb(163, 21, 21);"&gt;"timeout"&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;  );&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;             &lt;span style="color: rgb(0, 0, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt;         &lt;span style="color: rgb(0, 0, 0);"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt; &lt;/pre&gt;&lt;br /&gt;&lt;pre style="margin: 0em;"&gt; &lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-8119120278222032264?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/8119120278222032264/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=8119120278222032264' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/8119120278222032264'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/8119120278222032264'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2010/04/detecting-session-timeout-in-aspnet.html' title='Detecting Session Timeout in ASP.Net WebForms'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-8550516323828323223</id><published>2010-02-19T07:49:00.000-08:00</published><updated>2010-02-19T08:05:52.180-08:00</updated><title type='text'>EF4 &amp; SQL Server Date / DateTime Columns</title><content type='html'>&lt;span style="font-size:85%;"&gt;When using EF4 against SQL Server 2008 (though this would apply to 2005 as well), I kept getting this error on insert:&lt;br /&gt;&lt;div style="margin-left: 1em;"&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;System.Data.SqlClient.SqlException: The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="margin-left: -1em;"&gt;&lt;br /&gt;I had 2 date columns in the table I was attempting to insert into to begin with.  One was just a LastDateModified column with a default of GetDate() so I was mentally filtering that column out and focusing on the other column.  I changed that column from date to datetime which didn't fix the problem.  I then changed that column to DateTime(2,7) and it still didn't fix it.  Running a trace on the SQL that EF4 was attempting to insert revealed the problem.  EF4 isn't smart enough to see that my LastDateModified column has a default and shouldn't bother sending a value when the programmer doesn't set one.  It sent some huge min date that didn't fit into a datetime column.&lt;br /&gt;&lt;br /&gt;Thus, the workaround is to either set any columns I won't be explicitly setting in code to type date(2,7) or to explicitly set the value of those columns in code to DateTime.Now.  In any case, you can't use the SQL Server 2008 date column data type (which sucks).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-8550516323828323223?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/8550516323828323223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=8550516323828323223' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/8550516323828323223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/8550516323828323223'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2010/02/ef4-sql-server-date-datetime-columns.html' title='EF4 &amp; SQL Server Date / DateTime Columns'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-7601516467385563233</id><published>2009-12-12T16:05:00.000-08:00</published><updated>2009-12-22T13:28:06.031-08:00</updated><title type='text'>Entity Framework IEnumerable Lambda Join Sample</title><content type='html'>I figured this out from a sample, but it wasn't at all clear.  The docs provide no sample, and the parameter names are totally confusing.  If you're using EF, and you're wondering how the Join IEnumerable extension method works with your entities, here is the simplest example:&lt;br /&gt;&lt;p style="font: 8pt Consolas Courier"&gt;&lt;br /&gt;&lt;span style="color:blue"&gt;var&lt;/span&gt; parent_child = entities.Parent.Join&lt;br /&gt;&lt;br /&gt;&amp;nbsp;(&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;entities.Child, &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:green"&gt;// child entity&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;parent =&gt; parent.ParentId, &lt;span style="color:green"&gt;// function providing parent key&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;child =&gt; child.ChildId, &amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:green"&gt;// function providing child key&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;( parent, child ) =&gt; &lt;span style="color:blue"&gt;new&lt;/span&gt; &amp;nbsp;&amp;nbsp;&lt;span style="color:green"&gt;// projection (anonymous object returning what you want)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChildId = child.ChildId,&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WhateverElseFromChild = child.WhateverElse,&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WhateverElseFromParent = parent.WhateverElse,&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ParentId = parent.ParentId&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:green"&gt;// pc here is anonymous object created above&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;).Where( pc =&gt; pc.Condition == "some condition" ).FirstOrDefault();&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;Tracing this against  SqlServer showed very clean SQL.  The exact same SQL produced by this linq equivalent:&lt;br /&gt;&lt;p style="font: 8pt Consolas Courier"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue"&gt;var&lt;/span&gt; parent_child = ( &lt;span style="color:blue"&gt;from&lt;/span&gt; parent in entities.Parent&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:blue"&gt;join&lt;/span&gt; child &lt;span style="color:blue"&gt;in&lt;/span&gt; entities.Child &lt;span style="color:blue"&gt;on&lt;/span&gt; parent.ParentId &lt;span style="color:blue"&gt;equals&lt;/span&gt; child.ChildId&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:blue"&gt;where&lt;/span&gt; parent.Condition == "some condition"&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color:blue"&gt;select new&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChildId = child.ChildId,&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WhateverElseFromChild = child.WhateverElse,&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WhateverElseFromParent = parent.WhateverElse,&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ParentId = parent.ParentId&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}).FirstOrDefault();&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-7601516467385563233?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/7601516467385563233/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=7601516467385563233' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/7601516467385563233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/7601516467385563233'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2009/12/entity-framework-ienumerable-join.html' title='Entity Framework IEnumerable Lambda Join Sample'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-2073364073765007918</id><published>2009-11-19T07:11:00.000-08:00</published><updated>2009-12-10T14:46:50.762-08:00</updated><title type='text'>Handling Extensionless URIs in a WebForms Application</title><content type='html'>&lt;span style="font-size:85%;"&gt;[Edit: I wrote this just a few days before finding out that WebForms 4 does routing out of the box]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;ASP.Net MVC is all the rage, but I just needed to add extensionless functionality to a WebForms application.  I'm going to host this application in IIS7, so that's how I'm describing it; there is more work involved for IIS6.&lt;br /&gt;&lt;br /&gt;This all seems obvious now, but it took me awhile to figure out.&lt;br /&gt;&lt;br /&gt;I started by adding a class that supported IHttpHandler.  I need to have a handler (rather than a module) because I want to set a value in session, and that's not yet available within a module (at that phase in the IIS pipeline).&lt;br /&gt;&lt;br /&gt;&lt;p style="font-size: 7pt; font-family: courier new;"&gt;&lt;br /&gt;public class OnDemandHandler : IHttpHandler, System.Web.SessionState.IRequiresSessionState&lt;br /&gt;{&lt;br /&gt;    public void ProcessRequest( System.Web.HttpContext context )&lt;br /&gt;    {&lt;br /&gt;      ; // add something to session&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public bool IsReusable { get { return true; } }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&amp;lt;httphandlers&amp;gt;&lt;br /&gt;  &amp;lt;add verb="GET" path="*" type="MyNamespace.OnDemandHandler, MyDll" validate="false"&amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;That works fine, but it handles &lt;span style="font-style: italic;"&gt;everything&lt;/span&gt;.  How do I handle aspx pages, or images, or anything else?  Copy in all the base handlers from the web.config at the machine level to my web.config?  Move my httpHandler config element from my web.config to the machine web.config so it can fall last in order there and only run after all the base handlers have run?  Use a module instead of a handler?  I was having a hard time figuring out what to do until I decided to go check out a config of an MVC project.  After all, they are doing what I want to do:&lt;br /&gt;&lt;br /&gt;&lt;p style="font-family: courier new; font-size: 7pt;"&gt;&lt;br /&gt;&amp;lt;httphandlers&amp;gt;&lt;br /&gt;  &amp;lt;add verb="*" path="*.mvc" validate="false" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"&amp;gt;&lt;br /&gt;&amp;lt;/httphandlers&amp;gt;&lt;br /&gt;&amp;lt;httpmodules&amp;gt;&lt;br /&gt;  &amp;lt;add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"&amp;gt;&lt;br /&gt;&amp;lt;/httpmodules&amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;Again, it seems obvious now; use a module that checks for extensionless URIs, tack on my own pre-determined extension (just like they're using *.mvc), and send it off to my handler.  For URIs with extensions, let them pass on normally.&lt;br /&gt;&lt;br /&gt;So here's how it looks in the end:&lt;br /&gt;&lt;br /&gt;&lt;p style="font-family: courier new; font-size: 7pt;"&gt;&lt;br /&gt;public class OnDemandModule: IHttpModule&lt;br /&gt;{&lt;br /&gt;     &lt;br /&gt;  #region IHttpModule Members&lt;br /&gt;  public void Dispose()&lt;br /&gt;  {&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void Init( HttpApplication app )&lt;br /&gt;  {&lt;br /&gt;    app.BeginRequest += new EventHandler( OnBeginRequest );&lt;br /&gt;  }&lt;br /&gt;  #endregion&lt;br /&gt;&lt;br /&gt;  private void OnBeginRequest( object src, EventArgs e )&lt;br /&gt;  {&lt;br /&gt;    HttpContext context = ( src as HttpApplication ).Context;&lt;br /&gt;    var uriPath = context.Request.Path;&lt;br /&gt;    if ( UriIsExtensionless( uriPath ) )&lt;br /&gt;    {&lt;br /&gt;      /// Add the .inst extension so our handler will process it&lt;br /&gt;      context.Response.Redirect( context.Response.ApplyAppPathModifier( uriPath + ".inst" + context.Request.Url.Query));&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /// &amp;lt;param name="uriPath"&amp;gt;like /blah or /something.aspx.  Does not contain possible query params&amp;lt;/param&amp;gt;&lt;br /&gt;  /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br /&gt;  private bool UriIsExtensionless( string uriPath )&lt;br /&gt;  {&lt;br /&gt;    var result = false;&lt;br /&gt;    if ( uriPath[0].Equals( '/' ) )&lt;br /&gt;    {&lt;br /&gt;      var restOfURI = uriPath.Substring( 1 );&lt;br /&gt;      if ( restOfURI.Length &gt; 0 )&lt;br /&gt;    {&lt;br /&gt;      return !restOfURI.Contains( '.' );&lt;br /&gt;    }&lt;br /&gt;    }&lt;br /&gt;    return result;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class OnDemandHandler : IHttpHandler, System.Web.SessionState.IRequiresSessionState&lt;br /&gt;{&lt;br /&gt;  public void ProcessRequest( System.Web.HttpContext context )&lt;br /&gt;  {&lt;br /&gt;    context.Response.Write("OnDemandHandler fired");&lt;br /&gt;    context.Response.End();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public bool IsReusable { get { return true; } }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- for cassini --&amp;gt;&lt;br /&gt;&amp;lt;system.web&amp;gt;&lt;br /&gt;    &amp;lt;httphandlers&amp;gt;&lt;br /&gt;      &amp;lt;add verb="GET"&amp;gt;&lt;br /&gt;        path="*.inst"&lt;br /&gt;        type="MyNamespace.OnDemandHandler, MyAssembly"&lt;br /&gt;        validate="false" /&amp;gt;&lt;br /&gt;    &amp;lt;/httphandlers&amp;gt;&lt;br /&gt;  &amp;lt;httpmodules&amp;gt;&lt;br /&gt;      &amp;lt;add name="OnDemandModule" type="MyNamespace.OnDemandModule, MyAssembly"&amp;gt;&lt;br /&gt;  &amp;lt;/httpmodules&amp;gt;&lt;br /&gt;&amp;lt;/system.web&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- for IIS7 --&amp;gt;&lt;br /&gt;&amp;lt;system.webserver&amp;gt;&lt;br /&gt;  &amp;lt;modules runallmanagedmodulesforallrequests="true"&amp;gt;&lt;br /&gt;    &amp;lt;add name="OnDemandModule"&amp;gt;&lt;br /&gt;      type="MyNamespace.OnDemandModule, MyAssembly" /&amp;gt;&lt;br /&gt;  &amp;lt;/modules&amp;gt;&lt;br /&gt;  &amp;lt;handlers&amp;gt;&lt;br /&gt;    &amp;lt;add name="OnDemandSurvey"&amp;gt;&lt;br /&gt;      verb="GET"&lt;br /&gt;      path="*.inst"&lt;br /&gt;      preCondition="integratedMode"&lt;br /&gt;      type="MyNamespace.OnDemandModule, MyAssembly" /&amp;gt;&lt;br /&gt;    &amp;lt;/handlers&amp;gt;&lt;br /&gt;&amp;lt;/system.webServer&amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-2073364073765007918?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/2073364073765007918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=2073364073765007918' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/2073364073765007918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/2073364073765007918'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2009/11/handling-extensionless-uris-in-webforms.html' title='Handling Extensionless URIs in a WebForms Application'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-7818713989858341847</id><published>2009-11-16T11:03:00.000-08:00</published><updated>2009-11-16T11:26:07.848-08:00</updated><title type='text'>Getting the SQL (and other goodness) from a running transaction</title><content type='html'>I had run a bunch of SQL scripts against a SQL Server database during a deployment.  All tests after the updates checked out.  I went to close SSMS and got the message, "&lt;span style="font-style: italic;"&gt;There are uncommitted transactions. Do you wish to commit these transactions before closing the window&lt;/span&gt;"?&lt;br /&gt;&lt;br /&gt;WTF?  How could I have failed to commit a transaction yet testing all checked out?  Well that's a mystery I haven't yet figured out, but I did &lt;a href="http://searchsqlserver.techtarget.com/tip/0,289483,sid87_gci1356579,00.html"&gt;find&lt;/a&gt; a good query (that I had to alter somewhat to make work) for getting the text of the command that had not yet been committed:&lt;br /&gt;&lt;p style="font-family: Courier; font-size: 7pt;"&gt;&lt;br /&gt;SELECT&lt;br /&gt;&amp;nbsp;&amp;nbsp;st.Session_id, req.Blocking_Session_ID [Blocker], req.Wait_Type,&lt;br /&gt;&amp;nbsp;&amp;nbsp;req.Wait_Time [WaitTimeMS], req.Wait_Resource, req.open_transaction_count,&lt;br /&gt;&amp;nbsp;&amp;nbsp;req.percent_complete, dt.transaction_id, dt.database_transaction_begin_time,&lt;br /&gt;&amp;nbsp;&amp;nbsp;case  when dt.database_transaction_type = 1 then 'RW'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;when dt.database_transaction_type = 2 then 'R'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;when dt.database_transaction_type = 3 then 'Sys'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else 'Unknown'&lt;br /&gt;end [TranType],&lt;br /&gt;&amp;nbsp;&amp;nbsp;case  when dt.database_transaction_state = 1 then 'Not Initialized'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;when dt.database_transaction_state = 3 then 'Initialized, but no logs'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;when dt.database_transaction_state = 4 then 'Generated logs'&lt;br /&gt;&amp;nbsp;&amp;nbsp;when dt.database_transaction_state = 5 then 'Prepared'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;when dt.database_transaction_state = 10 then 'Committed'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;when dt.database_transaction_state = 11 then 'Rolled Back'&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;when dt.database_transaction_state = 12 then 'In process of committing'&lt;br /&gt;&amp;nbsp;&amp;nbsp;else 'Unknown'&lt;br /&gt;end [TranState],&lt;br /&gt;&amp;nbsp;&amp;nbsp;req.Status, req.Command, stxt.objectid [ExecObjID],&lt;br /&gt;(SUBSTRING(stxt.text, req.statement_start_offset/2,( CASE  WHEN req.statement_end_offset = -1 then LEN(CONVERT(nvarchar(max), stxt. text)) * 2&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ELSE req.statement_end_offset&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;end -req.statement_start_offset)/2)) [SubText],&lt;br /&gt;&amp;nbsp;&amp;nbsp;stxt.text, req.statement_start_offset&lt;br /&gt;FROM&lt;br /&gt;&amp;nbsp;&amp;nbsp;sys.dm_tran_database_transactions dt (nolock)&lt;br /&gt;&amp;nbsp;&amp;nbsp;inner join sys.dm_tran_session_transactions st (nolock) on dt.transaction_id = st.transaction_id&lt;br /&gt;&amp;nbsp;&amp;nbsp;inner join sys.dm_exec_requests req (nolock) on st.transaction_id = req.transaction_id&lt;br /&gt;&amp;nbsp;&amp;nbsp;CROSS APPLY sys.dm_exec_sql_text(req.sql_handle) [stxt]&lt;br /&gt;where&lt;br /&gt;&amp;nbsp;&amp;nbsp;dt.database_id = db_id() and st.is_user_transaction = 1&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;This query wouldn't work in my situation (would barf "Incorrect syntax near '.'" at the second to last dot), but it will work on a database with compatibility level 90 or better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-7818713989858341847?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/7818713989858341847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=7818713989858341847' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/7818713989858341847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/7818713989858341847'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2009/11/getting-sql-and-other-goodness-from.html' title='Getting the SQL (and other goodness) from a running transaction'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-4659636570652932058</id><published>2009-10-09T11:13:00.000-07:00</published><updated>2009-10-09T11:30:20.109-07:00</updated><title type='text'>IE8 Text Alignment Bug</title><content type='html'>Below demonstrates a bug in the current version of IE8 (8.0.6001.18702).  Two duplicate tables one on top of the other, but the text is not aligning correctly in the second (text-align:left is ignored).  This is admittedly an edge case since it only seems to happen with an image in the th element, and the image must apparently be of certain dimensions.&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;   &lt;tbody&gt;&lt;tr&gt;&lt;br /&gt;       &lt;th colspan="2"&gt;&lt;br /&gt;           &lt;!--550 X 100 image--&gt;&lt;br /&gt;          &lt;img src="http://4.bp.blogspot.com/_UTutUl_JPes/Ss9-OBCW31I/AAAAAAAAABY/U8Mu1uq3rIo/s400/whatever.bmp" alt="" /&gt;&lt;br /&gt;       &lt;/th&gt;&lt;br /&gt;   &lt;/tr&gt;&lt;br /&gt;   &lt;tr&gt;&lt;br /&gt;       &lt;td style="width: 3%; text-align: left;"&gt;36&lt;/td&gt;&lt;br /&gt;       &lt;td style="width: 97%; text-align: left;"&gt;&lt;br /&gt;           This sentence should left align with bob below.&lt;br /&gt;       &lt;/td&gt;&lt;br /&gt;   &lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;   &lt;tbody&gt;&lt;tr&gt;&lt;br /&gt;       &lt;th colspan="2"&gt;&lt;br /&gt;           &lt;img src="http://4.bp.blogspot.com/_UTutUl_JPes/Ss9-OBCW31I/AAAAAAAAABY/U8Mu1uq3rIo/s400/whatever.bmp" alt="" /&gt;&lt;br /&gt;       &lt;/th&gt;&lt;br /&gt;   &lt;/tr&gt;&lt;br /&gt;   &lt;tr&gt;&lt;br /&gt;       &lt;td style="width: 3%; text-align: left;"&gt;41&lt;/td&gt;&lt;br /&gt;       &lt;td style="width: 97%; text-align: left;"&gt;&lt;br /&gt;           bob&lt;br /&gt;       &lt;/td&gt;&lt;br /&gt;   &lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-4659636570652932058?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/4659636570652932058/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=4659636570652932058' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/4659636570652932058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/4659636570652932058'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2009/10/ie8-text-alignment-bug.html' title='IE8 Text Alignment Bug'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_UTutUl_JPes/Ss9-OBCW31I/AAAAAAAAABY/U8Mu1uq3rIo/s72-c/whatever.bmp' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-9195022168120322534</id><published>2009-09-30T08:06:00.000-07:00</published><updated>2009-10-05T07:21:44.381-07:00</updated><title type='text'>F# Forward composition operator</title><content type='html'>&lt;span style="font-size:85%;"&gt;I was trying to understand the difference between the plain pipe operator (|&gt;) and the forward composition operator (&gt;&gt;) in F# when &lt;a href="http://cs.hubfs.net/forums/post/9541.aspx"&gt;the F# forum&lt;/a&gt; pointed me to &lt;a href="http://blogs.msdn.com/chrsmith/archive/2008/06/14/function-composition.aspx"&gt;this blog post&lt;/a&gt;.  After reading the blog post, I still didn't quite understand.  I distilled it down to perhaps the simplest possible sample which I think is much easier to understand what it does and why:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;let squares wrist =&lt;br /&gt;List.map (fun x -&gt; x*x) wrist&lt;br /&gt;&lt;br /&gt;let sum wrist =&lt;br /&gt;List.fold (+) 0 wrist&lt;br /&gt;&lt;br /&gt;// Forward composition operator&lt;br /&gt;// don't need to declare any value: it's implied.&lt;br /&gt;let functionComp = squares &gt;&gt; sum&lt;br /&gt;&lt;br /&gt;// Equivalent function as above using pipe operator.&lt;br /&gt;// Note how above is more terse&lt;br /&gt;let pipage wrist =  wrist |&gt; squares |&gt; sum&lt;br /&gt;&lt;br /&gt;let wrist = [1;2;3]&lt;br /&gt;&lt;br /&gt;// results are the same&lt;br /&gt;let fc = functionComp wrist&lt;br /&gt;let p = pipage wrist&lt;br /&gt;&lt;/code&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-9195022168120322534?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/9195022168120322534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=9195022168120322534' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/9195022168120322534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/9195022168120322534'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2009/09/f-forward-composition-operator.html' title='F# Forward composition operator'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-5252435172207626907</id><published>2009-06-19T09:36:00.000-07:00</published><updated>2009-06-22T06:42:38.353-07:00</updated><title type='text'>The Question for .Net Web Developers</title><content type='html'>Here's what I think is the most important question right now for the .Net developer considering new applications.   It may be invalid, but here goes:&lt;br /&gt;&lt;br /&gt;Silverlight, or MVC?&lt;br /&gt;&lt;br /&gt;To me, silverlight turns the browser into a desktop application; when I worked on silverlight, I no longer thought about GET/POST whatsoever.  Yes, I still get data from services, but I'm almost completely unaware of HTTP.  Moreover, it seemed to lend itself to very clean applications from a pure OO perspective; same exact OO style on client and server.&lt;br /&gt;&lt;br /&gt;With MVC, I'm thinking GET/POST over HTTP all the while.   I'm getting back to basics in that regard (stepping back to the way things were before MS took desktop development and jammed it into the Internet with WebForms).&lt;br /&gt;&lt;br /&gt;IMO, blending silverlight with MVC is a bastardization (don't take it personally if you're doing it).  URLs need only have meaning in silverlight applications as a shortcut to start your application.  In any case, I consider WebForms legacy for non-trivial applications.  Still very useful when needed, but legacy.&lt;br /&gt;&lt;br /&gt;So this is my question for today's .Net developer: "&lt;span style="font-style: italic;"&gt;should we think about our new application like we did with desktop apps, or should we consider it RESTful?&lt;/span&gt;"  Obviously, there are myriad other considerations; I just think this may be the most pertinent.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-5252435172207626907?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/5252435172207626907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=5252435172207626907' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/5252435172207626907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/5252435172207626907'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2009/06/question-for-net-web-developers.html' title='The Question for .Net Web Developers'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-4160262400411343158</id><published>2009-04-15T12:17:00.000-07:00</published><updated>2009-04-15T14:11:32.398-07:00</updated><title type='text'>Workaround for changes to DataSet.Merge</title><content type='html'>We have a formerly open source system (nSurvey) running in production.  None of us know too much about it, but we had to learn a little something when we recently upgraded a parent site to (finally) run against .Net framework 2.0.  We tried to set the nSurvey site (which had to be a child site) to use framework 1.1 which is possible depending on what you have in the web.config of the parent site (parent as in parent in IIS).  In our case, it had AJAX entries which have attributes causes framework 1.1 to blow up.  As such we had to upgrade the nSurvey project to Visual Studio 2005 (framework 2.0).&lt;br /&gt;&lt;br /&gt;DataSet.Merge changed between .Net frameworks 1.1 and 2.0 when DataSets have namespaces causing the merge to fail.  There is a workaround, but &lt;a href="const%20string%20doc%20=%20@%22%3C?xml%20version=%22%221.0%22%22%20?%3E%3CRECS%20xmlns=%22%22http://deltek.vision.com/XMLSchema%22%22%20xmlns:xdv=%22%22http://deltek.vision.com/XMLSchema%22%22%20xmlns:xsi=%22%22http://www.w3.org/2001/XMLSchema-instance%22%22%3E%3CREC%3E%3CActivity%20keys=%22%22ActivityID%22%22%20name=%22%22Activity%22%22%20alias=%22%22Activity%22%22%20codeTableColVal=%22%22code%22%22%3E%3CROW%20tranType=%22%22INSERT%22%22%3E%3CActivityID%3E@Generate%3C/ActivityID%3E%3CClientID%20/%3E%3CContactID%3E%7B0%7D%3C/ContactID%3E%20%3CEmployee%3E%7B1%7D%3C/Employee%3E%20%3CType%3EEmail%3C/Type%3E%20%3CSubject%3ESafeMail%3C/Subject%3E%3CStartDate%3E%7B2%7D%3C/StartDate%3E%20%3CEndDate%20/%3E%3CReminderInd%3EN%3C/ReminderInd%3E%20%3CPriority%3EMedium%3C/Priority%3E%20%3CNotes%3E%7B3%7D%3C/Notes%3E%3CCompletionInd%3EN%3C/CompletionInd%3E%20%3CRecurrDailyFreq%3E1%3C/RecurrDailyFreq%3E%20%3CRecurrDailyWeekDay%3EN%3C/RecurrDailyWeekDay%3E%20%3CRecurrWeeklyFreq%3E1%3C/RecurrWeeklyFreq%3E%20%3CRecurrMonthlyFreq%3E1%3C/RecurrMonthlyFreq%3E%20%3CRecurrEndType%3EN%3C/RecurrEndType%3E%20%3CRecurrMonthlyOccurFreq%3E1%3C/RecurrMonthlyOccurFreq%3E%20%3C/ROW%3E%3C/Activity%3E%3CContactActivity%20keys=%22%22ActivityID,ContactID%22%22%20name=%22%22ContactActivity%22%22%20alias=%22%22ContactActivity%22%22%20codeTableColVal=%22%22code%22%22%3E%3CROW%20tranType=%22%22INSERT%22%22%3E%3CActivityID%3E@Generate%3C/ActivityID%3E%20%3CContactID%3E%7B0%7D%3C/ContactID%3E%20%3CPrimaryInd%3EY%3C/PrimaryInd%3E%20%3C/ROW%3E%3C/ContactActivity%3E%3C/REC%3E%3C/RECS%3E%22;"&gt;the place where it's described on MS docs&lt;/a&gt; is totally freaking hosed and makes no sense.&lt;br /&gt;&lt;br /&gt;Here is what we did which works fine for us (we're not about to go making big changes in this monster of a system):&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;            string cachedNamespace = dataSet1.Namespace;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;            dataSet1.Namespace = string.Empty;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;            string cachedNamespaceChild = dataSet2.Namespace;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;            answerDataSet.Namespace = string.Empty;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;            dataSet1.Merge( dataSet2 );&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;            dataSet1.Namespace = cachedNamespace;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;            dataSet2.Namespace = cachedNamespaceChild;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-4160262400411343158?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/4160262400411343158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=4160262400411343158' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/4160262400411343158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/4160262400411343158'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2009/04/workaround-for-changes-to-datasetmerge.html' title='Workaround for changes to DataSet.Merge'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-3622311666107842898</id><published>2009-02-11T11:01:00.000-08:00</published><updated>2009-02-11T11:23:02.596-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='&quot;Visual Studio Tools for Office&quot;'/><title type='text'>A Functional Deployment Template</title><content type='html'>&lt;span style="font-size:85%;"&gt;We had been using Excel spreadsheets to build out our deployment plans.  The biggest chunk of the plan was usually all the database scripts (I prefer listing them separately for better troubleshooting if one fails).  Perhaps there is a better way to deploy database changes (SQL Server), but I'm not aware of it.&lt;br /&gt;Anyhow, spreadsheets were not up to the task for a couple reasons:&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;We wanted to be able to have plain written documentation (paragraphs) in addition to some kind of "steps" checklist (we needed to start making complete deployment documents).   It's &lt;span style="font-style: italic;"&gt;possible&lt;/span&gt; to to this in Excel, but certainly not optimal.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Editing large scripts in Excel cells can prove clunky.   A line length limit makes it nearly impossible (if you try to paste in a script with a line too long nothing happens - no error and no pastey) to edit some large scripts.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:85%;"&gt;We thought about several possible tools, but what we really wanted was a Word template with some tables in it (for steps).   But one of the columns of the table needed to have a button (or something) that would pop up a separate editing window for editing the scripts.  The edited script would then "collapse" back into it's cell (basically like an Excel cell but with a better mechanism for editing large scripts).&lt;br /&gt;&lt;br /&gt;I searched for a fair amount of time and came up with absolutely nothing.  I did find a few deployment templates, but nothing with any functionality to them.   So I went ahead and implemented such a beast using VSTO over a Word template.   Perhaps someone will stumble upon this and find it useful.   Implementing it was more challenging than one might think.   Just like anything else, if you're not very familiar with VSTO, even small things are going to be difficult, but dynamically creating and persisting WinForms controls is actually sorta tricky.&lt;br /&gt;&lt;br /&gt;Anyway, here's what it looks like:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_UTutUl_JPes/SZMkF2vBx8I/AAAAAAAAABQ/aFtutREWf-Y/s1600-h/DeploymentTemplate.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 274px;" src="http://2.bp.blogspot.com/_UTutUl_JPes/SZMkF2vBx8I/AAAAAAAAABQ/aFtutREWf-Y/s320/DeploymentTemplate.PNG" alt="" id="BLOGGER_PHOTO_ID_5301620869355915202" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-3622311666107842898?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/3622311666107842898/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=3622311666107842898' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/3622311666107842898'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/3622311666107842898'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2009/02/functional-deployment-template.html' title='A Functional Deployment Template'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_UTutUl_JPes/SZMkF2vBx8I/AAAAAAAAABQ/aFtutREWf-Y/s72-c/DeploymentTemplate.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-4238131017464099894</id><published>2009-02-05T17:03:00.000-08:00</published><updated>2009-02-05T17:15:41.518-08:00</updated><title type='text'>Stranahan's Colorado Whiskey [off topic]</title><content type='html'>I was going to put this in an email, but I figured, what the heck.  Maybe some whiskey connoisseur will find it.&lt;br /&gt;&lt;br /&gt;I have gift cards from Christmas, and I keep going back to Tipsy's (the mega-liquor-store near my house) to attempt to get some Leopold's (whose &lt;a href="http://www.leopoldbros.com/Whiskeys.html" target="_blank"&gt;flavored whiskeys&lt;/a&gt; are still awesome) but they never have it - Leopold's production is low and demand high.  So I asked an employee if I could get a rain-check or something.  He asked if I wanted Stranahan's explaining that some just came in but it's going fast.  He directed me to the front desk where I asked for a little form to place a request and the next employee said, "for Stranahan's?"  Then a customer came up with a bottle of &lt;a href="http://www.stranahans.com/index.php?q=home" target="_blank"&gt;Stranahan's Colorado Whiskey&lt;/a&gt;.  The manager and customer started raving about it.  I asked them what it compares to, and they couldn't tell me.  The manager said, "it tastes like something that costs way, way more."  I said, "it already costs $60."  He just said, "I know" and then said you can't believe how good it is.  The customer said he'd open it and let me try if he could.&lt;br /&gt;&lt;br /&gt;So I figured what the heck, I got a gift card, I'll try some.  They were right.  I've never had 250 y/o whiskey, but I'd imagine it tastes something like this stuff.  Toward the middle of my glass I swear there was no burn on the tongue whatsoever.  And it doesn't compare with anything (the first sip tasted completely foreign).  It just tastes... clean and fresh.  It's amazing.  Apparently, there's much more to making smooth whiskey than age.&lt;br /&gt;&lt;br /&gt;IMO this stuff is like the next level.  Nothing I've had is anything close to as good.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-4238131017464099894?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/4238131017464099894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=4238131017464099894' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/4238131017464099894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/4238131017464099894'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2009/02/stranahans-colorado-whiskey-off-topic.html' title='Stranahan&apos;s Colorado Whiskey [off topic]'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-5468113959369958698</id><published>2009-01-30T21:10:00.001-08:00</published><updated>2009-02-03T20:18:34.541-08:00</updated><title type='text'>Silverlight the Right Choice for Web Applications</title><content type='html'>I've written about how I think that &lt;a href="http://codejournal.blogspot.com/2008/02/web-programming-is-hack-part-deux.html"&gt;web applications are a hack&lt;/a&gt;.  In that post I didn't think Silverlight was fully the answer, but at this point I think it's the best alternative.&lt;br /&gt;&lt;br /&gt;I couldn't be more strongly in favor of using Silverlight for web &lt;span style="font-style: italic;"&gt;applications&lt;/span&gt; (as opposed to web sites which only provide content) wherever possible.  Of course even content can be a good use of Silverlight as the NYT reader shows.  If an MS shop's target audience doesn't include IT goons who somehow put Silverlight in a different category than Acrobat Reader, I don't think you have any other choice for new applications.&lt;br /&gt;&lt;br /&gt;My coworkers are spending many hours trying to make one AJAX codebase work on different browsers.  After awhile it just gets demoralizing (and my employer is wasting tons of maintenance time).  My mind is boggled by all the hackage necessary to make AJAX popup "windows" drag/drop via HTML (sure Javascript makes it happen, but it's still just HTML).  With Silverlight you're working on a &lt;span style="font-style: italic;"&gt;platform&lt;/span&gt; designed for this kind of thing.  It's designed for dragging and dropping and animations and all the other things needed for applications (not to mention streaming).&lt;br /&gt;&lt;br /&gt;Yes, you can make all those things happen with Javascript, and I fully understand the power of functional languages, but who would rather maintain a line of business application written in Javascript in favor of C#?  Not to mention the aforementioned ever growing browser compatibility issues.&lt;br /&gt;&lt;br /&gt;How do loosely typed Javascript objects compare with full featured Silverlight controls with UI and logic contained in one distinct entity combined with design time configuration?  Not very well on the maintainability scale.&lt;br /&gt;&lt;br /&gt;That's how I cast my vote, anyway.  Long live Silverlight.  I doubt it will be a technology that fades away, but I hope it's user base grows and it continues to stay healthy in the future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-5468113959369958698?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/5468113959369958698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=5468113959369958698' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/5468113959369958698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/5468113959369958698'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2009/01/ive-written-about-how-i-think-that-web.html' title='Silverlight the Right Choice for Web Applications'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-3577458373321107749</id><published>2009-01-30T07:24:00.000-08:00</published><updated>2009-01-30T07:55:29.419-08:00</updated><title type='text'>SSIS Gotchas</title><content type='html'>&lt;span style="font-size:85%;"&gt;SQL Server Integration Services is very finicky (read “gives indecipherable errors and will make your life miserable”). I wrote some packages using VS2008 / SQL Server 2008. Following is a list of gotchas I ran across. Note that there’s no frigging way you can figure any of these out from the error messages alone:&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Restoring a database renders connections in packages unusable (even though everything looks good and testing the connection is fine). Thus, every time you restore a database that a package is pointing to (which I was doing repeatedly during testing), you must go into the package, add a new connection from a data source (by right clicking in the connection manager area of each package) and add in the same source that’s already being used (giving it a different name). Then you must go into each task item in the package and point to the new connection. If that task had mappings (as from a flat file to a table), you must re-map everything. Enjoy!&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;If you’re executing a package from .Net code, only the .Net connection types will run.&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;There are 3 different forms of essentially the same connection type: “Native OLE DB”, “.Net providers for OleDb”, and “.Net Providers”&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;The “.Net Providers” didn’t seem to work at all; the “Native OLE DB” providers would not execute when attempting to run the packages from a web page on a different server; both the “Native OLE DB” and “.Net providers for OleDb” worked from my local machine.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;It seems the proper choice for calling packages from code is “.Net providers for OleDb”.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;The “.Net providers for OleDb” will not execute from code directly from within visual studio (i.e., you can’t right click on the package and click execute) so you can't debug directly.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;The .Net connections ignore their timeout property. They simply won't work when running a long query.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Enjoy!&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;You can't include a package that deals with a table that doesn't yet exist.&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;So you can’t have a package that refers to a table that hasn’t yet been created. The package will give errors all over the place. So, for instance (IIRC), you can’t deploy a package that refers to a table that will be created by another package b/c it won’t validate on deployment.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Deployment of packages is a nightmare. There are myriad issues surrounding the demonic property of packages, “ProtectionLevel”.&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Under most circumstances, you would want to make your connection string properties configurable at the server. That way, you can move the packages around or point them to different servers w/o having to redeploy them. In my case, I had no end of problems with this (and the packages need only run annually) so I just deployed and ran this way:&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;For deployment, I would just do file | Save copy of [package] as and copy the package to the server running integration services. This would just embed the connection settings and not rely on any package configuration files. Then, for executing the packages from code, I would just refer to the server I copied the packages to.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;At one point, I had a package that had a bad path in one of its connection’s properties. This seemed to prevent all packages from working.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;Most destructive&lt;/span&gt;: Changing the connections and re-deploying (as described above) doesn't overwrite the connections. So I changed the connections from production back to QA, verified everything multiple times, redeployed (which prompts for confirmation whether I want to overwrite the existing packages), and ran a package. Much to my surprise &amp;amp; chagrin, the package executed against production! In this case, the existing packages must be deleted. In Reporting Services, there is some “overwrite data sources” property, but I couldn’t find this in SSIS.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;Another disturbing issue&lt;/span&gt;: packages run where they’re called from. If, in code, you execute some SQL against a particular server, that SQL will execute on the server. Confusingly (b/c I was importing and exporting data), when you execute a package, it executes on the machine where it was called, not on the server where the package exists!&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Warnings on package objects show up all over the place. There's no figuring out why they don't consistently work. E.G., login failure when there is nothing wrong with the connection. I think setting the property “BypassPrepare” to true helped.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Unlike the predecessor technology, DTS, there is no way to switch a connection vis-a-vis data flow objects w/o losing mappings. Enjoy!&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Names of all new packages are Package1 – you must rename them and delete file Package1 manually.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;If you have an extra line break at the end of a script task, it crashes. You can copy/paste that script into management studio and it will work fine.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Closing / reopening the project sometimes causes connection references from tasks to be lost.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;Yet another disturbing issue&lt;/span&gt;: I was not able to get it down to a reproducible set of steps, but the project was reverting my script changes. I found that I had to check my script changes into sourcesafe immediately after saving every time (I suspect that the reverting took place somewhere in deploying).&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:85%;"&gt;The fun part is that you can’t compare versions of packages in sourcesafe b/c a simple change to a script task changes all sorts of stuff in the dtsx file.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-3577458373321107749?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/3577458373321107749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=3577458373321107749' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/3577458373321107749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/3577458373321107749'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2009/01/ssis-gotchas.html' title='SSIS Gotchas'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-1049643191007148868</id><published>2009-01-08T07:23:00.000-08:00</published><updated>2009-01-08T07:45:11.704-08:00</updated><title type='text'>Best way to get record count using ADO.Net?</title><content type='html'>I think this may apply to the entity framework, but I'm not sure.&lt;br /&gt;&lt;br /&gt;I was modifying a stored procedure which needed to run a query and also return the row count of that query.  So the same (fairly long) query was pasted again using &lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;select count&lt;/span&gt;&lt;/span&gt; instead of &lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;select &lt;/span&gt;&lt;/span&gt;by which it set the value of an out parameter.  I didn't like this for a few reasons:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Dual maintenance of the query.&lt;/li&gt;&lt;li&gt;The stored procedure is twice as long.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Inefficiency of calling the query twice.  The count is already known by SqlServer after running the first query.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Having another parameter to configure and hard-code the name of in the calling code.&lt;/li&gt;&lt;/ul&gt;At first I was thinking that the count of any query is explicitly returned to any ADO call (unless the stored procedure includes "&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;set nocount on&lt;/span&gt;&lt;/span&gt;").  The count I'm thinking of is the count of records affected that shows in SqlServer's management studio after running any query (N row(s) affected).  Rows &lt;span style="font-style: italic;"&gt;affected&lt;/span&gt; in this case includes rows merely &lt;span style="font-style: italic;"&gt;selected&lt;/span&gt;.&lt;br /&gt;So I looked at the properties of the SqlDataReader.  It has a "RecordsAffected" property.  Sounds a lot like "rows affected" no?  Well, in order to get that count you must iterate through all the rows in the reader and close it.  Obviously, not what I'm looking for.&lt;br /&gt;&lt;br /&gt;Next I looked at the SqlCommand object.  When you call ExecuteNonQuery, you get records affected!  Cool, must be what I'm looking for.  Nope - when this object says "records &lt;span style="font-style: italic;"&gt;affected&lt;/span&gt;" it means just that (unlike what SqlServer means by "rows affected").  It will only return the count of rows updated, deleted, inserted.&lt;br /&gt;&lt;br /&gt;So what seems to be the best way is to include a secondary recordset in the stored procedure: "&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;select @@rowcount&lt;/span&gt;&lt;/span&gt;."  My coworker verified that this count is connection specific (you don't get someone else's count).  It's the count that management studio displays.&lt;br /&gt;Accessing this count from a reader goes like yay:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;span style="font-size:85%;"&gt;            _reader.NextResult();&lt;br /&gt;            _reader.Read();&lt;br /&gt;            _reader[0];&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The call to NextResult advances the reader to the next result set (the set that only includes the result of "&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;select @@rowcount&lt;/span&gt;&lt;/span&gt;").  We know that result set contains only the count so we don't need any explicit column names.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-1049643191007148868?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/1049643191007148868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=1049643191007148868' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/1049643191007148868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/1049643191007148868'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2009/01/best-way-to-get-record-count-using.html' title='Best way to get record count using ADO.Net?'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-6149114726224361532</id><published>2008-08-12T06:35:00.000-07:00</published><updated>2008-08-12T07:38:36.838-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='showPopup'/><category scheme='http://www.blogger.com/atom/ns#' term='PopupControlExtender'/><category scheme='http://www.blogger.com/atom/ns#' term='User Control'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='Repeater'/><title type='text'>ASP.Net Ajax PopupControlExtender gotchas</title><content type='html'>I recently completed a user control that included a PopupControlExtender which was used in repeater on the user control's host page.  I'm using the version of ajax that ships with visual studio 2008 (pre sp1).  I came across several gotchas:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Technically, the first gotcha is that my user control cannot include a ScriptManager since there can only be one per page, and since the user control is repeated many could be created.  Thus, the host page must own the ScriptManager effectively rendering my user control with my PopupControlExtender non-self containing.  I think this is a clumsy limitation of the current state of ajax.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The second gotcha applies regardless of the fact that there are more than one instance of the PopupControlExtender on the page: I don't want the object that pops up to be triggered when the referenced TargetControlID control receives focus (I can hardly imagine a scenario when someone would want this), I want it to pop up on a button click.  Thus, I must pop it up manually.  But when I do so, I must know (or learn by trial and error) that the client framework captures page events and &lt;span style="font-style: italic;"&gt;hides&lt;/span&gt; my popup (so when you click on other controls outside your popup it closes).  My pop function must look like the following.  Without "event.cancelBubble" my popup won't pop up.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;function pop(popExtenderID)&lt;br /&gt;  {&lt;br /&gt;      event.cancelBubble = true;&lt;br /&gt;      var popExtender = $find(popExtenderID);&lt;br /&gt;      // this one is the next gotcha&lt;br /&gt;      popExtender.set_OffsetY(popExtender.get_OffsetY() + document.body.scrollTop);&lt;br /&gt;      popExtender.showPopup();&lt;br /&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;This next one is also irrespective of the fact that my control is in a repeater.  The PopupControlExtender doesn't seem to account for scroll position.  Thus the call to set_OffsetY in the snippet above.  Even so, sometimes the position of the popup will be at the very top of the page.  I haven't been able to figure out why it doesn't always work; it doesn't seem to be consistent.&lt;/li&gt;&lt;li&gt;This one is certainly repeater related.  The function above takes as a parameter the ID of a PopupControlExtender.  If there are more than one, we have to accept the right one (the function is part of my user control so it will be repeated causing only the last one written to be the function that is used for all of my popups).   So in the code behind of my user control, I had to add the following in order to pass in the "current" extender.  Note that I had to ensure that the BehaviourID of the extender was unique.  The replace call is to make the ID conformable to HTML rules.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;      var ExtenderBehaviourID = '_' + Guid.NewGuid().ToString().Replace( '-', '_' );&lt;br /&gt;    this.PopupControlExtender1.BehaviorID = ExtenderBehaviourID;&lt;br /&gt;    this.btnPop.Attributes.Add( "onclick", "pop('" + ExtenderBehaviourID + "');" );&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;This one was caused by the fact that I wrapped the controls within my pop up in an UpdatePanel because they made server postbacks.  The code in the snippet above should only run when the host page loads or posts back, &lt;span style="font-style: italic;"&gt;but not when my user control posts back&lt;/span&gt;.  What I had is a search edit box/button and a GridView within my popup.  The search button causes a postback and so does paging on the grid.  Within these postbacks, I don't want my extender to receive a new unique id because if it does the javascript back on the page will receive the wrong ID - why I can't quite remember - I have a function that closes the popup.   In this case "this.IsPostback" doesn't work (nor does this.Parent.IsPostback which maps to the same result) because this would represent the host page's postback.  My &lt;span style="text-decoration: line-through;"&gt;hack&lt;/span&gt; elegant solution to this problem was to examine the BehaviourID of the PopupControlExtender.   By default, that BehaviourID would contain the ID of the PopupControlExtender itself.  If it is a postback of my control, I would've already changed that BehaviourID to be something like a guid (from the snippet above).   So here's the condition:&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;   private bool IsPostBackThisControl()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   return !this.PopupControlExtender1.BehaviorID.Contains(PopupControlExtender1.ID);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-6149114726224361532?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/6149114726224361532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=6149114726224361532' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/6149114726224361532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/6149114726224361532'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2008/08/aspnet-ajax-popupcontrolextender.html' title='ASP.Net Ajax PopupControlExtender gotchas'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-5994965068359162861</id><published>2008-07-08T12:16:00.000-07:00</published><updated>2008-07-08T13:59:04.198-07:00</updated><title type='text'>Business Vs. Technical Validated</title><content type='html'>My &lt;a href="http://codejournal.blogspot.com/2007/05/business-vs-technical.html"&gt;previous post&lt;/a&gt; which posited that the old yarn that &lt;span style="font-style: italic;"&gt;knowing the business domain is a more important skill for the programmer to improve than programming-specific skills&lt;/span&gt; is bunk has been partially validated by Joel Spolsky in &lt;a href="http://blog.stackoverflow.com/2008/05/podcast-7/"&gt;this podcast&lt;/a&gt;.&lt;br /&gt;In it, Jeff Atwood holds the opposing position, but Spolsky's comments were spot on.  He did some significant work on a medical application w/o caring a whit about the medical field.  I maintained an application which illustrated annuity performance w/o much caring about the specifics of annuities.&lt;br /&gt;I just cannot understand Jeff's position.  The specifics of how a given business works is brain filling fluff whereas programming related knowledge is a programmer's bread and butter.&lt;br /&gt;I'm currently working on software which supports educational institutions, but learning more about educational institutions is &lt;span style="font-style: italic;"&gt;never&lt;/span&gt; germane to making our software better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-5994965068359162861?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/5994965068359162861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=5994965068359162861' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/5994965068359162861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/5994965068359162861'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2008/07/business-vs-technical-validated.html' title='Business Vs. Technical Validated'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-7317409100131426256</id><published>2008-06-06T11:34:00.000-07:00</published><updated>2008-06-10T08:30:05.035-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='silverlight bar chart graph wizard'/><title type='text'>Silverlight Bar Chart and Wizard Samples</title><content type='html'>I spent some time on some silverlight samples, so I thought I'd make them available to the world.    Someone may find them useful as a starting point or just a learning exercise.  These are done with VS2008 and silverlight 2.0 beta 1.  They are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A silverlight bar chart / graph application.&lt;/li&gt;&lt;li&gt;A silverlight wizard.&lt;/li&gt;&lt;/ul&gt;&lt;a href="http://www.puretolerance.com/ChartProject.zip"&gt;&lt;span style="font-weight: bold;"&gt;Bar Chart&lt;/span&gt;&lt;/a&gt;:  The bar itself was stolen then modified from &lt;a href="http://www.codeproject.com/KB/silverlight/PathToReusableXAML.aspx"&gt;here&lt;/a&gt;.   Note if you download it that clicking on the service button won't work, just the update from HTML.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_UTutUl_JPes/SEmGiGQ0CEI/AAAAAAAAAAQ/AWk3iSFWEhs/s1600-h/BarChart.JPG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; cursor: pointer;" src="http://bp3.blogger.com/_UTutUl_JPes/SEmGiGQ0CEI/AAAAAAAAAAQ/AWk3iSFWEhs/s320/BarChart.JPG" alt="" id="BLOGGER_PHOTO_ID_5208842364385495106" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.puretolerance.com/Wizard.zip"&gt;&lt;span style="font-weight: bold;"&gt;Wizard&lt;/span&gt;&lt;/a&gt;:  This was created by &lt;a href="http://csharpconsultant.net/"&gt;this guy&lt;/a&gt;.  When I downloaded it, it didn't work.  Note that the arrows are actually images (which probably shouldn't be used as long as you have XAML).  It is a good model, though.  The whole wizard is one control, all the data is in one thing, no postbacks and the next/back is just a smooth animation.  It makes a wizard a very easy, clean thing.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_UTutUl_JPes/SEmHwmQ0CFI/AAAAAAAAAAY/htRu0lGh1FA/s1600-h/Wizard.JPG"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; cursor: pointer;" src="http://bp1.blogger.com/_UTutUl_JPes/SEmHwmQ0CFI/AAAAAAAAAAY/htRu0lGh1FA/s320/Wizard.JPG" alt="" id="BLOGGER_PHOTO_ID_5208843713005226066" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-7317409100131426256?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/7317409100131426256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=7317409100131426256' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/7317409100131426256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/7317409100131426256'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2008/06/silverlight-bar-chart-and-wizard.html' title='Silverlight Bar Chart and Wizard Samples'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_UTutUl_JPes/SEmGiGQ0CEI/AAAAAAAAAAQ/AWk3iSFWEhs/s72-c/BarChart.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-2183486698618234148</id><published>2008-02-27T07:49:00.000-08:00</published><updated>2008-06-17T14:49:46.834-07:00</updated><title type='text'>Web Programming is a Hack, Part Deux</title><content type='html'>Our current app displays again why web programming is a just a hack.  It's sort of a wizard approach - it has an intro, many steps, and a conclusion.  To get to the next step of the wizard, the user clicks our "next" button.  We also have a "back" button, but then a browser also has one of those thingies.    Any developer or casual browser user knows where I'm going with this.   "Back" and "Next" are for &lt;span style="font-style: italic;"&gt;hyperlinked documents&lt;/span&gt;, not &lt;span style="font-style: italic;"&gt;applications&lt;/span&gt;.&lt;br /&gt;It's just so fundamental.  We're sitting here debugging a problem that happens when the user mixes the browser's "back" with our "next".  We're tempted to yell at users, "don't click that button", but it makes perfect sense for them to do so.  The problem is that &lt;span style="font-style: italic;"&gt;web apps are hacks&lt;/span&gt;.  Browsers don't make good platforms.&lt;br /&gt;Of course, we fixed the "bug" (by "fixed the bug" I mean "made a better hack"), but the overarching hack remains.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;It sure seems to me that there needs to be something new for applications.  Browsers work great for HTML, but why isn't there something else (just as ubiquitous and standardized) for applications?  It seems like &lt;a href="http://www.infoq.com/articles/rest-introduction"&gt;RESTful apps&lt;/a&gt; are much less hacky than web applications, but not quite there.  Plug-ins like flash and silverlight embed applications in the browser, and while I know nothing about actionscript, silverlight can make for a full fledged clean application.   AJAX, hell no, but application plug-ins maybe.   But these plug-ins are always mixed with HTML...&lt;br /&gt;It may be that the hack will continue for a &lt;span style="font-style: italic;"&gt;very&lt;/span&gt; long time simply due to the fact that people keep making ever more hacks at an increasing rate.&lt;br /&gt;&lt;br /&gt;Hack on, I suppose.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-2183486698618234148?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/2183486698618234148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=2183486698618234148' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/2183486698618234148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/2183486698618234148'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2008/02/web-programming-is-hack-part-deux.html' title='Web Programming is a Hack, Part Deux'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-8701718516094065351</id><published>2008-01-31T15:55:00.001-08:00</published><updated>2008-01-31T19:46:24.542-08:00</updated><title type='text'>Web Programming is a Hack</title><content type='html'>I'm surely not the first person to make this observation, but I don't understand why it's rare.&lt;br /&gt;&lt;br /&gt;I've spent most of my career so far doing either non-web apps or things like web services that are cohesive programs.  Now I'm doing web development full time, so it's in my face.&lt;br /&gt;&lt;br /&gt;HTML/HTTP was (as we all know) not intended to be a systems development platform.  Nowadays, darn near every system &lt;span style="font-style: italic;"&gt;must&lt;/span&gt; run over it.  That's a fallacy, of course; many web apps don't need to be so (how many corporate internal web apps are there that could be much simpler as desktop apps), but most people think it's true.&lt;br /&gt;&lt;br /&gt;Everything is so fragmented in web development - you may have:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Code on the client for validation or whatever.&lt;/li&gt;&lt;li&gt;Different code on the client that has nothing to do with the other code (AJAX).&lt;/li&gt;&lt;li&gt;Code constructs in your CSS.&lt;/li&gt;&lt;li&gt;Code on the server.&lt;/li&gt;&lt;li&gt;Code directly on the page (sometimes necessary).&lt;/li&gt;&lt;/ul&gt;That's just the code; the process itself is enormously complicated - and I don't know the half of it. &lt;a href="http://codejournal.blogspot.com/2007/09/complex-isnt-cool.html"&gt;As I've said before&lt;/a&gt;, complex ain't cool. It's certainly possible to make some things clean in web development, but the whole process &lt;span style="font-style: italic;"&gt;isn't&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Consider what I had to do recently in order to make a simple animated gif run while a lengthy process takes place.  I fully realize there are other ways to do it (queuing the process and just returning a simple message seems the best candidate), and I'm constrained in this case by slightly older technology (.net 1.1), but still:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Client submits a batch of email messages.  (Note: IE locks animated gifs while waiting for the return of a post).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Server receives request, needs to return quickly so it starts an asynchronous process to send the messages, sends down a javascript handler to the page to receive the results of the asynchronous process, and turns on the gif.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The page receives the result so it starts animating the gif.&lt;/li&gt;&lt;li&gt;The asynch process starts sending email messages maintaining a collection of those that may have failed.&lt;/li&gt;&lt;li&gt;When it finishes, it can return text to the client, but that handler can't receive complex results (JSON not avail, can't use a web service here), so all it receives is the number of successful email messages.  It stuffs the failed collection in cache on the server.&lt;/li&gt;&lt;li&gt;Now the client receives the result, knows how many messages were successfully sent, but it doesn't have the data on the failure collection.  It builds a url to post back to the server with a query string sending the number of successful email messages back.&lt;/li&gt;&lt;li&gt;The server detects the successful email query string, checks for a failure collection in cache, binds that to a grid (and turns it on) if it exists, writes out the successful number (couldn't have done that on the client because the state would be lost on the second trip to the server) and returns.  Whew!&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-style: italic;"&gt;That's&lt;/span&gt; a hack.  But I have to do what I have to do.  The web constrained me.  It's still fun, but it always feels kludgey.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-8701718516094065351?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/8701718516094065351/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=8701718516094065351' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/8701718516094065351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/8701718516094065351'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2008/01/web-programming-is-hack.html' title='Web Programming is a Hack'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-5153780764690312743</id><published>2007-12-20T07:18:00.000-08:00</published><updated>2007-12-20T07:21:06.767-08:00</updated><title type='text'>Keeping it Simple</title><content type='html'>I posted this on &lt;a href="http://forums.thedailywtf.com/forums/thread/140380.aspx"&gt;worse than failure's sidebar&lt;/a&gt; because I just had to share it, but I'm putting it here in my diary for keeps:&lt;br /&gt;&lt;p&gt;I'm a hack looking for a new job.  Hack that I am, even I know that simplicity is a laudable goal in software development.  I was quite amused to see one poster proudly declare, "Our software is among the most complex ever created".  That is &lt;i&gt;some accomplishment!&lt;/i&gt;  Not sure how long &lt;a target="_blank" mce_href="http://72.14.205.104/search?q=cache:kigU0K2EC3QJ:jobview.monster.com/getjob.asp%3FJobID%3D63405334%26JobTitle%3DSales%2BConsultant%2B-%2BSoftware%26co%3Dxcsgsysx%26vw%3Db%26AVSDM%3D2007-10-05%2B16%253A14%253A00%26pg%3D1%26seq%3D7+%22most+complex%22+denver+c%23+site:monster.com&amp;amp;hl=en&amp;amp;ct=clnk&amp;amp;cd=1&amp;amp;gl=us" href="http://72.14.205.104/search?q=cache:kigU0K2EC3QJ:jobview.monster.com/getjob.asp%3FJobID%3D63405334%26JobTitle%3DSales%2BConsultant%2B-%2BSoftware%26co%3Dxcsgsysx%26vw%3Db%26AVSDM%3D2007-10-05%2B16%253A14%253A00%26pg%3D1%26seq%3D7+%22most+complex%22+denver+c%23+site:monster.com&amp;amp;hl=en&amp;amp;ct=clnk&amp;amp;cd=1&amp;amp;gl=us"&gt;google cache link&lt;/a&gt; will last.&lt;/p&gt;&lt;p&gt;This brings to mind some quotes from a couple luminaries:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;UNIX is simple.  It just takes a genius to understand its simplicity - Dennis Ritchie&lt;/li&gt;&lt;li&gt;There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies. - C.A.R. Hoare&lt;/li&gt;&lt;li&gt;Increasingly, people seem to misinterpret complexity as sophistication, which is baffling---the incomprehensible should cause suspicion rather than admiration. Possibly this trend results from a mistaken belief that using a somewhat mysterious device confers an aura of power on the user. - Niklaus Wirth&lt;/li&gt;&lt;li&gt;The belief that complex systems require armies of designers and programmers is wrong. A system that is not understood in its entirety, or at least to a significant degree of detail by a single individual, should probably not be built. - Niklaus Wirth&lt;/li&gt;&lt;li&gt;Inside every large program, there is a small program trying to get out.  - C.A.R. Hoare&lt;br /&gt;  &lt;/li&gt;&lt;/ul&gt; &lt;p&gt; I can imagine the laughter that would generated if I included as a bullet point on my resume, "My software is among the most complex ever created".&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-5153780764690312743?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/5153780764690312743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=5153780764690312743' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/5153780764690312743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/5153780764690312743'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/12/keeping-it-simple.html' title='Keeping it Simple'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-6633630237813865207</id><published>2007-12-06T11:40:00.000-08:00</published><updated>2007-12-06T11:55:02.642-08:00</updated><title type='text'>Object Oriented Programming and Functional Programming as inverse of each other</title><content type='html'>While listening to &lt;a href="http://www.dotnetrocks.com/default.aspx?showNum=266"&gt;John Harrop on .NET Rocks!&lt;/a&gt;, I noted something he said which seems quite illuminating to me.&lt;br /&gt;&lt;br /&gt;I'm going to paraphrase here, but this is my distillation.  OO and FP are basically inverse to one another:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;OO takes a problem and breaks it down by actors.  You end up portioning functionality into all the various methods of the classes.  If a group of objects all need to implement the same function, you put that in an interface.&lt;/li&gt;&lt;li&gt;FP takes a problem and breaks it down by actions.  Then you model your actors (the class hierarchy from OO) with a single data type (as in a tree).  You pattern match over the data, and functions do different things based on the match - the type of actor.&lt;/li&gt;&lt;/ul&gt;On oversimplification to be sure, but it sure seemed to turn on a light bulb in my head.  BTW, I suspect that F# has a &lt;span style="font-style: italic;"&gt;very&lt;/span&gt; bright future.  I can foresee even &lt;a href="http://www.codinghorror.com/blog/archives/001002.html"&gt;80%ers&lt;/a&gt; like me making use of it given a problem that lends itself to FP.  Especially since it can play with other .NET assemblies written using traditional OO languages.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-6633630237813865207?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/6633630237813865207/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=6633630237813865207' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/6633630237813865207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/6633630237813865207'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/12/object-oriented-programming-and.html' title='Object Oriented Programming and Functional Programming as inverse of each other'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-4439645834908565464</id><published>2007-12-06T11:18:00.000-08:00</published><updated>2007-12-06T11:36:47.347-08:00</updated><title type='text'>Iterative solution to Towers of Hanoi</title><content type='html'>When I was going through &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-4.html#%_toc_start"&gt;SICP&lt;/a&gt;, one of the early assignments was to come up with an iterative solution (rather than the traditional recursive one) to the classic &lt;a href="http://wipos.p.lodz.pl/zylla/games/hf.html"&gt;Towers of Hanoi puzzle&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The first thing to understand (something I didn't before going through that chapter) is that "iterative" doesn't mean that it doesn't make use of recursive functions.  A recursive solution is one that relies on the previous executions of some function; an iterative one does not.  So an iterative solution can take the towers in any legal state and complete the puzzle (regardless of whether it makes recursive calls); a recursive one cannot.  The challenge was to discover some local rule that would determine the next move.&lt;br /&gt;&lt;br /&gt;It took me awhile to discover one.  After examining &lt;a href="http://wipos.p.lodz.pl/zylla/games/hanoi-ex.html"&gt;the only other example I could find&lt;/a&gt;, I realize that mine is probably naive (story of my life).  Nonetheless, I figured I'd post it since it does work and I would imagine may be of interest to someone else.&lt;br /&gt;&lt;br /&gt;The rule is two-fold (Consider that the rings are numbered from smallest = 1 to largest = total count of rings):&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Odd / even rings always travel in opposite directions.  The direction each ring travels varies with the odd/even count of total rings.  If you have four total rings, then:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Odd rings: next move is always to the left (circling around to the other side when no more remain to the left).&lt;/li&gt;&lt;li&gt;Even rings: next move is always to the right.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;When deciding which piece to move next, scan the tops of each pile and move the largest ring which may legally move following the above rule.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-4439645834908565464?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/4439645834908565464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=4439645834908565464' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/4439645834908565464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/4439645834908565464'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/12/iterative-solution-to-towers-of-hanoi.html' title='Iterative solution to Towers of Hanoi'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-2473197635808783726</id><published>2007-11-09T08:44:00.000-08:00</published><updated>2007-11-09T09:19:55.748-08:00</updated><title type='text'>Shades of Laziness</title><content type='html'>I'm currently maintaining an EOL system.  As soon as I found out that the system was EOL, my development approach took a 180 degree turn.  No longer do I have to think of the long term ramifications of my code.  I no longer have any reason to refactor.  Indeed, I would be irresponsible to do so since refactoring always comes with the risk of introducing new bugs and I would be adding to the workload of the business analysts (who are also the QA engineers) since they are doing the double duty of working with this old system and transitioning to the new.&lt;br /&gt;I even came across some support for my position after the fact (see "&lt;a href="http://forums.construx.com/blogs/stevemcc/archive/2007/11/01/Technical-Debt.aspx"&gt;Delaying Development Expense&lt;/a&gt;").&lt;br /&gt;&lt;br /&gt;So now I'm free to be a lazy developer: throw code in the UI layer, add small hacks where I would usually refactor to allow for proper addition of new functionality; simply do the quickest, easiest thing.  It's amazing how much less time this requires than "proper" development.  Of course, if the system were to stick around, ever more time would be required.  This kind of lazy is different than &lt;a href="http://www.codinghorror.com/blog/archives/000373.html"&gt;the good kind of laziness&lt;/a&gt; in a developer; I've traded one lazy for another.&lt;br /&gt;&lt;br /&gt;One thing that is actually liberating is the fact that I no longer groan at all the ancient bad architecture in the system that I formerly had to work around.  Architecture is completely irrelevant; no given architecture is better than another at this stage - it's no longer a beast that I must fight.&lt;br /&gt;&lt;br /&gt;Liberating though it may be, I think I'd rather have my old lazy back.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-2473197635808783726?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/2473197635808783726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=2473197635808783726' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/2473197635808783726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/2473197635808783726'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/11/shades-of-laziness.html' title='Shades of Laziness'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-1302835063419206013</id><published>2007-10-31T14:12:00.001-07:00</published><updated>2007-11-02T11:40:30.906-07:00</updated><title type='text'>Fun with Scheme</title><content type='html'>As I've come across the time, I've watched some of &lt;a href="http://swiss.csail.mit.edu/classes/6.001/abelson-sussman-lectures/"&gt;the videos&lt;/a&gt; (and read &lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-4.html#%_toc_start"&gt;the book&lt;/a&gt;) of "Structure and Interpretation of Computer Programs."&lt;br /&gt;&lt;br /&gt;I've been using &lt;a href="http://www.scheme.com/"&gt;Petite &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Chez&lt;/span&gt; Scheme&lt;/a&gt; along with &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Textpad&lt;/span&gt; for my little learning exercises (some of the other implementations of Scheme seemed rather difficult to get working on windows).&lt;br /&gt;&lt;br /&gt;It's amazing how little there is in common between programming with a lisp language and mainstream object oriented code monkeying.  Sure, C# has anonymous methods, but the fact that they're available doesn't change much (although who knows how far the &lt;a href="http://blogs.msdn.com/hugunin/archive/2007/04/30/a-dynamic-language-runtime-dlr.aspx"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;DLR&lt;/span&gt;&lt;/a&gt; will take mainstream .Net developers down the dynamic language path).&lt;br /&gt;&lt;br /&gt;In one of the first lectures, Gerald Jay Sussman challenges the students to come up with an iterative rather than the commonly taught recursive solution to the famous "towers of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;hanoi&lt;/span&gt;" puzzle.  It turned out to be quite a little challenge for me; both discovering the algorithm and translating it into code the Scheme way.&lt;br /&gt;&lt;br /&gt;The first thing that I had to struggle with was (of course) all the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;parens&lt;/span&gt;.  Absolutely everything is inside pairs of parentheses.  I don't really understand the exact reason for this (it somehow enables easy creation of programs using declarative data), but one thing is for sure - it's &lt;span style="font-style: italic;"&gt;really&lt;/span&gt; easy to learn the syntax of the language (and there isn't a ton of crazy tricks as in C++ whereby on might use the language for years before discovering some).  Making sure your &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;paren&lt;/span&gt; pairs are matched up takes a bit of effort.  It seemed like I needed to transform into a human compiler in order to write a function with much length, but after awhile it's not so bad.  Conforming to the indenting conventions makes it easier, but it sure seems to make it difficult to cut and paste code or insert a comment at the right spot.&lt;br /&gt;&lt;br /&gt;The next thing that threw me was the fact that there are no reference parameters in Scheme; they are always by value.  At one point I was searching all around trying to figure out how to pass parameters by reference, and couldn't find a way before I finally figured out that &lt;span style="font-style: italic;"&gt;there is no way&lt;/span&gt;.  I'm pretty sure it's purposeful: functions produce no side effects.&lt;br /&gt;&lt;br /&gt;The last main hurdle to overcome is the fact that you're not supposed to declare and set variables as a rule.  Hell, you can't pass the suckers to functions, so what's the point anyway?  I learned that one the hard way.  I created my entire program (managing to test each function as I went along) only to discover that the last link was impossible.  My practice of using variables in the mainstream way painted me into a corner.  Instead of declaring variables, you create let blocks with the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;variable's&lt;/span&gt; value declared at the beginning of the block.  The language help says that let blocks are just another form of lambdas which is pretty cool (&lt;span style="font-style: italic;"&gt;everything&lt;/span&gt; is functional).&lt;br /&gt;&lt;br /&gt;Here was the easy part: using lists.  There are some funky things about lists that I don't quite understand, but one thing was easy: stuffing whatever I wanted in there.  I wanted a string to represent the name of each tower to be stored along with the integer values of the rings on that tower.  With &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;OO&lt;/span&gt;, you'd have to either define a type for such list or do some casting of objects coming out of a generic collection, but neither is necessary in Scheme.  The same would hold true with any dynamic language, of course.&lt;br /&gt;&lt;br /&gt;Overall, it was a pretty fun exercise.  It'd be neat if I could use functional programming at work.  With the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;DLR&lt;/span&gt;, that just might be possible (I could at least write test code or internal utilities or something).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-1302835063419206013?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/1302835063419206013/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=1302835063419206013' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/1302835063419206013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/1302835063419206013'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/10/fun-with-scheme.html' title='Fun with Scheme'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-107380771437770900</id><published>2007-09-26T13:07:00.000-07:00</published><updated>2007-09-26T13:49:22.754-07:00</updated><title type='text'>Complex isn't cool</title><content type='html'>I was IMing a coworker today talking about the ASP page/application life cycle.  I made a common comment of mine, that the Internet is nothing but a terrible hack of a way to deliver applications.  Then I commented, "web programming is so darn complicated" to which he responded, "yeah, ain't it great?"&lt;br /&gt;While I think I can understand his basic point, this is something that was written about recently at &lt;a href="http://worsethanfailure.com/Articles/The-Mythical-Business-Layer.aspx"&gt;worse than failure&lt;/a&gt;.  While that post received lots of negative comments, there was no disagreement that developers often complicate things unnecessarily, which appeals to our engineering drive, and that often a better solution is the more mundane.&lt;br /&gt;When I was in school I marveled at how complicated my code was.  All that does this!  Since it was my brain child (and only I could wrap my brain around it) there was a certain intellectual satisfaction involved.&lt;br /&gt;As developers, we should all be on the lookout for this.  The system gains nothing from it, and the next guy (whether ourself or some other monkey) stands to lose much (time, productivity, etc.).&lt;br /&gt;It is sort of neat that a gazillion things come together to allow for killer apps on the Internet, but I would be very hip to a better solution (a standardized way to deliver smart clients or something).  I'm not currently working on web apps, but when I do I always groan at the mountains of work that I'll have to put towards debugging the platform.&lt;br /&gt;&lt;a href="http://codewannabe.blogspot.com/2007/07/whats-single-best-rule-to-follow-in.html"&gt;As I've already written&lt;/a&gt; (but can't be repeated often enough), simplicity (or reduction of complexity) is the most important goal in development.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-107380771437770900?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/107380771437770900/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=107380771437770900' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/107380771437770900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/107380771437770900'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/09/complex-isnt-cool.html' title='Complex isn&apos;t cool'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-3853368543655844589</id><published>2007-07-18T07:57:00.000-07:00</published><updated>2007-07-27T13:32:07.326-07:00</updated><title type='text'>Shades of Development</title><content type='html'>I just recently interviewed with a small company that needs someone to be the person who:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Maintains programs which patch together the pieces of their enterprise, e.g.; do some processing between the Internet order and the ERP system, write reports which draw on the ERP system, etc...&lt;/li&gt;&lt;li&gt;Identifies (or refines when others identify) and creates process improvement solutions.&lt;/li&gt;&lt;li&gt;Helps to create / refine content to the web site.&lt;/li&gt;&lt;li&gt;Does other sundry bric-a-brac.&lt;/li&gt;&lt;/ul&gt;Now this seems to be a good opportunity:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The people seem great.&lt;/li&gt;&lt;li&gt;The company is small and growing fast.&lt;/li&gt;&lt;li&gt;I would be able to call the shots.&lt;/li&gt;&lt;li&gt;I would be getting in at the ground floor.&lt;/li&gt;&lt;li&gt;Productivity is inversely proportional to team size (with the probable exception that 2 are better than 1).&lt;/li&gt;&lt;/ul&gt;It does, however, illustrate shades of development.  One reason I'm code wannabe is that I often come across examples of the work of people who may be called "computer scientists".  Or at least what they're doing is something orders of magnitude more compelling and or useful than what the average business developer does.&lt;br /&gt;&lt;br /&gt;This position is not one for the computer scientist; nor should it be.  The business has a specific gap that needs filling - they need someone to apply the correct amount of lubrication at all the correct points to keep the enterprise at optimum operational capacity.  I frankly think I would be very good at this.&lt;br /&gt;&lt;br /&gt;One thing they made clear: things move fast, there would be a great amount of context switching, and they want someone amenable to as many interruptions as the business generates.  They don't want someone who is a "head down coder with the office door shut".  Once again, this is perfectly reasonable, but it's not without drawbacks from the standpoint of a purist (in this case purist being a favorable term for one of those really smart guy programmers described above):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.joelonsoftware.com/items/2006/07/30.html"&gt;"Closed door programming" is to be preferred&lt;/a&gt;.  But again, this presumes a certain type of programming.  I wouldn't be creating the kinds of solutions that require intense, focused concentration (at least I don't &lt;span style="font-style: italic;"&gt;think&lt;/span&gt; so).&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.joelonsoftware.com/articles/fog0000000022.html"&gt;Context switching is harmful&lt;/a&gt;.  &lt;a href="http://www.amazon.com/Code-Complete-Second-Steve-McConnell/dp/0735619670/ref=pd_bbs_sr_1/103-5280985-7580607?ie=UTF8&amp;s=books&amp;amp;qid=1185567870&amp;sr=8-1"&gt;Steve McConnell's quote&lt;/a&gt; also comes to mind, "&lt;span style="font-style: italic;"&gt;... programming requires more concentration than other activities. It's the reason programmers get upset about 'quick interruptions' - such interruptions are tantamount to asking a juggler to keep three balls in the air and hold your groceries at the same time.&lt;/span&gt;" I don't think there's any doubt it is a productivity killer.  In this company's environment, however, there's probably a greater benefit that outweighs it's drawbacks.&lt;/li&gt;&lt;/ul&gt;So this company's developer should be much different than many others.  This introduces the range of development:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Corporate developers working on in house applications at BloatedCorp.&lt;/li&gt;&lt;li&gt;&lt;a href="http://ycombinator.com/"&gt;Rock stars&lt;/a&gt; creating startup Internet applications.&lt;/li&gt;&lt;li&gt;&lt;a href="http://damienkatz.net/2005/01/formula-engine-rewrite.html"&gt;Lone developers&lt;/a&gt; working under unique conditions leading to killer solutions.&lt;/li&gt;&lt;li&gt;ISVs creating (formerly) shrinkwrap or (now usually) Internet apps.&lt;/li&gt;&lt;li&gt;Upper echelon programmers: those who create software for developers.  Folks who work directly on .Net or Java internals or on IDEs.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Luminaries like Richard Stallman, Linus Torvalds, or Edsger Dijkstra.&lt;/li&gt;&lt;li&gt;Contract or independant developers: there's a whole sub range in here.&lt;/li&gt;&lt;li&gt;Gaming programmers.&lt;/li&gt;&lt;li&gt;Embedded systems programmers.&lt;/li&gt;&lt;li&gt;Academics who may contribute to practical projects.&lt;/li&gt;&lt;li&gt;Monkeys who act as typists for business analysts adding new widgets to code in a system that should be redesigned to be configured directly by business analysts.  (That one is a bit specific because it's what I do now).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;If I take the job, I will probably be busier than a one legged man (you know the rest), so I'll probably have to forebear studying the more C.S. intensive subjects as I am sometimes wont to do.  One thing all good developers must share is the constant acquisition of new knowledge; just some more than others...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-3853368543655844589?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/3853368543655844589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=3853368543655844589' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/3853368543655844589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/3853368543655844589'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/07/shades-of-development.html' title='Shades of Development'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-6228150096303525840</id><published>2007-07-03T11:47:00.000-07:00</published><updated>2007-07-03T12:35:23.167-07:00</updated><title type='text'>What's the single best rule to follow in programming?</title><content type='html'>Actually, I think there are 2 that are equally important; one that pertains to code construction, the other to design (and so it may be the single most important thing).  I've recently seen these both expressed in a new light.&lt;br /&gt;&lt;br /&gt;The frst (pertaining more to construction than the other) is &lt;a href="http://wilshipley.com/blog/2007/05/pimp-my-code-part-14-be-inflexible.html"&gt;brevity&lt;/a&gt; or &lt;a href="http://www.codinghorror.com/blog/archives/000791.html"&gt;code less&lt;/a&gt;.  The first link, especially, sheds light on just how important this rule is.&lt;br /&gt;&lt;br /&gt;The second, one which I'm going to rate as the best rule simply because it always pertains to architecture and as such should have a greater effect on the system under development, is &lt;a href="http://dotnetrocks.com/default.aspx?showID=255"&gt;reduce complexity&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;The linked interview with software luminary &lt;a href="http://www.objectwatch.com/"&gt;Roger Sessions&lt;/a&gt; is the best I've heard in quite awhile.  In the interview, Sessions proposes using "equivalence relations" to determine the best possible partitions in developing enterprise architecture. &lt;br /&gt;&lt;br /&gt;You can listen to the interview for a further explanation, but I think his best points were about complexity.  He demonstrates (by contrasting the huge reduction in potential states representable by a single program with 12 variables [and 6 states] to 2 programs with 6 variables each) that partitioning a system greatly reduces complexity. &lt;br /&gt;&lt;br /&gt;Outwardly partitioned programs may not really be, however.  If 2 "separate" programs (like services or whatever) share a database, they're not partitioned. &lt;br /&gt;&lt;br /&gt;Sessions proclaims OO as the "worst partitioning technology".  Now, I've read a fair amount lately in favor of FP over OO, and the arguments are pretty good.  But I don't think they came close to Sessions' position against the traditional OO model - the creation of large hierarchies which merely tie everything together.  He's not opposed to OO, mind you, just the typical implementation where reuse is a major goal.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;"Reuse at the expense of complexity is unacceptable.  Reducing complexity is much more important than reusing code; it is the &lt;span style="font-weight: bold;"&gt;most&lt;/span&gt; important thing."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The interview was so interesting to me that, for a moment, I felt excited about things like architecture.  Then I remembered that I'm code wannabe and that I work at BloatedCorp (on the &lt;a href="http://worsethanfailure.com/Articles/Crash_Test__0x5f_dummy.aspx"&gt;Behemoth&lt;/a&gt; project) and I snapped back to reality.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-6228150096303525840?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/6228150096303525840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=6228150096303525840' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/6228150096303525840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/6228150096303525840'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/07/whats-single-best-rule-to-follow-in.html' title='What&apos;s the single best rule to follow in programming?'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-1900661543872441426</id><published>2007-06-22T06:38:00.000-07:00</published><updated>2007-07-03T11:47:43.621-07:00</updated><title type='text'>Who cares about code?</title><content type='html'>I'm the kind of code monkey who reads what I think are top blogs like &lt;a href="http://www.codinghorror.com/blog"&gt;coding horror&lt;/a&gt;,  &lt;a href="http://www.worsethanfailure.com/"&gt;worse than failure&lt;/a&gt;, &lt;a href="http://programming.reddit.com/"&gt;reddit&lt;/a&gt; (OK, it's not really a blog), and codebetter.  I've read many of the programming classics like &lt;a href="http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672/ref=pd_bbs_sr_1/105-9037569-2309242?ie=UTF8&amp;s=books&amp;qid=1182520721&amp;sr=8-1"&gt;Refactoring&lt;/a&gt;, &lt;a href="http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X/ref=pd_bbs_sr_2/105-9037569-2309242?ie=UTF8&amp;s=books&amp;qid=1182520746&amp;sr=8-2"&gt;Pragmatic Programmer&lt;/a&gt;, and &lt;a href="http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/0201835959/ref=pd_bbs_sr_1/105-9037569-2309242?ie=UTF8&amp;s=books&amp;qid=1182520773&amp;sr=8-1"&gt;Mythical Man Month&lt;/a&gt;.  As I find time, I'm going through &lt;a href="http://mitpress.mit.edu/sicp/"&gt;SICP&lt;/a&gt;.&lt;br /&gt;IOW, I strive for improvement in my "craft" (trite though that word may be).&lt;br /&gt;&lt;br /&gt;But, other than at my first job, I haven't discovered anyone else who cares a lick about software good practice.  Even if such "practices" are debatable, I used to expect that just about everybody endeavored to follow some.  In interviews I've sat through, almost all the questions I've been asked have been nearly inane.  I remember one interview a long time ago where one person focused on my ability to call windows API functions.  Huh?  I was so naive to think that they should ask me questions about my design practices or some other relevant topic.&lt;br /&gt;One shop recently interviewed my and didn't ask &lt;span style="font-style:italic;"&gt;anything&lt;/span&gt; about my practice, have me do any exercises, ask for a code sample; nothing.  I was amazed.&lt;br /&gt;&lt;br /&gt;I think the problem is that I glean info from the "upper echelons" of development while being employed at the bottom of the heap.  I don't think I'm going to find many star coding shops posting for jobs on amazon or careerbuilder.  It's not that I think I'm a star, but I'd at least like to work somewhere where such things are valued.&lt;br /&gt;&lt;br /&gt;Another factor is that the code monkeys in these upper echelons aren't writing business logic for BloatedCorp.  The shops where I've been employed during the last 4 years are building very narrow business specific systems, not crafting some innovative new system that businesses far and wide will use.&lt;br /&gt;&lt;br /&gt;The work I'm doing now can hardly be called development.  The architecture of the system is fixed, and there's no way it can (or even would be allowed to) be changed.  I add new widgets (each doing pretty much the same thing); that's it.  There's no ancillary technology (I just use my language's IDE); nothing at all other than scripting the rules for the new widget.  It's not even a job a programmer should be doing - a business analyst should.  If the system needs a change in the way it does something, I'm not the one to do it (for reasons outside my control).&lt;br /&gt;&lt;br /&gt;IMO, this is a massive waste of my potential.  But that's why I'm code wannabe.  That's why I write these missives to you, diary...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-1900661543872441426?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/1900661543872441426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=1900661543872441426' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/1900661543872441426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/1900661543872441426'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/06/who-cares-about-code.html' title='Who cares about code?'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-2546024434664379054</id><published>2007-05-11T07:06:00.000-07:00</published><updated>2007-05-11T08:05:11.768-07:00</updated><title type='text'>Business Vs. Technical</title><content type='html'>&lt;a href="http://www.developerdotstar.com/mag/articles/programmer_career.html"&gt;This article&lt;/a&gt; at developer.* claims advice on the career path of a programmer.  It suggests that the programmer needs to shift focus from technical to business specific knowledge.&lt;br /&gt;Similarly, Bertrand Meyer from the esteemed ETH wrote in &lt;a href="http://se.ethz.ch/%7Emeyer/publications/computer/outsourcing.pdf"&gt;an IEEE Computer article&lt;/a&gt;, "make sure you know the business as well as the technology; that will set you apart from mere techies."&lt;br /&gt;&lt;br /&gt;Both seem to guide the programmer away from engineering skills towards business skills.  As a survival guide, my current experience seems to bear this out.  The system I'm working on will be outsourced, but the business analysts will be retained.  But I have a real problem with the former article especially.  It's titled, "Career paths for Programmers," but IMO it should be titled "Why to give up Programming".  This isn't career guidance for programmers who want to know how to make it as a programmer.  This is advice for people who just want to make it, not caring how.  Being a business analyst is nothing like being a programmer, generally speaking.  I would never want to be a BA.  Where I work, people with the BA title handle BA and QA, so it's kinda strange, but BA work in general couldn't possibly hold my attention; I would fail.  There isn't anything related to problem solving or design in the BA's role.  Further, I totally disagree with the quote in the article,&lt;br /&gt;&lt;div style="margin-left: 8%;"&gt;&lt;br /&gt;"he could train anyone in the technical skills he needed for a project, but finding those people with the necessary business skills to guide an IT project to success was something that could not easily be obtained".&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;I think the exact reverse is true.  A person with good problem solving / design / logic skills either has such skills or not.  They can be cultivated, but not acquired.  Perhaps this person imagines a programmer / software engineer / developer as someone who just knows how to install and configure disparate technological tools.  That would be a description of pure technical knowledge that anyone could learn, but programming &lt;a href="http://www.codinghorror.com/blog/archives/000635.html"&gt;isn't something you can just teach anyone&lt;/a&gt;.&lt;br /&gt;Straight up business knowledge, on the other hand, could be stuffed into anyone's brain it seems to me.  You can't train just anyone to be an actuary, but you can train anyone the details of your life insurance business and make them a BA.&lt;br /&gt;I agree with the second article that the programmer who has the business knowledge is of more value, but this doesn't agree with the trend.  I see what's happening to me as a trend; the software (technical) work is portioned out to those whose business is software.  The particular business details are managed by BAs.  So the software people know how to make good software.  They don't devote themselves to business knowledge; they get that knowledge from BAs.&lt;br /&gt;This seems natural to me.  Now it may be that the software work may not have near the future that the strict business work will.  But there's no way I'm going to morph into a BA.  If I have to do something I hate, it surely won't be to &lt;a href="http://en.wikiquote.org/wiki/The_Office_(US)"&gt;fill my brain with details about Tonnage price of manila folders&lt;/a&gt;.  I'd much rather be a &lt;a href="http://www.unitedmedia.com/comics/dilbert/the_characters/html/character3.html#garbage"&gt;sanitation engineer&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-2546024434664379054?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/2546024434664379054/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=2546024434664379054' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/2546024434664379054'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/2546024434664379054'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/05/business-vs-technical.html' title='Business Vs. Technical'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-7211183751484494300</id><published>2007-05-10T12:17:00.000-07:00</published><updated>2007-05-10T12:32:04.755-07:00</updated><title type='text'>Outsourced!</title><content type='html'>Par for the course for code wannabe.  But it is a good thing.  After a brief search, I'd resigned myself to my current position for personal reasons; now I must get a better job.&lt;br /&gt;&lt;br /&gt;The decision of my employer to outsource the system I maintain seems a no-brainer to me.  I could speak all day about the flaws (despite the fact that it does, in fact, work).  The most logical reasons are these&lt;br /&gt;&lt;div style="margin-left: 10%;"&gt;&lt;br /&gt;1)  The system needed a re-write (as much as many of the current developers would disagree).  It makes more sense to do it over with fresh blood.&lt;br /&gt;2)  The third party company already handles analogous systems for competitors.  It's inevitable that we would follow suit so our customers (who are actually middle men) can  come to a central location when comparing.&lt;br /&gt;3)  Most importantly, my employer's core business isn't software and the industry has somewhat of a reputation for crappy (mostly internal) software.  It makes sense to keep the focus on those employees who deal directly with the core business and outsource software to a company who has software as it's core business.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Point #3 begs the question that I've heard (read) asked many times.  How much of a focus on business knowledge (of a particular vertical market) should a code monkey devote, and how much on software development itself?  Subject for another post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-7211183751484494300?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/7211183751484494300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=7211183751484494300' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/7211183751484494300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/7211183751484494300'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/05/outsourced.html' title='Outsourced!'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-8426108167719412249</id><published>2007-04-05T10:02:00.000-07:00</published><updated>2007-04-05T13:25:40.875-07:00</updated><title type='text'>Strangely Duplicated</title><content type='html'>I think avoidance of duplication is one of the most important maxims to follow in software development.  Martin Fowler wrote in &lt;a href="http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672/ref=pd_bbs_sr_1/103-9761673-8096668?ie=UTF8&amp;s=books&amp;amp;qid=1175792661&amp;sr=8-1"&gt;Refactoring&lt;/a&gt;, "By eliminating duplicates, you ensure that the code says everything once and only once which is the essence of good design".  I could've sworn he also wrote, "all information in a system should be represented in one place", but I can't find that quote anywhere.  Anyway, I would argue that it is more than just good design; it's essential if one wants to avoid problems.&lt;br /&gt;&lt;br /&gt;Duplication was a problem I pointed out in some code recently.  A design decision was made that is quite simply mind-boggling. &lt;br /&gt;Here's the scenario: The application runs desktop/web which share business objects.  A huge dummy object (discussion in itself) contains all input UI values.  For desktop, the UI is refreshed based on the values in the UI object after validation on that object occurs.  For web, a message pops up (someone else's decision) rather than the UI being refreshed.&lt;br /&gt;So the decision was made that for the desktop, we merely reload the values (after validation may change them in the dummy object) into the UI.  Simple enough.  For the web, we add an additional giant object that contains the before and a copy of the after values.  And for every single variable in the dummy UI object that is validated (&gt;500) there is a separate method that:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Caches the original value&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Sets the new value (if necessary)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Stores the new and old value along with a string indicating the name of the variable.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;When asked why this was done, the initial reply was merely because the web "shows a user message rather than simply changing the variable on screen".  When asked why it couldn't simply compare against the values in the UI object, the reply was essentially the same ("it needs to show a message").  In addition, the coder mentioned that the new data structure (with the duplicated data) could be a place to add additional functionality (can you say "&lt;a href="http://en.wikipedia.org/wiki/YAGNI"&gt;YAGNI&lt;/a&gt;"?).&lt;br /&gt;&lt;br /&gt;I pointed out (rather casually) these problems:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Duplication of data.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Forces the developer to remember to include a method copying the algorithm above for every new validation rule  (which I already forgot to do once, prompting the discussion).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The above algorithm is duplicated ad infinitum.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;The response was that this is merely my opinion, but I personally think it transcends opinion.  &lt;span style="font-style: italic;"&gt;If&lt;/span&gt; data is &lt;span style="font-style: italic;"&gt;ever&lt;/span&gt; to be duplicated, there should be a &lt;span style="font-style: italic;"&gt;very&lt;/span&gt; good reason for it because duplicated data opens the door for corrupt data - you may as well count on it.&lt;br /&gt;In this case, not only is there no reason, one wonders how such a solution could even be contrived.&lt;br /&gt;&lt;br /&gt;Anyway, this highlights 2 important red flags in the software development process:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Data duplication.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Multiple methods with near duplicate code.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;IMO, if you see the former, your design needs correcting.  If you see the later, figure out how to combine the code into a single method.  If that's not possible, your design needs correcting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-8426108167719412249?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/8426108167719412249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=8426108167719412249' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/8426108167719412249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/8426108167719412249'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/04/strangely-duplicated.html' title='Strangely Duplicated'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-607891560367862061</id><published>2007-02-07T09:15:00.000-08:00</published><updated>2007-02-07T09:35:57.199-08:00</updated><title type='text'>Teamwork and Development</title><content type='html'>Code wannabe strikes again (just changed the name of this formerly work-group oriented blog so the tone of posts are different though still software oriented).&lt;br /&gt;&lt;br /&gt;My boss tells me what I already know; I'm not playing well with my coworker.  I've failed.  Well, maybe not; lemme esplain:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;My coworker (my senior) is in another state.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Our personalities don't mesh.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;She has less experience (in time and most definitely in variety) than I do.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Our development philosophies are polar opposites; hers is git-r-done / hack it together, mine is do it according to widely accepted good development practices (although we both think our philosophy serves our customer best).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;She wants to continue to follow the ancient existing architecture, I want to change it wherever possible.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;And so it goes.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Because of the above, we don't communicate much.  It's not terrible; but far from optimal.  My boss suggested that he may move another developer (who is much more happy-go-lucky) to my spot and me to his system (a one man show).&lt;br /&gt;&lt;br /&gt;So on the one hand, I've failed to be a team player - that's evident.  But &lt;span style="font-style:italic;"&gt;should&lt;/span&gt; I have been one?  That's not evident.  If I'm relegated to a one-man system should I simply embrace that as an opportunity to call all my own shots and flourish as perhaps I can best, or should I consider that a step down and always strive for collaborative development?&lt;br /&gt;&lt;br /&gt;I believe one thing about lone development - it can be very fruitful.  &lt;a href="http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/0201835959/sr=8-1/qid=1170869157/ref=pd_bbs_sr_1/002-0838152-3645618?ie=UTF8&amp;s=books"&gt;The Mythical Man-Month&lt;/a&gt; and copious other writings detail the difficulties with team development and I believe that applies right down to teams of as few as 3.  2 may be a unique situation what with XP and all (or even w/o XP as long as 2 developers are on the same page and communicate well).  Yet, even with 2, the rule may apply.  Could &lt;a href="http://damienkatz.net/2005/01/formula-engine-rewrite.html"&gt;this cat&lt;/a&gt; have done what he did with a partner?  A partner would surely have only slowed him down.  Maybe that's only because he's a genius, but I suspect it applies to anyone who frequently gets in the zone during development.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-607891560367862061?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/607891560367862061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=607891560367862061' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/607891560367862061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/607891560367862061'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2007/02/teamwork-and-development.html' title='Teamwork and Development'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-116067134443629250</id><published>2006-10-12T09:14:00.000-07:00</published><updated>2006-10-12T09:42:24.466-07:00</updated><title type='text'>Brief guide to building a Delphi IDE AddIn</title><content type='html'>Someone in the Delphi IDE newsgroup asked the question, "Is there a guide anywhere about writing IDE addins"?  After experiencing my own pain in building a small add-in (or is it plug-in?), I decided to make up a quick post.  The answer to his question is a resounding "no."  Well, you might consider &lt;a href="http://www.gexperts.org/opentools/"&gt;this&lt;/a&gt; as something of a guide, but I had better luck getting started with these 2 docs:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://bdn1.borland.com/borcon2004/article/paper/0,1963,32119,00.html"&gt;http://bdn1.borland.com/borcon2004/article/paper/0,1963,32119,00.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://cc.borland.com/Item.aspx?id=19719"&gt;http://cc.borland.com/Item.aspx?id=19719&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;The first thing to note is that I found that writing the add-in in .Net seemed to make it work for both Win32 and .Net Delphi projects.&lt;br /&gt;&lt;br /&gt;When I started mine, I was really naive and thought there'd be some API with  calls like GetStartNextMethod or something.  You only get the buffer.&lt;br /&gt;&lt;br /&gt;So here's the start - getting the source editor (sorry - snippets lost their formatting - too much work to put back in using blogger):&lt;br /&gt;&lt;br /&gt;&lt;div  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;using Borland.Studio.ToolsAPI;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt; &lt;div  style="font-family:courier new;"&gt; &lt;/div&gt; &lt;div  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt; public class SourceViewer  // base class&lt;br /&gt;{&lt;/span&gt;&lt;/div&gt; &lt;div  style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;  protected IOTASourceEditor fSourceEditor;&lt;/span&gt;&lt;/div&gt; &lt;div face="courier new"&gt;&lt;span style="font-size:85%;"&gt;  public IOTASourceEditor sourceEditor { get { return fSourceEditor; }  }&lt;/span&gt;&lt;/div&gt; &lt;div style="font-family: courier new;"&gt; &lt;/div&gt; &lt;div style="font-family: courier new;"&gt;&lt;span style="font-size:85%;"&gt;  public SourceViewer()&lt;br /&gt;{&lt;br /&gt;IOTAModuleServices moduleServices =  BorlandIDE.ModuleServices;&lt;br /&gt;if ( moduleServices == null  )&lt;br /&gt;{&lt;br /&gt; fSourceEditor =  null;&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt; try&lt;br /&gt; {&lt;br /&gt;  fSourceEditor =  moduleServices.CurrentModule.CurrentEditor as  IOTASourceEditor;&lt;br /&gt; }&lt;br /&gt; catch&lt;br /&gt; {&lt;br /&gt;  fSourceEditor =  null;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt; &lt;div&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt; }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Then you use the source editor to get a reader to get the text of the buffer:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;IOTAFileReader reader = fSourceEditor.CreateReader();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;      private string getRawSourceText( IOTAFileReader reader )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;      {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;          const int READ_CHUNK = 1600;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;          if (reader == null)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;              throw new Exception( "No file reader" );&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;          StringBuilder sb = new StringBuilder();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;          System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;          Byte[] source = reader.Read( READ_CHUNK, 0 );&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;          while ( source.Length &gt; 0 )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;          {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;              sb.Append( enc.GetString(source) );&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;              source = reader.Read( READ_CHUNK, 0 );&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;          }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;          return sb.ToString();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;      }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To get the IDE to integrate your AddIn, implement IOTAMenuWizard:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;    public class TestPlugIn: IOTAMenuWizard&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    {&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        public static void Register()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            IOTAWizardService WizService = (IOTAWizardService)BorlandIDE.GetService( typeof( IOTAWizardService ) );&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            wizardID = WizService.AddWizard( new TestPlugIn() );&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;....&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Then implement the other methods of IOTAMenuWizard such as execute and enabled.  I wanted mine to be enabled when any source file is open (referencing the first class above):&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;return new SourceViewer().sourceEditor != null;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once your assembly is ready to go, register it with the IDE (so the IDE will load it on startup):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create a key under HKEY_CURRENT_USER\Software\Borland\BDS\4.0\Known IDE Assemblies.&lt;/li&gt;&lt;li&gt;Give the key a name (don't recall if the name matters / where it might show up, but I think it has to have a name).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add the path to your assembly there.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-116067134443629250?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/116067134443629250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=116067134443629250' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/116067134443629250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/116067134443629250'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/10/brief-guide-to-building-delphi-ide.html' title='Brief guide to building a Delphi IDE AddIn'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-116015760641089450</id><published>2006-10-06T10:20:00.000-07:00</published><updated>2006-10-06T11:39:23.350-07:00</updated><title type='text'>Ridding (not riding) the Range</title><content type='html'>&lt;span style="font-family:trebuchet ms;"&gt;I added a suggestion to David's list of potential improvements that we all discussed in Minneapolis.  He asked me to describe why it's a problem and what I think the solution is...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Why the Range global is a problem&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;It's like a master key that tightly couples all parts of the system.  We will not be able to separate annuity from life w/o either eliminating it or duplicating it for both.&lt;/li&gt;&lt;li&gt;It's a global (or rather a collection of globals; same thing).  Reference my blog post for reasons why this is bad.&lt;/li&gt;&lt;li&gt;It prevents the furtherance of OO development in the system.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;I Object!&lt;br /&gt;&lt;/span&gt;Objects are objects for a reason.  They should encapsulate their data.  The range object is a circumvention of OO.  A given product will manipulate any number of range variables for varying functionality.  So rather than being able to look at the product class methods and members to determine it's behaviour, you may have to guess what range variables it manipulates to do so.  Variables should be owned by the proper object that manipulates them.  Range variables are manipulated by any other object in the system.  This leads to conditional code multiplied all over.  So instead of this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;margin-left:1em"&gt;  BaseObject.DoThis;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We have this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;margin-left:1em"&gt;  If Rng.Something then&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;margin-left:2em"&gt;SpecificObject.DoSomething&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;margin-left:1em"&gt;else if Rng.TheOtherThing then&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;margin-left:2em"&gt;OtherSpecificObject.DoSomething;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;If the individual objects properly encapsulated their data, we wouldn't have this problem.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Solution&lt;/span&gt;&lt;br /&gt;I don't see any other way than to:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Forbid adding any new variables to the range object (with exceptions for exigent circumstances).&lt;/li&gt;&lt;li&gt;Start removing it's variables.  For each:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Search the system for it's use.&lt;/li&gt;&lt;li&gt;Determine which object at which level in the heirarchy should encapsulate the data.&lt;/li&gt;&lt;li&gt;Move the variable to the appropriate object.&lt;/li&gt;&lt;li&gt;Adjust the code that references it.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Whenever sets are encountered, this should be seen as an indicator that a new object may be needed.  Sets (and their brother case statements) should be rare in OO (1).  Unlike an object, they encapsulate nothing.  So if you look at a set in code, you learn nothing.  In order to learn how the system manipulates the members of the set, you would have to search the system for all references to the set.  When you do this search, you will no doubt encounter many case statements and for loops.  If the business logic were instead object based, you would simply call BaseType.DoSomething and polymorphism would handle the conditional behaviour of the members of the set.  Thus you don't end up with case statements and for loops that usually start out at a manageble size, but enevitably grow into something that is very difficult to maintain.&lt;/li&gt;&lt;/ul&gt;No doubt this will initially lead to some other objects becoming bloated, but this is a process.  The bloated objects should, in turn, be distilled into more granular objects.&lt;br /&gt;&lt;br /&gt;1) &lt;a href="http://www.amazon.com/gp/product/0201485672/qid=1147279647/sr=2-1/ref=pd_bbs_b_2_1/002-6501382-5112067?s=books&amp;v=glance&amp;amp;n=283155"&gt;Refactoring&lt;/a&gt;, p. 34, 82&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-116015760641089450?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/116015760641089450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=116015760641089450' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/116015760641089450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/116015760641089450'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/10/ridding-not-riding-range.html' title='Ridding (not riding) the Range'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-115989187562094721</id><published>2006-10-03T09:05:00.000-07:00</published><updated>2006-10-03T09:12:28.056-07:00</updated><title type='text'>Good Javascript Reference</title><content type='html'>I was working on something for our new App Wizard Search today and came across this Javascript reference on the Mozilla developers' site.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference"&gt;http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you go up a level or two there are all kinds of sections about various web development topics as well.  It is all geared for Mozilla but with some consideration it would most likely be applicable across most browsers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-115989187562094721?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/115989187562094721/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=115989187562094721' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/115989187562094721'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/115989187562094721'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/10/good-javascript-reference.html' title='Good Javascript Reference'/><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-115956204700385921</id><published>2006-09-29T10:39:00.000-07:00</published><updated>2006-09-29T13:34:07.093-07:00</updated><title type='text'>Regular Expression Tools</title><content type='html'>Since Kelly has been developing some regular expressions for modifying VB6 code in preparation for migration to VB.net (because he needs some things to end up differently in VB.net than the built in upgrade wizard would cause them to be), I had regex on the mind and decided to listen to &lt;a href="http://www.dotnetrocks.com/default.aspx?showID=198"&gt;this podcast&lt;/a&gt; about them.&lt;br /&gt;&lt;br /&gt;If you've never used them before, regular expressions are basically just strings with special characters and placeholders for manipulating (not just finding) text.  This is one I've used a few times to search through code.  I need regex because I want to find all ocurrences where any index of SameArray is modified but the identifier within the brackets varies.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold;"&gt;SomeArray\[\w+\]\s+:=&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family:georgia;"&gt;The text between the array index brackets can be anything.  'w' indicates anything that can be part of a language identifier.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:georgia;"&gt;The brackets themselves are escaped because they normally delimit character sets.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:georgia;"&gt;The '\s' indicates a space.  There might be more than one space between the right bracket and the assignment.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:georgia;"&gt;The '+' indicates one or more of the preceeding token.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;This is a simple expression that makes for a much better search.  I didn't have it until now, but &lt;a href="http://tools.osherove.com/Default.aspx?tabid=182"&gt;Regulazy&lt;/a&gt; is a graphical tool that is perfect for creating such expressions quickly.  Regulazy creates .Net regular expressions, and something new I learned on the podcast is that there is no "standard" implementation for regex.  The tool I use to search through files with the above expression is a &lt;a href="https://sourceforge.net/forum/?group_id=147235"&gt;simple utility&lt;/a&gt; done in Java, and this expression works for Java too.   The basic tokens are the same (kind of a standard, I guess), but each implementation varies; for example, .Net allows you to name groups and refer to them in other areas of your expression. Perl allows you to use variables in the expression. &lt;br /&gt;&lt;br /&gt;The podcast gave great resources for creating the expressions, but not for using them.  I haven't come across many good utilities for searching files with regex expressions (although it wouldn't be much work to write one with the .Net System.Text.RegularExpressions namespace).  Neither Notepad++ nor the grep search tool that comes with the GExperts suite that we use would run my expression (even though it uses only simple tokens that should be the same across all implementations).&lt;br /&gt;&lt;br /&gt;Here's the thing about regex; they can be &lt;span style="font-style: italic;"&gt;very&lt;/span&gt; powerful.  A single expression can be used as a substitute for a class with tons of conditional code.  But then, expressions like this are not very maintainable since they end up looking like a cartoon character's long outburst of profanity - that's the trade off.   One thing that helps a bit is that you can insert comments in .Net expressions like yay: (?# Look Mom! There's comments in my expression! ).&lt;br /&gt;&lt;br /&gt;Despite the complexity, some validation requirements are a no-brainer match (no pun intended) for regex - like validating email addresses.  I wrote an email address validation routine/object once - not easy after reading through the actual RFC for email addresses.  The .Net expression for this and other very common validations &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconRegularExpressionExamples.asp"&gt;are available on MSDN&lt;/a&gt;.   There are many more available on regexlib.com (along with an online expression tester).   I'm sure the expression that Kelly developed, no simple expression that, would be a good addition to regexlib.com.&lt;br /&gt;&lt;br /&gt;Even the &lt;a href="http://weblogs.asp.net/rosherove/"&gt;regex guru guest&lt;/a&gt; of the podcast recommended that they should be used sparingly.  If you do want to create one, use his regulazy tool.  That will get simple ones created for you very easily.  Then, if you need to create a sophisticated expression (replacements, named groups, ect.), use his &lt;a href="http://tools.osherove.com/CoolTools/Regulator/tabid/185/Default.aspx"&gt;Regulator&lt;/a&gt; tool.  This app includes things like intellisense for expression creation.  It will also interface with regexlib.com to help you find a pre-existing expression that may suit your needs.  Both are free!&lt;br /&gt;&lt;br /&gt;Another very useful resource that isn't regex, but is related is logparser.com.  This site maintains utilities that allow SQL like querying of commonly used log files (like IIS or SQLServer).&lt;br /&gt;&lt;br /&gt;One more note for .Net regex; if you are using the regex object to match repeatedly over alot of text, you can pass a param to the regex class that will cause the runtime to create an assembly (a class hard coded to meet your expression's specs) and run that assembly for speed.  Cool, huh?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-115956204700385921?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/115956204700385921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=115956204700385921' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/115956204700385921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/115956204700385921'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/09/regular-expression-tools.html' title='Regular Expression Tools'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-115275065531807098</id><published>2006-07-12T16:54:00.000-07:00</published><updated>2007-01-26T09:45:39.358-08:00</updated><title type='text'>Small Methodology</title><content type='html'>Judging from the amount of posts recently, I think I'm writing this to myself.  Oh well; dear diary...&lt;br /&gt;&lt;br /&gt;In this post I'm extolling the virtues of smaller methods.&lt;br /&gt;&lt;br /&gt;When I say small, how small do I really mean?  Several times&lt;span style="vertical-align: super;font-size:85%;" &gt;1&lt;/span&gt;, I've read no larger than what fits on a single screen although that's certainly debatable.&lt;br /&gt;Code Complete&lt;span style="vertical-align: super;font-size:85%;" &gt;2&lt;/span&gt;, the best code &lt;span style="font-style: italic;"&gt;construction&lt;/span&gt; book ever, has a section titled "How Long Can a Routine Be?"  It is surprisingly liberal, basically recommending smaller methods yet presenting some evidence that larger methods are not necessarily bad.   It almost contradicts itself in another section, "Scope", wherein it recommends "breaking related statements into separate, smaller routines".   The latter advice is given in the context of variable scope, so I suppose the lesson there is that length isn't as much a concern if there are few local variables involved.  But... I don't ever recall reading anything advising &lt;span style="font-style: italic;"&gt;larger&lt;/span&gt; methods.  The archives of &lt;a href="http://thedailywtf.com/"&gt;this site&lt;/a&gt; contain no end of examples of huge (edited) routines that caused no end of problems.&lt;br /&gt;&lt;br /&gt;In any case, here are some pros for smaller methods:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Much easier during maintenance to find the area of code needing change (let's see I know I need to change something somewhere in PlayThatFunkyMusic, but it's 1000 lines long... where?).  Note that you are in maintenance mode even when first developing the code.&lt;span style="vertical-align: super;font-size:85%;" &gt;3&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Code is &lt;span style="font-style: italic;"&gt;so much more readable.&lt;/span&gt;   Instead of trying to figure out if the next 10 lines are relevant to my problem, I read a MethodNameThatTellsMeWhatItDoes.&lt;/li&gt;&lt;li&gt;You end up with more efficient code since it's easier to see what you're doing.  If you keep adding more and more to a method w/o breaking it out to additional methods, there's a good chance you'll do more than what's necessary.  An example that surely came about in such fashion that I came across was a 600+ line method that had a nested 150 line if statement.  The nested if checked the same thing as the outer if, but had an else.  The compiler probably didn't give the unreachable code error because it was confused - or else I was confused.  Either way it made for a very difficult debugging exercise.&lt;/li&gt;&lt;li&gt;Communication of &lt;span style="font-style: italic;"&gt;intent&lt;/span&gt;.  Smaller methods with descriptive names are prefferable even to comments.  Intent is best communicated in structure and naming.  From Martin Fowler, "A block of code with a comment that tells you what it is doing can be replaced by a method whose name is based on the comment.  Even a single line is worth extracting if it needs explanation".&lt;span style="vertical-align: super;font-size:85%;" &gt;4&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;And here are some cons:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Function call overhead.  &lt;span style="font-style: italic;"&gt;Not!&lt;/span&gt;  Only in a case of a method/methods being called zillions of times would function call overhead (the cost of setting a spot in the register, adding to the stack, transferring execution to the new method, etc...) make a difference.  Besides, we never know when the compiler inlines methods under the covers eliminating this perf cost altogether.&lt;/li&gt;&lt;li&gt;Developer has to navigate around among more methods to get to where he/she needs to be.  There is some validity to this argument, but I think surely outweighed by the benefits and by the fact that there are ways (bookmarks, rapid finding [are you using GExperts?] and navigating among methods) to compensate for this.&lt;/li&gt;&lt;/ul&gt;In Extreme Programming Adventures in C#&lt;span style="vertical-align: super;font-size:85%;" &gt;5&lt;/span&gt;, Ron Jeffries (basically the founder of the XP movement) advises, "The 'right' structure for a method that does more than one thing is called 'Composed Method.'  Always create a method that is composed of nothing but method calls, all at the same level, rather than expanding any of the ideas out in line."  His example refactors this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public InputCommand(StringReader reader)&lt;br /&gt;{&lt;br /&gt;lines = new ArrayList();&lt;br /&gt;String line = reader.ReadLine();&lt;br /&gt;while (line != null &amp;&amp;amp; line != "*end")&lt;br /&gt;{&lt;br /&gt;lines.Add(line.TrimEnd());&lt;br /&gt;line = reader.ReadLine();&lt;br /&gt;}&lt;br /&gt;CleanTheLines();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;into this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;public InputCommand(StringReader reader)&lt;br /&gt;{&lt;br /&gt;ReadLines(reader);&lt;br /&gt;CleanTheLines();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;So each method that does multiple things makes calls to other methods.  Once a method does one distinct thing, it no longer needs refinement.  It's certainly my experience that such code is very easy to follow.&lt;br /&gt;&lt;br /&gt;Oh, and remember - BDS (and Visual Studio 2005) make extracting methods pretty easy.  Code on, brothers and sisters.  Oh wait, I'm just writing this to myself...&lt;br /&gt;&lt;br /&gt;Notes&lt;br /&gt;1)   Most recently in "Rules for Developing Safety Critical Code", IEEE Computer, June 2006; Code Complete also mentions this rule of thumb.&lt;br /&gt;2)  Code Complete is &lt;a href="http://www.books24x7.com/book/id_10482/toc.asp"&gt;Avail on the Intranet&lt;/a&gt; even though a search for it shows no results.&lt;br /&gt;3) &lt;a href="http://www.artima.com/intv/dry.html"&gt;Interview with Andy Hunt and Dave Thomas&lt;/a&gt;, "All Programming is Maintenance Programming".&lt;br /&gt;4) Refactoring, Page 77.&lt;br /&gt;5) Extreme Programming Adventures in C# is &lt;a href="http://http//common.books24x7.com/book/id_8355/book.asp?bookid=8355&amp;amp;refid=VOBZL"&gt;Avail on the Intranet&lt;/a&gt;.   Reference Chapter 9 under section, "InputCommand Refactoring".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-115275065531807098?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/115275065531807098/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=115275065531807098' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/115275065531807098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/115275065531807098'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/07/small-methodology.html' title='Small Methodology'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-114750258701982285</id><published>2006-05-12T22:37:00.000-07:00</published><updated>2006-05-18T16:21:34.930-07:00</updated><title type='text'>Intro to WinFX</title><content type='html'>Jenny and I attended a MS event about WinFX on the 12th.  Hopefully, this post will serve as a mini intro for anyone else interested in Microsoft's upcoming technologies.&lt;br /&gt;&lt;br /&gt;WinFX is basically MS's new API for windows.  It can be accessed via .Net 2.0 code and will come bundled as part of the next OS, Vista, as well as being available to install on WinXP and Server 2003.&lt;br /&gt;&lt;br /&gt;There are 3 pillars of WinFX that all follow the somewhat famous architecture outlined by Jack Greenfield in &lt;a href="http://msdn.microsoft.com/vstudio/teamsystem/workshop/sf/default.aspx?pull=/library/en-us/dnbda/html/softfact3.asp"&gt;his article&lt;/a&gt;, "Software Factories."  Greenfield was formerly a bigwig at Rational, where everything had UML as it's foundation and was supposed to be the shiznit, but fizzled.  Now his new ideas of using useful models to build real software (though there's more to the article) are becoming a reality.  So the model &lt;span style="font-style: italic;"&gt;is&lt;/span&gt; the code - just as you can design a form in our current tools and it is the actual form you run, so you can create models in a designer and it is the actual logic.&lt;br /&gt;&lt;br /&gt;Another main point about the new paradigm of development is that imperative and declaritive code can be separated much more easily.  So all the details of what you want to do (connect to this data store, use this protocol, make the interface look like this) are very easily separated from how (business logic).   All the declarative code goes into markup (XML or XaML).&lt;br /&gt;&lt;br /&gt;So the 3 pillars are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Windows Presentation Foundation - The all new UI.&lt;/li&gt;&lt;li&gt;Windows Communication Foundation - Web Services (or services that may reside on the same machine) enabling a service oriented architecture at any level.&lt;/li&gt;&lt;li&gt;Windows Workflow Foundation - Modeling as described above.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;Presentation Foundation (formerly Avalon)&lt;/span&gt;&lt;br /&gt;The UI uses "XaML" to represent any damn thing you can imagine.  The graphics engine supports regular bitmaps and vector graphics.  There is a pure UI designer piece called "Expression" whose graphics manipulation capabilities I can't adequately describe.  With XaML you can describe how you'd like a graphic to rotate, zoom (and vector graphics are crystal clear at any zoom factor), or whatever.  The controls you create that display all these graphics can reference templates for consistency.  Then the XaML is transferred to the developer.   &lt;a href="http://channel9.msdn.com/Showpost.aspx?postid=116327"&gt;Here's a video&lt;/a&gt; of a real application utilizing the presentation foundation.  One presenter mentioned that you will be able to run the same XaML on the desktop as is the browser, but this didn't seem to add up as there was a different Expression tool for web pages...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Communication Foundation (Formerly Indigo)&lt;/span&gt;&lt;br /&gt;Connect to anything using any transport mechanism with the same type of interface.  In a sample app, the presenter had connected to web services, but had also wrapped up communication with a regular human interfaced web page (querying availability of a product on a retailer's web site) for use in the same fashion.  So you communicate with another WinFX local service the same way as a web service.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Workflow Foundation (Formerly I don't know what)&lt;/span&gt;&lt;br /&gt;There used to be another piece to the WinFX pie called "WinFS," the "FS" for file system, I presume.  This piece dealt with an entirely new way to manage files.  Files had extensions (not in the name) that allowed for sophisticated organization and retrieval.  I'm not sure how much of that stayed in WinFX; as far as I can tell workflow foundation only deals with what I discussed above about being able to visually design your application's logic.&lt;br /&gt;You drop activities down on a design canvas and wire them together as a sequential diagram, a state machine (basically event driven), or as a rules driven machine.  You can even simply set a breakpoint on your activities and then step into them if they have additional code behind them.  I think this will &lt;span style="font-style: italic;"&gt;really &lt;/span&gt;encourage code re-use and third party vendors are already making lots of useful "activities".  So one of the out-of-box ones (I think) would be send an email message.  Drop down that activity, set some of it's properties and let 'er rip.  Activities can contain other activities, so you could even have a main activity be one that is the main gateway to persistence (save to data store).  Then each time execution enters that activity, it may flow into different sub-activities.  Another cool activity example is Amazon's purchase item activity.&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-114750258701982285?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/114750258701982285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=114750258701982285' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114750258701982285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114750258701982285'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/05/intro-to-winfx.html' title='Intro to WinFX'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-114722133292846443</id><published>2006-05-09T17:18:00.000-07:00</published><updated>2006-05-10T15:54:59.803-07:00</updated><title type='text'>Refactoring to eliminate duplication</title><content type='html'>As with a previous post, this may be obvious, but I think merits elucidation and discussion.&lt;br /&gt;There are many cases where  some code cries out, "refactor me!", but there never seems to be sufficient time.  In the opinion of most leaders in the software community, however, we should &lt;span style="font-style: italic;"&gt;make&lt;/span&gt; time; our efforts will always pay off.&lt;br /&gt;&lt;br /&gt;So here's something commonly seen:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;case PartyAnimal.Age of&lt;br /&gt;&amp;nbsp;2..12:&lt;br /&gt;&amp;nbsp;begin&lt;br /&gt;&amp;nbsp;&amp;nbsp;PutRightLegIn;&lt;br /&gt;&amp;nbsp;&amp;nbsp;PutRightLegOut;&lt;br /&gt;&amp;nbsp;&amp;nbsp;DoHokeyPokey;&lt;br /&gt;&amp;nbsp;&amp;nbsp;ShakeAbout;&lt;br /&gt;&amp;nbsp;end;&lt;br /&gt;&amp;nbsp;13..19:&lt;br /&gt;&amp;nbsp;begin&lt;br /&gt;&amp;nbsp;&amp;nbsp;PutRightLegIn;&lt;br /&gt;&amp;nbsp;&amp;nbsp;PutRightLegOut;&lt;br /&gt;&amp;nbsp;&amp;nbsp;DoMacarena;&lt;br /&gt;&amp;nbsp;&amp;nbsp;ShakeAbout;&lt;br /&gt;&amp;nbsp;end;&lt;br /&gt;&amp;nbsp;20..25:  //etcetera&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;We have some obvious repetition here that should be extracted into a method (wouldn't it be really cool if we had an IDE that would do this for us?  It does, you say?  Please teach me how; BDS gives me an error every time; VS2005 never did).&lt;br /&gt;&lt;br /&gt;To emphasize why it should be extracted into a method:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;When (note - not if) PutRightLegIn needs to change in every case, the change can be made in one place.&lt;/li&gt;&lt;li&gt;It makes for less code in the listing (and in the .exe).   Less code to do the same thing is &lt;span style="font-style: italic;"&gt;always&lt;/span&gt; a good thing. &lt;span style="font-size:78%;"&gt;(1)&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;To quote Martin Fowler, "the essence of good design is ensuring that the code says everything once and only once."  And better design makes for more efficient maintenance. &lt;span style="font-size:78%;"&gt;(2)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;It follows the DRY principle:  Every piece of knowledge in the development of something should have a single representation. (3)  The piece of knowledge in this case is RightLegIn, RightLegOut, X, ShakeAbout.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;So, of course, our refactored case statement (after adding our new method, DoPartyDanceWith) looks like:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;case PartyAnimal.Age of&lt;br /&gt;&amp;nbsp;2..12:&amp;nbsp;&amp;nbsp;DoPartyDanceWith( HokeyPokey );&lt;br /&gt;&amp;nbsp;13..19:&amp;nbsp;DoPartyDanceWith( Macarena );&lt;br /&gt;&amp;nbsp;20..25:  //etcetera&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt; I'm hoping the next time each of us has to modify something that looks like this, there will be a greater itch to refactor, then modify.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Notes:&lt;br /&gt;1) &lt;a href="http://www.faqs.org/docs/artu/"&gt;The Art of Unix Programming&lt;/a&gt; (and a zillion other places)&lt;br /&gt;2) &lt;a href="http://www.amazon.com/gp/product/0201485672/qid=1147279647/sr=2-1/ref=pd_bbs_b_2_1/002-6501382-5112067?s=books&amp;v=glance&amp;amp;n=283155"&gt;Refactoring&lt;/a&gt;&lt;br /&gt;3) &lt;a href="http://www.amazon.com/gp/product/020161622X/qid=1147280268/sr=2-1/ref=pd_bbs_b_2_1/002-6501382-5112067?s=books&amp;v=glance&amp;n=283155"&gt;The Pragmatic Programmer&lt;/a&gt; (and many other places)&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-114722133292846443?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/114722133292846443/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=114722133292846443' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114722133292846443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114722133292846443'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/05/refactoring-to-eliminate-duplication.html' title='Refactoring to eliminate duplication'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-114667687918941482</id><published>2006-05-03T10:06:00.000-07:00</published><updated>2006-05-03T10:21:19.200-07:00</updated><title type='text'>get_ and set_</title><content type='html'>By default, if you have a property named MyProp, Delphi assumes methods named GetMyProp and SetMyProp.  Per a Delphi 2005 book I have read, Delphi.NET actually compiles this code creating new methods get_MyProp and set_MyProp which in turn call the original methods.  We could eliminate this extra layer if we just use get_ and set_ for the original names.  This would have at least a minor improvement in performance.  So, should we set a standard of get_ and set_ for future property specifier names?&lt;br /&gt;&lt;br /&gt;PS:  if the specifiers simply refer to an element such as FMyProp, Delphi still creates get_ and set_methods that then access FMyProp.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-114667687918941482?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/114667687918941482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=114667687918941482' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114667687918941482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114667687918941482'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/05/get-and-set.html' title='get_ and set_'/><author><name>bilbo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-114667587412822848</id><published>2006-05-03T09:45:00.000-07:00</published><updated>2006-05-03T10:04:34.140-07:00</updated><title type='text'>Read only class attribute</title><content type='html'>Say I have a class that has some attribute that is basically read only.  Each child of the class has a fixed value for this attribute for all instances of that child class.  Three possible ways to implement this are:&lt;br /&gt;&lt;br /&gt;1.   Add an element named MyAttribute.  In the constructor, set the value of MyAttribute. &lt;br /&gt;&lt;br /&gt;2.  Add a function named MyAttribute that is overwritten in each child class.&lt;br /&gt;&lt;br /&gt;3.  Add an element named FMyAttribute and then add a MyField property with a read specifier of FMyField.  In the constructor, set the value of FMyAttribute.&lt;br /&gt;&lt;br /&gt;4.  Add a Get method named GetMyAttribute and then add a MyField property with a read specifier of GetMyField.  In each class, override GetMyAttribute.&lt;br /&gt;&lt;br /&gt;I assume option 1 is the least desirable since it doesn't enforce read-only and basically does not fit in with the standards we are striving for.  Option 4  is seems to be the most robust, but is overkill.  Any opinions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-114667587412822848?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/114667587412822848/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=114667587412822848' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114667587412822848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114667587412822848'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/05/read-only-class-attribute.html' title='Read only class attribute'/><author><name>bilbo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-114658733654893985</id><published>2006-05-02T09:09:00.000-07:00</published><updated>2006-05-03T08:02:58.523-07:00</updated><title type='text'>GAIM: Lotus SameTime client replacement</title><content type='html'>When ING blocked the external IM ports I for one found the Lotus client lacking in features compared to the clients that we had been using.  Well the other day on my Mac I noticed that the client I was using had an option for SameTime.  This made me ask why we couldn't use a different client at work as well.  So I did some looking and found several clients that said they had SameTime support.  The client I had previously been using, Trillian, did mention SameTime support but only in their "Pro" version.  Another client that said they support SameTime was GAIM.  I have been using this client on my Linux box at home for a few years now and have been happy with it.  It is free, open source software.  There is a Windows port of this program and the rest of this post details my experience so far with it.&lt;br /&gt;&lt;br /&gt;If you want to try GAIM for SameTime you first need to download the client using the link at the top of &lt;a href="http://gaim.sourceforge.net/win32/index.php"&gt;this page&lt;/a&gt;.  Once downloaded go ahead and install the program.  I used the default install options.&lt;br /&gt;&lt;br /&gt;Next you will need the GAIM plugin for the SameTime protocol.  This plugin is Meanwhile.  It can be downloaded from &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=110565&amp;package_id=119703&amp;amp;release_id=387119"&gt;this page&lt;/a&gt;. (Updated)  Be sure to pick the Windows version.  It should be the file with "win" in the name.  Once downloaded you can run the install.  It should place the plugin into the appropriate folder.&lt;br /&gt;&lt;br /&gt;Next open GAIM.  It will present you with a login dialog and most likely open the Accounts window.  I believe you need to go into Tools-&gt;Preferences and select the Meanwhile plugin in the plugins section before adding an account.  Forgive me but I don't remember the exact steps for this but  I believe it was intuitive.&lt;br /&gt;&lt;br /&gt;Once the plugin is active you should be able to use the accounts dialog to add a new account.  Select Meanwhile in the type dropdown list.  Enter your username and password.  Your password should be the same one used for logging into Exchange.  For the servername I cut and pasted out of the Lotus client settings.  Here's a screenshot of my account settings.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/4507/1352/1600/AccountSettings.0.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://photos1.blogger.com/blogger/4507/1352/320/AccountSettings.0.jpg" alt="" border="0" /&gt;&lt;/a&gt;You should now be ready to connect and start IM'ing.  For me my buddy list appeared the second I successfully connected.  Since it is stored on the server you can make changes here or in the Lotus client and both see the changes.  The only area that I've had trouble figuring out in GAIM is adding new buddies.  To do this I switch to the Lotus client, add the buddy, then go back to using GAIM.&lt;br /&gt;&lt;br /&gt;From here you can go in and customize your settings in Tools-&gt;Preferences.  I've turned on several of the plugins to improve the behavior as well as logging, conversation history, etc.  Here's a screenshot of my pimped out IM client.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/4507/1352/1600/ScreenShot.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://photos1.blogger.com/blogger/4507/1352/320/ScreenShot.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I've been using this client for a couple days now with no noticable problems.  If all else fails we have the Lotus client to fall back on.  Happy IM'ing!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-114658733654893985?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/114658733654893985/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=114658733654893985' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114658733654893985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114658733654893985'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/05/gaim-lotus-sametime-client-replacement.html' title='GAIM: Lotus SameTime client replacement'/><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-114615360063864177</id><published>2006-04-27T08:25:00.000-07:00</published><updated>2006-05-01T12:27:32.460-07:00</updated><title type='text'>Against Globalization</title><content type='html'>No, this isn't a political rant.  I'm discussing global variables; in our case the collection of globals in Rng, Inp, and Outp.&lt;br /&gt;&lt;br /&gt;Let me preface the discussion by saying that I understand that there is a good reason the globals exist (they go &lt;span style="font-style: italic;"&gt;way&lt;/span&gt; back).&lt;br /&gt;&lt;br /&gt;The following happened on Monday and illustrates one of the problems with globals:&lt;br /&gt;I was making last minute changes to a product.  I was setting an Rng variable in the product, but by the time the output code ran, that boolean always had a reverse value.  I searched the code for all places that changed that global, but didn't find any that I wasn't already aware of.  To temporarily solve the problem I implemented a hack.&lt;br /&gt;&lt;br /&gt;Cindy later explained to me why the global seemed to be changing, but no matter; the root problem is globals themselves.&lt;br /&gt;&lt;br /&gt;I'm sure you're all aware of all or part of the following, but I wanted to put together a good list of reasons why globals are bad&lt;span style="font-family:georgia;"&gt; with few exceptions:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;They make the code less modular; in fact they make it anti-modular - everything is tied to the globals.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;When globals are used, it's exponentially more difficult to determine what to change.  When all variables are in their own (smaller) object, you can find what needs to change much more quickly.&lt;/li&gt;&lt;li&gt;Using globals leads to duplicated and unused variables (of which Cindy and I have found several just since I've been here).&lt;/li&gt;&lt;li&gt;Better memory footprint: more objects, but fewer in memory at any given time.&lt;/li&gt;&lt;li&gt;Much easier debugging.  Even when you have a simple "dummy" member variable with an accessor at least you can set a breakpoint on the accessor and easily track down all callers.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:georgia;"&gt;This from &lt;/span&gt;&lt;a style="font-family: georgia;" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconfieldusageguidelines.asp"&gt;a portion of the coding standards&lt;/a&gt;&lt;span style="font-family:georgia;"&gt; that Rob referenced in a previous post (and another reason to always have accessors even if they're just dummy accessors): "If you avoid exposing fields directly to the developer, classes can be versioned more easily because a field cannot be changed to&lt;/span&gt; a property while maintaining binary compatibility. Consider providing get and set property accessors for fields instead of making them public. The presence of executable code in get and set property accessors allows later improvements, such as creation of an object on demand, upon usage of the property, or upon a property change notification."&lt;/li&gt;&lt;li&gt;They make test driven development (even though we may never actually adopt this) virtually impossible because you can't test objects individually; they all need globals that are manipulated by other parts of the main app.&lt;/li&gt;&lt;li&gt;For more, see &lt;a href="http://common.books24x7.com/book/id_10482/book.asp?bookid=10482&amp;refid=VOBZL"&gt;&lt;/a&gt;&lt;a href="http://common.books24x7.com/book/id_10482/book.asp?bookid=10482&amp;amp;refid=VOBZL"&gt;Code Complete&lt;/a&gt; | Chapter 13 | 13.3:  Global Data.&lt;/li&gt;&lt;/ul&gt;So, bottom line; I think we should begin avoiding them going forward if we want the app to evolve more easily.&lt;br /&gt;&lt;br /&gt;In the specific case outlined above, I should have added a member variable to the product class and accessed it from the output code (even though it's a little funky to access the product object at that point).&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-114615360063864177?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/114615360063864177/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=114615360063864177' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114615360063864177'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114615360063864177'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/04/against-globalization.html' title='Against Globalization'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-114607930085901091</id><published>2006-04-26T12:11:00.000-07:00</published><updated>2006-04-26T12:21:40.873-07:00</updated><title type='text'>Don't ever ask me to buy another book again!</title><content type='html'>I was just in a meetng were the ING Learning Centre has partnered with Skill Soft to provide ING employees with an electronic book library.  It is called Books 24X7.  It is amazing. &lt;br /&gt;&lt;br /&gt;I was taking a quick look at it and we already have access to the latest Delphi 2006 and Delphi 2005 books that were written.  From what I can tell certain books you can download and other are viewable through browser only. &lt;br /&gt;&lt;br /&gt;I think this is very exciting.  There was even a category for algorithms which I know Steve and Dennis will have a hay day with. &lt;br /&gt;Here is asome additional informaiton about Books 24/7:&lt;br /&gt;&lt;br /&gt;- ACCESSING Books24x7: Access to Books24x7 is through the icon on the Other Resources tab of the ILC. If you do not see the Other Resources tab, look for the Books24x7 Referenceware course in the Knowledge Tools section of your ILC homepage. If you had a previous subscription to Books24x7 and accessed their site directly, you will now need to go through the ILC to access it. Direct access to the Books24x7 site is no longer available.&lt;br /&gt;&lt;br /&gt;- HELP AND SUPPORT: There is an extensive help system in the Books24x7 site available from the Help tab at the top of the screen. If you require technical support, please contact your ILC Administrator for your business area (click on the ILC Contact button on the logon page or homepage of the ILC).&lt;br /&gt;&lt;br /&gt;- NEW BOOK NOTIFICATIONS: You will receive periodic email notifications from Books24x7 about interesting new books available through the service. If you want to access those new titles, enter Books24x7 through the ILC and search on those titles within the Books24x7 site.&lt;br /&gt;&lt;br /&gt;- DOWNLOADING BOOKS: Not all books are available for download or audio access. If you find a book that has these options, refer to the Help guide within Books24x7 for instructions.&lt;br /&gt;&lt;br /&gt;- CHANGING YOUR SETTINGS: Personal settings (except ID, name and email), can be changed using the Settings tab at the top of the screen in Books24x7. If your personal information changes (e.g., name, email address, etc.) you will need to make sure it gets changed in the ILC for it to reflect in Books24x7.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-114607930085901091?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/114607930085901091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=114607930085901091' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114607930085901091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114607930085901091'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/04/dont-ever-ask-me-to-buy-another-book.html' title='Don&apos;t ever ask me to buy another book again!'/><author><name>mightymouse</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-114606869721635432</id><published>2006-04-26T08:45:00.000-07:00</published><updated>2006-04-26T09:24:57.230-07:00</updated><title type='text'>SlickRun</title><content type='html'>Since Rob sent us a list of useful freeware, I couldn't resist posting about one of the utilities on the list that I &lt;span style="font-style: italic;"&gt;cannot&lt;/span&gt; live without; &lt;a href="http://www.bayden.com/SlickRun/"&gt;SlickRun&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I can't live without it mostly because I despise that evil little monstrosity next to my keyboard most people refer to as the "mouse".  But that doesn't mean you have to hate the hand manipulation device of doom to benefit from SlickRun.  It makes launching common tasks way more efficient.&lt;br /&gt;&lt;br /&gt;Here's what it is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A place to centralize and manage all of the apps you commonly run.&lt;/li&gt;&lt;li&gt;A scratchpad for temporary pasting text.&lt;/li&gt;&lt;li&gt;A quick calculator.&lt;/li&gt;&lt;/ul&gt;The command launcher is something you use to create and launch shortcuts.  So to open VSS I hit -&gt; Window Key + A, "s", enter.  As soon as I type "s" it completes my keyword for VSS ("sourcesafe") and hitting enter launches the app.  Any time I open something more than twice, I add it to SlickRun and make opening it the next time faster (while laughing at my mouse).  Any command you can enter at the run prompt works as well.&lt;br /&gt;&lt;br /&gt;But there's more.  You can add dynamic parameters to your commands.  So one of my commands is "compare".  When I run that command it prompts me for 2 file paths.  I browse to and right click (using the right click key of course) on 2 files I want to compare and put their paths on the clipboard (using &lt;a href="http://www.moonsoftware.com/download.asp"&gt;FileTargets&lt;/a&gt;, another handy utility), paste them into the prompt and it launches a file compare utility passing the paths to it which immediately shows me whether the files match.&lt;br /&gt;&lt;br /&gt;The "jot" scratchpad comes up with a keystroke and always auto saves.  So I invoke it, paste in some text and hit escape; it'll be there the next time I invoke it.&lt;br /&gt;&lt;br /&gt;The same little window that you type your commands into serves as a calculator.  I like to use it in favor of the windows calculator most of the time because I can easily enter several numbers with lots of parentheses.  You can see each step of the calc all at once.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-114606869721635432?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/114606869721635432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=114606869721635432' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114606869721635432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114606869721635432'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/04/slickrun.html' title='SlickRun'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-114606674482151757</id><published>2006-04-26T08:39:00.000-07:00</published><updated>2006-04-26T08:54:01.796-07:00</updated><title type='text'>Coding Standards</title><content type='html'>Well, since the Web Illustrations project came together so fast we never really took the time to hammer out any good coding standards for our new .NET code, as well as HTML, scripts, etc.  Now that the dust is settling a bit I'm going back and trying to clean up and comment some of my code.  We now have Delphi.NET, C#, JavaScript, HTML, CSS, and XML files just to name a few.  We do have documentation on Win32 Delphi coding standards, albeit a bit old.&lt;br /&gt;&lt;br /&gt;For our C# code we should follow the Microsoft recommendations.  It can be found on MSDN at:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconNETFrameworkDesignGuidelines.asp"&gt;Design Guidelines for Class Library Developers&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Would it also make sense for our Delphi.NET code to follow this standard as well?  Or should it follow closer to the Win32 Delphi standards we currently use?  Perhaps Rich or Steve could speak as to what they've been doing in the .NET code sections.&lt;br /&gt;&lt;br /&gt;I did some looking but could not find an authoritative JavaScript coding standard.  There were several mentions to a document on the Netscape developers site but it appears to be gone.  The Mozilla project doesn't seem to have anything similar.  It appears to me that most sites (including Microsoft) appear to use Camel Case for most of their JavaScript variables and methods.  I've tried to follow suit.&lt;br /&gt;&lt;br /&gt;HTML, CSS and XML standards are sort of a whole other animal and perhaps would be worthy of a thread all their own if anyone is interested.&lt;br /&gt;&lt;br /&gt;So I pose it to the group, what are your thoughts/feelings/recommendations on new and improved standards?  Perhaps some of the new people have experience from their previous lives?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-114606674482151757?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/114606674482151757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=114606674482151757' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114606674482151757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114606674482151757'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/04/coding-standards.html' title='Coding Standards'/><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-25574505.post-114546370318186841</id><published>2006-04-19T08:44:00.000-07:00</published><updated>2006-04-21T16:59:38.993-07:00</updated><title type='text'>Intro to OneNote</title><content type='html'>For those who don't know what it is, OneNote is a new app in the MS Office suite (so we all have a license).  I decided to try it out from day one here at ING.&lt;br /&gt;&lt;br /&gt;My motivation is this:  I (like most people)  frequently take notes with  paper and pencil.  For years, I've been in the habit of maintaining to-do lists with little boxes next to each item.  But this is inefficient:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I type much faster than I write.&lt;/li&gt;&lt;li&gt;It's easier to type while talking on the phone.&lt;/li&gt;&lt;li&gt;I can take notes on computer in more places using a laptop.&lt;/li&gt;&lt;li&gt;All my notes are in one place - on my machine.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;OneNote is a tool for managing lots of notes.&lt;br /&gt;&lt;br /&gt;At first it didn't seem too much different from a plain old word processor.  But here are some important differences:&lt;ul&gt;&lt;li&gt;You never have to create or save files.  Rather, you set a directory as your designated OneNote directory (and back it up of course) and OneNote manages the files (including auto-saving).&lt;/li&gt;&lt;li&gt;You can tag items paragraphs/sentences/bullets with "note flags".  You tag items with stars, question marks, rememeber for later, or check boxes.  Then you can search all your notes for a given note flag.&lt;/li&gt;&lt;li&gt;You can also simply draw something on your page freehand or easily take snapshots of some portion of your screen.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The organization for notes is section - page - subpage.  Within a page/subpage you create paragraphs/bullet lists/whatever.  Each of these items is automatically grouped into a draggable object thingy that makes it very easiy to cut and paste or drag and drop logically grouped info.&lt;/li&gt;&lt;/ul&gt;So here's a visual.  I have a section titled "Trackers", and each page is titled with a tracker ID.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/1084/2675/1600/OneNote.1.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://photos1.blogger.com/blogger/1084/2675/320/OneNote.1.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Under my "Meetings" section I have pages titled for each type of recurring meeting.  I haven't yet used subpages.&lt;br /&gt;&lt;br /&gt;Anyway, I'm really liking it.  There are other features of course; these are just the basics.  Maybe you will find it useful too!&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/blogger/1084/2675/1600/Trackers2.png"&gt;&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/25574505-114546370318186841?l=codejournal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codejournal.blogspot.com/feeds/114546370318186841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=25574505&amp;postID=114546370318186841' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114546370318186841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/25574505/posts/default/114546370318186841'/><link rel='alternate' type='text/html' href='http://codejournal.blogspot.com/2006/04/intro-to-onenote.html' title='Intro to OneNote'/><author><name>Brad</name><uri>http://www.blogger.com/profile/15076922240080087715</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry></feed>
