<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:admin="http://webns.net/mvcb/"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:content="http://purl.org/rss/1.0/modules/content/">

    <channel>
    
    <title>Devia News</title>
    <link>http://www.devia.be/news</link>
    <description>Devia news</description>
    <dc:language>en</dc:language>
    <dc:creator>Stefaan.Lesage@pandora.be</dc:creator>
    <dc:rights>Copyright 2012</dc:rights>
    <dc:date>2012-11-23T21:42:43+00:00</dc:date>
    <admin:generatorAgent rdf:resource="http://www.expressionengine.com/" />
    

    <item>
      <title>Be&#45;Delphi 2.0 was even better than last year.</title>
      <link>http://www.devia.be/news/article/be-delphi-2.0-was-even-better-than-last-year/</link>
      <guid>http://www.devia.be/news/article/be-delphi-2.0-was-even-better-than-last-year/#When:20:42:43Z</guid>
      <description>On the 22nd of november, Be&#45;Delphi organised it&#39;s second delphi conference in Belgium. I was quite proud to be invited as a speaker again, together with some big names in the Delphi world like Brian Long, Marco Cantu, Pawel Glowacki, Bruno Fierens, Bob Swart and Filip Lagrou.</description>
      <dc:subject>Software DevelopmentWindowsDelphi</dc:subject>
      <content:encoded><![CDATA[On the 22nd of november, Be-Delphi organised it's second delphi conference in Belgium. I was quite proud to be invited as a speaker again, together with some big names in the Delphi world like Brian Long, Marco Cantu, Pawel Glowacki, Bruno Fierens, Bob Swart and Filip Lagrou.<h3>What is Be-Delphi</h3>

<p>Well .. <a href="http://www.be-delphi.com" title="Be-Delphi">Be-Delphi</a> is an initiative from Filip Lagrou and his goal is to promote the use of Delphi by organizing events, consultancy, training, component- and tool reseller and custom development. Last year he organized the very first Be-Delphi Developer Event, and this year it was time for Be-Delphi 2.0. Last year I gave a presentation about Live Bindings in Delphi XE2 ... but this year I decided to talk about something else ... something I'm quite passionate about ...</p>

<h3>UI <>UX and why you should care about that</h3>

<p>For those of you who worked with me in the past, it wont be a big surprise, but I've always been a perfectionist when the User Experience is concerned. I'm probably one of those Delphi developers who can take of his <strong>Developer</strong> hat and look at an application or screen with a <strong>Common User</strong> hat. This has always allowed me to see things other developers don't notice, find bugs others don't, find holes in workflows ... and yes ... notice that buttons placed one pixel lower than all other buttons. </p>

<p>Many developers think about those things as a <strong>non-issue</strong>. Who cares about the pixel ... it works. And if it's only a pixel ... then they might be right. Personally I'm the developer who will try to fix those things. It probably takes longer to say 'Who cares about that pixel' than actually moving the button up one pixel anyway. I have also noticed that a lot of developers are big fans of their mouse. For most of them using keyboard shortcuts is just a wast of time ... although plenty of them know the shortcuts for Copy and Paste way too well :-)</p>

<p>So ... to make a long story short ... I decided not to show any code, but instead focus on the whole User Experience thing. Since I'm quite passionate about that ... it can also get a little emotional, and I think I put all of those emotions in my presentation. The presentation itself is available on SlideShare and I have embedded it into this post. Of course ... you will only get the slides and you will miss the emotions, stories and anecdotes I uses in my presentation.</p>


<p><iframe src="http://www.slideshare.net/slideshow/embed_code/15312032" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen webkitallowfullscreen mozallowfullscreen> </iframe></p><p> <strong> <a href="http://www.slideshare.net/StefaanLesage/ui-lt-ux-and-why-you-should-care-about-that-bedelphi-20" title="UI is not the same as UX and why you should care about that (Be-Delphi 2.0)" target="_blank">UI is not the same as UX and why you should care about that (Be-Delphi 2.0)</a> </strong> from <strong><a href="http://www.slideshare.net/StefaanLesage" target="_blank">Stefaan Lesage</a></strong></p>

<p>During the day I also shot a few pictures which I have uploaded to my Flickr stream. Feel free to go check them out in the <a href="http://www.flickr.com/photos/lesagestefaan/sets/72157632080274441/" title="Be-Delphi 2.0 set">Be-Delphi 2.0 set</a>.</p>

<h3>Questions, Comments, Suggestions and Feedback</h3>

<p>If you attended my session at Be-Delphi 2.0 and have any additional questions, comments, suggestions or feedback ... please feel free to get in touch. And if you encounter some nice examples of bad or good User Experience you can always take a picture and send it to me. Who knows ... I might add it to a revised version of this presentation.</p>]]></content:encoded>
      <dc:date>2012-11-23T20:42:43+00:00</dc:date>
    </item>

    <item>
      <title>Introduction to LiveBindings in Delphi XE2</title>
      <link>http://www.devia.be/news/article/introduction-to-livebindings-in-delphi-xe2/</link>
      <guid>http://www.devia.be/news/article/introduction-to-livebindings-in-delphi-xe2/#When:10:40:20Z</guid>
      <description>Yesterday at Be&#45;Delphi I gave a session on using the new LiveBindings in Delphi XE2 ..</description>
      <dc:subject>Software DevelopmentWindowsDelphi</dc:subject>
      <content:encoded><![CDATA[Yesterday at Be-Delphi I gave a session on using the new LiveBindings in Delphi XE2 ..<h3>Be-Delphi</h3>

<p>Yesterday was <a href="http://www.bedelphi.com" title="BEDelphi">Be-Delph</a>, and I was invited to give a talk on the new LiveBindings in Delphi XE2. Me and <a href="http://alphaware.be/" title="a colleague of mine">a colleague of mine</a> decided to drive up there together, which should have given me some time to relax. Sadly it didn't and I was kinda nervous.</p>

<p>Once we got welcomed by Pascal Lagrou and Bruno Fierens from <a href="http://www.tmssoftware.com/" title="TMS Software">TMS Software</a>, had a coffee or two and we were ready for the sessions. My session on LiveBindings in Delphi XE2 was only in the afternoon, so I still had some time to build up additional stress. In the end everything went quite well. I was nervous in the beginning, but once I could dive into familiar territory (the Delphi XE2 IDE) everything went a lot smoother.</p>

<p>I would personally want to thank everyone who made this even possible, including Filip Lagrou, Bruno Fierens, Thierry Laborde, Brian Long, Jason Vokes and Bob Swart, and everyone who helped behind the scenes. Also a big thank you for the Be-Delph sponsors <a href="http://www.tmssoftware.com/" title="TMS Software">TMS Software</a>, <a href="http://www.embarcadero.com/" title="Embarcadero">Embarcadero</a>, <a href="http://www.ebob42.com" title="Dr Bob">Dr Bob</a>,  <a href="http://www.remobjects.com/" title="RemObjects">RemObjects</a>, <a href="http://www.fast-report.com/" title="Fast Report">Fast Report</a>, <a href="http://www.experteam.be/" title="Expert Team">Expert Team</a>, <a href="http://www.cquel.be/" title="C-Quel Software Solutions">C-Quel Software Solutions</a>, <a href="http://www.raize.com/" title="Raize Software">Raize Software</a>, <a href="http://www.devart.com/" title="Devart">Devart</a>, <a href="http://www.blaisepascal.eu/" title="Blaise Pascal">Blaise Pascal</a>, and all sponsors who supplied us with prizes. In case I forgot some, you can find the full list of sponsors <a href="http://be-delphi.com/sponsors.php" title="right here">right here</a>.</p>

<p>I hope everyone enjoyed Be-Delphi and hope we will all meet up at the next Be-Delphi. For those of you who missed Be-Delphi, I have uploaded my presentation and the corresponding White Paper document :</p>

<h3>Presentation</h3>

<p><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/StefaanLesage/bedelphi-livebindings-in-delphi-xe2-devia" title="BEDelphi - LiveBindings in Delphi XE2 - Devia" target="_blank">BEDelphi - LiveBindings in Delphi XE2 - Devia</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/10215907" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe></p><p>View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/StefaanLesage" target="_blank">Stefaan Lesage</a></p>

<h3>The White Paper</h3>

<p><a title="View Be Delphi Live Bindings on Scribd" href="http://www.scribd.com/doc/73106743/Be-Delphi-Live-Bindings">Be Delphi Live Bindings</a><iframe class="scribd_iframe_embed" src="http://www.scribd.com/embeds/73106743/content?start_page=1&view_mode=list&access_key=key-21uji1b5n1kf5di06yqu" data-auto-height="true" data-aspect-ratio="0.707514450867052" scrolling="no" id="doc_40508" width="100%" height="600" frameborder="0"></iframe><script type="text/javascript">(function() { var scribd = document.createElement("script"); scribd.type = "text/javascript"; scribd.async = true; scribd.src = "http://www.scribd.com/javascripts/embed_code/inject.js"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(scribd, s); })();</script></p>]]></content:encoded>
      <dc:date>2011-11-18T10:40:20+00:00</dc:date>
    </item>

    <item>
      <title>Configuring Delphi XE2 and your mac to develop, test and deploy iOS apps</title>
      <link>http://www.devia.be/news/article/configuring-delphi-xe2-and-your-mac-to-develop-test-and-deploy-ios-apps/</link>
      <guid>http://www.devia.be/news/article/configuring-delphi-xe2-and-your-mac-to-develop-test-and-deploy-ios-apps/#When:12:41:30Z</guid>
      <description>Today we are back with another Delhi XE2 Video Tutorial ... this time I will be showing how to get ready to develop iOS applications using Delphi XE2 and FireMonkey.</description>
      <dc:subject>Software DevelopmentiOSMacWindowsDelphiNew MediaScreencasting</dc:subject>
      <content:encoded><![CDATA[Today we are back with another Delhi XE2 Video Tutorial ... this time I will be showing how to get ready to develop iOS applications using Delphi XE2 and FireMonkey.<h3>Prerequisites</h3>

<p>Unlike building a Mac version of your Delphi XE2 FireMonkey application, creating an iOS application using Delphi XE2 and FireMonkey has some prerequisites. </p>

<h4>XCode</h4>

<p>First of all you will need to install XCode on your Mac. This can easily be done by downloading XCode from the Mac AppStore, or through the developer portal website. For the iOS versions of your Delphi XE 2 FireMonkey apps you will have to compile them using XCode. From within XCode you will be able to debug those applications and deploy them on a physical device.</p>

<h4>FreePascal and FireMonkey</h4>

<p>In order to build your Delphi XE2 FireMonkey applications for iOS devices you will need the FreePascal compiler and the necessary FireMonkey files. Luckily this can be found in your Delphi XE2 installation folder. Simply copy the Disk Image File (dmg) over to your mac and run the installation.</p>

<h4>Apple Developer Program</h4>

<p>If you want to deploy your applications to a physical iOS device, you will need to register for the <a href="http://developer.apple.com/programs/ios/">iOS Developer Program</a> which will cost you about $99 or 79 € per year. You will also have to be part of that iOS Developer program if you ever want to publish you Delphi XE2 FireMonkey apps to the iOS AppStore.</p>

<h3>Creating a test iOS application using Delphi XE2 and FireMonkey</h3>

<h4>Creating a new FireMonkey iOS application</h4>

<p>Unlink Delphi XE2 FireMonkey applications for the Mac, FireMonkey iOS applications are a special type of Delphi XE2 project. So you will have to create a new application using the corresponding menu. In our example we will create a very simple application ... noting special ... just to show you everything works nicely.</p>

<h4>Exporting the Delphi XE2 FireMonkey Application to XCode</h4>

<p>As mentioned before ... you currently still need XCode and the FreePascal compiler to Build your iOS application. Due to some limitations in FreePascal your Delphi XE2 FireMonkey code will need to be modified slightly so it can be compiled (one example is the Dotted namespaces which doesn't seem to be working under FreePascal). In order to do this a little utility can be used called dprtoxcode.exe</p>

<p>The Tutorial shows you how you can add this little utility to your Delphi XE2 tools menu so it is easier to use.</p>

<h4>Building & Testing your application using XCode</h4>

<p>Once everything is ready, you can open the XCode version of your Delphi XE2 FireMonkey project, build it and run it in the Simulator to test it if necessary. From here you could also deploy it to a physical iOS device or the iOS AppStore, but for that you will need to enroll in the <a href="http://developer.apple.com/programs/ios/">iOS Developer Program</a>.</p>

<p>In our Video Tutorial we will be building a small sample application to show you how the process is supposed to be done. It isn't a full blown iOS application though, but just a little example.</p>

<h3>Final Words</h3>

<p>Well ... this tutorial should have shown you the basics of setting everything up and even showed you how to create your first iOS application. If you have any comments or suggestions ... feel free to post them here as a comment or contact us.</p>

<p>Meanwhile ... have fun with Delphi XE2 and FireMonkey ... and if you want to learn more about Delphi XE2, make sure you also check the <a href="http://embarcadero.com/products/delphi">Delphi XE2 page</a> or <a href="http://embarcadero.com/products/rad-studio">RAD Studio XE2 page</a> on the Embarcadero Website.</p>

<p>If you want, you can also have a look at the video on YouTube. You should be able to find <a href="http://bit.ly/qkt4u1">an HD version right here</a></p>


<div class="big-photo"><iframe width="853" height="510" src="http://www.youtube.com/embed/h93CZV9bRaQ?rel=0&amp;fmt=22&amp;hd=1" frameborder="0" allowfullscreen></iframe><p>Configuring Delphi XE2 and your mac to develop, test and deploy iOS apps with FireMonkey</p></div>]]></content:encoded>
      <dc:date>2011-09-29T12:41:30+00:00</dc:date>
    </item>

    <item>
      <title>Setting up Delphi XE2 and your Mac to run and debug cross&#45;platform applications using Delphi</title>
      <link>http://www.devia.be/news/article/setting-up-delphi-xe2-and-your-mac-to-run-and-debug-cross-platform-applicat/</link>
      <guid>http://www.devia.be/news/article/setting-up-delphi-xe2-and-your-mac-to-run-and-debug-cross-platform-applicat/#When:17:24:23Z</guid>
      <description>Today Embarcadero and Barnsten showed Delphi XE2 in action at the Delphi XE2 world tour in Brussels. Pawel Glowacki showed us that we can create Mac apps from using FireMonkey in Delphi.</description>
      <dc:subject>Software DevelopmentWindowsDelphi</dc:subject>
      <content:encoded><![CDATA[Today Embarcadero and Barnsten showed Delphi XE2 in action at the Delphi XE2 world tour in Brussels. Pawel Glowacki showed us that we can create Mac apps from using FireMonkey in Delphi.<h3>Delphi XE2 allows you to create Mac / iOS apps ?</h3>

<p>Well ... now that Delphi XE2 is finally available, the testers are no longer under NDA and I can safely say you can create Mac and even iOS applications using Delphi XE2 and FireMonkey. If you want to know more about FireMonkey, feel free to have a look at the information available on the Embarcadero website, or even have a look at this <a href="http://www.andreanolanusse.com/en/a-little-bit-about-firemonkey-and-delphi-xe2/" title="A little bit about FireMonkey and Delphi XE2">very interesting post about FireMonkey by Andrano Lanusse</a> (Embarcadero Technical Lead Evangelist for Latin America & Caribeean). Today I won't be going into a lot of detail about FireMonkey or what you can do with FireMonkey though ...</p>

<h3>Setting it up</h3>

<p>If you were at the World Tour in Brussels, you might have seen and heard Pawel Glowacki talk about using PAServer to deploy and debug Delphi XE2 FireMonkey applications on the Mac. If you have a Mac and already have Delphi XE2 you might be wondering what he was talking about and how you can set up  your machines to actually run Delphi XE2 FireMonkey applications on your Mac and still develop and debug them on your Windows Machine. Well ... it actually is a lot easier than you would think.</p>

<h3>A Screencast</h3>

<p>For those of you who want to get started right away, but are wondering how you should configure everything, I prepared a little Screencast. This Screencast guides you through the setup and configuration and even shows you how to develop / deploy and Debug a simple 'Hello World' application on your Mac which was developed using Delphi XE2 and FireMonkey on Windows. The Video is Hosted on YouTube and I have embedded it on this page. It might be interesting to look at the HD version in FullScreen Mode on YouTube thought ...</p>

<div class="big-photo"><iframe width="853" height="510" src="http://www.youtube.com/embed/lEB38jlrbYY?rel=0&amp;fmt=22&amp;hd=1" frameborder="0" allowfullscreen></iframe><p>Setting up Delphi XE2 and your Mac to run and debug cross-platform applications using Delphi</p></div>]]></content:encoded>
      <dc:date>2011-09-08T17:24:23+00:00</dc:date>
    </item>

    <item>
      <title>Simplify your Delphi Code using some basic rules, OO techniques and some refactoring (Part 4)</title>
      <link>http://www.devia.be/news/article/delphi-code-using-some-basic-rules-oo-techniques-refactoring-part-4/</link>
      <guid>http://www.devia.be/news/article/delphi-code-using-some-basic-rules-oo-techniques-refactoring-part-4/#When:12:55:53Z</guid>
      <description>Part 4 in the series.  Actually it&#39;s the rest of Part 3, since for some strange reason I couldn&#39;t get it into a single post.</description>
      <dc:subject>Software DevelopmentWindowsDelphi</dc:subject>
      <content:encoded><![CDATA[Part 4 in the series.  Actually it's the rest of Part 3, since for some strange reason I couldn't get it into a single post.<h3>Continued</h3>

<p>Since for some strange reason I couldn't fit everything in a single post, I had to split it up, so this is the rest of it</p>

<h4>The TdvStringSetting class</h4>

<h5>The explanation</h5>

<p>Basically the TdvSetting provides us with a skeleton we can use for our new Setting descendants.  I ended up with a TdvStringSetting, TdvIntegerSetting, TdvBooleanSetting and quite a few others, but lets start with the TdvStringSetting first.</p>

<h5>The Code</h5>

<pre>
<code><span style="font: 10pt Courier New;"><span class="pas1-space">  TdvStringSetting </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-reservedword">class</span><span class="pas1-symbol">(</span><span class="pas1-space"> TdvSetting </span><span class="pas1-symbol">)
</span><span class="pas1-space">  </span><span class="pas1-reservedword">private
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetDefaultValueAsString</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">protected
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetAsBoolean</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetAsDateTime</span><span class="pas1-symbol">:</span><span class="pas1-space"> TDateTime</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetAsFloat</span><span class="pas1-symbol">:</span><span class="pas1-space"> Double</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetAsInteger</span><span class="pas1-symbol">:</span><span class="pas1-space"> Longint</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetAsString</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetAsVariant</span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetValue</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">var</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">):</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetAsBoolean</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetAsDateTime</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> TDateTime</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetAsFloat</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Double</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetAsInteger</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Longint</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetAsString</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> aValue</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetVarValue</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> aValue</span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">public
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SaveToRegIni  </span><span class="pas1-symbol">(</span><span class="pas1-space"> aRegIni </span><span class="pas1-symbol">:</span><span class="pas1-space"> TRegistryIniFile</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aSection </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-space"> </span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> LoadFromRegIni</span><span class="pas1-symbol">(</span><span class="pas1-space"> aRegIni </span><span class="pas1-symbol">:</span><span class="pas1-space"> TRegistryIniFile</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aSection </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-space"> </span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> DefaultValue  </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-space">       </span><span class="pas1-reservedword">read</span><span class="pas1-space">  GetDefaultValueAsString</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> Value         </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-space">       </span><span class="pas1-reservedword">read</span><span class="pas1-space">  GetAsString
                                          </span><span class="pas1-reservedword">write</span><span class="pas1-space"> SetAsString</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

...

</span><span class="pas1-comment">{ TdvStringSetting }

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetAsBoolean</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">var
</span><span class="pas1-space">  S</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  S </span><span class="pas1-symbol">:=</span><span class="pas1-space"> GetAsString</span><span class="pas1-symbol">;
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">Length</span><span class="pas1-symbol">(</span><span class="pas1-identifier">S</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-symbol">&gt;</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">and</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-identifier">S</span><span class="pas1-symbol">[</span><span class="pas1-number">1</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-reservedword">in</span><span class="pas1-space"> </span><span class="pas1-symbol">[</span><span class="pas1-string">'T'</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-string">'t'</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-string">'Y'</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-string">'y'</span><span class="pas1-symbol">]);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetAsDateTime</span><span class="pas1-symbol">:</span><span class="pas1-space"> TDateTime</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> StrToDateTime</span><span class="pas1-symbol">(</span><span class="pas1-identifier">GetAsString</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetAsFloat</span><span class="pas1-symbol">:</span><span class="pas1-space"> Double</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> StrToFloat</span><span class="pas1-symbol">(</span><span class="pas1-identifier">GetAsString</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetAsInteger</span><span class="pas1-symbol">:</span><span class="pas1-space"> Longint</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> StrToInt</span><span class="pas1-symbol">(</span><span class="pas1-identifier">GetAsString</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetAsString</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-reservedword">not</span><span class="pas1-space"> GetValue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Result</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then</span><span class="pas1-space"> Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-string">''</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetAsVariant</span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">var
</span><span class="pas1-space">  S</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">if</span><span class="pas1-space"> GetValue</span><span class="pas1-symbol">(</span><span class="pas1-identifier">S</span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then</span><span class="pas1-space"> Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> S </span><span class="pas1-reservedword">else</span><span class="pas1-space"> Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> Null</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetDefaultValueAsString</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> FDefaultValue</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetValue</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">var</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">):</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Value  </span><span class="pas1-symbol">:=</span><span class="pas1-space"> FValue</span><span class="pas1-symbol">;
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> True</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">LoadFromRegIni</span><span class="pas1-symbol">(</span><span class="pas1-identifier">aRegIni</span><span class="pas1-symbol">:</span><span class="pas1-space"> TRegistryIniFile</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aSection</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> LoadFromRegIni</span><span class="pas1-symbol">(</span><span class="pas1-space"> aRegIni</span><span class="pas1-symbol">,</span><span class="pas1-space"> aSection </span><span class="pas1-symbol">);

</span><span class="pas1-space">  Value </span><span class="pas1-symbol">:=</span><span class="pas1-space"> aRegIni</span><span class="pas1-symbol">.</span><span class="pas1-identifier">ReadString</span><span class="pas1-symbol">(</span><span class="pas1-space"> aSection</span><span class="pas1-symbol">,</span><span class="pas1-space"> Identifier</span><span class="pas1-symbol">,</span><span class="pas1-space"> DefaultValue </span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SaveToRegIni</span><span class="pas1-symbol">(</span><span class="pas1-identifier">aRegIni</span><span class="pas1-symbol">:</span><span class="pas1-space"> TRegistryIniFile</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aSection</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> SaveToRegIni</span><span class="pas1-symbol">(</span><span class="pas1-space"> aRegIni</span><span class="pas1-symbol">,</span><span class="pas1-space"> aSection </span><span class="pas1-symbol">);

</span><span class="pas1-space">  aRegIni</span><span class="pas1-symbol">.</span><span class="pas1-identifier">WriteString</span><span class="pas1-symbol">(</span><span class="pas1-space"> aSection</span><span class="pas1-symbol">,</span><span class="pas1-space"> Identifier</span><span class="pas1-symbol">,</span><span class="pas1-space"> Value </span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetAsBoolean</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">const
</span><span class="pas1-space">  Values</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">array</span><span class="pas1-symbol">[</span><span class="pas1-identifier">Boolean</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-reservedword">of</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">[</span><span class="pas1-number">1</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-string">'F'</span><span class="pas1-symbol">,</span><span class="pas1-space"> </span><span class="pas1-string">'T'</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  SetAsString</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Values</span><span class="pas1-symbol">[</span><span class="pas1-identifier">Value</span><span class="pas1-symbol">]);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetAsDateTime</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> TDateTime</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  SetAsString</span><span class="pas1-symbol">(</span><span class="pas1-identifier">DateTimeToStr</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Value</span><span class="pas1-symbol">));
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetAsFloat</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Double</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  SetAsString</span><span class="pas1-symbol">(</span><span class="pas1-identifier">FloatToStr</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Value</span><span class="pas1-symbol">));
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetAsInteger</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  SetAsString</span><span class="pas1-symbol">(</span><span class="pas1-identifier">IntToStr</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Value</span><span class="pas1-symbol">));
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetAsString</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> aValue</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  FValue </span><span class="pas1-symbol">:=</span><span class="pas1-space"> aValue</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvStringSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetVarValue</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> aValue</span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  SetAsString</span><span class="pas1-symbol">(</span><span class="pas1-identifier">aValue</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;


</span></span>
</code></pre>

<h5>What does it do ?</h5>

<p>Since we had the skeleton of the TdvSetting in place, the only thing we needed to do was to override the necessary methods and implement our own features.  As you can see, we added approximately the same code as can be found in the TStringField in the VCL.</p>

<p>The only additional code is the implementation of the SaveToRegIni and LoadFromRegIni methods.  These methods will actually load and save the value of the Setting to the Registry.  Additionally when loading the value we will be using the Default value if the setting can't be found in the regsitry.  The Section where we will read / write the value can be supplied to the method and we will be using the identifier (name) of the setting as the key</p>

<h4>Creating the TdvSettings class</h4>

<h5>The explanation</h5>

<p>Well, now that we can make different type of Setting objects, we also need some kind of container to hold them.  For example our application might have quite a few settings : PrintInColor, CheckForUpdates, AutoConnect, ... but we will need some way to access them.  As mentioned before I created the TdvSettings class as a simple TObjectList.  It will hold a reference to the individual TdvSetting objects and we will be able to access them</p>

<h5>The Code</h5>

<pre>
<code><span style="font: 10pt Courier New;"><span class="pas1-space">  TdvSettings </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-reservedword">class</span><span class="pas1-symbol">(</span><span class="pas1-space"> TObjectList </span><span class="pas1-symbol">)
</span><span class="pas1-space">  </span><span class="pas1-reservedword">private
</span><span class="pas1-space">    FRootKey</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">protected
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> CreateSettings</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetItems</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Index</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">):</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetItems</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Index</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;</span><span class="pas1-space"> ASetting</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">);
</span><span class="pas1-space">  </span><span class="pas1-reservedword">public
</span><span class="pas1-space">    </span><span class="pas1-reservedword">constructor</span><span class="pas1-space"> Create</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aRootKey </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-space"> </span><span class="pas1-symbol">);

</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> Add</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ASetting</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">):</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> Extract</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Item</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">):</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> Remove</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ASetting</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">):</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> IndexOf</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ASetting</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">):</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> First</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> Last</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> SettingByIdentifier</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aIdentifier </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-space"> </span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> LoadFromRegistry</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SaveToRegistry</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> Insert</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Index</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;</span><span class="pas1-space"> ASetting</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">);
</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> Items</span><span class="pas1-symbol">[</span><span class="pas1-reservedword">Index</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">]:</span><span class="pas1-space"> TdvSetting </span><span class="pas1-reservedword">read</span><span class="pas1-space"> GetItems </span><span class="pas1-reservedword">write</span><span class="pas1-space"> SetItems</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">default</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> RootKey </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-space"> </span><span class="pas1-reservedword">read</span><span class="pas1-space"> FRootKey </span><span class="pas1-reservedword">write</span><span class="pas1-space"> FRootKey</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-space">  </span><span class="pas1-symbol">...

</span><span class="pas1-comment">{ TdvSettings }

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Add</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ASetting</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">):</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> Add</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ASetting</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">constructor</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> aRootKey</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> Create</span><span class="pas1-symbol">(</span><span class="pas1-space"> True </span><span class="pas1-symbol">);
</span><span class="pas1-space">  FRootKey </span><span class="pas1-symbol">:=</span><span class="pas1-space"> aRootKey</span><span class="pas1-symbol">;
</span><span class="pas1-space">  CreateSettings</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-comment">// Read the settings from the Registry once the Settings object list has
</span><span class="pas1-space">  </span><span class="pas1-comment">// been initialised.
</span><span class="pas1-space">  LoadFromRegistry</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">CreateSettings</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin

end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Extract</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Item</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">):</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> Extract</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Item</span><span class="pas1-symbol">));
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">First</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> First</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetItems</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Index</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">):</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> Items</span><span class="pas1-symbol">[</span><span class="pas1-identifier">Index</span><span class="pas1-symbol">]);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">IndexOf</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ASetting</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">):</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> IndexOf</span><span class="pas1-symbol">(</span><span class="pas1-identifier">aSetting</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Insert</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Index</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;</span><span class="pas1-space"> ASetting</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> Insert</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Index</span><span class="pas1-symbol">,</span><span class="pas1-space"> aSetting</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Last</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> Last</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">LoadFromRegistry</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">var
</span><span class="pas1-space">  lIndex   </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-space">  lSetting </span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">;
</span><span class="pas1-space">  lRegIni  </span><span class="pas1-symbol">:</span><span class="pas1-space"> TRegistryIniFile</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  lRegIni </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TRegistryIniFile</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-string">''</span><span class="pas1-symbol">);
</span><span class="pas1-space">  </span><span class="pas1-reservedword">try
</span><span class="pas1-space">    </span><span class="pas1-reservedword">for</span><span class="pas1-space"> lIndex </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> Pred</span><span class="pas1-symbol">(</span><span class="pas1-space"> Count </span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space">    </span><span class="pas1-reservedword">begin
</span><span class="pas1-space">      lSetting </span><span class="pas1-symbol">:=</span><span class="pas1-space"> Items</span><span class="pas1-symbol">[</span><span class="pas1-space"> lIndex </span><span class="pas1-symbol">];
</span><span class="pas1-space">      lSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">LoadFromRegIni</span><span class="pas1-symbol">(</span><span class="pas1-space"> lRegIni</span><span class="pas1-symbol">,</span><span class="pas1-space"> RootKey </span><span class="pas1-symbol">);
</span><span class="pas1-space">    </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">finally
</span><span class="pas1-space">    FreeAndNil</span><span class="pas1-symbol">(</span><span class="pas1-space"> lRegIni </span><span class="pas1-symbol">);
</span><span class="pas1-space">  </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Remove</span><span class="pas1-symbol">(</span><span class="pas1-identifier">ASetting</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">):</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> Remove</span><span class="pas1-symbol">(</span><span class="pas1-identifier">aSetting</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SaveToRegistry</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">var
</span><span class="pas1-space">  lIndex   </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-space">  lSetting </span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">;
</span><span class="pas1-space">  lRegIni  </span><span class="pas1-symbol">:</span><span class="pas1-space"> TRegistryIniFile</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  lRegIni </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TRegistryIniFile</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-string">''</span><span class="pas1-symbol">);
</span><span class="pas1-space">  </span><span class="pas1-reservedword">try
</span><span class="pas1-space">    </span><span class="pas1-reservedword">for</span><span class="pas1-space"> lIndex </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> Pred</span><span class="pas1-symbol">(</span><span class="pas1-space"> Count </span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space">    </span><span class="pas1-reservedword">begin
</span><span class="pas1-space">      lSetting </span><span class="pas1-symbol">:=</span><span class="pas1-space"> Items</span><span class="pas1-symbol">[</span><span class="pas1-space"> lIndex </span><span class="pas1-symbol">];
</span><span class="pas1-space">      lSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SaveToRegIni</span><span class="pas1-symbol">(</span><span class="pas1-space"> lRegIni</span><span class="pas1-symbol">,</span><span class="pas1-space"> RootKey </span><span class="pas1-symbol">);
</span><span class="pas1-space">    </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">finally
</span><span class="pas1-space">    FreeAndNil</span><span class="pas1-symbol">(</span><span class="pas1-space"> lRegIni </span><span class="pas1-symbol">);
</span><span class="pas1-space">  </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetItems</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Index</span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;</span><span class="pas1-space"> ASetting</span><span class="pas1-symbol">:</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">inherited</span><span class="pas1-space"> Items</span><span class="pas1-symbol">[</span><span class="pas1-identifier">Index</span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-symbol">:=</span><span class="pas1-space"> aSetting</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SettingByIdentifier</span><span class="pas1-symbol">(
</span><span class="pas1-space">  </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aIdentifier</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">):</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">var
</span><span class="pas1-space">  lcv </span><span class="pas1-symbol">:</span><span class="pas1-space"> Integer</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-reservedword">Nil</span><span class="pas1-symbol">;

</span><span class="pas1-space">  </span><span class="pas1-reservedword">for</span><span class="pas1-space"> lcv </span><span class="pas1-symbol">:=</span><span class="pas1-space"> </span><span class="pas1-number">0</span><span class="pas1-space"> </span><span class="pas1-reservedword">to</span><span class="pas1-space"> Pred</span><span class="pas1-symbol">(</span><span class="pas1-space"> Count </span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">do
</span><span class="pas1-space">  </span><span class="pas1-reservedword">begin
</span><span class="pas1-space">    </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-space"> Items</span><span class="pas1-symbol">[</span><span class="pas1-space"> lcv </span><span class="pas1-symbol">].</span><span class="pas1-identifier">Identifier </span><span class="pas1-symbol">=</span><span class="pas1-space"> aIdentifier </span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space">    </span><span class="pas1-reservedword">begin
</span><span class="pas1-space">      Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> Items</span><span class="pas1-symbol">[</span><span class="pas1-space"> lcv </span><span class="pas1-symbol">];
</span><span class="pas1-space">      Break</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span></span>
</code></pre>

<h5>What does it do ?</h5>

<p>Well, it is simply a container for a number of TdvSetting objects.  It has some basic code which will allow us to access the individual TdvSetting objects using their index or their Identifier (name).  We will be able to set the RootKey of the TdvSettings object and that is the base key which will be used when loading / storing the individual TdvSetting objects.</p>

<p>You willl notice that I added a CreateSettings method which is currently empty.  The goal is to implement this in descendant classes.  At the TdvSettings level we don't yet know which individual settings we will need, how they are called and what type they are ... Yet, I wanted to be able to create those settings from within the base class and once that is done read the settings if necessary.</p>

<p>In my TdvMyApplicationSettings I will override this method and add the necessary code to set up the individual TdvSetting objects I need for my applicaiton.</p>

<h3>What's next ?</h3>

<p>Currently we have a basic skeleton in place and we are able to continue from here.  If you're up for a challenge, you might want to create your own TdvSetting descendants.  I noticed I needed one for Integer values, DataTime values and Boolean values, so you could try to implement those.</p>

<p>As I mentioned at the end of the previous article, this isn't the only way, nor THE way to solve this problem, and I actually did try a few other approaches as well.  It did take me a few iterations to get to this stage.  For example, initial versions had the actual code for creating the TRegistryIniFile class inside the individual TdvSetting objects.</p>

<p>Quickly I noticed though that I had the exact same code in all my TdvSetting descendants LoadFromRegIni and SaveToRegIni methods so I started thinking again.  I thought that constructing & destroying the TRegistryIniFile might be something I don't want to execute for the 20 individual application settings so I ended up refactoring the code to it's current status</p>

<h3>Feedback</h3>

<p>I'm quite sure the code could be simplified and maybe improved, and I do welcome all suggestions and feedback.  So feel free to post all comments on this blog and I'll try to respond ASAP.  Maybe your feedback will shape the next article in this series ...</p>]]></content:encoded>
      <dc:date>2010-03-30T12:55:53+00:00</dc:date>
    </item>

    <item>
      <title>Simplify your Delphi Code using some basic rules, OO techniques and some refactoring (Part 3)</title>
      <link>http://www.devia.be/news/article/delphi-code-using-some-basic-rules-oo-techniques-refactoring-part-3/</link>
      <guid>http://www.devia.be/news/article/delphi-code-using-some-basic-rules-oo-techniques-refactoring-part-3/#When:12:37:15Z</guid>
      <description>Now that we have a basic idea of what we want to achieve and how we could do it, it&#39;s time to write some code and create some classes.</description>
      <dc:subject>Software DevelopmentWindowsDelphi</dc:subject>
      <content:encoded><![CDATA[Now that we have a basic idea of what we want to achieve and how we could do it, it's time to write some code and create some classes.<h3>Introduction</h3>

<p>So, basically we need a class / object which we can use to read and write some application settings from and to the Windows Registry.  Sounds pretty straightforward ... but we did some additional thinking and found out that we might need to add some stuff in the future.</p>

<h3>Basic Requirements of the code</h3>

<h4>Compatibility with Delphi 7</h4>

<p>Although quite a few new features were added to the language in the last years, we won't be using them 'yet'.  Our goal is that the code should compile / work under Delphi 7.</p>

<p>You may be asking yourselves "Who going though all that trouble for an old Delphi version ?", well I noticed that even today some of my clients still have older projects which get compiled in Delphi 7.  In later articles I might show you how to do it using some newer techniques, but for now lets just stick with something that will compile under Delphi 7</p>

<h4>Not limited to the Windows Registry</h4>

<p>Although we will be writing the code based on using the Windows Registry to Load and Save our data.  We want an easy way to adapt our code for some other things like storing the data in XML or an Ini file.  After all, we don't know what the future will bring yet.  We might be able to build applications for Windows Mobile, the Mac, iPhone or even iPad in the future (Would that be nice), and the  Windows Registry might not be available on those devices.</p>

<p>For now we will focus on the Windows Registry, but as you notice it is a good idea to keep a few other possibilities ready.  In the end, the only thing we care about is that we can store / load some settings.  How or where these settings are stored isn't all that important, it just needs to get done !</p>

<h4>Additional Things</h4>
	
<p>So far, we know we will need something to hold a set of settings.  We need to be able to load and save those settings.  We will probably be supplying a name for each individual setting, maybe even a default value and a description.  We need to be able to store Integers, Strings, but who knows even Passwords, Dates, ...</p>

<h3>Lets get Coding !</h3>

<h4>... well almost ...</h4>
<p>Well, ... actually before we start coding we could take a look at how some of these things get solved in the VCL.  Of course, we could do all the coding ourselves, but it might be a good idea to let our new classes inherit from some existing classes.  Since we need a list of things, you might want to take a look at the TList for example.</p>

<p>In my case, I knew I want to have a Setting which I will use to store Strings, one to store Integers and another one to store Booleans.  Once I had those, I quickly noticed I wanted some others for DateTime values and quite a few other things as well.  I actually ended up doing something quite similar to TField and TIntegerField, TStringField, ...</p>

<p>So, now that I know I will be using different types of Setting objects and I want to keep a list of those Setting Objects, I quickly decided that the TObjectList was a very good class to start with.</p>

<h4>Creating the TdvSetting class</h4>

<h5>The explanation</h5>

<p>Basically I need an object with a few properties like an Identifier (or Name, Caption), a Description (or Hint) and of course a Value.  I will need to be able to read the value from the Registry and write it to the registry.  Additionally when reading the value from the Registry I want to check if there is already something in the registry for the setting, and if nothing is found, the Default value should be used.</p>

<p>Just as with the TField and TStringField, I want to be able to get the Value of the TdvSetting as a String or as a Variant, so I added that code as well.  Additionally I want to set the value of the TdvSetting as well.  In the end, the descendant classes will implement most of this, but like with the TField in the VCL, I added some code which will raise an exception if a descendant class doens't implement a specific accessor.</p>

<p>This might sound a bit complex, but lets compare it with the TField and TStringField again.  With a TStringField, you can set the value using aField.Value := theValue or with aField.AsString := theValue.  Both things will work, but if aField is in instance of TField instead of TStringField an exception will be raised.  What I did was implement that functionality as well.</p>

<p>For now we will focus on the Windows Registry, but as you notice it is a good idea to keep a few other possibilities ready.  In the end, the only thing we care about is that we can store / load some settings.  How or where these settings are stored isn't all that important, it just needs to get done !</p>

<h5>The Code</h5>

<pre>
<code><span style="font: 10pt Courier New;"><span class="pas1-space">  TdvSetting </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-reservedword">class</span><span class="pas1-symbol">(</span><span class="pas1-space"> TObject </span><span class="pas1-symbol">)
</span><span class="pas1-space">  </span><span class="pas1-reservedword">private
</span><span class="pas1-space">    FValue        </span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant</span><span class="pas1-symbol">;
</span><span class="pas1-space">    FDefaultValue </span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant</span><span class="pas1-symbol">;
</span><span class="pas1-space">    FIdentifier   </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">;
</span><span class="pas1-space">    FCaption      </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetCaption</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">);
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetVisible</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">);
</span><span class="pas1-space">  </span><span class="pas1-reservedword">protected
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetAsBoolean</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetAsDateTime</span><span class="pas1-symbol">:</span><span class="pas1-space"> TDateTime</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetAsFloat</span><span class="pas1-symbol">:</span><span class="pas1-space"> Double</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetAsInteger</span><span class="pas1-symbol">:</span><span class="pas1-space"> Longint</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetAsString</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> GetAsVariant</span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetAsBoolean</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetAsDateTime</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> TDateTime</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetHint</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">);
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetAsFloat</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Double</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetIdentifier</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">);
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetAsInteger</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Longint</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetAsString</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetAsVariant</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">protected
</span><span class="pas1-space">    </span><span class="pas1-reservedword">function</span><span class="pas1-space"> AccessError</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> TypeName</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">):</span><span class="pas1-space"> Exception</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">dynamic</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SetVarValue</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value </span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant </span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">public
</span><span class="pas1-space">    </span><span class="pas1-reservedword">Constructor</span><span class="pas1-space"> Create</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aIdentifier</span><span class="pas1-symbol">,</span><span class="pas1-space"> aCaption </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">;
</span><span class="pas1-space">                        </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aDefaultValue </span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant </span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">destructor</span><span class="pas1-space"> Destroy</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">override</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> SaveToRegIni  </span><span class="pas1-symbol">(</span><span class="pas1-space">       aRegIni  </span><span class="pas1-symbol">:</span><span class="pas1-space"> TRegistryIniFile</span><span class="pas1-symbol">;
</span><span class="pas1-space">                              </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aSection </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-space"> </span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> LoadFromRegIni</span><span class="pas1-symbol">(</span><span class="pas1-space">       aRegIni  </span><span class="pas1-symbol">:</span><span class="pas1-space"> TRegistryIniFile</span><span class="pas1-symbol">;
</span><span class="pas1-space">                              </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aSection </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-space"> </span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> Clear</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">virtual</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> DefaultValue  </span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant       </span><span class="pas1-reservedword">read</span><span class="pas1-space">  FDefaultValue</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> AsBoolean     </span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean       </span><span class="pas1-reservedword">read</span><span class="pas1-space">  GetAsBoolean
                                           </span><span class="pas1-reservedword">write</span><span class="pas1-space"> SetAsBoolean</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> AsDateTime    </span><span class="pas1-symbol">:</span><span class="pas1-space"> TDateTime     </span><span class="pas1-reservedword">read</span><span class="pas1-space">  GetAsDateTime
                                           </span><span class="pas1-reservedword">write</span><span class="pas1-space"> SetAsDateTime</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> AsFloat       </span><span class="pas1-symbol">:</span><span class="pas1-space"> Double        </span><span class="pas1-reservedword">read</span><span class="pas1-space">  GetAsFloat
                                           </span><span class="pas1-reservedword">write</span><span class="pas1-space"> SetAsFloat</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> AsInteger     </span><span class="pas1-symbol">:</span><span class="pas1-space"> Longint       </span><span class="pas1-reservedword">read</span><span class="pas1-space">  GetAsInteger
                                           </span><span class="pas1-reservedword">write</span><span class="pas1-space"> SetAsInteger</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> AsString      </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-space">        </span><span class="pas1-reservedword">read</span><span class="pas1-space">  GetAsString
                                           </span><span class="pas1-reservedword">write</span><span class="pas1-space"> SetAsString</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> AsVariant     </span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant       </span><span class="pas1-reservedword">read</span><span class="pas1-space">  GetAsVariant
                                           </span><span class="pas1-reservedword">write</span><span class="pas1-space"> SetAsVariant</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> Identifier  </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-space">          </span><span class="pas1-reservedword">read</span><span class="pas1-space">  FIdentifier
                                           </span><span class="pas1-reservedword">write</span><span class="pas1-space"> SetIdentifier</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> Caption     </span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-space">          </span><span class="pas1-reservedword">read</span><span class="pas1-space">  FCaption
                                           </span><span class="pas1-reservedword">write</span><span class="pas1-space"> SetCaption</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">property</span><span class="pas1-space"> Value       </span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant         </span><span class="pas1-reservedword">read</span><span class="pas1-space">  GetAsVariant
                                           </span><span class="pas1-reservedword">write</span><span class="pas1-space"> SetAsVariant</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

...

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">AccessError</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> TypeName</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">):</span><span class="pas1-space"> Exception</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">resourcestring
</span><span class="pas1-space">  SSettingAccessError </span><span class="pas1-symbol">=</span><span class="pas1-space"> </span><span class="pas1-string">'Cannot access Setting ''%s'' (%s) as type %s'</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> Exception</span><span class="pas1-symbol">.</span><span class="pas1-identifier">CreateResFmt</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-symbol">@</span><span class="pas1-identifier">SSettingAccessError</span><span class="pas1-symbol">,
</span><span class="pas1-space">                                    </span><span class="pas1-symbol">[</span><span class="pas1-space"> Identifier</span><span class="pas1-symbol">,</span><span class="pas1-space"> Caption</span><span class="pas1-symbol">,</span><span class="pas1-space"> TypeName </span><span class="pas1-symbol">]</span><span class="pas1-space"> </span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Clear</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  FValue </span><span class="pas1-symbol">:=</span><span class="pas1-space"> Null</span><span class="pas1-symbol">;</span><span class="pas1-space">  
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">constructor</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> aIdentifier</span><span class="pas1-symbol">,</span><span class="pas1-space"> aCaption</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aDefaultValue</span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Create</span><span class="pas1-symbol">(</span><span class="pas1-space"> aIdentifier</span><span class="pas1-symbol">,</span><span class="pas1-space"> aCaption</span><span class="pas1-symbol">,</span><span class="pas1-space"> aCaption</span><span class="pas1-symbol">,</span><span class="pas1-space"> True</span><span class="pas1-symbol">,</span><span class="pas1-space"> aDefaultValue </span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetAsBoolean</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> AccessError</span><span class="pas1-symbol">(</span><span class="pas1-string">'Boolean'</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-comment">{ Do not localize }
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetAsDateTime</span><span class="pas1-symbol">:</span><span class="pas1-space"> TDateTime</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> AccessError</span><span class="pas1-symbol">(</span><span class="pas1-string">'DateTime'</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-comment">{ Do not localize }
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetAsFloat</span><span class="pas1-symbol">:</span><span class="pas1-space"> Double</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> AccessError</span><span class="pas1-symbol">(</span><span class="pas1-string">'Float'</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-comment">{ Do not localize }
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetAsInteger</span><span class="pas1-symbol">:</span><span class="pas1-space"> Longint</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> AccessError</span><span class="pas1-symbol">(</span><span class="pas1-string">'Integer'</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-comment">{ Do not localize }
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetAsString</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Result </span><span class="pas1-symbol">:=</span><span class="pas1-space"> ClassName</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">function</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">GetAsVariant</span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> AccessError</span><span class="pas1-symbol">(</span><span class="pas1-string">'Variant'</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-comment">{ Do not localize }
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">LoadFromRegIni</span><span class="pas1-symbol">(</span><span class="pas1-identifier">aRegIni</span><span class="pas1-symbol">:</span><span class="pas1-space"> TRegistryIniFile</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aSection</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Assert</span><span class="pas1-symbol">(</span><span class="pas1-space"> Assigned</span><span class="pas1-symbol">(</span><span class="pas1-space"> aRegIni </span><span class="pas1-symbol">),</span><span class="pas1-space"> </span><span class="pas1-string">'The aRegIni parameter should contain a TRegIni Instance'</span><span class="pas1-space"> </span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SaveToRegIni</span><span class="pas1-symbol">(</span><span class="pas1-identifier">aRegIni</span><span class="pas1-symbol">:</span><span class="pas1-space"> TRegistryIniFile</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">const</span><span class="pas1-space"> aSection</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  Assert</span><span class="pas1-symbol">(</span><span class="pas1-space"> Assigned</span><span class="pas1-symbol">(</span><span class="pas1-space"> aRegIni </span><span class="pas1-symbol">),</span><span class="pas1-space"> </span><span class="pas1-string">'The aRegIni parameter should contain a TRegIni Instance'</span><span class="pas1-space"> </span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetAsBoolean</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Boolean</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> AccessError</span><span class="pas1-symbol">(</span><span class="pas1-string">'Boolean'</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-comment">{ Do not localize }
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetAsDateTime</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> TDateTime</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> AccessError</span><span class="pas1-symbol">(</span><span class="pas1-string">'DateTime'</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-comment">{ Do not localize }
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetAsFloat</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Double</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> AccessError</span><span class="pas1-symbol">(</span><span class="pas1-string">'Float'</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-comment">{ Do not localize }
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetAsInteger</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Longint</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> AccessError</span><span class="pas1-symbol">(</span><span class="pas1-string">'Integer'</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-comment">{ Do not localize }
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetAsString</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">string</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> AccessError</span><span class="pas1-symbol">(</span><span class="pas1-string">'String'</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-comment">{ Do not localize }
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetAsVariant</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-space"> VarIsNull</span><span class="pas1-symbol">(</span><span class="pas1-space"> Value </span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space">  </span><span class="pas1-reservedword">begin
</span><span class="pas1-space">    Clear</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">end
</span><span class="pas1-space">  </span><span class="pas1-reservedword">else
</span><span class="pas1-space">  </span><span class="pas1-reservedword">begin
</span><span class="pas1-space">    SetVarValue</span><span class="pas1-symbol">(</span><span class="pas1-space"> Value </span><span class="pas1-symbol">);
</span><span class="pas1-space">  </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetCaption</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  FCaption </span><span class="pas1-symbol">:=</span><span class="pas1-space"> Value</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetHint</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  FHint </span><span class="pas1-symbol">:=</span><span class="pas1-space"> Value</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetIdentifier</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> </span><span class="pas1-reservedword">String</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  FIdentifier </span><span class="pas1-symbol">:=</span><span class="pas1-space"> Value</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TdvSetting</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SetVarValue</span><span class="pas1-symbol">(</span><span class="pas1-reservedword">const</span><span class="pas1-space"> Value</span><span class="pas1-symbol">:</span><span class="pas1-space"> Variant</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  </span><span class="pas1-reservedword">raise</span><span class="pas1-space"> AccessError</span><span class="pas1-symbol">(</span><span class="pas1-string">'Variant'</span><span class="pas1-symbol">);</span><span class="pas1-space"> </span><span class="pas1-comment">{ Do not localize }
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span></span>
</code></pre>

<h5>What does it do ?</h5>
	
<p>Actually this piece of code doesn't do all that much.  It just provides us with a base class we can now use as an ancestor for our other classes.  Basically we have some ErrorHandling and a skeleton for our specific Setting classes.</p>

<h3>Continued in Part 4</h3>

<p>For some reason I had problems fitting everything into one single post, so I had to split it up an two parts.  Go ahead and <a href="http://www.devia.be/news/article/delphi-code-using-some-basic-rules-oo-techniques-refactoring-part-4/" title="read the rest in part 4">read the rest in part 4</a>.</p>]]></content:encoded>
      <dc:date>2010-03-30T12:37:15+00:00</dc:date>
    </item>

    <item>
      <title>Simplify your Delphi Code using some basic rules, OO techniques and some refactoring (Part 2)</title>
      <link>http://www.devia.be/news/article/simplify-your-delphi-code-using-some-basic-rules-oo-techniques-refacto/</link>
      <guid>http://www.devia.be/news/article/simplify-your-delphi-code-using-some-basic-rules-oo-techniques-refacto/#When:08:40:02Z</guid>
      <description>In the First part of this series, we gave a brief overview of some general rules.  Meanwhile we&#39;ve had some time to think about what our code is supposed to do, so it&#39;s a good idea to continue with the second part.</description>
      <dc:subject>Software DevelopmentWindowsDelphi</dc:subject>
      <content:encoded><![CDATA[In the First part of this series, we gave a brief overview of some general rules.  Meanwhile we've had some time to think about what our code is supposed to do, so it's a good idea to continue with the second part.
<h3>Introduction</h3>

<p>Well, we did get some time to think a little more about what our code is supposed to do, so we have a pretty good idea about it already.  Sadly the people who originally created the code didn't really think about it.  In this article we'll take a close look at how everything was programmed and we'll have a look at some of the disadvantages and how we should solve them.</p>

<h3>The Old Code</h3>

<p>Basically the developers though about it and they had the idea that settings should be read from the registry when the user wanted to edit them.  Once the user finished changing the settings the code should store the new settings in the registry.  Apparently they also had the idea to load the settings when the first form gets displayed and save them when it gets closed.</p>

<p>So, in the main form they had some code which looks like this :</p>

<pre>
<code><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TfrmMain</span><span class="pas1-symbol">.</span><span class="pas1-identifier">FormShow</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Sender</span><span class="pas1-symbol">:</span><span class="pas1-space"> TObject</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">var
</span><span class="pas1-space">  aRegistry </span><span class="pas1-symbol">:</span><span class="pas1-space"> TRegistry</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  aRegistry </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TRegistry</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">try
</span><span class="pas1-space">    aRegistry</span><span class="pas1-symbol">.</span><span class="pas1-identifier">OpenKey</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-string">'&lt;THE_REGISTRY_PATH&gt;'</span><span class="pas1-symbol">,</span><span class="pas1-space"> True</span><span class="pas1-symbol">);
</span><span class="pas1-space">    </span><span class="pas1-comment">// FString, FInteger and FBoolean are private field declarations on
</span><span class="pas1-space">    </span><span class="pas1-comment">// TfrmMain.
</span><span class="pas1-space">    FString  </span><span class="pas1-symbol">:=</span><span class="pas1-space"> aRegistry</span><span class="pas1-symbol">.</span><span class="pas1-identifier">ReadString</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-string">'&lt;STRING_SETTING_KEY'</span><span class="pas1-space">  </span><span class="pas1-symbol">);
</span><span class="pas1-space">    FInteger </span><span class="pas1-symbol">:=</span><span class="pas1-space"> aRegistry</span><span class="pas1-symbol">.</span><span class="pas1-identifier">ReadInteger</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-string">'&lt;STRING_SETTING_KEY'</span><span class="pas1-space">  </span><span class="pas1-symbol">);
</span><span class="pas1-space">    FBoolean </span><span class="pas1-symbol">:=</span><span class="pas1-space"> aRegistry</span><span class="pas1-symbol">.</span><span class="pas1-identifier">ReadBool</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-string">'&lt;STRING_SETTING_KEY'</span><span class="pas1-space">  </span><span class="pas1-symbol">);
</span><span class="pas1-space">  </span><span class="pas1-reservedword">finally
</span><span class="pas1-space">    aRegistry</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TfrmMain</span><span class="pas1-symbol">.</span><span class="pas1-identifier">FormClose</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Sender</span><span class="pas1-symbol">:</span><span class="pas1-space"> TObject</span><span class="pas1-symbol">;</span><span class="pas1-space"> </span><span class="pas1-reservedword">var</span><span class="pas1-space"> Action</span><span class="pas1-symbol">:</span><span class="pas1-space"> TCloseAction</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">var
</span><span class="pas1-space">  aRegistry </span><span class="pas1-symbol">:</span><span class="pas1-space"> TRegistry</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  aRegistry </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TRegistry</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">try
</span><span class="pas1-space">    </span><span class="pas1-comment">// FString, FInteger and FBoolean are private field declarations on
</span><span class="pas1-space">    </span><span class="pas1-comment">// TfrmMain.
</span><span class="pas1-space">    aRegistry</span><span class="pas1-symbol">.</span><span class="pas1-identifier">OpenKey</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-string">'&lt;THE_REGISTRY_PATH&gt;'</span><span class="pas1-symbol">,</span><span class="pas1-space"> True</span><span class="pas1-symbol">);
</span><span class="pas1-space">    aRegistry</span><span class="pas1-symbol">.</span><span class="pas1-identifier">WriteString</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-string">'&lt;STRING_SETTING_KEY'</span><span class="pas1-symbol">,</span><span class="pas1-space"> FString  </span><span class="pas1-symbol">);
</span><span class="pas1-space">    aRegistry</span><span class="pas1-symbol">.</span><span class="pas1-identifier">WriteInteger</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-string">'&lt;STRING_SETTING_KEY'</span><span class="pas1-symbol">,</span><span class="pas1-space"> FInteger  </span><span class="pas1-symbol">);
</span><span class="pas1-space">    aRegistry</span><span class="pas1-symbol">.</span><span class="pas1-identifier">WriteBool</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-string">'&lt;STRING_SETTING_KEY'</span><span class="pas1-symbol">,</span><span class="pas1-space"> FBoolean  </span><span class="pas1-symbol">);
</span><span class="pas1-space">  </span><span class="pas1-reservedword">finally
</span><span class="pas1-space">    aRegistry</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Free</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;

</span><span class="pas1-reservedword">procedure</span><span class="pas1-space"> TfrmMain</span><span class="pas1-symbol">.</span><span class="pas1-identifier">mnuEditSettingsClick</span><span class="pas1-symbol">(</span><span class="pas1-identifier">Sender</span><span class="pas1-symbol">:</span><span class="pas1-space"> TObject</span><span class="pas1-symbol">);
</span><span class="pas1-reservedword">var
</span><span class="pas1-space">  aEditSettingsForm </span><span class="pas1-symbol">:</span><span class="pas1-space"> TfrmEditSettings</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  aEditSettingsForm </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TfrmEditSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-space"> Self </span><span class="pas1-symbol">);
</span><span class="pas1-space">  </span><span class="pas1-reservedword">try
</span><span class="pas1-space">    aEditSettingsForm</span><span class="pas1-symbol">.</span><span class="pas1-identifier">TheString</span><span class="pas1-space"> </span><span class="pas1-symbol">:=</span><span class="pas1-space"> FString</span><span class="pas1-symbol">;
</span><span class="pas1-space">    aEditSettingsForm</span><span class="pas1-symbol">.</span><span class="pas1-identifier">TheInteger </span><span class="pas1-symbol">:=</span><span class="pas1-space"> FInteger</span><span class="pas1-symbol">;
</span><span class="pas1-space">    aEditSettingsForm</span><span class="pas1-symbol">.</span><span class="pas1-identifier">TheBoolean </span><span class="pas1-symbol">:=</span><span class="pas1-space"> FBoolean</span><span class="pas1-symbol">;

</span><span class="pas1-space">    </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-space"> aEditSettingsForm</span><span class="pas1-symbol">.</span><span class="pas1-identifier">ShowModal </span><span class="pas1-symbol">=</span><span class="pas1-space"> mrOK </span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then
</span><span class="pas1-space">    </span><span class="pas1-reservedword">begin
</span><span class="pas1-space">      FString  </span><span class="pas1-symbol">:=</span><span class="pas1-space"> aEditSettingsForm</span><span class="pas1-symbol">.</span><span class="pas1-identifier">TheString</span><span class="pas1-symbol">;
</span><span class="pas1-space">      FInteger </span><span class="pas1-symbol">:=</span><span class="pas1-space"> aEditSettingsForm</span><span class="pas1-symbol">.</span><span class="pas1-identifier">TheInteger</span><span class="pas1-symbol">;
</span><span class="pas1-space">      FBoolean </span><span class="pas1-symbol">:=</span><span class="pas1-space"> aEditSettingsForm</span><span class="pas1-symbol">.</span><span class="pas1-identifier">TheBoolean</span><span class="pas1-symbol">;
</span><span class="pas1-space">    </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space">  </span><span class="pas1-reservedword">finally
</span><span class="pas1-space">    FreeAndNil</span><span class="pas1-symbol">(</span><span class="pas1-space"> aEditSettingsFrom </span><span class="pas1-symbol">)
</span><span class="pas1-space">  </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span>
</code></pre>

<h3>Will this work ?</h3>

<p>As you can see, the code will be working.  It will read the settings when the main form gets shown and store it in some private variables.  When the main form gets closed, the settings will be stored.  And there is even some code which will open a Edit Settings form, pass some values to it, and get some results back when the user closes the Edit Settings form by pressing the OK Button.</p>

<h3>So what's the problem ?</h3>

<h4>Is the code executed at the right time ?</h4>

<p>In my opinion the OnShow and OnClose events on the form arn't really the best places to execute this code.  What if the settings included things related to the visual appearance of the form ? Do you want to read and change those each time this form gets shown ? Maybe you have some other settings which should get read even before the first form is shown ?</p>

<p>In any case you might want to read the settings or store them at different points during the execution of your application.  In this example, that would require you to execute the OnShow event of the main form to load the settings.  Even worst is having to rewrite  or copy / paste the loading code in other locations.  Believe it or not, but that's what's happening in a lot of cases.</p>

<h4>What happens when a problem occurs while loading / saving the settingss ?</h4>

<p>The code isn't perfect, and strange things will happen when a certain registry key doesn't exist.  The code will raise an exception causing it to read or save only part of the settings and ending up with invalid settings.  In our case, it would be nice if a default value was used when a certain registry key doesn't exist.</p>

<p>Additionally when the user opens the form to change the settings, and closes it using the OK button, the new settings are passed back to the main form, but are not stored in the registry yet.  If some other part of your application now reads the settings from the registry again you might end up with different settings than the ones on your main form.</p>

<h4>Is it really the responsibility of the main form to Load or Save settings ?</h4>

<p>Well, in short NO ! Not at all ! </p>

<p>What if we had to create a command line version of our application ? We might still need to read some settings from the registry, but we won't need any forms at all.  What if I need to start a thread for some background processing, and need to read the settings in that thread as well ?</p>

<p>As you can see the Main From really shouldn't be responsible for the Loading and Saving of the settings.  It can call a method to do the job, but the actual code should never be in the main form.</p>

<p>Another rule of mine is that a form should only contain code which has an influence on the visual aspect of the form or its components / controls.  Reading settings and Writing settings doesn't have a visual inflence on the form, so it's code shouldn't be in a form.  You might need to change some visual aspects based on what you read from the registry, but the actual reading itself isn't the responsibility of a form.</p>

<h3>Is there a better alternative ?</h3>

<p>Well, it's one thing to say that something is incorrect, but when doing so you should at least try to tell how to do it correctly.  So, lets think a bit more about what we want and what we need.  Generally speaking we want something to load and save application settings.  It would be nice if we had some code we could use in whatever application we create in the future.  It really doesn't matter how many settings we need to read, or what they are called, and what format they are the only thing we care about is that we can Load / Save / Edit and Use them.  How this is done isn't our responsability but something the ApplicationSettings class should take care about.</p>

<p>If we need to use the settings in our applications we only need to use code which will look like this :</p>

<pre>
<code><span class="pas1-reservedword">var
</span><span class="pas1-space">  aApplicationSettings </span><span class="pas1-symbol">:</span><span class="pas1-space"> TApplicationSettings</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">begin
</span><span class="pas1-space">  aApplicationSettings </span><span class="pas1-symbol">:=</span><span class="pas1-space"> TApplicationSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">Create</span><span class="pas1-symbol">(</span><span class="pas1-space"> </span><span class="pas1-string">'&lt;OUR Registry Key&gt;'</span><span class="pas1-space"> </span><span class="pas1-symbol">);</span><span class="pas1-space">  
  </span><span class="pas1-reservedword">try
</span><span class="pas1-space">    </span><span class="pas1-comment">// Code used to load our settings  
</span><span class="pas1-space">    aApplicationSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">LoadFromRegistry</span><span class="pas1-symbol">;
</span><span class="pas1-space">    
    </span><span class="pas1-comment">// Code used to edit our settings
</span><span class="pas1-space">    </span><span class="pas1-reservedword">if</span><span class="pas1-space"> </span><span class="pas1-symbol">(</span><span class="pas1-space"> aApplicationSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">EditSettings </span><span class="pas1-symbol">)</span><span class="pas1-space"> </span><span class="pas1-reservedword">then</span><span class="pas1-space">    
    </span><span class="pas1-reservedword">begin
</span><span class="pas1-space">      </span><span class="pas1-comment">// Our settings got changed so we might want to do
</span><span class="pas1-space">      </span><span class="pas1-comment">// something if necessary.
</span><span class="pas1-space">    </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-space">        
    </span><span class="pas1-comment">// Code used to save our settings
</span><span class="pas1-space">    aApplicationSettings</span><span class="pas1-symbol">.</span><span class="pas1-identifier">SaveToRegistry</span><span class="pas1-symbol">;</span><span class="pas1-space">    
  </span><span class="pas1-reservedword">finally
</span><span class="pas1-space">    FreeAndNil</span><span class="pas1-symbol">(</span><span class="pas1-space"> aApplicationSettings </span><span class="pas1-symbol">);</span><span class="pas1-space">  
  </span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span><span class="pas1-reservedword">end</span><span class="pas1-symbol">;
</span></span>
</code></pre>


<h4>Who's responsible for what ?</h4>

<p>As you can see, our application / form or whatever doesn't really need to know how it should read the settings, it shouldn't really need to know how it is saving the settings, nor how we will display or edit the settings.  The only thing it has to know is that we have Application Settings and we can use them.</p>

<p>Our Application Settings class on the other hand needs to know which settings the application needs, what kind of settings they are and how it should load / save each of those settings.</p>

<h4>Are there any advantages to this approach ?</h4>

<p>Absolutely, otherwise I wouldn't have taken the time to write all this down.  Our main goal here is to use Delphi as an Object Oriented programming language, not just a RAD tool.  We will be creating some classes based on our new approach, and our goal is to reuse those classes whenever necessary.  </p>

<p>If we need to write another application tomorrow and it needs to save / load some application settings we will only have to let the system know which settings are needed, how they are called and what data type they are.  All the rest of the code will simply be reused.  We will spend a little more time creating the base classes and their code, but next time we need it, everything will be (almost) ready for us.</p>

<h4>What's next ?</h4>

<p>Well, we've been thinking and talking a lot so far, but we havn't really done any true coding yet.  Maybe a few people are thinking they could have written the code in the time they read these two articles.</p>  

<p>I'm quite sure that's possible, and I've seen it done ... </p>

<p>Sadly I've also been the guy who got hired 5 years after the application got written to debug the whole application in search of why something didn't work in some cases.  I've also been the person who had to search through thousands of lines of code wondering why one setting never got saved or got replaced by an incorrect value.  And yes, I've been that person who wished they had taken the time to think about their code before they actually started working on it :-P</p>

<p>Anyway, next time I'll show you how I would do it, and hopefully share some code with you.</p>]]></content:encoded>
      <dc:date>2010-03-17T08:40:02+00:00</dc:date>
    </item>

    <item>
      <title>Simplify your Delphi Code using some basic rules, OO techniques and some refactoring (Part 1)</title>
      <link>http://www.devia.be/news/article/simplify-your-delphi-code-using-some-basic-rules-oo-techniques-and-som/</link>
      <guid>http://www.devia.be/news/article/simplify-your-delphi-code-using-some-basic-rules-oo-techniques-and-som/#When:10:36:18Z</guid>
      <description>Quite often clients require me to work on their existing code to fix some problems or add some new features.  Most of the time the code was initially written many years ago, and has never been refactored or improved.  Most of the times this is causing the code to become hard to read,  understand and even maintain.</description>
      <dc:subject>Software DevelopmentWindowsDelphi</dc:subject>
      <content:encoded><![CDATA[Quite often clients require me to work on their existing code to fix some problems or add some new features.  Most of the time the code was initially written many years ago, and has never been refactored or improved.  Most of the times this is causing the code to become hard to read,  understand and even maintain.<h3>Introduction</h3>

<p>In this series of articles I will try to show how you could easily improve your 'old' code with some simple OO techniques and some refactoring.  When writing some Delphi Code I presonally have a few rules I abide by.  It would probably require my a few pages to explain them all, but here are just a few to get you started with :</p>

<ul>
	<li>Write down what your code is supposed to do</li>
	<li>Think before you start writing your first line of code !</li>
	<li>Sketch a little Class Diagram / Class Hierarchy if necessary</li>
	<li>If you copy / pasted the same lines of code more than twice, it's time to refactor it ! (same rule applies if you are writing the same code more than two times)</li>
	<li>Classes should do what they are responsible for, nothing more, nothing less</li>
	<li>Try to think in Objects with their responsibilities instead of thinking in procedures and processes !</li>
</ul>

<p>To illustrate this I will be using a little example of some code which could be used in almost any application : Saving & Loading some applicaiton settings.  It's a pretty simple task, but in quite a few occasions the code used to do it is ... well ... not the best example of OO development.  So, lets take this example and see what we can do with our few simple rules.</p>

<h3>A closer look at 'The Rules'</h3>

<h4>Write down what your code is supposed to do</h4>

<p>I think pretty much every application will be storing some settings.  It doens't really matter if you use a ClientDataSet, and INI File, a simple Text file or even the Windows Registry to do it.  What really matters is that an application can have some settings, they user might be able to change those settings and the application will probably need to read the settings and save them.</p>  

<p>Well that's about it really, we have written down what our code should do.  Of course we might change this in the future or add some new things to it, but basically we have everything we need to get started.</p>  

<p>An additional advantage we have now is that we have already written some very basic documentation for our code ! This is really a good way to do it, since most of the time, if you have to write the documentation once everything is finished, chances are you'll never have any documentation.  Of course we still need the discipline to update our documentation if things change, but we have something to get started.</p>

<h4>Think before you start writing your first line of code !</h4>

<p>While writing out what your code is supposed to do, you should also get into the habit of thinking about how it's going to do it, what it will need, ... So, what our piece of code will need is :</p>

<ul>
	<li>Some Application Settings</li>
	<li>Some way to load the settings</li>
	<li>Some way to save the settings</li>
	<li>Some place to save to and load from</li>
	<li>Some way to display the settings</li>
	<li>Some way to edit the settings</li>
	<li>Some form we will use for display / editing purposes</li>
	<li>Some way to use the settings in our application</li>
</ul>

<p>In order to make it simple, we will assume that we will be storing our Application Settings in the Windows Registry for now.  We could make it quite generic though and have a load / save mechanism for the Windows Registry / INI Files or any other presistance mechanism, but that's not the main focus (yet), so we'll stick with the Windows Registry.</p>

<h4>What's next ?</h4>

<p>Well, this is a good place to end this first article.  In the next installment we'll be taking a look at some of the other rules, and maybe have a look at some 'old' code too and check how we could improve it.  Meanwhile we have some time to think about what our code needs to do, and some time to sketch out a little Class Diagram as well ...</p>]]></content:encoded>
      <dc:date>2010-03-09T10:36:18+00:00</dc:date>
    </item>

    <item>
      <title>The future of Delphi looks brighter than ever before</title>
      <link>http://www.devia.be/news/article/the-future-of-delphi-looks-brighter-than-ever-before/</link>
      <guid>http://www.devia.be/news/article/the-future-of-delphi-looks-brighter-than-ever-before/#When:16:48:26Z</guid>
      <description>A few weeks ago I was invited to a meet and greet in Brussels with David Intersimone, better known as David I in the Delphi Community.  David was going to tell us something about the future Roadmap for Delphi.</description>
      <dc:subject>Software DevelopmentWindows.NetDelphi</dc:subject>
      <content:encoded><![CDATA[A few weeks ago I was invited to a meet and greet in Brussels with David Intersimone, better known as David I in the Delphi Community.  David was going to tell us something about the future Roadmap for Delphi.
<p>The last 10 years I have been developing software using Borland Delphi (later on CodeGear, and now Embarcadero), and this was the perfect opportunity to get some 'behind the scenes' information.</p>
<h3>Delphi Everywhere</h3>
<div class="small-photo-left"><img src="http://devia.ehclients.com/images/uploads/news/Embarcadero_Logo_300w_thumb.jpg" alt="image" width="307" height="80" /><p></p></div><p>The message was very clear, but it came somewhat as a surprise to me when David I mentioned the Mission Statement : <em>Delphi Everywhere</em>.  Later on during the session he even said <em>Native Delphi Everywhere</em>, mentioning Mac OS X, Linux, but also mobile devices.  He even hinted at possibilities to build phone (even iPhone) applications  using Delphi.</p>
<p>At that time I didn't really know what to think about it, but the possibilities of developing applications for Mobile Devices sounded, well ... to be honest, it sounded like a dream.  But during the course of the other presentations, I noticed that they might actually be pretty close to fulfilling it !</p>
<h3>Delphi Touch</h3>
<p>Well, they actually called it <em>Delphi Natural Input</em> to be correct.  The goal is to allow delphi and it's VCL components to interact with many different forms of input devices ranging from <em>touch screens, surface tables, accelerometers, GPS, Speech, WebCams, ...</em> </p>
<p>All these features will get included in a future version of the Delphi VCL.  Since I am working on a Mac, and am using an iPhone, I had a pretty good idea about the possibilities, but I never thought it would be possible to achieve something like that in Delphi.  Well, David I showed us a demo, and proved me I was wrong ...</p>
<p>The demo was actually pretty simple, and didn't require any programming at all.  All you had to do was add a new <em>GestureManager</em> component to your application.  The next step would be <em>creating the gestures or using one of the many predefined gestures</em> already available in the Gesture Manager.  The only thing you had to do was <em>add some code in the OnGesture event</em> and execute some code based on the Gesture that triggered it.</p>
<p>For those who have been developing in Delphi, you could actually compare it to a TActionList in which you can add some default actions, and add your own custom actions as well.</p>
<p>At this point it became clear to me that the possibility of creating applications for Mobile Devices using Delphi wasn't just a dream.  Apparently they have already spent quite some work on it, and the whole Gestures thing demonstrated that it could actually be done.</p>
<h3>The Delphi Roadmap</h3>
<p>I was glad to see that de team behind Delphi is very busy working on the next releases of Delphi.  Apparently de developers have been divided into several teams working on a few bug projects.  I will give you a brief list of those projects and what they will be focusing on.  Don't ask me about release dates, since they didn't mention any.  As David wisely said : <strong>There are 75 or more ways to ask us when it will be shipping, and there is only one right answer <em>"When it's ready"</em></strong>
<h4>Project Weaver</h4>
<ul><li>Project "Weaver" will mainly be focusing on larger and smaller IDE enhancements, improved usability and productivity.</li>
<li>Added support for Natural Input devices like Touch, Gestures, ...</li>
<li>Improved documentation and increased Team Productivity</li>
<li>DataSnap with HTTP support, built in REST server, and .Net proxies for DataSnap</li>
<li>IDE Insight (tm) - Keyboard access to everything</li>
<li>Windows 7 API support and Direct2D</li>
<li>Enhanced RTTI Support</li>
<li>Source Code Control with a new Open Tools API interface that provides support for Source Control Management (Weaver will have some Subversion Implementation)</li>
<li>.Net Aspect Oriented Programming (this seemed quite impressive to me)</li>
</ul>
<h4>Project Delphi X</h4>
<ul><li>Cross-platform Windows, Linux and MacOS</li></ul>
<p>Some other features under consideration :</p>
<ul><li>Cross-platform component library</li>
<li>DataSnapX with the ability to create both the Server and the Client on Windows, MacOS, Linux and the Web</li></ul>
<h4>Project Chromium</h4>
<ul><li>The main thrust of Chromium will be quality, quality and quality… </li>
<li>Focus on developer productivity (Enhancing usability, Remove long-standing issues, Focus on closing as many bugs as possible, Setting a new standard of reliability ...</li>
<li>Lightweight O/R mapping</li>
<li>Documentation of the OTA</li>
<li>A new Databinding model allowing binding to almost any property on a control.</li>
<li>More integration with the database tools</li></ul>
<h4>Project Commodore</h4>
<ul><li>Bring native 64-bit development to Delphi, C++ Builder and the VCL</li></ul>
<p>Some other features under consideration :</p>
<ul><li>Full compiler, RTL and VCL support for native 64 Compilation</li>
<li>Multi-Core / Multi-Threaded applications</li>
<li>Support for parallelization in the RTL</li></ul>
<h4>And much more to come</h4>
<p>It looks like there is a lot more to come, and some projects might come in Parallel.  Sadly, no information was given on when a specific product would be available to the public.  The only thing David I mentioned was that the plan is to get a new version of Delphi each year.</p>
<div class="small-photo-left"><img src="http://devia.ehclients.com/images/uploads/news/AdvSmoothListbox1.png" alt="image" width="250" height="346" /><p>TMS Smooth Controls : TAdvSmoothListBox</p></div><h3>TMS Smooth Controls</h3>
<p>Here in Belgium we have quite a few Delphi developers, and we also have companies like <a href="http://www.tmssoftware.com" title="TMSSoftware">TMSSoftware</a> who are developing some very nice components.  There were some a few people from TMS Software in the room, and they gave us a brief demo of their <a href="http://www.tmssoftware.com/site/advsmoothcontrols.asp" title="TMS Smooth Controls Pack">TMS Smooth Controls Pack</a> which is a set of feature-rich, sophisticated looking & smoothly animated controls.</p>
<p>The controls really looked impressive and immediately gave me the impression you would have when using an iPhone application.  The components looked clean, pretty, had lots of animations.</p>
<p>Those of us who have been using an iPhone know what I am talking about.  When navigating from one page to the other on the iPhone's applications screen, you get a smooth animation instead of simply repainting the whole screen.  Well, the Smooth Controls did exactly the same thing on Windows.  This gave everything a smoother and more visual look and feel</p>
<h3>Conclusion</h3>
<p>I actually missed the first part of the day due to traffic, but I gladly got there in time for the Delphi Roadmap, and I must say, it looks impressive.  There have been times when we didn't know what to expect from Delphi, and some people even thought the good old days were over for Delphi.  For those of you who are still hesitating about the future of Delphi, ... well, ... let me tell you :</p>
<center><h3>The Future of Delphi looks brighter than ever before !</h3></center>
]]></content:encoded>
      <dc:date>2009-06-23T16:48:26+00:00</dc:date>
    </item>

    
    </channel>
</rss>