<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Nick Hodges</title>
	<atom:link href="http://blogs.embarcadero.com/nickhodges/feed" rel="self" type="application/rss+xml" />
	<link>http://blogs.embarcadero.com/nickhodges</link>
	<description>The Blog of the Delphi Product Manager</description>
	<pubDate>Mon, 14 Jun 2010 22:07:53 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en-US</language>
			<item>
		<title>Random Thoughts on the Passing Scene #162</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/06/14/39454</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/06/14/39454#comments</comments>
		<pubDate>Mon, 14 Jun 2010 22:07:53 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/06/14/39454</guid>
		<description><![CDATA[
What is the Delphi component that you can’t live without? 
The on demand replay for the &#34;Extreme Cross-Platform .NET with Delphi Prism 2011&#34; webinar is now available at http://forms.embarcadero.com/forms/AMUSCA1006DelphiPrism20116-2. 
I’ve always been a big Jeff Duntemann fan, because he’s a great writer, an interesting guy, and because he’s been a Pascal/Delphi fan from way back.&#160; [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href="http://stackoverflow.com/questions/3017743/delphi-component-you-cant-live-without">What is the Delphi component that you can’t live without?</a> </li>
<li>The on demand replay for the &quot;Extreme Cross-Platform .NET with Delphi Prism 2011&quot; webinar is now available at <a href="http://forms.embarcadero.com/forms/AMUSCA1006DelphiPrism20116-2">http://forms.embarcadero.com/forms/AMUSCA1006DelphiPrism20116-2</a>. </li>
<li>I’ve always been a big Jeff Duntemann fan, because he’s a great writer, an interesting guy, and because he’s been a Pascal/Delphi fan from way back.&#160; (I was honored when he sent me an autographed copy of his excellent <a href="http://www.amazon.com/Cunning-Blood-Jeff-Duntemann/dp/0975915622/">The Cunning Blood</a> – a book I thoroughly enjoyed &#8211;&#160; back when the new Turbo products were released.)&#160;&#160;&#160; Anyway, Jeff has a new collection of short stories out called <a href="http://jeff-duntemann.livejournal.com/245360.html">Cold Hands and Other Stories</a>.&#160; You can <a href="http://www.lulu.com/product/paperback/cold-hands-and-other-stories/11064883">get it on lulu.com</a> – my favorite place to buy books.</li>
<li><a href="http://edn.embarcadero.com/article/40662">The US Geological Survey built it with Delphi.</a></li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39454&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39454" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23162&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F06%2F14%2F39454" id="akst_email_39454" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/06/14/39454/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Delphi Pretty Good Practices #5 &#8211; Don&#8217;t Use Literals</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/06/09/39453</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/06/09/39453#comments</comments>
		<pubDate>Wed, 09 Jun 2010 18:03:37 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Best Practices]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/06/09/39453</guid>
		<description><![CDATA[If there is a bedrock, bottom line, everyone-should-follow-it-all-the-time rule in programming it is “The DRY Principle” – Don’t Repeat Yourself.&#160; This simple rule states that you should write code once and only once, and that you shouldn’t allow the same code to be used all over the place.&#160; Or, as the Wikipedia article deftly states: [...]]]></description>
			<content:encoded><![CDATA[<p>If there is a bedrock, bottom line, everyone-should-follow-it-all-the-time rule in programming it is “<a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">The DRY Principle</a>” – Don’t Repeat Yourself.&#160; This simple rule states that you should write code once and only once, and that you shouldn’t allow the same code to be used all over the place.&#160; Or, as the <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">Wikipedia article deftly states</a>: &quot;Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.&quot;&#160; Put more simply, it means that you shouldn’t have the same thing repeated all over your code, but that you should create a single identifier and use that in the many places where it might be needed.</p>
<p>As a practical matter, the DRY principle in its most basic form tells us that we should, as a matter of course, not use literals in our code, but instead should declare constants (or <font face="Courier New">resourcestring</font> types as we’ll discuss in a minute) and use those instead. That way, if you need to change the value for something, you can do it in a single place instead of having to make multiple, error-prone changes throughout your existing code.</p>
<p>For example:&#160; Say you have a system that has an arbitrary number of required repetitions, say 17.&#160; You might end up writing a whole bunch of code like this:</p>
<pre><code>
<b>for</b> i := 1 <b>to</b> 17 <b>do</b>
<b>begin</b>
  ProcessStuff;
  DoSomeMoreStuff;
<b>end</b>;

</code></pre>
<p>Now imagine that you have that kind of code all over the place, and then your boss comes around and says &quot;Hey, we need to repeat all that stuff 18 times now, not just seventeen.” Well, if you haven&#8217;t followed the DRY Principle, you could very well end up with a lot of code to change.&#160; And don&#8217;t use search and replace, because what if you change the 17 that is part of a variable name or something?&#160; Things could get ugly fast.</p>
<p>Of course, the thing to do is to declare a constant:</p>
<pre><code>
<b>const</b>
  NumberOfRepetitions = 17;

</code></pre>
<p>and declare your loops as</p>
<pre><code>
<b>for</b> i := 1 <b>to</b> NumberOfRepetitions  <b>do</b>
<b>begin</b>
  ProcessStuff;
  DoSomeMoreStuff;
<b>end</b>;

</code></pre>
<p>and now when your boss switches things up, you have but one simple change to make, and all is well.</p>
<p>Now this is a pretty simple, basic thing to do, but I’m constantly surprised at how often I find myself forgetting to do it.&#160; (For instance, if you look through the code for TextScrubber, you’ll probably notice that I need to apply the DRY Principle to the <font face="Courier New">TVersionInfo</font> constructor in <font face="Courier New">uTextScrubberTypes.pas.</font>) You might be surprised how many literals you use in your code. I often take advantage of the syntax highlighting feature to scan code for specific colors for strings and numbers and replace them with constant values as much as possible. For instance, some code from TextScrubber used to look like this:</p>
<pre><code>
<b>procedure</b> TStraightTextMainForm.InitializeMainFormInformation;
<b>var</b>
  IniFile: TIniFile;
<b>begin</b>
  IniFile := TIniFile.Create(IniFileName);
  <b>try</b>
    TextScrubberOptions.ClickChoice := TClickChoice(
      IniFile.ReadInteger(<font color="yellow">'Options'</font>, cClickChoice, 0));
      TextScrubberOptions.ShouldTrim := IniFile.ReadBool(cOptions,
      <font color="yellow">'ShouldTrimText'</font>, False);
  <b>finally</b>
    IniFile.Free;
  <b>end</b>;
<b>end</b>;

</code></pre>
<p>with a bunch of string literals.&#160; Instead, now, I&#8217;ve declared two constants in the <font face="Courier New">uTextScrubberConsts.pas</font> unit</p>
<pre><code>
<b>const</b>
  cOptions = <font color="yellow">'Options'</font>;
  cClickChoice = <font color="yellow">'ClickChoice'</font>;
  cShouldTrimText = <font color="yellow">'ShouldTrimText'</font>;
  cVersionLangCodePage = <font color="yellow">'040904E4'</font>;

</code></pre>
<p>and the new code looks like this:</p>
<pre><code>
<b>procedure</b> TStraightTextMainForm.InitializeMainFormInformation;
<b>var</b>
  IniFile: TIniFile;
<b>begin</b>
  IniFile := TIniFile.Create(IniFileName);
  <b>try</b>
    TextScrubberOptions.ClickChoice := TClickChoice(
      IniFile.ReadInteger(cOptions,   cClickChoice, 0));
    TextScrubberOptions.ShouldTrim := IniFile.ReadBool(cOptions,
      cShouldTrimText, False);
  <b>finally</b>
    IniFile.Free;
  <b>end</b>;
<b>end</b>;

</code></pre>
<p>Those constants are also used when I write out information to the INI file, so that I can change the value in one place if I need to, and so that I can know that there won’t be any typographical errors in my strings that will cause a bug.&#160; The same string value is always going to be used for the INI file entry.</p>
<p>Now let’s take a look specifically at strings.&#160; Strings are a bit special because they are very often used to communicate information, and as such, they frequently need to be translated into other languages through the process of “localization”.&#160; Windows provides an easy way to do this via string resources, and Delphi provides an easy way to create string resources via the <font face="Courier New">resourcestring</font> identifier.&#160; These strings are then created as resources, making them easy to translate.&#160; And “easy to translate” can often be, well, translated into “cheaper to translate” and that is a good thing.</p>
<p>Practically speaking, I apply this principle by placing as many <font face="Courier New">const</font> and <font face="Courier New">resourcestring</font> declarations as I can in a single file, thus centrally locating them for easy management and translation.&#160; In our case with the <font face="Courier New">TextScrubber</font> project, I’ve created a file called <font face="Courier New">uTextScrubberConsts.pas</font> and put constants and resource string values into it.&#160; If you look through the project code, you’ll probably notice that I need to apply the DRY Principle to the <font face="Courier New">TVersionInfo</font> constructor in <font face="Courier New">uTextScrubberTypes.pas</font>, even if it is keeping those constants within the unit.</p>
<p>One question that might get asked is “How do you choose what to make a <font face="Courier New">const</font> and what to make a <font face="Courier New">resourcestring</font>?”&#160; My answer is that as a general rule, any string that could change without changing the UI or the functionality of the code, make a <font face="Courier New">const</font>.&#160; Any string that, if changed, will trigger a change in UI or translation should be made a <font face="Courier New">resourcestring</font>.&#160; There are exceptions to that, of course. More simply, a rule to use that anything that might get translated should be a <font face="Courier New">resourcestring</font>.</p>
<p>Now, this is a pretty simple “pretty good practice” to follow, but for you folks who have <strong><em>not</em></strong> been following this principle,&#160; simply doing so can make your code more readable and maintainable.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39453&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39453" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Delphi%20Pretty%20Good%20Practices%20%235%20%26ndash%3B%20Don%26rsquo%3Bt%20Use%20Literals&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F06%2F09%2F39453" id="akst_email_39453" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/06/09/39453/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #161</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/06/08/39452</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/06/08/39452#comments</comments>
		<pubDate>Tue, 08 Jun 2010 22:27:28 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Random Thoughts]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/06/08/39452</guid>
		<description><![CDATA[
One of the cool features of Delphi Prism 2011 is the built-right-into-the-language support for Aspect Oriented Programming (AOP).&#160; John Moshakis has a nice blog post giving an example of exactly the kind of things that Aspects can to do make your code cleaner and easier to maintain:&#160; providing a data and domain object validation aspect.&#160; [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>One of the cool features of <a href="http://www.embarcadero.com/products/delphi-prism">Delphi Prism 2011</a> is the built-right-into-the-language support for Aspect Oriented Programming (AOP).&#160; <a href="http://www.moshine.com/blog/">John Moshakis</a> has a nice blog post giving an example of exactly the kind of things that Aspects can to do make your code cleaner and easier to maintain:&#160; <a href="http://www.moshine.com/blog/post/2010/06/Domain-Object-Validation-with-AOP.aspx">providing a data and domain object validation aspect</a>.&#160; And he demonstrates it in a Silverlight application and using MVC.&#160; All in Delphi Prism. Which you can <a href="http://www.embarcadero.com/how-to-buy">buy right now</a>.&#160; Cool. I tell you, it’s never been a better time to be doing Delphi Programming.&#160; </li>
<li>By the way,I am now making it my personal mission to put the phrase “DelphI Programming” into every one of my blog posts. <img src='http://blogs.embarcadero.com/nickhodges/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </li>
<li>If you are really into Delphi Programming, and would like to gain some insight into your code, you might be interested in <a href="http://www.peganza.com/whatsnew_pal5.htm">the special reduced price being run by the folks at Peganza for their Pascal Analyzer 5</a>. </li>
<li>Yea! <a href="http://stackoverflow.com/questions/2639281/code-golf-the-mandelbrot-set/2979121#2979121">More Delphi Code Golf!</a> </li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39452&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39452" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23161&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F06%2F08%2F39452" id="akst_email_39452" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/06/08/39452/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #160</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/06/04/39451</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/06/04/39451#comments</comments>
		<pubDate>Fri, 04 Jun 2010 17:43:34 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Random Thoughts]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/06/04/39451</guid>
		<description><![CDATA[
The topic of newsgroup participation came up in our Delphi.non-technical group, and I mentioned that it appears that more people seem to be using StackOverflow to get answers to their questions.&#160;&#160; Craig Stuntz turned around and in his own inimitable way, proved that such is the case.&#160; I know that I check StackOverflow a couple [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>The topic of <a href="http://forums.embarcadero.com">newsgroup participation</a> came up in our Delphi.non-technical group, and I mentioned that it appears that more people seem to be using <a href="http://www.stackoverflow.com">StackOverflow</a> to get answers to their questions.&#160;&#160; <a href="http://blogs.teamb.com/craigstuntz">Craig Stuntz</a> turned around and in his own inimitable way, <a href="http://cloudexchange.cloudapp.net/stackoverflow/q/2200">proved that such is the case</a>.&#160; I know that I check StackOverflow a couple of times a day, and try to make modest contributions.&#160; I endeavor to vote for good answers and to give good answers when I can.&#160; The cool part is that if you are only interesting in Delphi Programming questions, you can really make it “<a href="http://stackoverflow.com/questions/tagged/delphi">DelphiOverflow</a>” by simply paying attention to the correct tags.&#160; </li>
<li>Speaking of stuff on StackOverflow, <a href="http://robstechcorner.blogspot.com/">Robert Love</a> pointed out something I hadn’t seen before on there: <a href="http://stackoverflow.com/questions/tagged/code-golf">Code-Golf</a>.&#160; This is a question that asks a small development problem, and then folks post their answers in their favorite languages using as few characters as possible (low score wins, like in golf).&#160; Kind of fun.&#160; <a href="http://www.delphifeeds.com/go/f/68687?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed:+delphifeeds+(DelphiFeeds.com)">Robert threw in a Delphi answer for this question</a>, and he inspired me <a href="http://stackoverflow.com/questions/2969696/code-golf-phone-number-to-words">to post my own Code Golf problem</a>.&#160;&#160; So, if you are so inclined, I’d love to see a Delphi solution, though I’m sure it will be tough to compete with some of the command line scripting languages. Next time I’ll make the criteria be a command line EXE.&#160; <img src='http://blogs.embarcadero.com/nickhodges/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </li>
<li>Forgive me, but <a href="http://www.youtube.com/watch?v=hkDD03yeLnU">I found this quite funny</a>. Please note the text bubble near the end. Now if she had decided to use Delphi, well, that might have been a different story.&#160; I am also reminded that <a href="http://twitter.com/delphijunkie/status/15393371112">Jack Bauer uses Delphi</a> – and <a href="http://bauerkillcount.com/">I strongly recommend against crossing Jack Bauer</a>.</li>
<li>I’ve mentioned that there is a new version of Delphi Prism – and one of it’s new features is the ability to put some C# code on the clipboard and paste it as Prism code.&#160; If any of you is interested in automating the process, there is <a href="http://code.remobjects.com/p/csharptoxy/">a command line version of that tool available</a>.</li>
<li>Oh, and don’t worry, I haven’t given up on the “Pretty Good Practices” series.&#160; I’ve got a few drafts in the queue, but they are a bit tougher to write than the Random Thoughts items.</li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39451&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39451" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23160&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F06%2F04%2F39451" id="akst_email_39451" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/06/04/39451/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #159</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/06/02/39449</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/06/02/39449#comments</comments>
		<pubDate>Wed, 02 Jun 2010 19:52:40 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Random Thoughts]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/06/02/39449</guid>
		<description><![CDATA[
Delphi Prism 2011 is now available for purchase.  There are some very cool features in it, the biggest of which is integration into Visual Studio 2010 and complete support for the .Net 4.0 framework.  It also includes CodeSite Delphi Prism Edition, which gives you an amazing view into your code.  And here is another cool [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href="http://www.embarcadero.com/products/delphi-prism">Delphi Prism 2011</a> is now available for purchase.  <a href="http://prismwiki.embarcadero.com/en/New_Features">There are some very cool features in it</a>, the biggest of which is integration into Visual Studio 2010 and complete support for the .Net 4.0 framework.  It also includes <a href="http://www.raize.com/DevTools/codesite/Default.asp">CodeSite Delphi Prism Edition</a>, which gives you an amazing view into your code.  And here is another cool thing:  <a href="http://www.embarcadero.com/products/rad-studio/prismoffer">Buy RAD Studio 2010 and get a free upgrade to Delphi Prism 2011</a>.</li>
<li><a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">Delphi Programming is now at #9 with two up green arrows</a>, and Objective-C has shot like a bullet into the Top 10.</li>
<li>I think some of you have been hearing about the Tool Cloud.  We have <a href="http://www.embarcadero.com/solutions/tools-management">a web page that talks about it</a>, including some PDF’s for your reading pleasure.  Delphi and RAD Studio are going to become part of the Tool Cloud in the coming releases, and so you might want to check it out.  Let me clear, though, that if you <strong><em>aren’t</em></strong> interested in the Tool Cloud, you don’t have to participate.  You’ll still be able to get your Delphi like you always have.  But if you <strong><em>are</em></strong> interested in the Tool Cloud for RAD Studio, there is a lot of interesting stuff going on there.</li>
<li><a href="http://edn.embarcadero.com/article/40500">Have you signed up for Delphi Live yet?</a> We are looking forward to seeing you there.</li>
<li>More good stuff from <a href="http://blog.marcocantu.com/blog/help_insight_customization.html">Marco about the under-appreciated (and under-utilized, even by us) Help Insight feature</a>.  For the record, I have provided copious Help Insight comments for <a href="http://sourceforge.net/projects/tsmiley/">TSmiley</a>.   I actually found it rather fun to write the comments, and I personally don’t mind them in the code and don’t view them as “clutter”.  A cool IDE feature would be to “auto hide all XMLDoc comments” or something like that.</li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39449&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39449" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23159&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F06%2F02%2F39449" id="akst_email_39449" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/06/02/39449/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Coin Flip</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/05/30/39448</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/05/30/39448#comments</comments>
		<pubDate>Mon, 31 May 2010 02:28:01 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/05/30/39448</guid>
		<description><![CDATA[I had occasion to write a little routine called CoinFlip:

function CoinFlip: Boolean;
begin
  Result := Random &#62; 0.5;
end;


I don&#8217;t know why I found it mildly amusing.&#160; And I bet someone will tell me that it is slightly biased in one direction.&#160; Because it is.&#160; Anyway, thought you all might enjoy it, too. 
Share This &#124; [...]]]></description>
			<content:encoded><![CDATA[<p>I had occasion to write a little routine called CoinFlip:</p>
<pre><code>
<b>function</b> CoinFlip: Boolean;
<b>begin</b>
  Result := Random &gt; 0.5;
<b>end</b>;

</code></pre>
<p>I don&#8217;t know why I found it mildly amusing.&#160; And I bet someone will tell me that it is slightly biased in one direction.&#160; Because it is.&#160; Anyway, thought you all might enjoy it, too. </p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39448&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39448" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Coin%20Flip&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F05%2F30%2F39448" id="akst_email_39448" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/05/30/39448/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #158</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/05/26/39447</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/05/26/39447#comments</comments>
		<pubDate>Wed, 26 May 2010 17:01:39 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/05/26/39447</guid>
		<description><![CDATA[
DataRage 2 is going on right now, and it is not too late to get involved.
Delphi Prism 2011 will be generally available very soon, and Marc Hoffman has a good rundown on what you’ll get in this significant release.&#160; My favorite part is the support for VS2010 right as this new version is out.&#160; You [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href="http://www.embarcadero.com/datarage2">DataRage 2 is going on right now</a><em>, </em>and it is not too late to get involved.</li>
<li><a href="http://www.embarcadero.com/products/delphi-prism">Delphi Prism</a> 2011 will be generally available very soon, and Marc Hoffman has <a href="http://blogs.remobjects.com/blogs/mh/2010/05/23/p1504">a good rundown on what you’ll get in this significant release</a>.&#160; My favorite part is the support for VS2010 right as this new version is out.&#160; You give up nothing and get a lot with Delphi Prism. </li>
<li>I thought this <a href="http://www.webdesignerdepot.com/2010/05/7-personality-types-of-developers-today/">taxonomy of developer types</a> was particularly insightful.&#160; Which one are you? </li>
<li><a href="http://stackoverflow.com/questions/2908120/delphi-pascal-training-in-high-school-college-university">Does your high school or university teach Delphi?</a> </li>
<li>Did I mention this earlier?&#160; We are <a href="http://www.surveymonkey.com/s/embt-developer">conducting a survey</a> to learn about the application development market – what are the challenges developers face as well as the technologies and tools they’re using.&#160;&#160; It’s not “The Delphi Survey”, but instead a more general survey about developers, processes, etc.&#160; We’d love your input.</li>
<li>And if you are interested in the broader perspective about where Embarcadero is headed, you might be interested in <a href="http://bit.ly/abk6al">this press release about our new XE line of products</a>.&#160; RAD Studio will eventually become an “XE Product”, and so it should be of interest to you all.&#160; You can learn more about it via what is currently going on <a href="http://www.youtube.com/watch?v=isAeFzUEciU">with some of the DatabaseGear tools in this video</a>.</li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39447&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39447" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23158&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F05%2F26%2F39447" id="akst_email_39447" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/05/26/39447/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #157</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/05/24/39446</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/05/24/39446#comments</comments>
		<pubDate>Mon, 24 May 2010 20:57:28 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/05/24/39446</guid>
		<description><![CDATA[
This guy on StackOverflow has a question about the best desktop development platform.&#160; Maybe you guys have some suggestions for him. 
Did I post this link to an article in SDTimes about Delphi Prism 2011?&#160; One of the cool additions to the product is the integration of CodeSite Prism Edition from Raize Software.&#160; CodeSite allows [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href="http://stackoverflow.com/questions/2852191/which-are-the-current-emerging-desktop-development-technologies-worth-looking-int">This guy on StackOverflow has a question about the best desktop development platform</a>.&#160; Maybe you guys have some suggestions for him. </li>
<li><a href="http://www.sdtimes.com/link/34300">Did I post this link to an article in SDTimes about Delphi Prism 2011</a>?&#160; One of the cool additions to the product is the integration of CodeSite Prism Edition from <a href="http://www.raize.com/devtools/">Raize Software</a>.&#160; CodeSite allows you to get a very deep, intimate look at how your code is running and what it is doing, enabling you to get a better idea where problems may lie and how your code can work better for you and your customers.&#160; And it is included with your purchase, upgrade, and subscription.&#160; <a href="http://www.raize.com/devtools/codesite">The full CodeSite product</a> also works with Delphi and C++Builder, so if it proves useful, consider upgrading so you can use it with all your RAD Studio projects. Sweet! </li>
<li>Hey, Delphi for PHP <a href="http://blogs.embarcadero.com/joseleon/2010/05/21/delphi-for-php-brainstorming-site/">now has a “brainstorming” site</a> for letting you input what you’d like to see in the next version.&#160; If you are <a href="http://www.embarcadero.com/products/delphi-for-php">Delphi for PHP</a> customer, or thinking about being one, stop by and let us know what you think.</li>
<li>I think a bunch of you have been to CodeRage before.&#160; Starting tomorrow we are running <a href="http://now.eloqua.com/es.asp?s=608&amp;e=282316&amp;elq=dd6e6cdfb4da4d89b3fc9fb10a6e9995">another DataRage</a>.&#160; And it <a href="http://forms.embarcadero.com/forms/DataRage2Registration?elq=dd6e6cdfb4da4d89b3fc9fb10a6e9995">isn’t too late to register</a>.&#160; This is a good opportunity to get a look at the DataGear side of the tool chest.</li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39446&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39446" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23157&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F05%2F24%2F39446" id="akst_email_39446" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/05/24/39446/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #156</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/05/12/39445</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/05/12/39445#comments</comments>
		<pubDate>Wed, 12 May 2010 22:54:06 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[RAD Studio]]></category>

		<category><![CDATA[Random Thoughts]]></category>

		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/05/12/39445</guid>
		<description><![CDATA[
“The board &#34;highly recommended&#34; switching to Pascal/Delphi because it is stable and was designed to teach programming and problem solving.”
Cary Jensen has an interesting survey up on his blog, asking about how much you use the “non-core” features of RAD Studio.&#160; Now this is an interesting question. He’s asking particularly about the unit testing, audit, [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href="http://www.theregister.co.uk/2010/05/12/aqa_c_php/">“The board &quot;highly recommended&quot; switching to Pascal/Delphi because it is stable and was designed to teach programming and problem solving.”</a></li>
<li><a href="http://caryjensen.blogspot.com">Cary Jensen</a> has an interesting survey up on his blog, asking about <a href="http://caryjensen.blogspot.com/2010/05/delphi-non-core-feature-survey-you-can.html">how much you use the “non-core” features of RAD Studio</a>.&#160; Now this is an interesting question. He’s asking particularly about the unit testing, audit, metrics, and design patterns features on the product.&#160; Now these are some unheralded features, particularly the audits and metrics.&#160; Cary’s a little inaccurate in that while the Together <em><strong>product</strong></em> did go with Borland, the codebase that was Together for Visual Studio and which was eventually adapted into the RAD Studio IDE came with us to Embarcadero and continues to advance and evolve.&#160; In fact, the modeling and the accompanying features like audits, metrics, and the code formatter are all alive and quite well and being improved as we speak.&#160; But in any event, I’ll be curious to see the outcome.&#160; Please do go and fill out the survey, and if you aren’t using those features, please give them a look.&#160; There is a lot of power there. </li>
<li><a href="http://www.delphi.org/2010/05/40-nick-hodges-part-1/">I did a podcast</a> with Jim McKeeth for The <a href="http://www.delphi.org">Delphi Podcast.</a>&#160; Unfortunately, it stopped recording in the middle, so I guess it will be a two parter.&#160; <img src='http://blogs.embarcadero.com/nickhodges/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
<li>I’ve been using <a href="http://www.evernote.com/about/home.php">Evernote</a> more and more these days. Interesting service, and free for up to 40MB a month, which is far more than I’m using now.&#160; I haven’t upgraded to their <a href="http://www.evernote.com/about/premium/">Premium</a> services yet, but I can see that coming.&#160; It’s really just a cloud app – I can make and view notes on the web and my computer, and then view them on the web, my Android phone, anywhere.&#160; </li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39445&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39445" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23156&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F05%2F12%2F39445" id="akst_email_39445" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/05/12/39445/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Delphi Development Pretty Good Practices #4 &#8211; Do Work in Classes</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/05/05/39444</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/05/05/39444#comments</comments>
		<pubDate>Wed, 05 May 2010 17:29:40 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Best Practices]]></category>

		<category><![CDATA[Delphi]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/05/05/39444</guid>
		<description><![CDATA[The next principle for the “Pretty Good Practices” we’ll discuss is this notion:&#160; Whenever possible and as much as possible, put functionality in a class &#8211;&#160; preferably a class that can be easily unit tested, reused, and separated from any user interface.
TextScrubber demonstrates this via the use of the TTextScrubber class in the uTextScrubber.pas unit.&#160; [...]]]></description>
			<content:encoded><![CDATA[<p>The next principle for the “Pretty Good Practices” we’ll discuss is this notion:&#160; <strong>Whenever possible and as much as possible, put functionality in a class &#8211;&#160; preferably a class that can be easily unit tested, reused, and separated from any user interface</strong>.</p>
<p><font face="Courier New">TextScrubber</font> demonstrates this via the use of the <font face="Courier New">TTextScrubber</font> class in the <font face="Courier New">uTextScrubber.pas</font> unit.&#160; <font face="Courier New">TTextScrubber</font>&#160; is a simple <font face="Courier New">TObject</font> descendant that does all the work for the whole application, really.&#160; It is a standalone class – you could take the <font face="Courier New">uTextScrubber.pas</font> unit and use it in most any project you cared to.&#160; Because of this, it is also very easy to write unit tests for this class.&#160; (We covered unit testing in my previous series “Fun with Testing DateUtils.pas”, but I’ll discuss Unit Testing in a later post in this series as well.)&#160; The class attempts to follow the “<a href="http://en.wikipedia.org/wiki/Law_of_Demeter">Law of Demeter</a>”, which says that classes should know as little as possible about outside entities.&#160; The three principles of the Law of Demeter are as follows:</p>
<ul>   </ul>
<ul>
<li>Each class should have only limited or hopefully no knowledge of other classes. </li>
<li>If a class must have knowledge of other classes, it should only have connections to classes that know about it as well. </li>
<li>Classes should never “reach through” one class to talk to a third class </li>
</ul>
<p>In the case of <font face="Courier New">TTextScrubber</font>, it only knows about and utilizes the <font face="Courier New">TClipboard</font> class and nothing else.&#160; It doesn’t try to grab things out of <font face="Courier New">TClipboard</font> or attach to or require any other class.&#160; It pretty much minds its own business, utilizes the services of the clipboard, and provide an easy way to get at its functionality.&#160; It endeavors to do one thing:&#160; scrub text, by both straightening and “un-formatting” it.&#160; It has short, sweet method bodies, and ensures that it doesn’t try to do too much beyond exactly what it is supposed to do.&#160; Following the Law of Demeter tends to make your code more maintainable and reusable. By reducing dependencies, you ensure that a class is as flexible as possible and that changes to it don’t tend to have far reaching consequences.&#160; </p>
<p>So, to as large a degree as possible, you should endeavor to put the functionality of your program into classes.&#160; One way to tell you are <strong><em>not</em></strong> doing this is if you tend to do “<font face="Courier New">OnClick</font>” programming, or relying on event handlers to do the work of your application.&#160; The Pretty Good Practices way of programming would dictate that your event handlers would contain code that merely instantiated and used other classes instead of having the actual code in them to do the work of your application.&#160; </p>
<p>So for instance, most of the work in TextScrubber gets done in an <font face="Courier New">OnClick</font> event of the <font face="Courier New">TTrayIcon</font> component.&#160; That code looks like this:</p>
<pre><code>
<b>procedure</b> TStraightTextMainForm.MainTrayIconClick(Sender: TObject);
<b>begin</b>
  MainTrayIcon.Animate := True;
  <b>case</b> TextScrubberOptions.ClickChoice <b>of</b>
    ccStraightenText:
      <b>begin</b>
        DoStraightenText;
      <b>end</b>;
    ccScrubClipboard:
      <b>begin</b>
        DoPurifyText;
      <b>end</b>;
  <b>end</b>;
<b>end</b>;

</code></pre>
<p>It merely calls one of two functions, <font face="Courier New">DoStraigthenText</font> or <font face="Courier New">DoPurifyText</font>, that scrub the text on the clipboard.&#160; Those two methods look pretty much the same – they merely create a <font face="Courier New">TTextScrubber</font>, use it, and then free it.&#160; <font face="Courier New">DoStraightenText</font> looks like this:</p>
<pre><code>
<b>procedure</b> TStraightTextMainForm.DoStraightenText;
<b>var</b>
  TS: TTextScrubber;
<b>begin</b>
  TS := TTextScrubber.Create(TextScrubberOptions.ShouldTrim);
  <b>try</b>
    TS.StraightenTextOnClipboard;
  <b>finally</b>
    TS.Free;
  <b>end</b>;
<b>end</b>;
</code></pre>
<p>This method is very simple and to the point &#8212; it utilizes the <font face="Courier New">TTextScrubber</font> class to do the work.&#160; It’s not always entirely possible, but I try to make as many of&#160; my event handlers and methods follow this pattern of merely utilizing the functionality of external classes.&#160; Doing so enables a few things:</p>
<ul>
  </ul>
<ul>
<li>It means that functionality is much easier to unit test.&#160; Isolated classes with specific functionality make unit testing really easy.&#160; </li>
<li>Functionality is easier to share and reuse.&#160; An isolated, decoupled class can easily be moved to new applications as it has few or no dependencies.</li>
<li>Lean event handlers mean that your user interface isn’t tightly coupled to the work code.&#160; This means that adjusting or altering your UI is easier to do, and adjusting and altering the work code doesn’t mean a change in the way the UI works. </li>
</ul>
<p>So, to sum up – always try to build standalone classes to do the work or your application.&#160; </p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39444&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39444" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Delphi%20Development%20Pretty%20Good%20Practices%20%234%20%26ndash%3B%20Do%20Work%20in%20Classes&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F05%2F05%2F39444" id="akst_email_39444" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/05/05/39444/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #155</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/04/30/39442</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/04/30/39442#comments</comments>
		<pubDate>Fri, 30 Apr 2010 18:29:23 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Random Thoughts]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/04/30/39442</guid>
		<description><![CDATA[
Delphi Prism 2011 is coming soon, and you can read more about it at SDTimes.&#160; Or maybe you are more of an InfoWorld guy and want to read their article about it.&#160; 
If you are a RemObjects customer, you might be interested in testing their Public Chat system. 
As part of my “Pretty Good Practices” [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>Delphi Prism 2011 is coming soon, and you can <a href="http://www.sdtimes.com/link/34300">read more about it at SDTimes</a>.&#160; Or maybe you are more of an InfoWorld guy and <a href="http://www.infoworld.com/d/developer-world/delphi-development-offered-microsoft-visual-studio-2010-348">want to read their article about it</a>.&#160; </li>
<li>If you are a <a href="http://www.remobjects.com">RemObjects</a> customer, you might be interested in <a href="http://blogs.remobjects.com/blogs/ck/2010/04/23/p1484">testing their Public Chat system</a>. </li>
<li>As part of my “Pretty Good Practices” series, I talked just a bit about naming conventions.&#160; One of the commenters pointed out <a href="http://edn.embarcadero.com/article/10280">this classic EDN article</a> by Charlie Calvert that outlines a “Style Guide” for writing code.&#160; I want to stress that I’m a firm believer that there is no one true way to style your code. I have a way I like to do it, but your way is great, too. The important thing is to have a set of rules and stick to them. </li>
<li>For everybody who reads our newsgroups via NNTP:&#160; Make sure that your newsgroup reader is pointed to <font face="Courier New">forums.embarcadero.com</font> and <strong><em>not</em></strong> to a <font face="Courier New">*.codegear.com</font> address.&#160; </li>
<li><a href="http://blogs.embarcadero.com/joseleon/2010/04/30/delphi-for-php-next-release-recapitulation/">The Delphi for PHP “look aheads” done by Jose continue apace</a>.&#160; There are a lot of cool things coming out of those videos.&#160; Give them a look.</li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39442&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39442" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23155&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F04%2F30%2F39442" id="akst_email_39442" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/04/30/39442/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Delphi Development Pretty Good Practices #3 – File Setup</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/04/28/39435</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/04/28/39435#comments</comments>
		<pubDate>Wed, 28 Apr 2010 16:22:18 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Best Practices]]></category>

		<category><![CDATA[Delphi]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/?p=39435</guid>
		<description><![CDATA[Okay, hopefully by now you’ve read the introduction of this series, and you’ve downloaded (or better yet, pulled from source control) the latest version of TextScrubber and given it a once over.&#160; In this installment, I’m going to discuss the file structure of the project and why I did things the way I did. 

First, [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, hopefully by now you’ve <a href="http://blogs.embarcadero.com/nickhodges/2010/04/19/39404">read the introduction</a> of this series, and <a href="http://blogs.embarcadero.com/nickhodges/2010/04/23/39416">you’ve downloaded (or better yet, pulled from source control) the latest version of TextScrubber</a> and given it a once over.&#160; In this installment, I’m going to discuss the file structure of the project and why I did things the way I did. </p>
<blockquote>
<p>First, an admin note:&#160; I’ve made some small changes to the code for TextScrubber.&#160; You can get these by going to the main directory for your code and typing <font face="Courier New">svn up</font>.&#160; They aren’t any big deal – comments, some cleanup and organization, but it sure is easy to get the latest changes, isn’t it.</p>
</blockquote>
<p>Taking a look at the file set that makes up the TextScrubber project, you see a number of different files, each with a particular purpose. I’ll describe each file in turn, telling what its purpose is and why it exists.&#160; Future installements will go in depth a bit more.</p>
<p><img border="0" alt="TextScrubberProjectManager" src="http://blogs.embarcadero.com/files/2010/04/textscrubberprojectmanager_2577.png" /></p>
<table border="1" cellspacing="0" cellpadding="6" width="100%">
<thead>
<tr>
<td width="142" align="center"><strong></p>
<h3>FileName</h3>
<p>        </strong></td>
<td align="center"><strong></p>
<h3>Discussion</h3>
<p>        </strong></td>
</tr>
</thead>
<tbody>
<tr>
<td width="142"><font face="Courier New">frmAboutBox.pas</font></td>
<td>Every Application should have an About Box.&#160; The About Box should display the Application Icon, give Version information, copyright notices, and contain a short description of what the application is or does.&#160; </td>
</tr>
<tr>
<td width="142"><font face="Courier New">frmStraightText.pas</font></td>
<td>This is the “main form” for the application, but since TextScrubber doesn’t have a main for, but it simply a container for some non-visual controls.</td>
</tr>
<tr>
<td width="142"><font face="Courier New">frmTextScrubberOptions.pas</font></td>
<td>Every application should have a single dialog that allows the user to set all the configurable options and preferences for the application. </td>
</tr>
<tr>
<td width="142"><font face="Courier New">NixUtils.pas</font></td>
<td><font face="Courier New">NixUtils.pas</font> is a general purpose file of handy utilities and routines that I’ve built up over the years.&#160; I use it in TextScrubber, so I’ve included it in the project.&#160; Normally, I keep this file in a separate directory.</td>
</tr>
<tr>
<td width="142"><font face="Courier New">uTextScrubber.pas</font></td>
<td>This is the “workhorse” unit that contains the class that does all the work of the application. </td>
</tr>
<tr>
<td width="142"><font face="Courier New">uTextScrubberConsts.pas</font></td>
<td>This file has one and only one purpose:&#160; To hold all the constants for the project. It will include all constant declarations, as well as the strings declared with resourcestring. </td>
</tr>
<tr>
<td width="142"><font face="Courier New">uTextScrubberTypes.pas</font></td>
<td>This file contains all the types declarations for the project, including classes, enumerations, records, etc.</td>
</tr>
<tr>
<td width="142"><font face="Courier New">uTextScrubberUtils.pas</font></td>
<td>This file contains those little, standalone, “helper” routines that you use to build the product.&#160; Routings that go into this unit are often considered as candidates to end up in NixUtils.pas, but most often, they are very specific to a purpose of the project.</td>
</tr>
</tbody>
</table>
<h3>A Note About Naming Conventions</h3>
<p>For this project, I’ve used a pretty simple naming convention. For filenames, I put ‘<font face="Courier New">frm</font>’ at the front of forms, ‘<font face="Courier New">u</font>’ at the beginning of standalone units. DataModules would get ‘<font face="Courier New">dm</font>’. Constants start with ‘<font face="Courier New">c</font>’, and resourcestrings start with ‘<font face="Courier New">str</font>’.&#160; Parameters are prefixed with ‘<font face="Courier New">a</font>’, and all local variables (well, almost all) are prefaced with ‘<font face="Courier New">Temp</font>’.&#160; Those latter two help keep things straight inside class methods.&#160; I try to make my identifiers descriptive, and I never worry about their length.&#160; A well named identifier makes code clearer, and Code Completion can do all the work if you are worried about typing.&#160; (But in my view, you should <strong><em>never</em></strong> worry about typing if typing less means writing unclear code…..)</p>
<p>I use those as a general set of rules, but I’m not dogmatic about it.&#160; I try to be consistent for my and your benefit.&#160; The exact rules of naming aren’t nearly as important as <strong><em>having</em></strong> a naming convention.&#160; My recommendation is to find a system that you like and stick with it.&#160; Naming conventions are a great source of religious debates. I generally leave that to others, and simply recommend that you find something that works for you and stick with it.&#160; </p>
<h3>More Detail to Come</h3>
<p>I’ll be talking a bit more specifically about each of the files in future installments.&#160; This entry should just give you a brief rundown on the basics.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39435&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39435" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Delphi%20Development%20Pretty%20Good%20Practices%20%233%20%E2%80%93%20File%20Setup&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F04%2F28%2F39435" id="akst_email_39435" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/04/28/39435/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Delphi Development Pretty Good Practices #2 – Source Control</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/04/23/39416</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/04/23/39416#comments</comments>
		<pubDate>Fri, 23 Apr 2010 21:35:48 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Best Practices]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/?p=39416</guid>
		<description><![CDATA[Okay, so for this first installment, I’ll be illustrating one of my core principles for developing applications:&#160; All my code of any importance at all goes under source control.&#160; All of it.
I’m all by myself – why should I use source control?
We ask about source control use on the annual survey, and a surprisingly large [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, so for this first installment, I’ll be illustrating one of my core principles for developing applications:&#160; <strong>All my code of any importance at all goes under source control.&#160; All of it.</strong></p>
<h3>I’m all by myself – why should I use source control?</h3>
<p>We ask about source control use on the annual survey, and a surprisingly large percentage of you <em>are not using source control at all. </em>&#160;&#160; That as a bit of a surprise.&#160; If you are working on a team of any size, using source control is a no brainer.&#160; But even if you are working alone, using source control is a really good idea.&#160; </p>
<p>Why, you might ask?&#160; Well, there are a number of good reasons:</p>
<ol>
<li><em><strong>It’s good to be in the habit.</strong></em>&#160; Sure, you may be working alone.&#160; But in the future you may not be.&#160; Or your “weekend hobby project” might turn into a popular project with many developers.&#160; If anything like that happens, being in the habit of using source code control will stand you in good stead. </li>
<li><em><strong>It protects your code.</strong></em>&#160; Since your code is stored in on a server apart from your development machine, you have a backup. And then, you can even backup the code on the server.&#160; Sure, you can zip it all up any time you want, but you don’t get all the other benefits I’m listing here. </li>
<li><strong><em>It can save your butt.</em></strong>&#160; Sometimes, you might accidently delete something.&#160; You might make mistakes and change code that you didn’t want changed.&#160; You might start off on some crazy idea when you are feeling a bit saucy, and then regret it.&#160; Source control can save you from all of these by making it a piece of cake to revert to any previous state.&#160; It’s like a really powerful “undo” feature. </li>
<li><strong><em>It allows you to “turn back time”</em></strong>. Say you are a shareware author. You like to release updates and new versions.&#160; And say you get a support request from a customer that has a bug while using a version that is two major releases old. Source control lets you easily recreate the code base for that exact release and debug the problem that the user is seeing. </li>
<li><strong><em>It makes you think about your process</em></strong>.&#160; Even if you work alone, you should be deliberate and organized in how you write code. If you are in the habit of checking your code into a source control system, you’ll end up thinking more about what you are doing, how you are doing things, and you’ll end up being more organized and deliberate.&#160; </li>
<li><strong><em>It gives you the freedom to experiment.&#160; </em></strong>Somewhat the mirror image of the previous reason, source control gives you the freedom to say “What the heck, I’ll try that wacky way of doing things!”&#160; Since you know that you can always get back to a known good state, you can be free to experiment and try something that might otherwise hesitate to do. And that experiment might just prove to be a brilliant way to do it.&#160; </li>
<li><strong><em>It lets you backtrack.</em></strong>&#160; Even when we work alone, we can’t remember every single thing we do and every single change we make.&#160; And I bet at least once in your life you’ve looked at some code and said “Huh? When the heck did <strong><em>that</em></strong> happen?”&#160; With a source control system, you can answer that question very easily.&#160; You can track where a specific change came from and when it was made and maybe even the comment you made when you checked the change in. </li>
<li><em><strong>It lets you see what changed.</strong></em>&#160; Sometimes, things start acting up. Maybe a section of your application that you haven’t used in a while is behaving differently than you expected.&#160; Maybe it is totally broken and you have no idea why.&#160; Source control can let you track the process and peer into the history of a specific chunk of code to see what changes were made and how those changes affected the project as a whole. </li>
</ol>
<p>I’m sure you all can think of more reasons.&#160; Bottom line is that if you aren’t using source control, then you should start, no matter what your development situation is.&#160; ZIP files just aren’t going to cut it.&#160; Seriously.</p>
<h3>Okay, I’m convinced. What now?</h3>
<p>I’m convinced that my points above are so compelling that you are in violent agreement with me, so I’m going to make you use the Subversion client to get the code for this series&#8217; demo project, TextScrubber. <a href="http://sourceforge.net/projects/textscrubber/">TextScrubber is only available from SourceForge under Subversion</a>.&#160;&#160; If you don’t use Subversion for source control, you should at least have the command line client on your machine, because Subversion is everywhere, and you should at least know how to get code from code repositories that use it.&#160; I know that there are other well known source control management systems out there.&#160; <a href="http://git-scm.com/">Git</a> and <a href="http://mercurial.selenic.com/">Mercurial</a> are growing in popularity, but Subversion is probably the most widely used source control system out there.&#160; We use Subversion internally here on the RAD Studio team.</p>
<h3>Getting the Subversion Command Line Client</h3>
<p>So the first thing you’ll need to do is to get the Subversion client.&#160; (If you already have the client, you can skip this whole section) A whole lot of projects out there &#8212; whether on <a href="http://www.sourceforge.net">SourceForge</a> or <a href="http://code.google.com">GoogleCode</a> or <a href="http://www.codeplex.com/">CodePlex</a> &#8212; use Subversion, so having the client is pretty useful.&#160; It’s also small and easy to use, so here’s how you get it:</p>
<ol>
<li>I’d recommend getting the binary package from <a href="http://www.collabnet.com">Collabnet</a>:&#160; In order to do that, you’ll have to get an account with them. You can sign up here:&#160; <a title="http://www.open.collab.net/servlets/Join" href="http://www.open.collab.net/servlets/Join">http://www.open.collab.net/servlets/Join</a>&#160; If you don’t want to do that, you can get the binaries here as well:&#160; <a title="http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91" href="http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91">http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91</a> </li>
<li>Go to:&#160; <a title="http://www.collab.net/downloads/subversion/" href="http://www.collab.net/downloads/subversion/">http://www.collab.net/downloads/subversion/</a> and choose the <strong><em>second</em></strong> download entitled:&#160; “CollabNet Subversion Command-Line Client v1.6.9 (for Windows)” </li>
<li>There is a big orange button there that says “Download”.&#160; Note again that this is the <em><strong>second </strong></em>button on that page as we are downloading the client only. </li>
<li>Press the button and download the file.&#160; </li>
<li>Execute the installer that you downloaded.&#160; </li>
</ol>
<p>There, you just installed the Subversion client.&#160; The path to the client should now be on your DOS PATH (if it isn’t, you can put it there) and you should be all ready to go on the command line.&#160; </p>
<blockquote>
<p>Note: Subversion has only very recently been brought under the umbrella of the Apache Project. As such, it is licensed under the very friendly <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.&#160;&#160; It was originally founded by Collabnet, but moved over to be a part of the Apache set of tools just this past February.&#160; It is open source, so if you are really hard core, you can download the source and compile it all yourself.&#160; Me?&#160;&#160; I’m not that hardcore. I use the convenient binaries provided by the good folks at Collabnet.&#160; </p>
</blockquote>
<h3>Grabbing the Code for TextScrubber</h3>
<p>Once you have the command line Subversion client installed (it’s called <font face="Courier New">svn.exe</font>, by the way), you can easily download the code for <a href="http://sourceforge.net/projects/textscrubber/">TextScrubber</a>.&#160; Seriously, it’s like falling off a log.&#160; Just do the following:</p>
<ol>
<li>Open a command window and go to the <strong><em>parent</em></strong> directory where you want the code to go.&#160; For instance, if you want the code to go into <font face="Courier New">c:\code\textscrubber</font>, you want to start with your command prompt at <font face="Courier New">c:\code</font> </li>
<li>Issue the following command:&#160; </li>
</ol>
<p><font face="Courier New">svn co https://textscrubber.svn.sourceforge.net/svnroot/textscrubber/trunk textscrubber </font></p>
<p>‘<font face="Courier New">co</font>’ stands for ‘checkout’. The second parameter is the URL for the ‘tip’ of the Subversion repository. This command will pull from SourceForge the most recent version of the code into the <font face="Courier New">\textscrubber\trunk</font> directory. That last parameter there is the name of the subdirectory that will be created and filled with the code from SourceForge.&#160; </p>
<p>That’s it. You now have the most recent, up to date code for TextScrubber on your machine.&#160; You are all ready to start straightening and unformatting text!</p>
<h3>Using Subversion</h3>
<p>In the future, if I make updates to the project, then all you need to do is to navigate to the <font face="Courier New">\textscrubber\trunk</font> directory and do a “7up” or <font face="Courier New">&quot;svn up&quot;</font> command, and it will get the latest and greatest code for you in a jiffy.&#160; Can’t be much simpler than that. That’s the command you’ll end up using the most, probably.</p>
<p>Since it is so popular and commonly used, there is a lot of information about using Subversion out on the web.&#160; <a href="http://svnbook.red-bean.com/en/1.1/index.html">I’ve found this tutorial to be very useful</a>, as well as the book (written by the same guys that wrote the tutorial..): <a href="http://www.amazon.com/gp/product/0596004486?ie=UTF8&amp;tag=nickhodges-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0596004486">Version Control with Subversion</a><img style="margin: 0px" border="0" alt="" src="http://www.assoc-amazon.com/e/ir?t=nickhodges-20&amp;l=as2&amp;o=1&amp;a=0596004486" width="1" height="1" /> </p>
<p>Another useful tool for using Subversion is <a href="http://tortoisesvn.tigris.org/">TortoiseSVN</a>.&#160; TortoiseSVN is a Windows shell plug-in that provides all the functionality of the Subversion client in an easy to use GUI.&#160; Below is a screen shot of the TortoiseSVN Log Window for the <a href="http://sourceforge.net/projects/tsmiley">TSmiley project on SourceForge</a>.</p>
<p><a href="/files/2010/04/tortoise_2562.png"><img src="/files/2010/04/tortoise_2562.png" /></a> </p>
<p>TortoiseSVN is also an open source project, so you can get it for free.&#160; If TortoiseSVN proves to be valuable to you, I’d also encourage you make <a href="http://tortoisesvn.tigris.org/donate.html">a generous donation to the project</a>.&#160; I did.</p>
<h3>Getting and Setting Up the Subversion Server</h3>
<p>If you make the wise and sagely decision to go ahead and use source control for all of your code, you can easily set up the Subversion server.&#160; You can, of course, download the Collabnet binaries and install them, but if you want to go the pathetically easy route (which I recommend), you should download and install <a href="http://www.visualsvn.com/server/">Visual SVN Server</a>.&#160; I’m not even going to go through the steps to installing the server, because they are not much more than download, run the install, and you are done.&#160; That’s it.&#160; It takes like two minutes.&#160; Seriously. They even provide you with a nice Management Console application for administering the server, making that really easy as well.&#160; </p>
<p><a href="/files/2010/04/visualsvnserver_2565.png"><img src="/files/2010/04/visualsvnserver_2565.png" /></a> </p>
<p>(And while you are looking at VisualSVN Server, you can consider upgrading to their <a href="http://www.visualsvn.com/server/licensing/">Enterprise edition</a>.)&#160; </p>
<p>Now, I myself run the full server (Apache, etc. – the whole ball &#8216;o’ wax….) on my local machine and use it to manage my code.&#160; This enables me to browse my code in a browser and do other things that are supported by a full blown server&#160;&#160; But that might be a bit of overkill for some of you (I’m weird that way – I just want the “full” experience and like to be in learning mode…) and you might not want to do that.&#160; Instead, you can simply create local repositories on your local disk.&#160;&#160; The Subversion tutorial above can show you how to do that.&#160; </p>
<p>I have been using the server locally since I use a laptop exclusively and move it between work and home.&#160; But I think I’ll set up the server on a machine at home and check in there. That way, my code will be stored on a separate machine.</p>
<h3>More About Source Control</h3>
<p>As you can probably tell, this post isn’t meant to be a primer on Subversion or source control in general.&#160; The tutorial I listed above is a good place to learn about Subversion.&#160; If you want to learn more about source control in general, I recommend reading <a href="http://www.ericsink.com/scm/source_control.html">Source Control HOWTO</a> by Erik Sink.&#160; Eric is a really interesting guy who has a great blog and also runs <a href="http://www.sourcegear.com/">SourceGear</a>, a commercial vendor of developer tools including <a href="http://www.sourcegear.com/vault/">Vault</a>, a source control management tool that I recommend considering.&#160; You might be interested to note that Vault is free for single users. </p>
<h3>That’s it.</h3>
<p>And so that is the first “Pretty Good Practice” for developing with Delphi:<em> Manage your code with a source control system.</em></p>
<p>So, what do you think?&#160; Are you ready to make the move to source control management?</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39416&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39416" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Delphi%20Development%20Pretty%20Good%20Practices%20%232%20%E2%80%93%20Source%20Control&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F04%2F23%2F39416" id="akst_email_39416" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/04/23/39416/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Delphi Development Pretty Good Practices #1</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/04/19/39404</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/04/19/39404#comments</comments>
		<pubDate>Mon, 19 Apr 2010 23:38:35 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Best Practices]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[RAD Studio]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/04/19/39404</guid>
		<description><![CDATA[A while back someone (I can’t remember who, sadly, sorry to the person who made the suggestion…) suggested that someone do a series of articles about “the best practices on how to develop a Delphi application”.&#160; That’s a good idea.&#160; There are a lot of ways to do things, and clearly there are some good [...]]]></description>
			<content:encoded><![CDATA[<p>A while back someone (I can’t remember who, sadly, sorry to the person who made the suggestion…) suggested that someone do a series of articles about “the best practices on how to develop a Delphi application”.&#160; That’s a good idea.&#160; There are a lot of ways to do things, and clearly there are some good way and some bad ways, some okay ways and some really cool ways to develop with Delphi.</p>
<p>This series of articles will cover my personal ideas behind a good way to organize and build a Delphi application.&#160; I’ll build a small application that does a few things.&#160; I’ll organize the application in such a way that it illustrates some techniques that I believe are a good way to organize things.&#160; I will explain my reasoning and in doing so I hope that you guys learn something.&#160; This won’t be an exhaustive list or collection of ideas.</p>
<p>What I will <strong><em>not </em></strong>do is pretend that what I do and the way I do it is the only way to do things.&#160; Heck, it may be that you end up thinking the way I do things is ridiculous.&#160; I’ll let you all be the judge of that.&#160;&#160; If you guys have different ideas, please feel free to express them.&#160; If you like what you see, let me know.&#160; I’ve been using Delphi for a long time, and so I think I’ve learned a thing or two along the way, but I’m not the world’s greatest Delphi developer and I certainly won’t claim to be the final arbiter of how things should be done.&#160; I generally don’t like the term “Best Practices”, so I’ve titled this using “Pretty Good Practices”. </p>
<p>My goal here, really, is to be informative and stimulative and to evoke conversation and discussion.&#160; I have developed a way of doing things over the years and I’ll be outlining them in this series of articles.&#160; I don’t believe that this series will be all inclusive – that is, I won’t be covering every single aspect of every single development practice that I’ve ever thought of. Again, I hope merely to stimulate some discussion and do my humble part to&#160; improve the way Delphi applications are developed. </p>
<p>The application I’ll use as an illustration is one that I use practically every day.&#160; I call it “TextScrubber”, and it is a simple application that resides in the tray and let’s me “clean up text”, either by removing formatting, removing line breaks, or both.&#160; I use it when I copy text from the web or from an MS Word document that contains formatting information that I in turn want to paste into another document when I don’t want the formatting to come along.&#160; I copy the text, click on the icon in the tray, and the text is “scrubbed” and put back on the clipboard.&#160; (It is basically a much simpler version of <a href="http://www.stevemiller.net/puretext/">PureText</a> – a product that I heartily recommend that you use if you want this kind of functionality.)&#160; TextScrubber is actually a very simple application with not a lot of code, but I’ve laid it out in such a way that it illustrates many of the methods that I have developed over the years.&#160; Thus, I hope it will suffice to illustrate the things I want to discuss.</p>
<p>To start, I’ll talk about a few general ideas that drive how I do things. These are the general ideas that drive what I do when I develop:</p>
<ul>
<li>Any code of consequence at all should be managed under source control, even if I am the only one using and writing the code.&#160; I use Subversion for this. I actually run the Subversion server on my local machine, but you don’t need to do that.&#160; You can manage a Subversion repository merely as a set of local files, if you want.&#160; But even if you develop all alone, I think using source control is a great idea.</li>
<li>I want everything I write to be easily expandable and scalable.&#160; I try to organize and write code that can easily be extended and enhanced.&#160; I try to write classes that have a sensible hierarchy and that can be easily inherited from. </li>
<li>I want my code to be testable.&#160; I want to write it in such a way that it is conducive to writing unit tests.&#160; I want it to be easy to isolate and easy to find problems if they crop up.&#160; </li>
<li>To as large a degree as possible, I separate the logic of an application from the user interface.&#160; I don’t go full bore into an MVC application usually – that almost requires a special framework, but I do try very hard to separate out functionality into separate, testable classes.</li>
<li>I want my code to be well modularized.&#160; That is, I want each class and each unit to have a single purpose, and be linked to other units and classes as loosely as possible.&#160; </li>
</ul>
<p>What would you add to this list?&#160; What are some of the general rules you try to follow when developing an application?</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39404&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39404" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Delphi%20Development%20Pretty%20Good%20Practices%20%231&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F04%2F19%2F39404" id="akst_email_39404" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/04/19/39404/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Cool Stuff with Delphi #29</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/04/16/39403</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/04/16/39403#comments</comments>
		<pubDate>Fri, 16 Apr 2010 18:48:23 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/04/16/39403</guid>
		<description><![CDATA[SamContacts is a “Simple Address Manager” that enables you to quickly and easily manage your contact information. 
 
You can read more, or take a quick tour on their website.&#160; 
]]></description>
			<content:encoded><![CDATA[<p><a href="http://samcontacts.com/">SamContacts</a> is a “Simple Address Manager” that enables you to quickly and easily manage your contact information. </p>
<p> <img src="http://samcontacts.com/sam_app_blue.png" />
<p>You can <a href="http://samcontacts.com/about/information-for-bloggers/">read more</a>, or take <a href="http://samcontacts.com/tour/">a quick tour on their website</a>.&#160; </p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39403&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39403" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Cool%20Stuff%20with%20Delphi%20%2329&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F04%2F16%2F39403" id="akst_email_39403" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/04/16/39403/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #154</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/04/16/39402</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/04/16/39402#comments</comments>
		<pubDate>Fri, 16 Apr 2010 18:31:46 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Random Thoughts]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/04/16/39402</guid>
		<description><![CDATA[
Delphi Prism is on Channel 9.&#160; David I give a quick rundown on Delphi Prism working in Visual Studio 2010.&#160; 
Joe Meyer alerted me to a German guy who has done a bunch of Delphi tutorials (in German…).&#160; Looks pretty good.&#160; (And while you are over on YouTube, be sure not to miss the Annoying [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href="http://channel9.msdn.com/posts/VSIPMarketing/VSIP-Partners-CAN-DO--Embarcadero-Technologies-Delphi-Prism/">Delphi Prism is on Channel 9</a>.&#160; David I give a quick rundown on Delphi Prism working in Visual Studio 2010.&#160; </li>
<li>Joe Meyer alerted me to a German guy who <a href="http://www.youtube.com/user/pctutsgerman#p/c/56A55BFFBCBE29E8">has done a bunch of Delphi tutorials</a> (in German…).&#160; Looks pretty good.&#160; (And while you are over on YouTube, be sure not to miss the <a href="http://www.youtube.com/realannoyingorange">Annoying Orange</a>.&#160; He’s really, really annoying.) </li>
<li>Have you signed up for the <a href="http://now.eloqua.com/es.asp?s=608&amp;e=268166&amp;elq=e4c4deb0a8ae47199fc0e9524eee7375">expanded Delphi Developer Days in the United States</a>? </li>
<li>Delphi for PHP is getting an update, and Jose has more information on <a href="http://blogs.embarcadero.com/joseleon/">his blog</a> – particularly <a href="http://blogs.embarcadero.com/joseleon/2010/04/08/delphi-for-php-next-release-early-preview-1/">Preview #1</a>, <a href="http://blogs.embarcadero.com/joseleon/2010/04/09/delphi-for-php-next-release-early-preview-2/">Preview #2</a>, <a href="http://blogs.embarcadero.com/joseleon/2010/04/12/delphi-for-php-next-release-early-preview-3/">Preview #3</a>, and <a href="http://blogs.embarcadero.com/joseleon/2010/04/13/delphi-for-php-next-release-early-preview-4/">Preview #4</a>.&#160; Looks pretty cool to me.&#160; While you are at it, you can follow along on Twitter:&#160; <a href="http://twitter.com/qadram">http://twitter.com/qadram</a>. </li>
<li>The Blaise Pascal magazine has <a href="http://www.blaisepascal.eu/index.php?actie=./rozlog/page1">a free article online</a> from our very own <a href="http://blogs.embarcadero.com/michaelrozlog/">Michael Rozlog</a>.&#160; Mike gives a great rundown on some of the more advanced tools in Delphi including modeling and audits/metrics.&#160; There is a lot of power there, and I think that a lot of Delphi developers don’t take as much advantage of that power as they should.&#160; </li>
<li>For those of you who want a bit more on Test-driven Development, you might want to give a look <a href="http://delphixtreme.com/wordpress/">to the DelphiXtreme blog</a>. </li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39402&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39402" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23154&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F04%2F16%2F39402" id="akst_email_39402" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/04/16/39402/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Fun With Testing DateUtils.pas #8</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/04/15/39401</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/04/15/39401#comments</comments>
		<pubDate>Thu, 15 Apr 2010 22:34:15 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/04/15/39401</guid>
		<description><![CDATA[Okay, first up:&#160; I’ve put the tests and updates for DateUtils.pas on CodeCentral.&#160; 
So far, I’ve been writing tests in a pretty organized way.&#160; But I write each individual test, one at a time.&#160; I often end up writing a lot of “piece-meal” tests by hand.&#160; I end up with a lot of code that [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, first up:&#160; <a href="http://cc.embarcadero.com/item/27675">I’ve put the tests and updates for DateUtils.pas on CodeCentral</a>.&#160; </p>
<p>So far, I’ve been writing tests in a pretty organized way.&#160; But I write each individual test, one at a time.&#160; I often end up writing a lot of “piece-meal” tests by hand.&#160; I end up with a lot of code that looks like this:</p>
<pre><code>
<b>procedure</b> TDateUtilsTests.Test_IncMinuteBeforeEpochAdding;
<b>var</b>
  TestDate, Expected, TestResult: TDateTime;
<b>begin</b>
  TestDate   := EncodeDateTime(945, 12, 7, 13, 34, 26, 765);

  TestResult := IncMinute(TestDate, 1);
  Expected   := EncodeDateTime(945, 12, 7, 13, 35, 26, 765);
  CheckTrue(SameDateTime(TestResult, Expected), Format(<font color="lime">'IncMinute couldn'</font><font color="lime">'t add
     a single minute to %s '</font>, [DateTimeToStr(TestDate)]));

  TestResult := IncMinute(TestDate, 45);
  Expected   := EncodeDateTime(945, 12, 7, 14, 19, 26, 765);
  CheckTrue(SameDateTime(TestResult, Expected), Format(<font color="lime">'IncMinute couldn'</font><font color="lime">'t add
     45 minutes to %s '</font>, [DateTimeToStr(TestDate)]));

  TestResult := IncMinute(TestDate, MinsPerDay);
  Expected   := EncodeDateTime(945, 12, 8, 13, 34, 26, 765);
  CheckTrue(SameDateTime(TestResult, Expected), Format(<font color="lime">'IncMinute couldn'</font><font color="lime">'t add
     a days worth of minutes to %s '</font>, [DateTimeToStr(TestDate)]));

<b>end</b>;

</code></pre>
<p>Now those tests are fine, but they aren’t very easy to write. Adding another one either takes a lot of typing, or runs the risk of cut-n-paste errors that slow things down.&#160; Wouldn’t it be cool if there were a more systematic way of running tests that made it easier to add a specific test?</p>
<p>Well, one of our R&amp;D guys did that for the <font face="Courier New">DateUtils.pas</font> unit.&#160; Denis Totoliciu works on the RTL as part of our Romanian team.&#160;&#160; Now Denis is a pretty smart guy and a big proponent of test driven development.&#160; He has been busy writing tests for <font face="Courier New">DateUtils.pas</font> as well, and he’s a lot more efficiency minded than I am.&#160; As a result, he’s also a lot more productive and prolific. This is why I am the manager and he is the developer.&#160; <img src='http://blogs.embarcadero.com/nickhodges/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>If you look at the code for the unit tests, you can probably see where he has written tests and where I have (though I’ll be taking up Denis’s method for future tests).&#160; He recognized that most tests for any given DateUtils.pas routine are all going to be pretty similar, so he created a system whereby you create a large array of data, and then iterate over that array and run the tests on the data in each element. This way, if you want to add tests, you can simply add an item to the data array with the input and expected output.&#160; </p>
<p>For instance, when he first did this, I noticed that he didn’t always add data to test dates before the epoch.&#160; Since I’ve learned the hard way that whenever you test a routine you should also test dates before the epoch as well as after, it was really easy for me to simply add the data to the array and expand the number of tests that were run.&#160; </p>
<p>Here’s how this looks:</p>
<pre><code>
<b>procedure</b> TDateUtilsTests.Test_DayOfTheMonth;
<b>const</b>
  CMax = 16;
<b>type</b>
  TDateRec = <b>record</b>
    Year, Month, Day: Word;
    ExpectedDay: Word;
  <b>end</b>;
  TDates = <b>array</b> [1..CMax] <b>of</b> TDateRec;

<b>const</b>
  CDates: TDates = (
    (Year: 2004; Month: 01; Day: 01; ExpectedDay: 01),  <b><font color="red"><i>// 1</i></font></b>
    (Year: 2004; Month: 01; Day: 05; ExpectedDay: 05),
    (Year: 2004; Month: 01; Day: 08; ExpectedDay: 08),  <b><font color="red"><i>// 3</i></font></b>
    (Year: 2004; Month: 02; Day: 14; ExpectedDay: 14),
    (Year: 2004; Month: 02; Day: 29; ExpectedDay: 29),  <b><font color="red"><i>// 5</i></font></b>
    (Year: 2004; Month: 04; Day: 24; ExpectedDay: 24),
    (Year: 2004; Month: 07; Day: 27; ExpectedDay: 27),  <b><font color="red"><i>// 7</i></font></b>
    (Year: 2004; Month: 12; Day: 29; ExpectedDay: 29),

    (Year: 2005; Month: 01; Day: 01; ExpectedDay: 01),  <b><font color="red"><i>// 9</i></font></b>
    (Year: 2005; Month: 01; Day: 03; ExpectedDay: 03),
    (Year: 2005; Month: 05; Day: 05; ExpectedDay: 05),  <b><font color="red"><i>// 11</i></font></b>
    (Year: 2005; Month: 07; Day: 12; ExpectedDay: 12),
    (Year: 2005; Month: 09; Day: 11; ExpectedDay: 11),  <b><font color="red"><i>// 13</i></font></b>
    (Year: 2005; Month: 02; Day: 21; ExpectedDay: 21),
    (Year: 2005; Month: 02; Day: 25; ExpectedDay: 25),  <b><font color="red"><i>// 15</i></font></b>
    (Year: 2005; Month: 04; Day: 10; ExpectedDay: 10),
     );

<b>var</b>
  TestDate: TDateTime;
  Expected: Word;
  Result: Word;
  i: Integer;
<b>begin</b>
  <b>for</b> i := Low(CDates) <b>to</b> High(CDates) <b>do</b>
  <b>begin</b>
    TestDate := EncodeDate(CDates[i].Year, CDates[i].Month, CDates[i].Day);
    Expected := CDates[i].ExpectedDay;
    Result := DayOfTheMonth(TestDate);

    CheckTrue(SameDate(Expected, Result), Format(<font color="lime">'DayOfTheMonth failed
        for test %d.'</font>, [i]));
  <b>end</b>;
<b>end</b>;

</code></pre>
<p>Note that the first thing this code does is declare a really big array full of dates (all after the epoch, too). The array is of type <font face="Courier New">TDates</font>, which is simply an array of type <font face="Courier New">TDateRec</font>. All of these types are declared locally, so each routine can have it&#8217;s own separated data types. The array holds all the inputs as well as the expected result. Each element of the array is informally numbered, and when one fails, the number of the test is identified by the counter used in the <font face="Courier New">for</font> statement. </p>
<p>Now for me to add a bunch of tests that use data before the epoch is a piece of cake. I merely change the value for <font face="Courier New">CMax</font> and then make the array look like this:</p>
<pre><code>
<b>const</b>
  CDates: TDates = (
    (Year: 2004; Month: 01; Day: 01; ExpectedDay: 01),  <b><font color="red"><i>// 1</i></font></b>
    (Year: 2004; Month: 01; Day: 05; ExpectedDay: 05),
    (Year: 2004; Month: 01; Day: 08; ExpectedDay: 08),  <b><font color="red"><i>// 3</i></font></b>
    (Year: 2004; Month: 02; Day: 14; ExpectedDay: 14),
    (Year: 2004; Month: 02; Day: 29; ExpectedDay: 29),  <b><font color="red"><i>// 5</i></font></b>
    (Year: 2004; Month: 04; Day: 24; ExpectedDay: 24),
    (Year: 2004; Month: 07; Day: 27; ExpectedDay: 27),  <b><font color="red"><i>// 7</i></font></b>
    (Year: 2004; Month: 12; Day: 29; ExpectedDay: 29),

    (Year: 2005; Month: 01; Day: 01; ExpectedDay: 01),  <b><font color="red"><i>// 9</i></font></b>
    (Year: 2005; Month: 01; Day: 03; ExpectedDay: 03),
    (Year: 2005; Month: 05; Day: 05; ExpectedDay: 05),  <b><font color="red"><i>// 11</i></font></b>
    (Year: 2005; Month: 07; Day: 12; ExpectedDay: 12),
    (Year: 2005; Month: 09; Day: 11; ExpectedDay: 11),  <b><font color="red"><i>// 13</i></font></b>
    (Year: 2005; Month: 02; Day: 21; ExpectedDay: 21),
    (Year: 2005; Month: 02; Day: 25; ExpectedDay: 25),  <b><font color="red"><i>// 15</i></font></b>
    (Year: 2005; Month: 04; Day: 10; ExpectedDay: 10),
    <b><font color="red"><i>// Before the Epoch</i></font></b>
    (Year: 1004; Month: 01; Day: 01; ExpectedDay: 01),  <b><font color="red"><i>// 17</i></font></b>
    (Year: 1004; Month: 01; Day: 05; ExpectedDay: 05),
    (Year: 1004; Month: 01; Day: 08; ExpectedDay: 08),  <b><font color="red"><i>// 19</i></font></b>
    (Year: 1004; Month: 02; Day: 14; ExpectedDay: 14),
    (Year: 1004; Month: 02; Day: 29; ExpectedDay: 29),  <b><font color="red"><i>// 21</i></font></b>
    (Year: 1004; Month: 04; Day: 24; ExpectedDay: 24),
    (Year: 1004; Month: 07; Day: 27; ExpectedDay: 27),  <b><font color="red"><i>// 23</i></font></b>
    (Year: 1004; Month: 12; Day: 29; ExpectedDay: 29),

    (Year: 1005; Month: 01; Day: 01; ExpectedDay: 01),  <b><font color="red"><i>// 25</i></font></b>
    (Year: 1005; Month: 01; Day: 03; ExpectedDay: 03),
    (Year: 1005; Month: 05; Day: 05; ExpectedDay: 05),  <b><font color="red"><i>// 27</i></font></b>
    (Year: 1005; Month: 07; Day: 12; ExpectedDay: 12),
    (Year: 1005; Month: 09; Day: 11; ExpectedDay: 11),  <b><font color="red"><i>// 29</i></font></b>
    (Year: 1005; Month: 02; Day: 21; ExpectedDay: 21),
    (Year: 1005; Month: 02; Day: 25; ExpectedDay: 25),  <b><font color="red"><i>// 31</i></font></b>
    (Year: 1005; Month: 04; Day: 10; ExpectedDay: 10)
  );

</code></pre>
<p>And now I have a complete set of tests for dates before the epoch.&#160; Piece of cake.&#160; If I find specific dates that I want to test, then I can easily add those as well.&#160; The actual code that runs the tests doesn’t care how many elements there are in the array; it will happily process all the data passed to it.&#160; Now, you don’t get to write as many fun error messages as you do when you do it the more straightforward way, but that is a small price to pay for the efficiency gained. </p>
<p>And if a test fails, you are given the test number, and you can see the test data and expected result right away right in the code. </p>
<p>And here’s a further aside for those of you who don’t like me using random dates:&#160; this test for <font face="Courier New">EncodeDateDay</font> and <font face="Courier New">DecodeDateDay</font> tests every single day in every single year.&#160; <img src='http://blogs.embarcadero.com/nickhodges/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<pre><code>
<b>procedure</b> TDateUtilsTests.Test_EncodeDateDay_DecodeDateDay;
<b>var</b>
  TempYear, MinYear, MaxYear: Word;
  RYear: Word;
  TestDate: TDateTime;
  RDayOfWeek: Word;
  TempDay: Integer;
  RDayOfYear: Word;

<b>begin</b>
  <b><font color="red"><i>// Test every possible day for every possible year.</i></font></b>
  MinYear := MinAllowableYear; <b><font color="red"><i>// 1</i></font></b>
  MaxYear := MaxAllowableYear; <b><font color="red"><i>// 9999</i></font></b>
  <b>for</b> TempYear := MinYear <b>to</b> MaxYear <b>do</b>
  <b>begin</b>
    <b>for</b> TempDay := 1 <b>to</b> DaysPerYear[IsLeapYear(TempYear)] <b>do</b>
    <b>begin</b>
      TestDate := EncodeDateDay(TempYear, TempDay);
      DecodeDateDay(TestDate, RYear, RDayOfYear);

      CheckEquals(TempYear, RYear,
        Format(<font color="lime">'EncodeDateDay() / DecodeDateDay() failed.
             TempYear = %d; RYear = %d'</font>, [TempYear, RYear]));
      CheckEquals(TempDay, RDayOfYear,
        Format(<font color="lime">'EncodeDateDay() / DecodeDateDay() failed.
             TempDay = %d; RDayOfYear = %d'</font>, [TempDay, RDayOfYear]));
    <b>end</b>;
  <b>end</b>;
<b>end</b>;

</code></pre>
<p>It takes a little longer to process, but it covers every single possible test case, I believe.</p>
<p>So that should cover it.&#160; I think I’ll wrap the series up here.&#160; I’m almost done writing tests for <font face="Courier New">DateUtils.pas</font>.&#160; When I am done, I think I will move on to <font face="Courier New">StrUtils.pas</font>.&#160; </p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39401&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39401" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Fun%20With%20Testing%20DateUtils.pas%20%238&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F04%2F15%2F39401" id="akst_email_39401" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/04/15/39401/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Fun With Testing DateUtils.pas #7</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/04/14/39396</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/04/14/39396#comments</comments>
		<pubDate>Wed, 14 Apr 2010 16:03:42 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/04/14/39396</guid>
		<description><![CDATA[Okay, so after that last post, and after all the fixes that I did, things have settled down a little bit.  I thought I’d take advantage of this interlude to tell you some interesting things about TDateTime in Delphi, because along the way here, I have discovered a thing or two along that way that [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, so after that last post, and after all the fixes that I did, things have settled down a little bit.  I thought I’d take advantage of this interlude to tell you some interesting things about <span style="font-family: Courier New">TDateTime</span> in Delphi, because along the way here, I have discovered a thing or two along that way that was surprising.</p>
<p>The first thing that you might be interested in is that the calendar used by the Delphi <span style="font-family: Courier New">TDateTime</span> has a specific name:  <a href="http://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar">The Proleptic Gregorian Calendar</a>.  Calendars, of course, have been notoriously inaccurate over the years, and even ours isn’t entirely accurate in that we have to have leap years every so often (and not as often as one might believe…). We even have these “<a href="http://en.wikipedia.org/wiki/Leap_second">leap seconds</a>” every once and a while, though the notion of being able to measure things down that precisely is kind of weird.  Starting with the Romans – Julius Caesar, actually – the Western world used the <a href="http://en.wikipedia.org/wiki/Julian_calendar">Julian calendar</a>.  And that worked pretty well, actually.  The Julian calendar worked pretty well – it has 365 days and a leap year every four years – but it wasn’t entirely accurate, and (as you can read in the Wikipedia entry) politics got involved, and the calendar got out of whack pretty easily and pretty often.</p>
<p>So anyway, as you may have noticed, some of the tests that I have written include some pretty big time increments – like 1000 years worth of seconds and things like that.  And I also wanted to makes sure that the incrementing routines worked across the epoch of December 30, 1899.  So I had to be able to do some pretty serious calculations.  I found a pretty good website to do those calculations called <a href="http://www.timeanddate.com/">timeanddate.com</a>.  This site has a bunch of calculators for measuring between dates and time and for calculating a date based on distance from another date.  So I used it to figure out what the date was if you decremented two hundred years worth of seconds (that’s 6,307,200,000   seconds for you math geeks….) from, say, Noon on June 30, 1945.  (It’s not exactly noon on  June 30, 1745 due to leap days.)  Well, <a href="http://www.timeanddate.com/date/dateadded.html?m1=6&amp;d1=30&amp;y1=1945&amp;h1=12&amp;i1=0&amp;s1=0&amp;type=sub&amp;ay=&amp;am=&amp;ad=&amp;ah=&amp;ai=&amp;as=6307200000">I would calculate it</a>, and then write the tests, but they would fail because my expected result was always eleven days different than the test result.  Eleven days – how weird, huh?</p>
<p>Well, here’s the deal.  Somewhere along the way, the really smart guys who figure out this kind of thing came up with a new calendar – the Gregorian calendar.  It’s different from the Julian calendar, and starting in the 16th century, the world gradually converted over to use the Gregorian Calendar instead of the Julian calendar (A good chunk of Europe started in 1582, and the last folks to make the switch were the Russians who didn’t change until 1918).  But to do that, you usually had to skip about 10 or 11 days.  Great Britain and all of its possessions (including the colonies that would become the United States) made the switch in 1752.  Therefore, in the English world, the day following September 2, 1752 was September 14, 1752.  There was no September 3 – 13, 1752.  Just didn’t exist.  Once I discovered that, it explained the missing eleven days.</p>
<p>But what does this mean for our trusty <span style="font-family: Courier New">TDateTime</span>?  For a minute there I was afraid that I was going to have to do all these special calculations to account for this unusual anomaly, but then I came to my senses and realized:  That can’t be right.  And I was right.  Instead, Delphi uses, as I mentioned above, the Proleptic Gregorian Calendar – that is, it assumes that the Gregorian calendar is in force all the way  back to January 1, 0001.  So for TDateTime, there is a September 4, 1752 (Noon on that day is the value: -53807.5) and every single date “like normal” all the way down to Year 1.  This makes sense, because trying to devise a calendaring system that keeps track of all the vagaries of the Julian calendar system would be basically impossible.  Instead, Delphi uses a system that “makes sense” for a computer.  A number of other languages and tools use the Proleptic Gregorian Calendar, including MySQL and PHP.</p>
<p>That was probably more than you wanted to know about <span style="font-family: Courier New">TDateTime</span>, but it’s all stuff that you have to know to write a complete test suite for <span style="font-family: Courier New">DateUtils.pas</span>. So far, that summarizes the issues that I&#8217;ve run across in testing the unit. I have a ways to go to have a complete test suite, but if I run across more issues, I&#8217;ll post on them.</p>
<p>The next post I do will be about a testing scheme that one of our developers, Alexander Ciobanu, devised to make writing tests for testing date functions a little easier.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39396&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39396" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Fun%20With%20Testing%20DateUtils.pas%20%237&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F04%2F14%2F39396" id="akst_email_39396" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/04/14/39396/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Fun With Testing DateUtils.pas #6</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/04/13/39391</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/04/13/39391#comments</comments>
		<pubDate>Tue, 13 Apr 2010 23:55:03 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/?p=39391</guid>
		<description><![CDATA[Okay, so when we last left off, IncMillisecond was still failing in certain circumstances.  Let’s take a look at that.  Note, too, that I have this crazy notion that if you have a function called IncMillisecond, then it should be able to, you know, increment a millisecond.  
Here is the IncMilliseconds that you very [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, so when we last left off, <span style="font-family: Courier New">IncMillisecond</span> was still failing in certain circumstances.  Let’s take a look at that.  Note, too, that I have this crazy notion that if you have a function called <span style="font-family: Courier New">IncMillisecond</span>, then it should be able to, you know, increment a millisecond. <img src='http://blogs.embarcadero.com/nickhodges/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Here is the <span style="font-family: Courier New">IncMilliseconds</span> that you very likely have on your computer:</p>
<pre><code>
<strong>function</strong> IncMilliSecond(<strong>const</strong> AValue: TDateTime;
  <strong>const</strong> ANumberOfMilliSeconds: Int64): TDateTime;
<strong>begin</strong>
  <strong>if</strong> AValue &gt; 0 <strong>then</strong>
    Result := ((AValue * MSecsPerDay) + ANumberOfMilliSeconds) / MSecsPerDay
  <strong>else</strong>
    Result := ((AValue * MSecsPerDay) - ANumberOfMilliSeconds) / MSecsPerDay;
<strong>end</strong>;

</code></pre>
<p>Now that probably works just fine for you &#8212; as long as you don&#8217;t have a date that has a value less than the epoch. Below the epoch, and particularly in that magic "48 Hours" area right around the epoch itself, things go horribly awry. As we saw last time, this test will fail:</p>
<pre><code>
  TestDate := 0.0;
  TestResult := IncMillisecond(TestDate, -1);
  Expected := EncodeDateTime(1899, 12, 29, 23, 59, 59, 999);
  CheckTrue(SameDateTime(Expected, TestResult), <span style="color: lime">'IncMillisecond failed
    to subtract 1ms across the epoch'</span>);

</code></pre>
<p>It fails because of a number of reasons actually. The first is precision. The current implementation of <span style="font-family: Courier New">IncMillisecond</span> does division using a very small number in the denominator.  In the case of this test the numerator is a really big number multiplied by a really small number.  All of this cries out “precision error!”. (You should thank me – I almost used the <span style="font-family: Courier New">&lt;blink&gt;</span> tag there.  Phew!)  And that is basically what happens.  <span style="font-family: Courier New">IncMillisecond</span> isn’t precise enough to “see” the difference.</p>
<p>Plus, if you do things around the value of zero, it gets <strong><em>really</em> </strong>weird.  For instance, check out the output of this console application:</p>
<pre><code>
<strong>program</strong> IncMillisecondTest;

<strong><span style="color: red"><em>{$APPTYPE CONSOLE}</em></span></strong>

<strong>uses</strong>
  SysUtils, DateUtils;

<strong>var</strong>
  TestDate: TDateTime;
  TestResult: TDateTime;
  DateStr: <strong>string</strong>;

<strong>begin</strong>
  TestDate := 0.0;
  TestResult := IncMilliSecond(TestDate, 1001);
  DateStr := FormatDateTime(<span style="color: lime">'dd mmmm, yyyy hh:mm:ss:zzz'</span>,  TestResult);
  WriteLn(DateStr);
  TestResult := IncMilliSecond(TestDate, -1001);
  DateStr := FormatDateTime(<span style="color: lime">'dd mmmm, yyyy hh:mm:ss:zzz'</span>,  TestResult);
  WriteLn(DateStr);
  ReadLn;
<strong>end</strong>.

</code></pre>
<p><a href="$baddate6.png"><img src="$baddate_thumb4.png" border="0" alt="" width="453" height="335" /></a></p>
<p>I think it is safe to say that something is amiss.</p>
<p>So finally, it is time to rework <span style="font-family: Courier New">IncMillisecond</span>, because this pesky little routine is actually at the heart of a bunch of issues with <span style="font-family: Courier New">DateUtils.pas</span>. As it will turn out, if you call any of the <span style="font-family: Courier New">IncXXXX</span> routines, it all ends up as a call to <span style="font-family: Courier New">IncMilliseconds</span>, so this needs to be right.</p>
<p>Okay, so I started out writing this really cool implementation that checked for before and after the epoch, and divided large increments into years and months and days to make sure that their was no loss of precision.  I spent a lot of time on it, and had  whole bunch of tests written and passing with it.   But then it suddenly occurs to me that the trusty <span style="font-family: Courier New">TTimeStamp</span> data type and its accompanying conversion routines can once again come to the rescue:</p>
<pre><code>
<strong>function</strong> IncMilliSecond(<strong>const</strong> AValue: TDateTime;
  <strong>const</strong> ANumberOfMilliSeconds: Int64 = 1): TDateTime;
<strong>var</strong>
  TS: TTimeStamp;
  TempTime: Comp;
<strong>begin</strong>
  TS := DateTimeToTimeStamp(AValue);
  TempTime := TimeStampToMSecs(TS);
  TempTime := TempTime + ANumberOfMilliSeconds;
  TS := MSecsToTimeStamp(TempTime);
  Result := TimeStampToDateTime(TS);
<strong>end</strong>;

</code></pre>
<p>And here is the cool thing:  I was able to change from my sweet but overly complicated version to the new version above without worrying too much about it, because when I made the switch – <em>all of the tests that I had written for my original version still passed</em>.  This was so cool – I could make the change with confidence because of the large set of tests that I had that exercised all aspects on <span style="font-family: Courier New">IncMillisecond</span>.</p>
<p>Anywhow….  Again, the <span style="font-family: Courier New">TTimeStamp</span> type is precise, and easy. No need to do direct arithmetic on the <span style="font-family: Courier New">TDateTime</span> itself. Instead, we can deal with integers and get the exact answer every time no matter how many milliseconds you pass in. You can pass in 5000 years worth of milliseconds, and all will be well. For instance, this test passes just fine.</p>
<pre><code>
TestDate := EncodeDate(2010, 4, 8);
MSecsToAdd := Int64(5000) * DaysPerYear[False] * HoursPerDay * MinsPerHour *
    SecsPerMin *  MSecsPerSec; <strong><span style="color: red"><em>// 1.5768E14 or 157680000000000</em></span></strong>
TestResult := IncMilliSecond(TestDate, MSecsToAdd);
Expected := EncodeDate(7010, 4, 8);
ExtraLeapDays := LeapDaysBetweenDates(TestDate, Expected);
Expected := IncDay(Expected, -ExtraLeapDays);
CheckTrue(SameDate(Expected, TestResult), <span style="color: lime">'IncMillisecond failed to
   add 5000 years worth of milliseconds.'</span>);

</code></pre>
<p>And for you curious folks, here the implementation for the helper function LeapDaysBetweenDates:</p>
<pre><code>
<strong>function</strong> TDateUtilsTests.LeapDaysBetweenDates(aStartDate,
       aEndDate: TDateTime): Word;
<strong>var</strong>
  TempYear: Integer;
<strong>begin</strong>
  <strong>if</strong> aStartDate &gt; aEndDate <strong>then</strong>
    <strong>raise</strong> Exception.Create(<span style="color: lime">'StartDate must be before EndDate.'</span>);
  Result := 0;
  <strong>for</strong> TempYear := YearOf(aStartDate) <strong>to</strong> YearOf(aEndDate) <strong>do</strong>
  <strong>begin</strong>
    <strong>if</strong> IsLeapYear(TempYear) <strong>then</strong>
      Inc(Result);
  <strong>end</strong>;
  <strong>if</strong> IsInLeapYear(aStartDate) <strong>and</strong>
     (aStartDate &gt; EncodeDate(YearOf(aStartDate), 2, 29)) <strong>then</strong>
    Dec(Result);
  <strong>if</strong> IsInLeapYear(aEndDate) <strong>and</strong>
     (aEndDate &lt; EncodeDate(YearOf(aEndDate), 2, 29)) <strong>then</strong>
    Dec(Result);
<strong>end</strong>;

</code></pre>
<p>From there, the rest of the <span style="font-family: Courier New">IncXXXXX</span> routines are simple –- they merely multiply by the next “level up” of time intervals, and call the previous one.  I’ve marked them all <span style="font-family: Courier New">inline</span> so that it all happens in one need function call.  Thus, we have:</p>
<pre><code>
<strong>function</strong> IncHour(<strong>const</strong> AValue: TDateTime;
  <strong>const</strong> ANumberOfHours: Int64 = 1): TDateTime;
<strong>begin</strong>
  Result := IncMinute(AValue, ANumberOfHours * MinsPerHour);
<strong>end</strong>;

<strong>function</strong> IncMinute(<strong>const</strong> AValue: TDateTime;
  <strong>const</strong> ANumberOfMinutes: Int64 = 1): TDateTime;
<strong>begin</strong>
  Result := IncSecond(AValue, ANumberOfMinutes * MinsPerHour);
<strong>end</strong>;

<strong>function</strong> IncSecond(<strong>const</strong> AValue: TDateTime;
  <strong>const</strong> ANumberOfSeconds: Int64 = 1): TDateTime;
<strong>begin</strong>
  Result := IncMilliSecond(Avalue, ANumberOfSeconds * MSecsPerSec);
<strong>end</strong>;

</code></pre>
<blockquote><p>One thing to note: <span style="font-family: Courier New">DateUtils.pas</span> will only handle years from 1 to 9999. <span style="font-family: Courier New">TDateTime </span>won&#8217;t handle any date less than midnight on January 1, 0001 nor a date larger than December 31, 9999. So if you are using Delphi to track specific dates in dates before that (or if you plan on doing some time travel into the far future) you&#8217;ll have to use some other data type to keep track of dates.</p></blockquote>
<p>Now, once you’ve done the above, it is tempting to say “Hey, for <span style="font-family: Courier New">IncDay</span>, I’ll just add the days to the value passed in.  I mean, that’s all you are really doing.  Well guess what!  You can’t do that!  If you have this for your <span style="font-family: Courier New">IncDay</span>:</p>
<pre><code>
<strong>function</strong> IncDay(<strong>const</strong> AValue: TDateTime;
  <strong>const</strong> ANumberOfDays: Integer = 1): TDateTime;
<strong>begin</strong>
  Result := AValue + ANumberOfDays;
<strong>end</strong>;

</code></pre>
<p>Then this test will not pass because of the strange “48 hour” deal we talked about last post:</p>
<pre><code>
  TestDate := EncodeDateTime(1899, 12, 30, 1, 43, 28, 400);
  TestResult := IncDay(TestDate, -1);
  Expected := EncodeDateTime(1899, 12, 29, 1, 43, 28, 400);
  CheckTrue(SameDate(Expected, TestResult), <span style="color: lime">'IncDay failed to
    decrement one day from the epoch'</span>);

</code></pre>
<p>Instead, you have to send it all the way back to milliseconds via <span style="font-family: Courier New">IncHour</span>, <span style="font-family: Courier New">IncMinute</span>, and <span style="font-family: Courier New">IncSecond</span>:</p>
<pre><code>
<strong>function</strong> IncDay(<strong>const</strong> AValue: TDateTime;
  <strong>const</strong> ANumberOfDays: Integer = 1): TDateTime;
<strong>begin</strong>
  Result := IncHour(AValue, ANumberOfDays * HoursPerDay);
<strong>end</strong>;

</code></pre>
<p>Once you put those changes in, well, things get a lot greener.  I have now written a very thorough set of unit test  for testing <strong><em>all</em></strong> of the <span style="font-family: Courier New">IncXXXX</span> routines, adding and subtracting dates for both before and after the epoch.  I also test very carefully incrementing and decrementing <strong><em>across</em></strong> the epoch and inside that crazy little 48 hour spot.  They are all passing.</p>
<p>I’ll create a unit with these new fixes in it that you can use if you want.  I’ll also publish the unit that includes these tests that I’ve written.  (When you look at it, be nice.  It’s not very pretty, but it gets the job done.)  As I continue through, I’ll update that file with any other fixes and changes that get made.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39391&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39391" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Fun%20With%20Testing%20DateUtils.pas%20%236&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F04%2F13%2F39391" id="akst_email_39391" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/04/13/39391/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Fun With Testing DateUtils.pas #5</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/04/07/39380</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/04/07/39380#comments</comments>
		<pubDate>Wed, 07 Apr 2010 18:02:47 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[RAD Studio]]></category>

		<category><![CDATA[Unit Testing]]></category>

		<category><![CDATA[ednfront]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/04/07/39380</guid>
		<description><![CDATA[Okay, so when I left you hanging in the last post, I promised I’d explain what was up with IncMillisecond.&#160; But before I do that, I have to explain a bunch of stuff about TDateTime. And as it turns out, we’ll have to take a detour, and we won’t exactly get to IncMillisecond this time [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, so when I left you hanging in the last post, I promised I’d explain what was up with <font face="Courier New">IncMillisecond</font>.&#160; But before I do that, I have to explain a bunch of stuff about <font face="Courier New">TDateTime</font>. And as it turns out, we’ll have to take a detour, and we won’t exactly get to <font face="Courier New">IncMillisecond</font> this time around.&#160; </p>
<p>Most of you probably know how <font face="Courier New">TDateTime</font> works.&#160; <font face="Courier New">TDateTime</font> is a <font face="Courier New">Double</font> that keeps track of minutes in the “front” of the decimal and seconds in the fraction, or the “back”.&#160; The key thing to know is the value of the “epoch” that I mentioned previously.&#160; For <font face="Courier New">TDateTime</font>, the epoch is 0.0, which corresponds to exactly 00:00:00.000 (midnight) on December 30, 1899. (<a href="http://blogs.msdn.com/ericlippert/archive/2003/09/16/eric-s-complete-guide-to-vt-date.aspx">For can read up on all the gory details about why it is December 30, 1899, and not December 31, 1899</a>)&#160; </p>
<p>What this means is that a date time of 2.0 is January 1, 1900 at midnight.&#160; 2.5 would be noon on January 1, 1900.&#160; 1000.25 would be one thousand days and six hours past December 30, 1899, or <a href="http://www.timeanddate.com/date/dateadded.html?m1=12&amp;d1=30&amp;y1=1900&amp;h1=&amp;i1=&amp;s1=&amp;type=add&amp;ay=&amp;am=&amp;ad=1000&amp;ah=6&amp;ai=&amp;as=">September 26, 1903 at 6:00:00 AM</a>.&#160; It also means that –1 is December 29, 1899.&#160; and –1000.25 is Sunday, April 4, 1898 at 6:00:00 AM.&#160; </p>
<p>Now, that last one was a bit tricky if you look carefully at it.&#160; The days part was negative (-1000) but the <strong><em>hours</em> </strong>part was not.&#160; Remember, the left part of the double is the number of days before the epoch, but the decimal part – the part to the right, if you will – is <strong><em>always a positive value starting at midnight of the day in question. </em></strong>&#160; I emphasized that last part pretty strongly because once a date goes negative, a counter intuitive thing happens.&#160; The negative part only really applies to the left portion of the value.&#160; The decimal value represents a <strong><em>positive</em></strong> value from midnight.&#160; So to do the last calculation above, I actually had to subtract 999 days and 18 hours to get the right answer.&#160; And there in lies the heart of the problem that we have run into with incrementing milliseconds (and seconds and minutes and hours, as it turns out) for days before the epoch.&#160; </p>
<p>Here’s another way to think about it:&#160; what is the date time value for –0.5?&#160; Well, the correct answer is noon on 29 December 1899.&#160; But look at the left part of the value – it is still zero, which is, of course, 30 December 1899!&#160; And what if you make the call <font face="Courier New">Frac(-0.5)</font> to that value?&#160; You get – ready for it? &#8212; <font face="Courier New">-0.5</font>!&#160; And I just got done telling you that you can’t have a “negative” time value.&#160; Time values always are positive values from midnight.&#160; And herein lies our problem.&#160; </p>
<blockquote><p>Another interesting note:&#160; In the particular world of <font face="Courier New">TDateTime</font>, 0 has an unusual “feature”.&#160; When viewed as the “left” side of a TDateTime, it actually represents a span of time just a hair less than 48 hours.&#160; According to the pure mathematical formula for managing dates and times in Delphi, December 30, 1899 actually has 48 hours.&#160; That is, it stretches from –0.999… to 0.999…. in time.&#160; This is weird, huh?&#160; Never really thought about that, did you?&#160; Well, the whole Date/Time system has to account for this little anomaly.&#160; </p>
</blockquote>
<p>So, we have two related issues here:&#160; Time values for negative <font face="Courier New">TDateTime</font> values are really positive, and this weird 48 hour day thing right at the epoch.&#160; Well, frankly I didn’t think about or know about either one when I started out writing my unit tests (until they revealed this issue to me.&#160; Unit testing rocks…) and I am very sad to say that the original author of <font face="Courier New">DateUtils.pas</font> didn’t either.&#160; Both of these errors manifest themselves when calculating times at and before the epoch.&#160; That’s the bad part.&#160;&#160;&#160; And I know all of this because of unit testing.&#160; That’s the good part.&#160; </p>
<p>But wait, there is more.&#160; As it turns out, all of the time calculations in <font face="Courier New">DateUtils.pas</font> are based on floating point values.&#160; Very, very small floating point values, in fact.&#160; For instance, take a look at the current implementation of <font face="Courier New">IncMillisecond</font>:</p>
<pre><code>
<b>function</b> IncMilliSecond(<b>const</b> AValue: TDateTime;
  <b>const</b> ANumberOfMilliSeconds: Int64): TDateTime;
<b>begin</b>
  <b>if</b> AValue &gt; 0 <b>then</b>
    Result := ((AValue * MSecsPerDay) + ANumberOfMilliSeconds) / MSecsPerDay
  <b>else</b>
    Result := ((AValue * MSecsPerDay) - ANumberOfMilliSeconds) / MSecsPerDay;
<b>end</b>;
</code></pre>
<p>The value for <font face="Courier New">MSecsPerDay</font> is pretty large &#8212; 86,400,000 – and when you start dividing small numbers by really big numbers you get even smaller numbers &#8211;numbers so small that they lose precision.&#160; Now, you can see that our developer at least recognized that <strong><em>something</em></strong>&#160; was going a little goofy with the dates before zero, but the current implementation has the error we are currently looking at.&#160; Alas.</p>
<p>Or even better, go to <font face="Courier New">SysUtils.pas</font> and take a look at <font face="Courier New">TryEncodeTime</font>, which really does some arithmetic fraught with the possibilities for errors and inaccuracies:</p>
<pre><code>
<b>function</b> TryEncodeTime(Hour, Min, Sec, MSec: Word; out Time: TDateTime): Boolean;
<b>begin</b>
  Result := False;
  <b>if</b> (Hour &lt; HoursPerDay) <b>and</b> (Min &lt; MinsPerHour)
    <b>and</b> (Sec &lt; SecsPerMin) <b>and</b> (MSec &lt; MSecsPerSec) <b>then</b>
  <b>begin</b>
    Time := (Hour * (MinsPerHour * SecsPerMin * MSecsPerSec) +
             Min * (SecsPerMin * MSecsPerSec) +
             Sec * MSecsPerSec +
             MSec) / MSecsPerDay;
    Result := True;
  <b>end</b>;
<b>end</b>;
</code></pre>
<p>That will create some seriously small values, won’t it, given data near midnight on either side?&#160; I’ve subsequently reworked this routine to be more precise.&#160; (I’ll post all this new code for your real soon now.)</p>
<p>Okay, so where to turn in all of this?&#160; The first thing I did was to rewrite <font face="Courier New">IncMilliseconds</font>.&#160; But as you’ll see, even this was really, really tricky and fraught with peril as well.</p>
<p>Okay, so I thought – I’m doing all this test driven development; what I need to do right now is to write some test cases that I know should pass before I even start.&#160; First, I thought that if you have a function called <font face="Courier New">IncMillisecond</font>, then it ought to at least have enough accuracy and precision to at the very least create a different date/time combination, right?</p>
<pre><code>
  TestDate := 0.0;
  TestResult := IncMillisecond(TestDate);
  CheckFalse(SameDateTime(TestDate, TestResult), <font color="lime">'IncMilliseocnd failed to
     change the given date'</font>);
</code></pre>
<p>And of course, this fails.&#160; Good – I expected it to. But after a few hours of writing code, and wondering why it keeps failing, I suddenly realize that <font face="Courier New">SameDateTime</font> is the problem here!&#160; Argh! </p>
<p>And then it hits me – Uh oh.&#160; I’ve started pulling on a thread, and if I keep pulling on it, it is going to keep unraveling and unraveling….&#160; And that is exactly what happened.</p>
<p>Checkout your <font face="Courier New">SameDateTime</font>:</p>
<pre><code>
<b>function</b> SameDateTime(<b>const</b> A, B: TDateTime): Boolean;
<b>begin</b>
  Result := Abs(A - B) &lt; OneMillisecond;
<b>end</b>;
</code></pre>
<p>Now, that looks all well and good. Take the absolute value of the difference, and as long as it is less than 1ms, then the times are effectively the same. <font face="Courier New">OneMillisecond</font> is defined as: <font face="Courier New">OneMillisecond = 1 / MSecsPerDay</font>, or <font face="Courier New">1.15740741 × 10-8</font>. And in the world of computers, that is a pretty small number. So small, in fact, that it is pretty easy to have small values not register. In our simple test here, the A value is 0, and the B value <font face="Courier New">-1.1574074074e-08</font>. And guess what, that difference is not quite enough to get <font face="Courier New">SameDateTime</font> to return <font face="Courier New">False</font>. It returns <font face="Courier New">True</font> instead. </p>
<p>So, let&#8217;s follow this loose thread a bit more, and then we&#8217;ll quit for today. We need a <font face="Courier New">SameDateTime</font> function (and, as it turns out, a <font face="Courier New">SameTime</font> function) that returns a correct answer for dates that actually are <font face="Courier New">OneMillisecond</font> apart. We need something that gives answers based on real number so of milliseconds.&#160; And <font face="Courier New">SysUtils.pas</font> has the answer:&#160; <font face="Courier New">TTimeStamp</font></p>
<p><font face="Courier New">TTimeStamp</font> is declared as follows:</p>
<pre><code>
<b><font color="red"><i>{ Date and time record }</i></font></b>

  TTimeStamp = <b>record</b>
    Time: Integer;      <b><font color="red"><i>{ Number of milliseconds since midnight }</i></font></b>
    Date: Integer;      <b><font color="red"><i>{ One plus number of days since 1/1/0001 }</i></font></b>
  <b>end</b>;
</code></pre>
<p>Now, that is more like it &#8212; integers and not these fuzzy floating point numbers! The accompanying <font face="Courier New">DateTimeToTimeStamp</font> function is exactly what we need. Now, we can write a very precise <font face="Courier New">SameDateTime</font> and <font face="Courier New">SameDate</font> functions:</p>
<pre><code>
<b>function</b> SameDateTime(<b>const</b> A, B: TDateTime): Boolean;
<b>var</b>
  TSA, TSB: TTimeStamp;
<b>begin</b>
  TSA := DateTimeToTimeStamp(A);
  TSB := DateTimeToTimeStamp(B);
  Result := (TSA.Date = TSB.Date) <b>and</b> (TSA.Time = TSB.Time);
<b>end</b>;

<b>function</b> SameTime(<b>const</b> A, B: TDateTime): Boolean;
<b>begin</b>
  Result := (DateTimeToTimeStamp(A).Time = DateTimeToTimeStamp(B).Time);
<b>end</b>;
</code></pre>
<p>Those two new implementations will, in fact, return correct results for two dates one millisecond apart.&#160; And let’s just say that <font face="Courier New">TTimeStamp</font> is going to be making more appearances in the new, updated <font face="Courier New">DateUtils.pas</font> in the future.</p>
<p>Okay, so our original, simple test above passes now. But guess what: this second one still doesn&#8217;t: </p>
<pre><code>
  TestDate := 0.0;
  TestResult := IncMillisecond(TestDate, -1);
  CheckFalse(SameDateTime(TestDate, TestResult), <font color="lime">'IncMilliseocnd failed
    to change the given date'</font>);
  Expected := EncodeDateTime(1899, 12, 29, 23, 59, 59, 999);
  CheckTrue(SameDateTime(Expected, TestResult), <font color="lime">'IncMillisecond failed
    to subtract 1ms across the epoch'</font>);
</code></pre>
<p>So next time, we&#8217;ll get cracking on that.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39380&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39380" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Fun%20With%20Testing%20DateUtils.pas%20%235&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F04%2F07%2F39380" id="akst_email_39380" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/04/07/39380/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Fun With Testing DateUtils.pas #4</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/04/01/39379</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/04/01/39379#comments</comments>
		<pubDate>Thu, 01 Apr 2010 22:39:02 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[RAD Studio]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/04/01/39379</guid>
		<description><![CDATA[First, an admin note:&#160; I’ve adjusted the color of strings in my code.&#160;&#160; I was optimizing the colors for reading on my blog proper as opposed to the main site (hadn’t even thought of it, actually, sorry.), and someone pointed out that the colors weren’t working on the main site at all.&#160; Hope that this [...]]]></description>
			<content:encoded><![CDATA[<p>First, an admin note:&#160; I’ve adjusted the color of strings in my code.&#160;&#160; I was optimizing the colors for reading on my blog proper as opposed to the main site (hadn’t even thought of it, actually, sorry.), and someone pointed out that the colors weren’t working on the main site at all.&#160; Hope that this post is better.&#160; I changed the last post from Yellow to Lime.&#160; If you have a better color suggestion, please let me know.&#160; I’ve also endeavored to wrap those long code lines. The code won’t compile as shown, but I trust that you guys can figure it out……</p>
<p>Okay back to the topic at hand.</p>
<p>So things are rolling along.&#160; I’ve been writing tons of tests, they are all passing, things are going well, and it’s been fun.</p>
<p>But if you have any flair for the dramatic, you can see where this is going….</p>
<p>So there I was rolling along, writing tests for <font face="Courier New">WeeksInAYear</font> (bet you didn’t know that according to ISO 8601, some years have 53 weeks in them, did you.&#160; 1981 has 53 weeks, for example) <font face="Courier New">Today</font>, <font face="Courier New">Yesterday</font> – you know, normal stuff.&#160; I’m checking edge conditions, standard conditions, all kinds of years, every year.&#160; You know, really exercising things.&#160; All was rolling along smoothly.</p>
<p>For instance, here are the tests for <font face="Courier New">Yesterday</font>.&#160; Not too hard to test, as there is really only one thing you can do:</p>
<pre><code>
<b>procedure</b> TDateUtilsTests.Test_Yesterday;
<b>var</b>
  TestResult: TDateTime;
  Expected  : TDateTime;
<b>begin</b>
  TestResult := Yesterday;
  Expected   := IncDay(DateOf(Now), -1);
  CheckEquals(TestResult, Expected, <font color="lime">'The Yesterday function failed to
    return the correct value.'</font>);

  TestResult := Yesterday;
  Expected   := DateOf(Now);
  CheckFalse(SameDate(TestResult, Expected), <font color="lime">'The Yesterday function thinks
    Yesterday is Today, and means that Einstein was totally wrong.'</font>);

<b>end</b>;
</code></pre>
<p>Just a couple of tests that you can do – or at least what I can think of.&#160; (Anyone have any other ideas?)&#160; The fun part is that these tests will fail if <font face="Courier New">IncDay</font> and <font face="Courier New">DateOf</font> fail to perform as advertised, we get triple the testing!&#160; Sweet!</p>
<p>Things were going along swimmingly, and then all of a sudden, out of left field, all this unit testing stuff suddenly proved to be as valuable as everyone says it is.</p>
<p>Here’s how it happened: I was going along, writing tests, and I wrote this one:</p>
<pre><code>
<b>procedure</b> TDateUtilsTests.Test_EndOfTheDay;
<b>var</b>
  TestDate  : TDateTime;
  TestResult: TDateTime;
  i         : Integer;
  Expected  : TDateTime;
<b>begin</b>
  <b>for</b> i        := 1 <b>to</b> 500 <b>do</b>
  <b>begin</b>
    TestDate   := CreateRandomDate(False, 100, 2500);

    TestResult := EndOfTheDay(TestDate);
    <b><font color="red"><i>// First, don't change the date</i></font></b>
    CheckEquals(DayOf(TestDate), DayOf(TestResult), Format(<font color="lime">'EndOfTheDay changed
      the day for test date: %s (Result was: %s)'</font>, [DateTimeToStr(TestDate),
      DateTimeToStr(TestResult)]));

    <b><font color="red"><i>// Next, is it really midnight?</i></font></b>
    Expected := DateOf(TestDate);
    Expected := IncMillisecond(Expected, -1);
    Expected := IncDay(Expected);
    CheckTrue(SameDateTime(TestResult, Expected), Format(<font color="lime">'EndOfTheDay didn'</font><font color="lime">'t
      return midnight for test date: %s (Result was: %s, Expected was: %s)'</font>,
      [DateTimeToStr(DateOf(TestDate)), DateTimeToStr(TestResult),
       DateTimeToStr(Expected)]));

  <b>end</b>;
<b>end</b>;
</code></pre>
<p>&#160;</p>
<p>Pretty simple and straightforward.&#160; But &#8212; BOOM – this thing fails. Badly.&#160; If you run this test on your computer, the second check, the call to <font face="Courier New">CheckTrue</font>, will pretty quickly fail and you’ll get a message something like:</p>
<blockquote>
<p><font face="Courier New">Test_StartEndOfTheDay: ETestFailure at&#160; $0051FF06 EndOfTheDay didn&#8217;t return midnight for test date: 5/12/0366 (Result was: 5/12/0366 11:59:59 PM, Expected was: 5/14/0366 11:59:59 PM), expected: &lt;True&gt; but was: &lt;False&gt;</font></p>
</blockquote>
<p>Since the test is creating random dates, you’ll never get the exact same error, but pretty soon I figured out that it only failed for dates before the epoch – that is, for dates that have a negative value and are thus earlier than 30 December 1899.&#160; </p>
<p>Naturally, I was left scratching my head.&#160; The first inclination is that the test is somehow not correct. But I stared at it for a good long while and came to the conclusion that the test wasn’t the problem.&#160; </p>
<p>The first check is fine – the call to <font face="Courier New">EndOfTheDay</font> doesn’t actually change the date as it shouldn’t.&#160; But the second test is where the trouble started.&#160; </p>
<p><font face="Courier New">EndOfTheDay</font> is a pretty simple function;&#160; it returns the very last millisecond of the date for the date/time combination passed to it – that is, 11:59.999pm for the day in question. It is implemented like so: </p>
<pre><code>
<b><font color="red"><i>// From DateUtils.pas</i></font></b>
<b>function</b> EndOfTheDay(<b>const</b> AValue: TDateTime): TDateTime;
<b>begin</b>
  Result := RecodeTime(AValue, 23, 59, 59, 999);
<b>end</b>;
</code></pre>
<p>So the natural thing is to actually check to see if the result is indeed that value.&#160; So, I did the natural thing:&#160; I set the expected date to midnight on the date of the value to be tested, decremented one millisecond, and since that changed the date back one day, I moved it forward again with <font face="Courier New">IncDay</font>.&#160; Then I checked to see if they were indeed the same date/time combination.&#160; Well, guess what.&#160; They weren’t.&#160; </p>
<p>I originally had a single line of code combining the three that set the value for <font face="Courier New">Expected</font>.&#160; A quick look at the debugger told me that the <font face="Courier New">Expected</font> result wasn’t getting properly calculated.&#160; Breaking it down quickly pointed to a strange phenomenon:&#160; for dates before the epoch, the <font face="Courier New">IncMillisecond</font> call was actually moving the date portion <strong><em>forward</em></strong>&#160; by two days if the date was before the epoch.&#160; (Mysteriously, dates <strong><em>after</em>&#160;</strong>epoch all worked fine.&#160; Weird.)&#160; That, of course, is a big bad bug.&#160; </p>
<p>And this is the part where using the library itself to test other parts of the library is helpful.&#160; Because I used <font face="Courier New">IncMillisecond</font> in my test for <font face="Courier New">EndOfTheDay</font>, I found a bug in <font face="Courier New">IncMillisecond</font>. If I hadn’t done so, the problem might have been left lurking for a while longer.&#160; Or maybe it never would have revealed itself, depending on how diligent my testing of it ended up once I actually got there.&#160; </p>
<p>Luckily, it would appear that not too many of you are manipulating milliseconds for dates before the epoch, because there hasn’t been a big hue and cry about this problem. <a href="http://qc.embarcadero.com/wc/qcmain.aspx?d=67444">There have been some QC reports about it, though</a>.&#160; But clearly something is dreadfully wrong here.&#160; </p>
<p>In the next post, we’ll take a look at just what that is.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39379&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39379" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Fun%20With%20Testing%20DateUtils.pas%20%234&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F04%2F01%2F39379" id="akst_email_39379" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/04/01/39379/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #153</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/03/31/39378</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/03/31/39378#comments</comments>
		<pubDate>Thu, 01 Apr 2010 01:03:49 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[CodeGear]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Delphi Prism]]></category>

		<category><![CDATA[Random Thoughts]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/03/31/39378</guid>
		<description><![CDATA[
Andreano has a new blog, or at least it is new to me – just found it today.&#160; He has two items there that caught my eye:

His RADTweet project – a Delphi-based Twitter client – is online.&#160; He has wisely put it on SourceForge for easy access, downloading, and updating.&#160; 
A project that shows how [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>Andreano has a new blog, or at least it is new to me – just found it today.&#160; He has two items there that caught my eye:
<ul>
<li><a href="http://www.andreanolanusse.com/blogen/radtweet-twitter-desktop-client-build-with-delphi/">His RADTweet project</a> – a Delphi-based Twitter client – is online.&#160; <a href="http://sourceforge.net/projects/radtweet/">He has wisely put it on SourceForge</a> for easy access, downloading, and updating.&#160; </li>
<li>A project that shows how to <a href="http://www.andreanolanusse.com/blogen/datasnap-2010-authentication-throught-tcpip-transport/">do HTTP authentication with DataSnap</a> </li>
<li>While you are at it, check out his post on “<a href="http://www.andreanolanusse.com/blogen/using-linq-to-objetcs-in-delphi-prism/">Using LINQ to Objetcs in Delphi Prism</a>”. </li>
</ul>
</li>
<li>The inestimable Mike Rozlog is on a hot streak, and he continues to give cool and interesting Webinars.&#160; His latest is <a href="http://edn.embarcadero.com/article/40516">“Mastering Database Application Development with Delphi”</a>.&#160; Once again, he’ll be giving the webinar at three times during the day of 14 April 2010, so no matter where you are in the world, you should be able to attend one of them.&#160; </li>
<li>These marketing people are busy.&#160; What to know about RAD In Action regarding building database applications?&#160; <a href="http://www.embarcadero.com/rad-in-action/database">There’s a web page for that</a>.&#160; </li>
<li><a href="http://community.devexpress.com/blogs/ctodx/">Julian Bucknall</a>, the CTODX (Chief Technology Officer of Developer Express) has <a href="http://community.devexpress.com/blogs/ctodx/archive/2010/03/31/time-for-some-delphi-and-vcl-news.aspx">an update for their VCL customers</a>. </li>
<li>My mentioning of our move caused a bit of a stir in the comment section.&#160;&#160; A couple of more thoughts on it.&#160; I can only speak for myself, but so far it is working out pretty well.&#160; I like the new space.&#160; I like my cube.&#160; I like that everyone is fairly close together but not too close.&#160; Our previous space was <strong><em>waaaaay</em></strong>&#160; to big for us, and you could go weeks without seeing someone from Sales or Support.&#160; Now, we are are all in one space, and it feels more like we are one team, which of course we are.&#160; I like that this new place is a good fit.&#160; I like that this place is significantly more appropriate and significantly less expensive that our previous space.&#160; I like that this place is a new start. I like that we have a gigabit network.&#160; I like that we have projectors hanging from the ceilings in the conference rooms.&#160; I like that it is closer to the shopping mall across the street. But most of all, I like that it represents a significant investment in and commitment to our team. So for me, this is a big win. </li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39378&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39378" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23153&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F03%2F31%2F39378" id="akst_email_39378" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/03/31/39378/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Fun With Testing DateUtils.pas #3</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/03/30/39374</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/03/30/39374#comments</comments>
		<pubDate>Wed, 31 Mar 2010 03:20:24 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Fun with Unit Testing]]></category>

		<category><![CDATA[RAD Studio]]></category>

		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/03/30/39374</guid>
		<description><![CDATA[Okay, things have settled down again, and it is time to get back to my adventure in TDateTime and DateUtils.pas.
When we last left off, I had started at the top of DateUtils, and just started working my way down.&#160; I had written some tests for DateOf and TimeOf, and tried to write tests that pretty [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, things have settled down again, and it is time to get back to my adventure in <font face="Courier New">TDateTime</font> and <font face="Courier New">DateUtils.pas</font>.</p>
<p>When we last left off, I had started at the top of <font face="Courier New">DateUtils</font>, and just started working my way down.&#160; I had written some tests for <font face="Courier New">DateOf</font> and <font face="Courier New">TimeOf</font>, and tried to write tests that pretty thoroughly exercised those functions.&#160; I tried to hit the edges and boundaries, and to test all the different permutations and combinations of a date only, a time only, and both together.&#160; </p>
<p>From there, I worked my way down the list, writing tests for <font face="Courier New">IsLeapYear</font>, IsPM, etc.&#160; </p>
<p>One thing I did was to add <font face="Courier New">IsAM</font> to <font face="Courier New">DateUtils.pas</font> and simply implemented it as: </p>
<pre><code>
<b>function</b> IsAM(<b>const</b> AValue: TDateTime): Boolean;
<b>begin</b>
  Result := <b>not</b> IsPM(AValue);
<b>end</b>;
</code></pre>
<p>Now, that is really simple.&#160; Shoot, you don’t really need to write tests for that, right?&#160; I mean, I wrote a whole suite of tests for <font face="Courier New">IsPM</font>, and so how could <font face="Courier New">IsAM</font> go wrong? Well, any number of ways – but the main one is that some day in the future, someone might come along and try to get cute or super-smart or something and change the implementation.&#160; So I went ahead and wrote a whole bunch of tests for <font face="Courier New">IsAM</font> anyway.&#160; Now, if something changes, or if someone changes something, the tests should be able to recognize that.&#160; </p>
<blockquote>
<p><em><strong>Philosophical Note: </strong></em>As I’m doing this, I’m seeing more clearly than ever that writing tests is all about confidence moving forward.&#160; Once you have taken the effort to write thorough, complete suites of unit tests, you can move forward with confidence.&#160; You can make changes and fixes while feeling confident that if your change has unintended consequences, you’ll likely know about it. If you do find a bug, you write a test that “reveals” it, fix the bug so the test passes, and then you can move forward confident that you’ll know right away if that bug comes back to haunt you.&#160; Confidence is a really good thing when it comes to writing code.</p>
</blockquote>
<p>So, for instance, let’s look at the tests for <font face="Courier New">IsInLeapYear</font>.&#160; Leap years are a bit funky.&#160; Some years that you think are leap years are not – Quick:&#160; Was 1600 a leap year?&#160; What about 1900?&#160; Wikipedia actually has <a href="http://en.wikipedia.org/wiki/Leap_year">a good page on leap years</a>.&#160; (Did you know that leap years are also called “intercalary years”? I sure didn’t.)&#160; The actual calculation of a leap year is a bit more complicated that “Is it divisible by 4?”.&#160; </p>
<pre><code>
<b>function</b> IsLeapYear(Year: Word): Boolean;
<b>begin</b>
  Result := (Year <b>mod</b> 4 = 0) <b>and</b> ((Year <b>mod</b> 100 &lt;&gt; 0) <b>or</b> (Year <b>mod</b> 400 = 0));
<b>end</b>;
</code></pre>
<p>Examine the code, you can see that the answer to the questions above are Yes and No.&#160; (As a side note, our QA Manager is a “Leapling”, born on February 29th.&#160; He’s really only 12 years old.)</p>
<p>So, how do you test something called <font face="Courier New">IsInLeapYear</font>?&#160; The declaration is actually quite simple:</p>
<pre><code>
<b>function</b> IsInLeapYear(<b>const</b> AValue: TDateTime): Boolean;
<b>begin</b>
  Result := IsLeapYear(YearOf(AValue));
<b>end</b>;
</code></pre>
<p>But just because it is simple doesn’t mean that you shouldn’t thoroughly test it!&#160; So I wrote a whole bunch of tests. First, I checked that random dates in years I know are leap years were properly identified as being in a leap year:</p>
<pre><code>
TestDate   := EncodeDate(1960, 2, 29);
  TestResult := IsInLeapYear(TestDate);
  CheckTrue(TestResult, Format(<font color="lime">'%s is in a leap year, but IsInLeapYear says
    that it isn'</font><font color="lime">'t.  Test #1'</font>, [DateToStr(TestDate)]));

  TestDate   := EncodeDate(2000, 7, 31);
  TestResult := IsInLeapYear(TestDate);
  CheckTrue(TestResult, Format(<font color="lime">'%s is in a leap year, but IsInLeapYear says
    that it isn'</font><font color="lime">'t.  Test #2'</font>, [DateToStr(TestDate)]));

  TestDate   := EncodeDate(1600, 7, 31);
  TestResult := IsInLeapYear(TestDate);
  CheckTrue(TestResult, Format(<font color="lime">'%s is in a leap year, but IsInLeapYear says
    that it isn'</font><font color="lime">'t.  Test #4'</font>, [DateToStr(TestDate)]));

  TestDate   := EncodeDate(1972, 4, 5);
  TestResult := IsInLeapYear(TestDate);
  CheckTrue(TestResult, Format(<font color="lime">'%s is in a leap year, but IsInLeapYear says
    that it isn'</font><font color="lime">'t.  Test #5'</font>, [DateToStr(TestDate)]));

  TestDate   := EncodeDate(1888, 2, 29);
  TestResult := IsInLeapYear(TestDate);
  CheckTrue(TestResult, Format(<font color="lime">'%s is in a leap year, but IsInLeapYear says
    that it isn'</font><font color="lime">'t.  Test #7'</font>, [DateToStr(TestDate)]));

  TestDate   := EncodeDate(2400, 2, 29);
  TestResult := IsInLeapYear(TestDate);
  CheckTrue(TestResult, Format(<font color="lime">'%s is in a leap year, but IsInLeapYear says
    that it isn'</font><font color="lime">'t.  Test #8'</font>, [DateToStr(TestDate)]));
</code></pre>
<p>Note that I checked &quot;normal&quot; dates, but also dates in the far future (including the tricky 2400) as well as dates before the epoch (which is December 30, 1899, or a datetime value of 0.0). I’ll talk a little more about the epoch in a future post because the epoch is really, really important to <font face="Courier New">TDateTime</font>. It is also really, really troublesome.&#160; <img src='http://blogs.embarcadero.com/nickhodges/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Another thing to note is that this code uses (and thus tests) <font face="Courier New">EncodeDate</font>. And <font face="Courier New">IsInLeapYear</font> itself will exercise <font face="Courier New">YearOf</font> and <font face="Courier New">IsLeapYear</font> indirectly.&#160; If a test in <font face="Courier New">IsInLeapYear</font> fails indirectly because of one of these, you’ll be able to figure that out pretty quickly, write tests specifically to reveal those problems, fix the problems, and then move forward with confidence that you’ve resolved the issues.</p>
<p>Anyway, I also wrote some negative test cases, checking to see that it returned <font face="Courier New">False</font> for dates that most definitely were not in leap years.&#160;&#160; I also wrote tests for dates in years that many folks might thing are leap years but are in fact not leap years:</p>
<pre><code>
  <b><font color="red"><i>// Years that end in 00 are /not/ leap years, unless divisible by 400</i></font></b>
  TestDate   := EncodeDate(1700, 2, 28);
  TestResult := IsInLeapYear(TestDate);
  CheckFalse(TestResult, Format(<font color="lime">'%s is in a leap year, but IsInLeapYear says
    that it isn'</font><font color="lime">'t.  Test #6'</font>, [DateToStr(TestDate)]));

  TestDate   := EncodeDate(1900, 2, 28);
  TestResult := IsInLeapYear(TestDate);
  CheckFalse(TestResult, Format(<font color="lime">'%s is in a leap year, but IsInLeapYear says
    that it isn'</font><font color="lime">'t.  Test #7'</font>, [DateToStr(TestDate)]));
</code></pre>
<p>Now that might seem like overkill for a simple function like <font face="Courier New">IsInLeapYear</font>, but I don&#8217;t think so. I am now really confident that, since we will be running these tests almost continuously on our Hudson server, no one can mess or alter or change or otherwise break the way leap years are calculated without us knowing about it immediately. And that&#8217;s sort of the whole point, right?</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39374&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39374" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Fun%20With%20Testing%20DateUtils.pas%20%233&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F03%2F30%2F39374" id="akst_email_39374" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/03/30/39374/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #152</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/03/23/39373</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/03/23/39373#comments</comments>
		<pubDate>Tue, 23 Mar 2010 22:08:37 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Random Thoughts]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/03/23/39373</guid>
		<description><![CDATA[
As you may know, we are moving to a new office very nearby where we are now.&#160; We got to visit the new digs today.&#160; Friday is moving day, and we’ll be in the new place for a great new start on Monday morning.&#160; I’m excited – I think that the move will be a [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>As you may know, we are moving to a new office very nearby where we are now.&#160; We got to visit the new digs today.&#160; Friday is moving day, and we’ll be in the new place for a great new start on Monday morning.&#160; I’m excited – I think that the move will be a great fresh start for us in a new place.&#160; We’ll be moving from offices to cubes, so that will be a bit of a culture shift and an adjustment, but it should be great.&#160; Pursuant to the move, of course, we have been and will be migrating servers to our new location.&#160; So if things aren’t working 100% correctly, give it a bit and try again.&#160; If things are persistently not working, then let us know.&#160; Our IT team is working very hard to make sure that the migration goes smoothly, but there will inevitably be hiccups along the way. Your patience and understanding are appreciated.</li>
<li>From time to time, people ask how to make a deep copy of an existing instance of a class.&#160; Well, using the new, super cool RTTI, <a href="http://alex.ciobanu.org/?p=325">Alex is on the case</a>. </li>
<li>Our Haiti Auction <a href="http://www.mercurynews.com/california/ci_14711011?nclick_check=1">got written up in the San Jose Mercury News</a>.&#160; Nice! </li>
<li>New Delphi site offering specials on Delphi components: <a title="http://www.delphiday.com/" href="http://www.delphiday.com/">http://www.delphiday.com/</a></li>
<li>One of the best parts about Delphi is the awesome community, and one of the best parts of the community is the <a href="http://www.delphi-jedi.org/">JEDI team</a>.&#160; These guys are awesome, and provide and an incredible amount of value to all of us.&#160; They had some newsgroups at forums.talko.net that have apparently stopped working. As a result, they have a new server at <font face="Courier New">news.delphi-jedi.org</font> where you can point your NNTP newsreader on port 119.&#160; </li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39373&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39373" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23152&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F03%2F23%2F39373" id="akst_email_39373" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/03/23/39373/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #151</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/03/18/39372</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/03/18/39372#comments</comments>
		<pubDate>Fri, 19 Mar 2010 00:22:03 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Random Thoughts]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/03/18/39372</guid>
		<description><![CDATA[
I’m a big Joel Spolsky fan, but I wasn’t too impressed when I read that he went out of his way to steal Pascal’s with statement and add it to VBA for Excel, well…..
Cary Jensen is doing a series of Webinars on Migrating to Unicode.&#160; It’s not as hard as you think.&#160; He’ll be showing [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>I’m a big <a href="http://www.joelonsoftware.com">Joel Spolsky</a> fan, but I wasn’t too impressed when I read that <a href="http://www.joelonsoftware.com/items/2006/06/16.html">he went out of his way to steal Pascal’s <font face="Courier New">with</font> statement</a> and add it to VBA for Excel, well…..</li>
<li><a href="http://www.embarcadero.com/rad-in-action/migration-upgrade-center">Cary Jensen is doing a series of Webinars on Migrating to Unicode</a>.&#160; It’s not as hard as you think.&#160; He’ll be showing you that and more at three different times over March 24 and March 25.&#160; You can find out more at our <a href="http://www.embarcadero.com/rad-in-action/migration-upgrade-center">Migration Center</a>. While you are there, you can download a White Paper Cary wrote called “Delphi Unicode Migration for Mere Mortals .”&#160; Kudos to the marketing guys for getting all these great Webinars put together.&#160; And do note that there are three times around the clock, so that you should be able to find a convenient time to watch no matter where you are in the world.</li>
<li><strong>Turbopower Update</strong>:&#160; One of our incomparable sales guys, Al Mannarino, has published two very useful articles.&#160; The first is called “<a href="http://edn.embarcadero.com/article/40491">Delphi 2010: Installing TurboPower Orpheus</a>“ which, not surprisingly, tells you how to install <a href="http://sourceforge.net/projects/tporpheus/">Turbopower Orpheus</a> into Delphi 2010.</li>
<li>Did you know that <a href="http://www.linkedin.com/groups?homeNewMember=&amp;gid=2551723">Embarcadero has its own page on LinkedIn</a>?&#160; And <a href="http://www.facebook.com/embarcaderotech">Facebook</a>? And <a href="http://twitter.com/EmbarcaderoTech">Twitter</a>? And <a href="http://www.youtube.com/embarcaderotechnet">YouTube</a>?</li>
<li>Craig Stuntz has a <a href="http://blogs.teamb.com/craigstuntz/2010/03/18/38566/">very interesting blog post about a new and potentially game-breaking type of encryption</a>.&#160; I’d type the name here, but I’m not sure I can even say it right.&#160; <img src='http://blogs.embarcadero.com/nickhodges/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39372&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39372" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23151&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F03%2F18%2F39372" id="akst_email_39372" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/03/18/39372/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #150</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/03/17/39371</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/03/17/39371#comments</comments>
		<pubDate>Wed, 17 Mar 2010 16:59:39 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Random Thoughts]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/03/17/39371</guid>
		<description><![CDATA[
David I is doing another webinar:&#160; RAD/AJAX-based Web Application Development using RAD Studio 2010.&#160; He is giving it three different times on Thursday, March 18, 2010, so no matter where you are in the world, you should be able to tune in. 
Anders Ohlsson has wrapped up the Haiti auction, and when all is said [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li><a href="http://blogs.embarcadero.com/davidi">David I</a> is doing another webinar:&#160; <a href="http://now.eloqua.com/es.asp?s=608&amp;e=256580&amp;elq=8b0ef34905734663b69b804dc882e925">RAD/AJAX-based Web Application Development using RAD Studio 2010</a>.&#160; He is giving it three different times on Thursday, March 18, 2010, so no matter where you are in the world, you should be able to tune in. </li>
<li>Anders Ohlsson has wrapped up the Haiti auction, and when all is said and done, you all will have helped to contribute over US$26,000 to Haitian relief.&#160; That’s amazing.&#160; A huge thank you to all that bid and bought items, and to those that help spread the word.&#160; You all were very generous and frequently paid quite a bit more than fair market value.&#160; ;-)&#160; Thanks, also, to folks like Anders Hejlsberg, <a href="http://www.dannythorpe.com">Danny Thorpe</a>, <a href="http://www.removingalldoubt.com/">Chuck Jazdzewski</a>, <a href="http://www.theopenforce.com/">Zack Urlocker</a>, Gary Whizin and others that made the effort to sign some of the items and increase their value.&#160; A huge thank you to <a href="http://blogs.embarcadero.com/ao">Anders</a> who did the lion’s share of the work.&#160; All in all, it was a great thing you all did.&#160;&#160; Very cool.</li>
<li>Just two items today, as I wanted to get the David I seminar posted…..</li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39371&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39371" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23150&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F03%2F17%2F39371" id="akst_email_39371" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/03/17/39371/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Fun With Testing DateUtils.pas #2</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/03/16/39370</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/03/16/39370#comments</comments>
		<pubDate>Tue, 16 Mar 2010 18:26:50 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Fun with Unit Testing]]></category>

		<category><![CDATA[General]]></category>

		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/03/16/39370</guid>
		<description><![CDATA[First of all, thanks for the help improving the CreateRandomDate function.&#160; I confess that I didn’t spend enough time thinking on it, and I’ll also confess that you guys are way smarter than I am.&#160; ;-)&#160; I’ll post the “updated” version for your perusal in a separate post.&#160; 
In addition, you all were right – [...]]]></description>
			<content:encoded><![CDATA[<p>First of all, thanks for the help improving the <font face="Courier New">CreateRandomDate</font> function.&#160; I confess that I didn’t spend enough time thinking on it, and I’ll also confess that you guys are way smarter than I am.&#160; ;-)&#160; I’ll post the “updated” version for your perusal in a separate post.&#160; </p>
<p>In addition, you all were right – that code formatting sucks.&#160;&#160; The plug-in I got for Live Writer was not very configurable.&#160; I am now <a href="http://cc.embarcadero.com/Item.aspx?id=14531">using John Kasters “YAPP” tool</a>, and it all looks a lot better.&#160; </p>
<p>Okay, back to the show…..</p>
<p>So to get going with unit testing <font face="Courier New">DateUtils.pas</font>, I naturally simply “plugged in” to our existing RTL unit test framework.&#160; We have an existing RTL set of unit tests for running DUnit tests on the RTL.&#160; I simply added the unit <font face="Courier New">UnitTest.DateUtils.pas</font> to the project, created the new class:</p>
<pre><code>
TDateUtilsTests = <b>class</b>(TTestCase)
<b>end</b>;
</code></pre>
<p>and I was in business.&#160; From there, it’s merely a matter of declaring published methods that run the DUnit tests.</p>
<p>So, I started right at the top with <font face="Courier New">DateOf</font> and <font face="Courier New">TimeOf. </font>So, what to test? Well, the most obvious thing: Does <font face="Courier New">DateOf</font> actually return the date portion of a given <font face="Courier New">TDateTime</font>?&#160; Well, lets create a <font face="Courier New">TDateTime</font> with a random time, then, lets create a <font face="Courier New">TDate</font> with the same date but no time at all, and see if DateOf can do it’s magic?</p>
<pre><code>
<b>procedure</b> TDateUtilsTests.Test_DateOf;
<b>var</b>
  TestDate: TDateTime;
  Expected: TDateTime;
  Result  : TDateTime;
<b>begin</b>
  TestDate := EncodeDateTime(1945, 12, 1, 1, 46, 13, 112);
  Expected := EncodeDate(1945, 12, 1);
  Result   := DateOf(TestDate);
  CheckTrue(SameDate(Result, Expected), <font color="yellow">'Test date and Expected date were not the same.'
             + ' DateOf function failed. Test #1'</font>);
<b>end</b>;
</code></pre>
<p>So this is a pretty straightforward test – you create two dates, and see if they are the same after the call to <font face="Courier New">DateOf</font>.&#160; Simple.</p>
<p>What if you, say, increment the time part by one millisecond.&#160; Come on, that can’t hurt anything right?&#160; Better make sure:</p>
<pre><code>
  <b><font color="limegreen"><i>// This test will fail if it gets run at 23:59.999 at night.
  // I'm willing to gamble that this will never happen.</i></font></b>
  TestDate := Now;
  Expected := IncMillisecond(TestDate);
  Result   := DateOf(TestDate);
  CheckTrue(SameDate(Result, Expected), <font color="yellow">'Test date and Expected date were not the same.'
          + ' DateOf function failed. Test #2'</font>);
</code></pre>
<p>Okay, those are some “positive test cases”.&#160; (I have a bunch more different ones along these lines….)&#160; What about testing the negative case?&#160; That is, test where we <strong><em>know</em></strong> that the two dates should be different after the call, and we test to make sure that they are, indeed different.</p>
<pre><code>
  TestDate := Now;
  Expected := DateOf(IncDay(TestDate));
  Result   := DateOf(TestDate);
  CheckFalse(SameDate(Result, Expected), <font color="yellow">'Test date and Expected date should have'
	+ ' been different but they weren'</font><font color="yellow">'t.  Test #2'</font>);
</code></pre>
<p>I have a similar set of tests for <font face="Courier New">TimeOf</font>.&#160; These are pretty basic, but that is where you start, right?&#160; With the basics?&#160; From there, I wrote tests that change only the milliseconds, the seconds, the minutes and the hours.&#160; All should never allow the <font face="Courier New">DateOf</font> function to return anything other than the date.&#160; For TimeOf, I do the same – change the year, month, and date and make sure the time is the same.&#160; Then I purposefully change the time and make sure that the function actually does change the time.&#160; </p>
<p>Now, some of you are going to chastise me for using other <font face="Courier New">DateUtils</font>.pas functions to write tests.&#160; Two schools of thought on that.&#160; One says that you should never rely on <strong><em>anything</em></strong> outside of the actually call being tested.&#160; Another says to use those library functions because they’ll get tested all the more when used in other tests. I’m going to be following the latter philosophy, and as well see in a later post, this way of doing things actually will reveal a pretty significant bug in a routine that was used to test another routine.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39370&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39370" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Fun%20With%20Testing%20DateUtils.pas%20%232&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F03%2F16%2F39370" id="akst_email_39370" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/03/16/39370/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Fun With Testing DateUtils.pas #1</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/03/10/39369</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/03/10/39369#comments</comments>
		<pubDate>Wed, 10 Mar 2010 17:22:21 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Fun with Unit Testing]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/03/10/39369</guid>
		<description><![CDATA[Okay, so I’m a Development Manager. My job is to see to the health, welfare, productivity, effectiveness, and proper tasking of a big chunk of the RAD Studio development team. I share these duties with the excellent and capable Mike Devery.&#160; I mainly manage the guys that work on the IDE, the RTL, and the [...]]]></description>
			<content:encoded><![CDATA[<p>Okay, so I’m a Development Manager. My job is to see to the health, welfare, productivity, effectiveness, and proper tasking of a big chunk of the RAD Studio development team. I share these duties with the excellent and capable <a href="http://blogs.embarcadero.com/michaeldevery/">Mike Devery</a>.&#160; I mainly manage the guys that work on the IDE, the RTL, and the frameworks.&#160; I do things like make sure they are working on the right thing via our SCRUM interations, that they have good machines, nice chairs, vacations when they want them, the right keyboard, etc.&#160; I manage the development process in that we on the “War Team” spend a lot of time triaging bugs, managing and defining requirements, tracking progress, finding better ways to write better code – you know, development manager stuff.</p>
<p>But, like all good development managers, my heart really is in coding.&#160; And I don’t do much of that anymore.&#160; So I’ve tried to keep my fingers in things by taking on some small development tasks where I can keep my skills up, stimulate my brain in that way, and not cause too much damage.&#160; </p>
<p>What better way to do that than to write unit tests?&#160; I’m a bit weird in that I actually like to write unit tests. I find them challenging and enjoy the “puzzle solving” aspect of it.&#160; I like to try to find corner and edge cases where the tests might fail.&#160; I like knowing that ever test I write means less work down the road because any regressions will be found sooner – hopefully immediately.&#160; And I can write tests to my hearts content without worrying about breaking the product.&#160; <img src='http://blogs.embarcadero.com/nickhodges/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>So I started in on DateUtils.pas.&#160; This is a pretty cool unit with a lot of good functionality, and it’s ripe for expanding on our unit tests.&#160; It was written a while ago, and its unit test coverage wasn’t where it should be.&#160; So in my “spare time” (hehe….) I’ve been writing unit tests for the routines in that unit.&#160; It’s been pretty fun, and I think, too, that it’s been illustrative of how beneficial unit testing can be.&#160; So I thought I’d write a series of blog posts about it, and this is the first one.&#160; </p>
<p>So, one of the first things I realized was that I needed to be able to generate dates.&#160; Now, I realized that you don’t want that many non-deterministic tests (or maybe you don’t want any at all – it depends).&#160; But I need to be sure that many of the DateUtils.pas routines can pass with <strong><em>any</em></strong> date.&#160; So I wrote the following routine to generate a legitimate but random date:</p>
<pre></pre>
<pre><span style="color: #008000">/// &lt;summary&gt;</span>
</pre>
<pre><span style="color: #008000">///   This creates a random, valid date from year 1 to aYearRange</span>
</pre>
<pre><span style="color: #008000">/// &lt;/summary&gt;</span>
</pre>
<pre><span style="color: #0000ff">function</span> CreateRandomDate(aMakeItLeapYear: Boolean = False; aYearRange: Word = 2500): TDateTime;
</pre>
<pre><span style="color: #0000ff">var</span>
</pre>
<pre>  AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word;
</pre>
<pre><span style="color: #0000ff">begin</span>
</pre>
<pre>  AYear := Random(aYearRange) + 1;
</pre>
<pre>  <span style="color: #0000ff">if</span> (<span style="color: #0000ff">not</span> IsLeapYear(AYear)) <span style="color: #0000ff">and</span> (aMakeItLeapYear) <span style="color: #0000ff">then</span>
</pre>
<pre>  <span style="color: #0000ff">begin</span>
</pre>
<pre>    <span style="color: #0000ff">repeat</span>
</pre>
<pre>      Inc(AYear);
</pre>
<pre>    <span style="color: #0000ff">until</span> IsLeapYear(AYear);
</pre>
<pre>  <span style="color: #0000ff">end</span>;
</pre>
<pre>  AMonth := Random(MonthsPerYear) + 1;
</pre>
<pre>  <span style="color: #0000ff">if</span> IsLeapYear(AYear) <span style="color: #0000ff">and</span> (AMonth = 2) <span style="color: #0000ff">then</span>
</pre>
<pre>  <span style="color: #0000ff">begin</span>
</pre>
<pre>    ADay := Random(29) + 1;
</pre>
<pre>  <span style="color: #0000ff">end</span> <span style="color: #0000ff">else</span> <span style="color: #0000ff">begin</span>
</pre>
<pre>    ADay := Random(28) + 1;
</pre>
<pre>  <span style="color: #0000ff">end</span>;
</pre>
<pre>  AHour := Random(HoursPerDay) - 1;
</pre>
<pre>  AMinute := Random(MinsPerHour) - 1;
</pre>
<pre>  ASecond := Random(SecsPerMin) - 1;
</pre>
<pre>  AMilliSecond := Random(MSecsPerSec);
</pre>
<pre>  Result := EncodeDateTime(AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond);
</pre>
<pre><span style="color: #0000ff">end</span>;</pre>
<p>Now I’ll bet that you guys can come up with a better algorithm, but this works just fine for testing purposes and is pretty clear in what it does.&#160; I use it to test, say, 1000 random dates against a routine that takes a Date as a parameter.&#160; (By the way, it uses some constants from <font face="Courier New">SysUtils</font> and from <font face="Courier New">DateUtils</font>.)&#160; I mix that in with tests that used constant dates every time.&#160; I debated whether to do the random date thing (if a test fails, you can’t necessarily reproduce it), but I decided in favor of it because I’ll make sure all the tests clearly report the date that was failing, and because I wanted to test to make sure that any date would be handled correctly, and you simply can’t do that with a limited, fixed set of dates.&#160; Constantly running a large set of random dates is as close as you can come to testing “every” date. </p>
<p>Another thing that I knew I’d need was to generate to do date testing is valid “Leap Days&#8217;”, that is, a valid February 29 date.&#160; When you unit test, you are constantly looking for corner cases, and Leap Days are a corner case for dates.&#160; Naturally, I’ll utilize <font face="Courier New">CreateRandomDate</font> to help out:</p>
<pre></pre>
<pre><span style="color: #0000ff">function</span> GetRandomLeapDay: TDate;
</pre>
<pre><span style="color: #0000ff">begin</span>
</pre>
<pre>  Result := DateOf(CreateRandomDate(True));
</pre>
<pre>  Result := RecodeDate(Result, YearOf(Result), 2, 29);
</pre>
<pre><span style="color: #0000ff">end</span>;</pre>
<p>So, now I can generate random dates, and easily create corner case LeapDays.&#160; </p>
<p>I’ll probably also eventually add a <font face="Courier New">GenerateRandomTime</font> routine as well.&#160; </p>
<p>That’s it for now – next time I’ll talk about the basics of how I got tests up and running. By the way, I am using <a href="http://dunit.sourceforge.net/">DUnit</a>.&#160; We use DUnit extensively internally.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39369&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39369" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Fun%20With%20Testing%20DateUtils.pas%20%231&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F03%2F10%2F39369" id="akst_email_39369" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/03/10/39369/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Random Thoughts on the Passing Scene #149</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/03/09/39368</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/03/09/39368#comments</comments>
		<pubDate>Tue, 09 Mar 2010 21:42:28 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Random Thoughts]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/03/09/39368</guid>
		<description><![CDATA[
If you are a registered user of Delphi 2010, you can now download a digital copy of Marco Cantu’s new book, Delphi 2010 Handbook. (From Marco’s Site: “The book covers all the new features of Delphi 2010 for Win32, from Extended RTTI to new IDE features, from Windows 7 support to the improved DataSnap architecture. [...]]]></description>
			<content:encoded><![CDATA[<ul>
<li>If you are a registered user of Delphi 2010, <a href="http://cc.embarcadero.com/myreg/delphi">you can now download a digital copy of Marco Cantu’s new book, Delphi 2010 Handbook</a>. (From Marco’s Site: <em>“The book covers all the new features of Delphi 2010 for Win32, from Extended RTTI to new IDE features, from Windows 7 support to the improved DataSnap architecture. This is a brand new book, there is no overlapping material with the Delphi 2007 Handbook and Delphi 2009 Handbook (which you can consider buying along with this book in printed or electronic format).”</em>) I think you all know by now how great Marco’s stuff is.&#160; You can also order a hard-copy of the book as well <a href="http://www.marcocantu.com/dh2010/">from Marco’s site</a>.&#160; (Marco now is using <a href="https://www.createspace.com/">CreateSpace</a> as his publishing center.&#160; The CreateSpace guys are actually here in our current building – I play basketball with a couple of the guys that work there….) </li>
<li>Anders apparently can’t control himself and has <a href="http://blogs.embarcadero.com/ao/2010/03/05/39097">put a few more items up for auction</a>, including an autographed <a href="http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&amp;item=200446794359&amp;ssPageName=STRK:MESELX:IT">by Allen Bauer copy of Delphi 1</a>. </li>
<li>Michael Swindell sent me this link today:&#160; <a href="http://technologizer.com/2010/03/08/the-secret-origin-of-windows/">The Secret Origin of Windows</a> or as he called it “How Turbo Pascal Shaped Windows 1.0”.&#160; Read and enjoy.</li>
</ul>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39368&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39368" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Random%20Thoughts%20on%20the%20Passing%20Scene%20%23149&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F03%2F09%2F39368" id="akst_email_39368" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/03/09/39368/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
		<item>
		<title>Fun Phone Calls with Delphi Prism</title>
		<link>http://blogs.embarcadero.com/nickhodges/2010/03/05/39367</link>
		<comments>http://blogs.embarcadero.com/nickhodges/2010/03/05/39367#comments</comments>
		<pubDate>Fri, 05 Mar 2010 23:05:25 +0000</pubDate>
		<dc:creator>Nick Hodges </dc:creator>
		
		<category><![CDATA[Aspect Oriented Programming]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Delphi Prism]]></category>

		<category><![CDATA[General]]></category>

		<category><![CDATA[ednfront]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/nickhodges/2010/03/05/39367</guid>
		<description><![CDATA[I was talking with a customer yesterday.&#160; It was a pretty typical conversation – they have a big investment in Delphi, with hundreds of thousands of lines of code.&#160; They had built a major application for a major business using DataSnap and dbGo (formerly ADOExpress).&#160; They had started to build some new web systems with [...]]]></description>
			<content:encoded><![CDATA[<p>I was talking with a customer yesterday.&#160; It was a pretty typical conversation – they have a big investment in Delphi, with hundreds of thousands of lines of code.&#160; They had built a major application for a major business using DataSnap and dbGo (formerly ADOExpress).&#160; They had started to build some new web systems with C#, and were trying to figure out where to go next with their existing code base.</p>
<p>Phone calls like this are really fun now.&#160; You know why?&#160; <a href="http://www.embarcadero.com/products/delphi-prism">Delphi Prism</a>, that’s why.&#160; These guys were looking at renewing their RAD Studio Software Assurance, and so they have full access to Delphi Prism.&#160; They were using C#, but when they started hearing about what Prism could do for them, they were quite interested.&#160; They loved the notion of being able to write ASP.NET applications that talk to their DataSnap servers, and they loved the notion of being able to use Delphi syntax for all of their .Net needs.</p>
<p>And Delphi Prism can do that.&#160; It can meet all of your .Net needs.&#160; The Delphi Prism team at <a href="http://www.remobjects.com">RemObjects</a> have done an incredible job with the language.&#160; You give up absolutely nothing if you choose Delphi Prism with the Oxygene language, and you gain a lot over competing languages.&#160; Prism was designed from the ground up with .Net in mind.&#160; There is nothing in the .Net world the Oxygene language can’t do. <a href="http://prismwiki.codegear.com/en/Delphi_Prism_vs._CSharp">And there is a lot in the language that other .Net languages can’t do</a>.&#160; <a href="http://prismwiki.codegear.com/en/LINQ">LINQ</a>, <a href="http://prismwiki.codegear.com/en/Generics">Generics</a>, <a href="http://prismwiki.codegear.com/en/Anonymous_Methods_and_Delegates">Anonymous methods, delegates</a>, <a href="http://prismwiki.codegear.com/en/Attributes">attributes</a>, <a href="http://prismwiki.codegear.com/en/Futures">futures</a>, <a href="http://prismwiki.codegear.com/en/Nullable_Types">nullable types</a>, <a href="http://prismwiki.codegear.com/en/Sets">sets</a>, <a href="http://prismwiki.codegear.com/en/Anonymous_Types">anonymous types</a> – its all there.&#160; And the cool part is that the language keeps moving forward, with powerful new features like direct support for <a href="http://prismwiki.codegear.com/en/Cirrus">Aspect Oriented Programming</a> and <a href="http://blogs.remobjects.com/blogs/mh/2010/02/20/p1116">Expression types</a>.&#160; And all with our beloved begin…end and the rest of the familiar Delphi syntax.&#160; You want to build a <a href="http://prismwiki.codegear.com/en/Silverlight">Silverlight</a> application?&#160; No problem.&#160; Need to develop for Linux with Mono?&#160; The Mac?&#160; We have you covered.&#160; Want to develop with Prism /on/ the Mac and /on/ Linux? We’ll have you covered there, too, with the next release.&#160; You give up nothing and gain a lot.&#160; Wait, I already said that.&#160; But I guess it bears repeating.</p>
<p>But the team is not resting on their laurels – they are pressing forward.&#160; The upcoming release will support the new Visual Studio 2010. It will be integrated into the <a href="http://monodevelop.com/">MonoDevelop</a> platform.&#160; It will provide full language support for the .Net 4.0 platform, including support for dynamic language structures, expression types, <a href="http://blogs.remobjects.com/blogs/mh/2010/02/17/p1086">a cool new Extension Method</a> syntax, and more.&#160; (And while they are at it, they’ve even <a href="http://www.remobjects.com/script.aspx">developed a Delphi-based .Net Scripting tool</a>.&#160; And it’s free, too. How cool is that?)&#160;&#160; </p>
<p>It’s not overstating the case to say that Prism is out in front of the pack with regard to supporting .Net.&#160; Have I mentioned that you give up nothing and gain a lot if you use Prism?</p>
<p>If you haven’t given Delphi Prism a look, you should.&#160; <a href="https://downloads.embarcadero.com/free/delphi_prism">You can download a trial</a> and give it a whirl. <a href="http://prismwiki.codegear.com/">You can peruse the documentation online</a>.&#160; Need information on how to get started?&#160; <a href="http://prismwiki.codegear.com/en/The_Prism_Primer">Check out the Prism Primer</a>. </p>
<p><em>P.S.&#160; The team that brings you Delphi Prism also develops powerful Delphi tools like </em><a href="http://www.dataabstract.com/"><em>DataAbstract</em></a><em> and the </em><a href="http://www.remobjectssdk.com/"><em>RemObjects SDK</em></a><em>.&#160; well worth a look.&#160; RemObjects is also moving into the area of Mac/OS X development.&#160; Nothing seems to stop moving with those guys, and everything moves in a very cool direction.&#160; </em></p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/nickhodges/?p=39367&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_39367" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Fun%20Phone%20Calls%20with%20Delphi%20Prism&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fnickhodges%2F2010%2F03%2F05%2F39367" id="akst_email_39367" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/nickhodges/2010/03/05/39367/feed</wfw:commentRss>
	<gravatar>https://secure.gravatar.com/avatar/ad243151d19525c6e83a18d75c2eb3b6?r=g&amp;d=https%3a%2f%2fstatic.codegear.com%2fimages%2fno_avatar.jpg&amp;s=50</gravatar>
	</item>
	</channel>
</rss>
