<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.foxite.com/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Andy Kramek</title><link>http://weblogs.foxite.com/andykramek/default.aspx</link><description>Andy's VFP Weblog</description><dc:language>en-US</dc:language><generator>CommunityServer 2.0 (Build: 60217.2664)</generator><item><title>FoxRockX – Time to Put up, or Shut up</title><link>http://weblogs.foxite.com/andykramek/archive/2008/03/18/5731.aspx</link><pubDate>Tue, 18 Mar 2008 09:21:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:5731</guid><dc:creator>andykr</dc:creator><slash:comments>4</slash:comments><comments>http://weblogs.foxite.com/andykramek/comments/5731.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/andykramek/commentrss.aspx?PostID=5731</wfw:commentRss><description>&lt;P class=MsoNormal&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Over the years much has been made about the FoxPro Community and how important it is to the life and survival of the product. However, as I have said many times&amp;nbsp;(most recently in my "So, no more Visual FoxPro. Now what?" blog entry from May of 2007), it has often been noticeable that the "Community" has been long on talk and short on reaching for their wallets.&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;Of course, in the past year Microsoft has announced that VFP will not get another version and that future work, if any, on the product will be limited to critical fixes only. Add to that, the fact that participation at conferences has fallen to the point where from having one major international conference and two or three regional conferences per year in the USA there is now just one regional conference dedicated to FoxPro left – SW Fox had over 150 attendees last year (out of how many thousand FoxPro users in the USA alone - where were the rest of them?) See &lt;/FONT&gt;&lt;A href="http://www.swfox.net/"&gt;&lt;FONT face=Tahoma color=#800080 size=2&gt;http://www.swfox.net&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; for details of the 2008 conference...&amp;nbsp;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face=Tahoma size=2&gt;Subscription to magazines has dropped off to the point that the two major monthly publications dedicated to FoxPro both essentially died on their feet. Participation in the technical on-line forums has dropped significantly over the past 10-12 months.&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face=Tahoma size=2&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;&lt;STRONG&gt;Into this picture, at this moment in time, steps Rainer Becker.&amp;nbsp;&amp;nbsp;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;&lt;STRONG&gt;Who is Rainer Becker?&amp;nbsp;&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;SPAN class=bodytextChar&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Rainer Becker is the leader of the German Foxpro user group DFPUG since 1993, publishes the small magazine Foxx Professional, runs an interactive Visual FoxPro forum at &lt;/FONT&gt;&lt;A href="http://forum.dfpug.de/" target=_blank&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;forum.dfpug.de&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;, a Visual FoxPro document portal at &lt;/FONT&gt;&lt;A href="http://portal.dfpug.de/" target=_blank&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;portal.dfpug.de&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;, a &lt;/FONT&gt;&lt;A href="http://fox.wikis.com/wc.dll?Wiki~VisualFoxPro"&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Visual FoxPro&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; eNewsletter at &lt;/FONT&gt;&lt;A href="http://newsletter.dfpug.de/" target=_blank&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;newsletter.dfpug.de&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;, an international online shop at &lt;/FONT&gt;&lt;A href="http://shop.dfpug.com/" target=_blank&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;shop.dfpug.com&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; and has organized the German Devcon&amp;nbsp;since 1994. He has been a speaker at various Microsoft events as the &lt;/FONT&gt;&lt;A href="http://fox.wikis.com/wc.dll?Wiki~DevDays"&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Dev Days&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;, &lt;/FONT&gt;&lt;A href="http://fox.wikis.com/wc.dll?Wiki~FoxTeach"&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Fox Teach&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; and &lt;/FONT&gt;&lt;A href="http://fox.wikis.com/wc.dll?Wiki~CeBIT"&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Ce BIT&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; - at &lt;/FONT&gt;&lt;A href="http://fox.wikis.com/wc.dll?Wiki~CeBIT"&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Ce BIT&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; fair he was at the VFP demo machine 1993-2005. In his spare time he undertakes consulting work for "&lt;/FONT&gt;&lt;A href="http://fox.wikis.com/wc.dll?Wiki~WizardsBuilders"&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Wizards Builders&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;" and for "&lt;/FONT&gt;&lt;A href="http://fox.wikis.com/wc.dll?Wiki~ISYSGmbH"&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;ISYS GmbH&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;" as well as publishing the Visual FoxPro framework "&lt;/FONT&gt;&lt;A href="http://fox.wikis.com/wc.dll?Wiki~VisualExtend"&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Visual Extend&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt;".&lt;BR&gt;A&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;dditionally he has been a Microsoft MVP for his work in promoting and supporting Visual FoxPro in Europe since 1997 and in 2007 was a recipient of the FoxPro Community Lifetime Achievement Award.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;What has he done?&lt;/STRONG&gt;&lt;/FONT&gt;&amp;nbsp;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face=Tahoma size=2&gt;First he has undertaken the enormous (and very risky) task of&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;starting a completely new bi-monthly magazine dedicated to Visual FoxPro – which will be available both on-line and in printed version. That is FoxRockX. &lt;BR&gt;&lt;/FONT&gt;&lt;FONT face=Tahoma size=2&gt;Second he has bought up the entire FoxTalk archive and is making it available, on-line to subscribers to the new magazine, at no additional charge!&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;You can find full details of FoxRockX here: &lt;/FONT&gt;&lt;A href="http://www.foxrockx.com/seite.htm"&gt;&lt;FONT face=Tahoma color=#800080 size=2&gt;http://www.foxrockx.com/seite.htm&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; &lt;BR&gt;&lt;/FONT&gt;&lt;FONT face=Tahoma size=2&gt;And you can subscribe by going to either:&lt;BR&gt;&lt;/FONT&gt;&lt;A href="http://www.hentzenwerke.com/"&gt;&lt;FONT face=Tahoma color=#800080 size=2&gt;http://www.hentzenwerke.com&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; (USA/Asia)&lt;BR&gt;&lt;/FONT&gt;&lt;A href="http://shopdfpug.com/"&gt;&lt;FONT face=Tahoma size=2&gt;http://shopdfpug.com&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma size=2&gt; (Europe)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;Of course the most important question for many people is, how much will it cost? &lt;BR&gt;O&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;n-Line Subscription (including access to the archives) &lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;US$ 99.00 &lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;( 75 EUR )&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;BR&gt;Printed Subscription (includes on-line and archive) &lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;US$ 158.00 &lt;SPAN&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;( 109 EUR )&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;BR&gt;(Note if you are an existing FoxTalk subscriber you can upgrade your existing on-line subscription to the printed version by paying only the difference i.e. US$ 59.00 (34 EUR).&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN&gt;&lt;o:p&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;Marcia and I have already bought our subscription to the printed version, we have an article in the first issue and plan to continue writing for FoxRockX as long as they will have us.&amp;nbsp;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;However, the success of this venture is going to rely totally on the FoxPro community. &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;If the community puts its money where its mouth is, it will succeed and could help bring a new lease on life for the product that we all use and love. If the community refuses to support the initiative then the effort will die, and I am very much afraid that all hope for FoxPro will die along with it.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;So it is my opinion that this really is crunch time for the FoxPro community. &lt;STRONG&gt;&lt;EM&gt;Whatever you may think about the situation personally, either put up and support this international community-led effort, or shut up!&lt;o:p&gt;&lt;/o:p&gt;&lt;/EM&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN&gt;&lt;o:p&gt;&lt;FONT size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=5731" width="1" height="1"&gt;</description></item><item><title>More on the Advantage Database Server</title><link>http://weblogs.foxite.com/andykramek/archive/2008/03/02/5683.aspx</link><pubDate>Sun, 02 Mar 2008 18:23:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:5683</guid><dc:creator>andykr</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/andykramek/comments/5683.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/andykramek/commentrss.aspx?PostID=5683</wfw:commentRss><description>&lt;P&gt;If you are interested in learning more about the advantage database server that I mentioned on this blog a couple of months ago, then you should visit J D Mullin's blog here:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://jdmullin.blogspot.com/2008/02/getting-started-with-visual-foxpro-and.html"&gt;http://jdmullin.blogspot.com/2008/02/getting-started-with-visual-foxpro-and.html&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;He has put together a very nice ScreenCast (about 10 minutes long) that shows how to get started and some of the things you can do with VFP and Advantage Database Server. &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=5683" width="1" height="1"&gt;</description></item><item><title>Form Event Sequences</title><link>http://weblogs.foxite.com/andykramek/archive/2008/01/26/5586.aspx</link><pubDate>Sat, 26 Jan 2008 11:47:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:5586</guid><dc:creator>andykr</dc:creator><slash:comments>4</slash:comments><comments>http://weblogs.foxite.com/andykramek/comments/5586.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/andykramek/commentrss.aspx?PostID=5586</wfw:commentRss><description>&lt;P class=firstparagraph&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;One of the things that occasionally seems to confuse people is the question of the order in which the events happen when a form is instantiated. The basic answer, in terms of the Form's own events, is given by the acronym "LISA G", which stands for:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN&gt;L =&amp;gt; Load&lt;BR&gt;I =&amp;gt; Init ()each control first, then Form last)&lt;BR&gt;S =&amp;gt; Show&lt;BR&gt;A =&amp;gt; Activate&lt;BR&gt;G =&amp;gt; GotFocus (first control in the Tab order)&lt;BR&gt;&lt;/SPAN&gt;Actually you could argue that this should be "LISAR G" – because whenever the &lt;I&gt;Activate()&lt;/I&gt; event of a form is triggered, a &lt;I&gt;Refresh()&lt;/I&gt; is also initiated. Anyway, while these are the native form events, there are other things happening when a form is instantiated, most notably when a DataEnvironment is involved. &lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;For a form&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;which uses a DE, and contains an exit button and pageframe with two pages the full initialization sequence is:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=codefirstline&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM.DATAENVIRONMENT.OPENTABLES&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM.DATAENVIRONMENT.BEFOREOPENTABLES&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.LOAD&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.DATAENVIRONMENT.CURSOR1.INIT&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.DATAENVIRONMENT.INIT&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.CMDEXIT.INIT&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.CMDREFRESH.INIT&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.PGFMAIN.PAGE1.GRDCUSTOMER.COLUMN2.TXTCOL2.INIT&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.PGFMAIN.PAGE1.GRDCUSTOMER.INIT&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.PGFMAIN.PAGE1.INIT&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.PGFMAIN.PAGE2.TB01.INIT&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.PGFMAIN.PAGE2.CB03.INIT&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.PGFMAIN.PAGE2.TB02.INIT&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.PGFMAIN.PAGE2.INIT&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.PGFMAIN.INIT&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT face="Courier New" size=2&gt;FORM1.INIT&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;The whole thing starts with the DataEnvironment &lt;I&gt;OpenTables()&lt;/I&gt; which is an event that calls the &lt;I&gt;BeforeOpenTables()&lt;/I&gt;, and then proceeds with the Form’s &lt;I&gt;Load() &lt;/I&gt;event. After that the sequence is pretty much as expected. The objects contained by the form (Command Button and Pageframe) are initialized first, in the order in which they were added to the form, followed by the containers themselves, beginning with the DataEnvironment. This part of the sequence finishes with the Form’s &lt;I&gt;Init(). &lt;o:p&gt;&lt;/o:p&gt;&lt;/I&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;This is, of course,&lt;I&gt; &lt;/I&gt;why parameters passed to a form have to be received in the &lt;I&gt;Init()&lt;/I&gt;. It is the first form method that fires after all the controls are available, but before any of them have actually been updated. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT face=Tahoma size=2&gt;The next part of the process is concerned with updating the controls from their data sources (which is what the &lt;I&gt;Refresh()&lt;/I&gt; method actually does) and then making the form visible, the events fire as follows:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=codefirstline&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.SHOW&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.PGFMAIN.PAGE1.ACTIVATE&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.ACTIVATE&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.REFRESH&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.CMDEXIT.REFRESH&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.CMDREFRESH.REFRESH&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.PGFMAIN.REFRESH&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.PGFMAIN.PAGE1.REFRESH&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.PGFMAIN.PAGE1.GRDCUSTOMER.REFRESH&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.CMDREFRESH.WHEN&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;FORM1.GOTFOCUS&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT face="Courier New" size=2&gt;FORM1.CMDEXIT.WHEN&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT face=Tahoma size=2&gt;Notice, however, that only the &lt;I&gt;active page&lt;/I&gt; (Page1) of the pageframe gets refreshed. This means that the controls on Page 2 have not yet been updated and this explains why you always need to do an explicit &lt;I&gt;Refresh()&lt;/I&gt; when navigating to a new page. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT face=Tahoma size=2&gt;There is one thing to watch here, though. If you simply add a "&lt;I&gt;ThisForm.Refresh()&lt;/I&gt;" to the activate event of the first page of your pageframe you would actually end up calling it THREE times when initializing a form. Once (implicitly) from the Form.Activate(), a second time explicitly when the first page of the pageframe is refreshed and finally when the page itself is activated. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=noteoneline&gt;&lt;FONT face=Arial size=2&gt;&lt;EM&gt;Note: This underlines just how important it is to avoid the (way-too-common) practice of calling ThisForm.Refresh() from all over the place. A form level refresh should really only be called when you are certain that it is needed. In other words, ThisForm.Refresh() should always be preceded by some sort of test! &lt;/EM&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=noteoneline&gt;&lt;EM&gt;&lt;FONT face=Arial size=2&gt;One way to handle this is to create a wrapper method for the Form Refresh() and include a test for a form level property that is set by events that will require a form level refresh (like moving the record pointer, or changing the form's mode from "Add" to "View" for example). We use a method named "RefreshForm" to handle this and it looks like this:&lt;/FONT&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P class=codefirstline&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;LPARAMETERS tlSetObjMode&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;WITH Thisform&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;IF .FormRefreshNeeded&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;.LockScreen = .T.&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;IF .BeforeRefresh()&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;IF tlSetObjMode&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;.SetObjMode( This )&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;.Refresh()&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;.AfterRefresh()&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;.LockScreen = .F.&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;STRONG&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;ENDWITH&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=noteoneline&gt;&lt;SPAN&gt;&lt;EM&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;The parameter is used to determine whether to re-evaluate the form's mode and change any object whose state depends on that mode (handled by the SetObjMode() method). Notice that we also have hooks to "Before" and "After" methods that allow us to modify the behavior, and even cancel a refresh (by returning .F. from BeforeRefresh()) if necessary. By always calling this RefreshForm() method instead of directly calling Refresh() we buy ourselves a lot of flexibility.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT face=Tahoma size=2&gt;Incidentally, if you instantiate a form from a &lt;/FONT&gt;&lt;B&gt;&lt;SPAN&gt;VCX &lt;/SPAN&gt;&lt;/B&gt;&lt;FONT face=Tahoma size=2&gt;instead of an &lt;/FONT&gt;&lt;B&gt;&lt;SPAN&gt;SCX&lt;/SPAN&gt;&lt;/B&gt;&lt;FONT face=Tahoma size=2&gt; the event sequence is identical except, of course, that there are no dataenvironment events. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;So what happens when we release a form? The answer is that it depends on on HOW the form is released. &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN&gt;There are basically &lt;/SPAN&gt;three ways of killing a form. First you can explicitly call its &lt;I&gt;Release()&lt;/I&gt; method (i.e. &lt;SPAN class=bodytextChar&gt;&lt;I&gt;&lt;SPAN&gt;ThisForm.Release()&lt;/SPAN&gt;&lt;/I&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;B&gt;&lt;SPAN&gt; &lt;/SPAN&gt;&lt;/B&gt;&lt;FONT face=Tahoma size=2&gt;). Second, you can click on the ‘close’ button, which actually calls the form’s &lt;I&gt;QueryUnload()&lt;/I&gt; method and third you can release the object reference to the form: ( i.e.&lt;SPAN class=bodytextChar&gt;&lt;I&gt;&lt;SPAN&gt; RELEASE ThisForm&lt;/SPAN&gt;&lt;/I&gt;&lt;/SPAN&gt;) &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;SPAN class=subhead4Char&gt;&lt;SPAN&gt;&lt;STRONG&gt;&lt;EM&gt;&lt;FONT face=Arial size=2&gt;[1] Form Release() called:&lt;/FONT&gt;&lt;/EM&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;R =&amp;gt; Release&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;D =&amp;gt; Destroy (Form FIRST, then all contained controls in reverse of the Init order)&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;U =&amp;gt; Unload&lt;BR&gt;&lt;/FONT&gt;&lt;SPAN class=subhead4Char&gt;&lt;SPAN&gt;&lt;STRONG&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;[2] Close button used:&lt;/FONT&gt;&lt;/EM&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;SPAN&gt;&lt;BR&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Q =&amp;gt; QueryUnload&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;D =&amp;gt; Destroy (Form FIRST, then all contained controls in reverse of the Init order)&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;U =&amp;gt; Unload&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN class=subhead4Char&gt;&lt;SPAN&gt;&lt;STRONG&gt;&lt;EM&gt;&lt;FONT face=Arial size=2&gt;[3] Object Reference released (note that neither Release(), nor QueryUnload() are fired in this case):&lt;/FONT&gt;&lt;/EM&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;BR&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;D =&amp;gt; Destroy (Form FIRST, then all contained controls in reverse of the Init order)&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;U =&amp;gt; Unload&lt;BR&gt;In each case, the form's DE does not get released until AFTER the form Unload - so tables are still available in the Unload as well as properties - but no controls. &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;There is a potential problem here though. Notice that the first event common to all three methods is the &lt;I&gt;Destroy()&lt;/I&gt;. However, once the Form's Destroy fires there is no getting out of it, even a NODEFAULT will not stop the release process. That means that there is no single native method or event in which you can place code that checks to determine whether a form should be released or not. (It also means that if you release the object reference, it absolutely will be killed - there is no way to undo such this action because it fires the &lt;I&gt;Destroy()&lt;/I&gt; directly).&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;If you do need to check that it is Ok to release a form you will either have to disable the 'close' button on all your forms, or place the checking code in a custom method that is called from BOTH the form's &lt;I&gt;Release()&lt;/I&gt; and &lt;I&gt;QueryUnload()&lt;/I&gt; events because a NODEFAULT in either of these methods will halt the destruction of the form. This code, in both events, will do the trick:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=codefirstline&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;IF NOT ThisForm.OK2Destroy()&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;NODEFAULT&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT face="Courier New" size=2&gt;ENDIF&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;The most usual reason for this sort of code is to prevent users from closing a form with uncommitted changes pending, so the &lt;I&gt;OK2Destroy()&lt;/I&gt; will typically call the form's &lt;I&gt;CheckForChanges()&lt;/I&gt; method. As usual we prefer to call 'control methods' that then call the actual 'action' methods so that if we do need to modify behavior there is a place to do it from. &lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=5586" width="1" height="1"&gt;</description></item><item><title>Advantage Database Server V9.0 released as Beta</title><link>http://weblogs.foxite.com/andykramek/archive/2008/01/05/5530.aspx</link><pubDate>Sat, 05 Jan 2008 10:58:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:5530</guid><dc:creator>andykr</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/andykramek/comments/5530.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/andykramek/commentrss.aspx?PostID=5530</wfw:commentRss><description>&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;Sybase Anywhere have been working on a Visual FoxPro compatible version of the Advantage Database Server for some time and, just before Christmas, the long-awaited Version 9.0 was released in Beta. You can download the Beta version (time limited until the end of March 2008) from here:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;A href="http://devzone.advantagedatabase.com/dz/content.aspx?Key=20"&gt;&lt;FONT face=Tahoma color=#800080 size=2&gt;http://devzone.advantagedatabase.com/dz/content.aspx?Key=20&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;For a full version you will need to download the Server, the Data Architect and the Advantage OLEDB and ODBC drivers. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;Now some of you may be wondering why this should be news, or maybe you have never heard of the Advantage Database server. There is a lot of very good information on this neat little tool on their web site and I have been very impressed with it but there are a couple of things that should make it of immediate and very real interest to all VFP Users:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;[1] The ODBC driver will access all current VFP Data Table and Data Types. Yes, including Auto-Inc, Varchar() and all the newest features. For any of you who have been unable to move off VFP 6.0 because you need to access your data through ODBC there is now a solution!&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;[2] The advantage server can be used to connect directly to DBF files, replacing the DBC with a true multi-threaded, multi-user, remote server that includes, among many other features, a SQL Debugger (yes, you can step through SQL Queries one line at a time!), replication and merge functionality, and that runs on Windows, Linux or Netware.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;I have been playing with this version for a couple of weeks now and have been very impressed by its capabilities and potential. I am not going to try and cover all the things that the Advantage Database Server can do, but perhaps the one thing that is worth mentioning is that it can remove the necessity for users to have direct access to your DBF files. This requirement has long been one of the major objections to the DBF file as a data store because of the ease with which these files can be read and even corrupted. The Advantage Database Server makes this direct access unnecessary. DBF Files can now be hidden away from prying eyes (only the server needs access) and the server also manages locking and concurrency issues. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;Coming so soon on the news that Microsoft are abandoning VFP to its fate, it is nice to see that someone out there thinks that there is still some value in the product and is willing to put some effort into it. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;Here is what the Help File has to say about VFP support:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=subhead1&gt;&lt;STRONG&gt;&lt;FONT size=5&gt;&lt;FONT face=Arial&gt;Visual FoxPro 9 File Format Support&lt;/FONT&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=subhead1&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;Advantage support for FoxPro DBF tables and CDX/IDX index files has been enhanced to include all data types supported by Visual FoxPro 9.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;This includes support for Auto-increment, BLOB (Binary Large Objects), Currency, DateTime (timestamp), VarBinary, and VarChar field types.&lt;SPAN&gt;&amp;nbsp; &lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;Null field support has also been added to give true SQL-style NULL handling for Visual FoxPro DBF tables.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Support for true unique (candidate) indexes is now also available on DBF tables; this allows for better SQL optimization, the definition of primary keys, and the creation of referential integrity rules.&lt;SPAN&gt;&amp;nbsp; &lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;EM&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;Additionally, support for long field names with DBF tables has been added.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;In addition to supporting the robust and high-performance Advantage proprietary locking on the new table format, Advantage also supports Visual FoxPro compatibility locking, which allows you to use Advantage-enabled applications to share tables with existing Visual FoxPro applications that are not using Advantage.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P class=subhead1&gt;&lt;STRONG&gt;&lt;FONT size=5&gt;&lt;FONT face=Arial&gt;Visual FoxPro Upsizing Utility&lt;/FONT&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=subhead1&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;To complement the enhanced support for Visual FoxPro tables, this release includes an upsizing utility that aids in updating your application to use your existing Visual FoxPro tables with Advantage Database Server.&lt;SPAN&gt;&amp;nbsp; &lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;It is not necessary to update your tables or indexes to allow them to be used with Advantage Database Server.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;However, the upsizing utility will export much of the information in your Visual FoxPro Database Container (.DBC) to an Advantage Data Dictionary (.add) to allow support for features such as long field names, primary keys, referential integrity, and triggers.&lt;SPAN&gt;&amp;nbsp; &lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;EM&gt;&lt;FONT face=Arial size=2&gt;This utility, written as a Visual FoxPro application that you can modify, currently has the ability to export view definitions, referential integrity rules, default field values, field and table validation rules, and primary keys.&lt;/FONT&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;If you are still not sure what this is all about, here is an extract from the Overview section of the (very comprehensive) help file for Version 9.0:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;Advantage Database Server is a high performance client/server RDBMS for stand-alone, networked, Internet, and mobile database applications. Advantage Database Server allows developers the flexibility to combine powerful SQL statements and relational data access methods with the performance and control of navigational commands. Advantage has native development interfaces designed to leverage existing knowledge of popular development tools. With optimized data access methodology for easily delivering unparalleled performance, Advantage provides security, stability, and data integrity while being completely maintenance-free.&lt;BR&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;The Advantage Database Server is the key to improved database performance in network environments. The server can be visualized as an intelligent controller that reduces competition for resources and off-loads much of the work normally performed by each client workstation. It is responsible for all database access, including all reading and writing of data, and lock management. Working with the network operating system, the Advantage Database Server processes data requests and returns the information to the network clients.&lt;BR&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;The Advantage Database Server supports the NetWare, Windows, and Linux operating systems. The Advantage Database Server for NetWare is implemented as a NetWare Loadable Module (NLM). An NLM is simply an executable for the NetWare operating system. The Advantage Database Server for Windows operates as a Windows Service.&lt;BR&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;Note&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;The Advantage Database Server for Windows is a Service. It cannot be run as a standard Windows application. See Installing and Starting the Advantage Database Server for Windows , for more information on Windows Services and how to start them.&lt;BR&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;
&lt;P class=MsoNormal&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;The Advantage Database Server retrieves requests for database operations to be performed on behalf of the clients. The Advantage Database Server locates tables on the server and processes the database operations. The result of the operation is then returned to the client across the network, eliminating the need to send the database to the client for processing. This provides far better concurrency control and system integrity than is otherwise available.&lt;BR&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;Traditional non-client/server applications send raw data from the server across the network to be processed on the workstation. With the Advantage Database Server, much of the data is processed by the Advantage Database Server on the file server. By decreasing network traffic, you increase performance.&lt;BR&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;EM&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;The Advantage Database Server integrity system ensures that database updates either run to completion or do not begin. The Advantage Database Server will not execute partial commands. This means that the integrity of your database no longer depends on the stability of the workstations on the network. Because the Advantage Database Server is responsible for all database access (on behalf of the clients), it can do a far better job of concurrency control than traditional systems, where concurrency must be synchronized between remote workstations. Better concurrency control means better multi-user performance.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;What we have still to find out is what the new version will cost! But if you are looking for ways to leverage your VFP data and applications without the costs&amp;nbsp;involved in&amp;nbsp;porting to SQL Server or MySQL, this may be something that you should take a long hard look at - for the next couple of months at least it&amp;nbsp;will be&amp;nbsp;freely available for download and evaluation.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=5530" width="1" height="1"&gt;</description></item><item><title>Frankfurt Developer Conference is just 1 Week Away</title><link>http://weblogs.foxite.com/andykramek/archive/2007/10/29/5243.aspx</link><pubDate>Mon, 29 Oct 2007 09:34:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:5243</guid><dc:creator>andykr</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/andykramek/comments/5243.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/andykramek/commentrss.aspx?PostID=5243</wfw:commentRss><description>&lt;P&gt;By now I am sure you will have seen the rave reviews for SW Fox held last week in Mesa, Arizona. Rick, Doug and Tamar put together a fabulous conference which was really positive and upbeat.&amp;nbsp;I have not been to such a great VFP conference in the US in many years!&lt;/P&gt;
&lt;P&gt;However, for those of you who missed it, there is still time to get to the 14th Microsoft Visual FoxPro Developer Conference 2007 to be held&amp;nbsp;&amp;nbsp;between 8/10th November in Frankfurt, Germany.&lt;/P&gt;
&lt;P&gt;Apart from the setting, the food, the free beer and the warmth of the welcome, the Speakers for the English Track&amp;nbsp;list is impressive including:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Marcia Akins&lt;/LI&gt;
&lt;LI&gt;Craig Bernston&lt;/LI&gt;
&lt;LI&gt;Steven Black&lt;/LI&gt;
&lt;LI&gt;Yair Alan Griver&lt;/LI&gt;
&lt;LI&gt;Doug Hennig&lt;/LI&gt;
&lt;LI&gt;Vennelina Jordanova&lt;/LI&gt;
&lt;LI&gt;Andy Kramek&lt;/LI&gt;
&lt;LI&gt;Rick Schummer&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;For just 999 Euros (less than £700!) you get the full conference registration indcluding meals,&amp;nbsp;(and WHAT meals they are). &amp;nbsp;There are special conference rates at the hotel, and the flights are really good value at this time of year too.&lt;/P&gt;
&lt;P&gt;The range of topics available is extensive and there is no doubt that it is great value for money. You can find details here: &lt;A href="http://devcon.dfpug.de/"&gt;http://devcon.dfpug.de/&lt;/A&gt;&amp;nbsp;and an English Registration form is at &lt;A href="http://portal.dfpug.de/dFPUG/Dokumente/Konferenzen/Konferenzprogramm2007/Anmeldeformular%20engl.doc"&gt;http://portal.dfpug.de/dFPUG/Dokumente/Konferenzen/Konferenzprogramm2007/Anmeldeformular%20engl.doc&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;For reviews of previous Frankfurt Devcons check out the Wiki at &lt;A href="http://fox.wikis.com/wc.dll?Wiki~GreatThingsAboutDevconGermany~VFP"&gt;http://fox.wikis.com/wc.dll?Wiki~GreatThingsAboutDevconGermany~VFP&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Hopefully a few more of my countrymen will make the effort this year and I look forward to seeing you there. (Apart from anything else, it is always embarassing when I am asked why I am the only Brit in the place &lt;img src="/emoticons/emotion-1.gif" alt="Smile [:)]" /&gt;)&lt;/P&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=5243" width="1" height="1"&gt;</description></item><item><title>Creating Classes with a Factory</title><link>http://weblogs.foxite.com/andykramek/archive/2007/08/04/4508.aspx</link><pubDate>Sat, 04 Aug 2007 12:22:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:4508</guid><dc:creator>andykr</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/andykramek/comments/4508.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/andykramek/commentrss.aspx?PostID=4508</wfw:commentRss><description>&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;This implementation uses the abstract factory pattern to avoid one of the most difficult code maintenance issues. This is the problem that arises whenever we need to change either the class name, or the source library (or both) from which we want to instantiate an object, or simply need to make changes to an existing class definition. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;To change a name is fraught with peril and the only way to do it is to search the source code for all occurrences of the item that we want to change and replace it with the new one. This works just fine providing that we don’t miss one, or mistype either the name (or library, or both!) The more occurrences we have to fix the more likely it is that a mistake will be made – even using tools like “Code References”. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Even routine maintenance and enhancements can cause problems, especially when a team of developers is involved because a class library cannot be shared. So there is always a danger that changes made by one person get overwritten by changes in a different class made by another. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;The implementation described here addresses both of these issues.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=subhead2&gt;&lt;STRONG&gt;&lt;FONT face=Arial&gt;What is a Factory?&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;A factory class is basically one whose function is to instantiate other classes. It is an example of the more general ‘Abstract Factory’ design pattern, which is defined in &lt;I&gt;“Design Patterns – Elements of Reusable Object-Oriented Software” (Gamma, Helm, Johnson &amp;amp; Vlissides, Addison Wesley 1997) &lt;/I&gt;as:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=noteoneline&gt;&lt;EM&gt;&lt;FONT face=Arial size=2&gt;Provide an interface for creating families of related or dependent objects without specifying their concrete classes&lt;/FONT&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P class=subhead2&gt;&lt;STRONG&gt;&lt;FONT face=Arial&gt;What are the components of the factory?&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT face=Tahoma size=2&gt;The factory pattern requires a minimum of two components and, usually three (See Figure 3). &lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV class=bulletfirst&gt;&lt;FONT face=Tahoma size=2&gt;The Client – the object that requires an instance of a class. This is where, in conventional code, the &lt;I&gt;CREATEOBJECT()&lt;/I&gt; (or &lt;I&gt;NEWOBJECT()&lt;/I&gt;) function call would normally be located &lt;/FONT&gt;&lt;/DIV&gt;
&lt;LI&gt;
&lt;DIV class=bulletfirst&gt;&lt;FONT face=Tahoma size=2&gt;The Factory - this is usually instantiated as a stand-alone object at application startup, although it can also be implemented as a method on an Application Object. &lt;/FONT&gt;&lt;SPAN&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;LI&gt;
&lt;DIV class=bulletfirst&gt;&lt;SPAN&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;The Metadata - this, is what makes this implementation so useful in my opinion, and why VFP is such an ideal tool in which to implement this particular pattern&lt;/FONT&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=figure&gt;&lt;EM&gt;&lt;FONT face=Arial size=2&gt;Figure 1: Abstract Factory Components&lt;/FONT&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P class=figure&gt;&lt;STRONG&gt;&lt;FONT face=Arial&gt;&lt;SPAN&gt;&lt;IMG src="/photos/andykramek/images/4509/original.aspx" border=0&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=figure&gt;&lt;STRONG&gt;&lt;FONT face=Arial&gt;When should I use a Class Factory?&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;The short answer is always! There is really no reason not to use a factory to instantiate objects and the only real question is whether it should be implemented as a global object in its own right, or as a method on some other (i.e. Application) object. My personal preference is to create the factory as a separate object because I always use metadata to drive it, and it helps keep things tidy if the factory can run in its own private datasession.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;The key thing to remember is that the role of the metadata in the abstract factory is to separate the functionality from the information that is used to drive it. In this case we are concerned with instantiating objects which would normally be handled explicitly by using code like this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=codefirstline&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;loObject = CREATEOBJECT( ‘MyClass’ )&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=code&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;OR&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=codelastline&gt;&lt;STRONG&gt;&lt;FONT face="Courier New" size=2&gt;loObject = NEWOBJECT(&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;‘MyClass’, MyClassLibrary’ )&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;As noted above, problems arise with this if either the class name, or the source library changes, or even if we want to test a new version of a class because we must either change the original class definition, or change the calling code. Either way we have to update, recompile and re-distribute the application. The solution is that, instead of hard coding the instantiation directly into the application, we hand the task off to another object. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;In order to do that we need to associate a non-definitive “key” (that will be used in the code) with the actual class, and library names that can be looked up at run time to instantiate the correct class. Since the interpretation of the key name is handled inside the factory, there is never any need to amend the source code when changes to either class, or class library, are made. All that is needed is to change the metadata.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=subhead2&gt;&lt;STRONG&gt;&lt;FONT face=Arial&gt;Implementation&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;The metadata table for the factory class is shown in Table 1. Notice that the metadata, in addition to the Key, Class and Library names includes a memo field which we use to define default values for specific properties by listing them as Attribute/Value pairs. There is also a logical field which allows us to disable particular classes when necessary (more on that later).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;&lt;SPAN&gt;Table 1: Factory Class Metatdata&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;&lt;SPAN&gt;&lt;IMG src="/photos/andykramek/images/4510/original.aspx" border=0&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;The factory class itself is defined programmatically using the session base class so that it always runs in its own private datasession. This obviates any possibility that the tables it uses will be affected by the application itself. The interface is very simple as shown in Table 2:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;&lt;SPAN&gt;Table 2: Factory Class Interface&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;&lt;SPAN&gt;&lt;IMG src="/photos/andykramek/images/4511/original.aspx" border=0&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;In practice we define TWO identical tables. The first is named “&lt;I&gt;classes.dbf&lt;/I&gt;” and is the production version of the table, the second is named “&lt;I&gt;wipclasses.dbf&lt;/I&gt;” (for &lt;I&gt;Work-In-Progress&lt;/I&gt;). The code in the factory always checks for the key in the &lt;I&gt;wipclasses&lt;/I&gt; table first so that we don’t actually have to modify things on the production side (&lt;I&gt;classes.dbf&lt;/I&gt;) until we are sure that the new version is correct.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;The consequence is that new classes can be tested by the developer, &lt;B&gt;&lt;I&gt;actually in the EXE&lt;/I&gt;&lt;/B&gt;, without re-compiling the code. All that is needed is an active entry in &lt;I&gt;wipclasses.dbf&lt;/I&gt; to override the current ‘production’ version.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Another consequence is that, in a team environment, each developer can have their own local &lt;I&gt;wipclasses&lt;/I&gt; table, and a read-only copy of the main &lt;I&gt;classes.dbf&lt;/I&gt;. That way when someone is developing a class they don’t affect everyone else’s code while they are de-bugging their changes.&amp;nbsp;Once a new class, or sub-class, is ready for production, all that needs to be done is to update the appropriate class library and (if needed) modify the entry classes table and the application begins using the new class immediately.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT face=Tahoma size=2&gt;The factory class is defined in code as a sub-class of the Session base class. This, as noted above, means that the factory can be instantiated in the application environment as a global object that maintains its own private datasession. The class includes a property (&lt;/FONT&gt;&lt;SPAN class=codeChar&gt;&lt;SPAN&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;lWIPTable&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;) this serves as a flag that is set when the class is instantiated so that we don't have to keep testing for the presence of the WIP table. The &lt;I&gt;Init()&lt;/I&gt; method is responsible for setting up the metadata, and setting this flag.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT face=Tahoma size=2&gt;All of the real work is handled in the exposed &lt;I&gt;New() &lt;/I&gt;method. It accepts a key name, and up to five additional parameters which (if present) are passed directly to the &lt;I&gt;Init()&lt;/I&gt; of the object. If the object is instantiated correctly, a reference to the new object is returned to the client, otherwise a NULL value is handed back.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT face=Tahoma size=2&gt;Note that the class determines, from the extension of the specified class library, whether to use &lt;I&gt;CREATEOBJECT()&lt;/I&gt; if the library has been explicitly declared, or &lt;I&gt;NEWOBJECT() &lt;/I&gt;if not. If the object is instantiated successfully, and there are settings defined as defaults in the Properties column, then the factory will attempt to set those values as well (see the &lt;I&gt;GetProperties()&lt;/I&gt; and &lt;I&gt;Str2Exp()&lt;/I&gt; methods) – this is, of course, in addition to any parameters that may be passed and handled by the class code directly. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;So to create an instance of an object defined in the application source code all that has to be done is for the application to have access to the factory object and to call its &lt;I&gt;New()&lt;/I&gt; method with the key name. The return value will either be an object reference or NULL, and the client handles both possibilities: &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=codefirstline&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;TRY&lt;BR&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;loObject = oFactory.New( ‘Required_Object_KeyName’ )&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;IF ISNULL( loObject )&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ERROR “Unable to instantiate” + Required_Object_KeyName )&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;CATCH TO loErr&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;MESSAGEBOX( loErr.Message + “ in ” + loErr.Procedure, 16, “Factory Error” )&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT face="Courier New" size=2&gt;ENDTRY&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;You may be wondering why this does not create a dangling object reference. The reason is simply that the object is created as LOCAL inside the &lt;I&gt;Factory.New()&lt;/I&gt; method. So when the method completes, the local reference goes out of scope and is released, leaving the returned reference as the only one in existence.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=subhead2&gt;&lt;STRONG&gt;&lt;FONT face=Arial&gt;Summary&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT face=Tahoma size=2&gt;The implementation of the factory pattern illustrated here offers two major benefits. First, and most obviously, it avoids the issues that arise when class and library names are embedded directly in code. Second, it allows developers to work on, and test in a production environment, code that is still ‘work-in-progress’ without breaking anyone else’s version of the application. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;The code for our factory class is here:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=codefirstline&gt;
&lt;P class=bodytext&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;o:p&gt;&lt;FONT face="Courier New" size=2&gt;&lt;SPAN&gt;&lt;FONT face="Courier New"&gt;******************************************************************************************&lt;BR&gt;*** Program: Factory.prg&lt;BR&gt;*** Written by Andy Kramek &amp;amp; Marcia G. Akins &lt;BR&gt;*** Abstract: Abstract factory responsible for object instantiation&lt;BR&gt;*** Parameters: keyword from classes table to look up class info and up to 4 optional parameters&lt;BR&gt;*** Compiler.: Visual FoxPro 09.00.0000.3504 for Windows&lt;BR&gt;*****************************************************************************************&lt;BR&gt;DEFINE CLASS factory AS Session&lt;BR&gt;*** Give it a private data session so we can set exact ON&lt;BR&gt;*** so we can accurately use a SEEK into the classes table&lt;BR&gt;DataSession = 2&lt;BR&gt;lWIPTable = .F.&lt;BR&gt;******************************************************&lt;BR&gt;FUNCTION Init()&lt;BR&gt;******************************************************&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** This is a private data session so just force exact ON&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;SET EXACT ON&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** Open the classes table&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;IF NOT USED( 'Classes' )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;USE Classes AGAIN IN 0&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** Open WipClasses if we have it available, and set property&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;IF NOT USED( 'WIPclasses' )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;IF FILE( 'WIPclasses.dbf' )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;USE WIPclasses AGAIN IN 0&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;This.lWIPTable = .T.&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ELSE&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;This.lWIPTable = .T.&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;ENDFUNC&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;****************************************************************************&lt;BR&gt;FUNCTION New( tcKey, tuParam1, tuParam2, tuParam3, tuParam4, tuParam5 )&lt;BR&gt;*****************************************************************************&lt;BR&gt;LOCAL lcLibType, lcCommand, lnParm, lnParmCount, loObject, llFound, lcKey, lnSelect, llCreate, lcProperties&lt;BR&gt;LOCAL lcLibrary, lcClassName&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** Make sure we got a keyword&lt;BR&gt;IF EMPTY( tcKey )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;RETURN .NULL.&lt;BR&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** Get the class information&lt;BR&gt;lcKey = UPPER( ALLTRIM( tcKey ) )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** Check to see if the developers are using a local classes table&lt;BR&gt;*** to test work in progress. If there is one, use the information&lt;BR&gt;*** from the local table&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;if it is there. Only check the application&lt;BR&gt;*** classes table if the keyword can't be found in the local one&lt;BR&gt;lnSelect = SELECT()&lt;BR&gt;IF This.lWIPTable&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;SELECT WIPClasses&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;llFound = SEEK( lcKey, 'WIPclasses', 'cKey' ) AND WipClasses.lActive&lt;BR&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;*** Now check the application classes table if&lt;BR&gt;*** we need to&lt;BR&gt;IF NOT llFound&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;SELECT Classes&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;llFound = SEEK( lcKey, 'Classes', 'cKey' ) AND Classes.lActive&lt;BR&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;IF NOT llFound&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** Make sure keyword was found in classes table&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;RETURN .NULL.&lt;BR&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** Save pertinent info and force to upper case&lt;BR&gt;lcProperties = ALLTRIM( Properties )&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;lcLibrary = UPPER( ALLTRIM( cLibrary ) )&lt;BR&gt;lcClassName = UPPER( ALLTRIM( cClassName ) )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** Is this class in a vcx or a prg?&lt;BR&gt;lcLibType = This.ChkLibType( lcLibrary )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;*** Make sure our class library has an extension&lt;BR&gt;*** Just in case one was not specified in Classes.dbf&lt;BR&gt;IF EMPTY( lcLibType ) &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;RETURN .NULL.&lt;BR&gt;ELSE&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;lcLibrary = FORCEEXT( lcLibrary, lcLibType )&lt;BR&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** Now, see if our prg or vcx has been set &lt;BR&gt;IF lcLibType = 'PRG'&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;llCreate = ( lcLibrary $ SET( 'PROCEDURE' ) ) OR ;&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;( FORCEEXT( lcLibrary, 'FXP' ) $ SET( 'PROCEDURE' ) )&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;ELSE&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;llCreate = lcLibrary $ SET( 'CLASSLIB' )&lt;BR&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;IF llCreate&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;lcCommand = 'CreateObject( "' + lcClassName + '"'&lt;BR&gt;ELSE&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;lcCommand = 'NewObject( "' + lcClassName + '", "' + lcLibrary + '"'&lt;BR&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** Now tack the parameters on to the end of the command&lt;BR&gt;*** if any were passed&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;lnParmCount = PCOUNT() - 1&lt;BR&gt;IF&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;lnParmCount &amp;gt; 0&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** Only add the third parameter if we are using NewObject&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;IF NOT llCreate&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcCommand = lcCommand + ', ""'&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;FOR lnParm = 1 TO&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;lnParmCount&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcCommand = lcCommand + ', tuParam' + TRANSFORM( lnParm )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ENDFOR&lt;BR&gt;ENDIF&lt;BR&gt;lcCommand = lcCommand + ' )'&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** Go ahead and instantiate the object&lt;BR&gt;loObject = &amp;amp;lcCommand&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** Now see if we have some properties to set&lt;BR&gt;IF NOT EMPTY( lcProperties )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** First make sure we have an object&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;IF VARTYPE( loObject ) = 'O'&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;This.GetProperties( loObject, lcProperties )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;SELECT ( lnSelect )&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;RETURN loObject&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;ENDFUNC&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*****************************************************************************&lt;BR&gt;PROTECTED FUNCTION GetProperties( toObject, tcProperties )&lt;BR&gt;*****************************************************************************&lt;BR&gt;LOCAL lnTotal, laProps[ 1 ], lnCnt, lcPropName, lcPropValue, lcType, loItem, luValue&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** get all the attribute/value pairs in the memo field into a single array element&lt;BR&gt;lnTotal = ALINES( laProps, tcProperties )&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;*** And process each pair in the array&lt;BR&gt;FOR lnCnt = 1 TO lnTotal&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** Get the name of the property&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;lcPropName = ALLTRIM( GETWORDNUM( laProps[ lnCnt ], 1, '=' ) )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;lcPropValue = ALLTRIM( GETWORDNUM( laProps[ lnCnt ], 2, '=' ) ) &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** Make sure it is a property on the object&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;IF PEMSTATUS( toObject, lcPropName, 5 )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** See if we can get its data type&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;loItem = 'toObject.' + lcPropName&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcType = TYPE( loItem )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** Now get back the value in the appropriate data type&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;luValue = This.Str2Exp( lcPropValue, lcType )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&amp;amp;loItem = luValue&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;ENDFOR&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;********************************************************************************&lt;BR&gt;PROTECTED FUNCTION Str2Exp( tcExp, tcType )&lt;BR&gt;********************************************************************************&lt;BR&gt;LOCAL lcExp, luRetVal, lcType, lcStr&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** Verify parameters&lt;BR&gt;IF VARTYPE( tcExp ) # 'C'&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ASSERT .F. MESSAGE TRANSFORM( tcExp ) + ' is NOT a character expression and you MUST pass a character expression to Str2Exp!'&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;RETURN tcExp&lt;BR&gt;ENDIF&lt;BR&gt;IF EMPTY( tcType )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ASSERT .F. MESSAGE 'You MUST pass a data type to Str2Exp!'&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;RETURN tcExp&lt;BR&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** If no type passed -- map to expression type&lt;BR&gt;lcType = UPPER( ALLTRIM( tcType ) )&lt;BR&gt;*** Remove any NULL characters, and leading/trailing spaces&lt;BR&gt;lcExp = CHRTRAN( ALLTRIM( tcExp ), CHR( 0 ), '' )&lt;BR&gt;*** Convert from Character to the correct type&lt;BR&gt;DO CASE&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;*** Integers&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;CASE INLIST( lcType, 'I', 'N' ) AND INT( VAL( lcExp ) ) == VAL( lcExp ) &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;luRetVal = INT( VAL( lcExp ) )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** Other Numeric &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;CASE INLIST( lcType, 'N', 'B' )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;luRetVal = VAL( lcExp )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** Currency&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;CASE lcType = "Y"&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;luRetVal = NTOM( VAL( lcExp ))&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** Character or memo&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;CASE INLIST( lcType, 'C', 'M' ) &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** Remove delimiting marks if present.&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;IF INLIST( LEFT(lcExp,1), CHR(91), CHR(34), CHR(39))&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** We begin with a delimiter&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcExp = SUBSTR( lcExp, 2 )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** So we should end with a delimiter&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;IF INLIST( RIGHT(lcExp,1), CHR(93), CHR(34), CHR(39))&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcExp = LEFT( lcExp, LEN( lcExp )- 1 )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;luRetVal = lcExp&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** Logical&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;CASE lcType = 'L'&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;luRetVal = IIF( !EMPTY( CHRTRAN( lcExp, 'Ff0.', "" ) ), .T., .F.)&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** Date&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;CASE lcType = 'D' &amp;amp;&amp;amp; Date&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** Check for separators in the string&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;IF CHRTRAN( lcExp, "/.-", "" ) == lcExp&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** We are in yyyymmdd format&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcStr = LEFT( lcExp, 4) + "," + SUBSTR( lcExp, 5, 2 ) + "," + RIGHT( lcExp, 2)&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;luRetVal = DATE( &amp;amp;lcStr )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ELSE&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** We are in DTOC() format&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;luRetVal = CTOD( lcExp )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** DateTime&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;CASE lcType = 'T' &amp;amp;&amp;amp; DateTime &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** Check for date separators in the string&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;IF CHRTRAN( lcExp, "/.-", "" ) == lcExp&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** No separators so we have something other than TTOC() format&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;IF LEN( lcExp ) &amp;gt; 8&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** This one must be in yyyymmddhhmmss format&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** So get the date part first&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcStr = LEFT( lcExp, 4) + "," + SUBSTR( lcExp, 5, 2 ) + "," + SUBSTR( lcExp, 7, 2)&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** and convert to the correct date string format&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcStr = DTOC( DATE( &amp;amp;lcStr ))&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** Now tack on the hours part&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcStr = lcStr + " " + SUBSTR( lcExp, 9, 2 )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** Minutes&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;IF LEN( lcExp ) &amp;gt; 10&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcStr = lcStr + ":" + SUBSTR( lcExp, 11, 2 )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ELSE&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcStr = lcStr + ":00"&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** Seconds&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;IF LEN( lcExp ) &amp;gt; 12&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcStr = lcStr + ":" + SUBSTR( lcExp, 13, 2 )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ELSE&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcStr = lcStr + ":00"&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;luRetVal = CTOT( lcStr )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ELSE&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** This must be a date in yyyymmdd format which we want to force to DateTime format&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcStr = LEFT( lcExp, 4) + "," + SUBSTR( lcExp, 5, 2 ) + "," + RIGHT( lcExp, 2)&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;luRetVal = DTOT( DATE( &amp;amp;lcStr )) &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ELSE&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** We are already in TTOC() format&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;luRetVal = CTOT( lcExp )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;OTHERWISE&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;*** We have an invalid combination of value and data type&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;MESSAGEBOX( "Cannot convert " + lcExp + " to Data Type " + tcType, 16, "Conversion Failed " )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;luRetVal = lcExp&lt;BR&gt;ENDCASE&lt;BR&gt;*** Return value as Data Type&lt;BR&gt;RETURN luRetVal&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*****************************************************************************&lt;BR&gt;PROTECTED FUNCTION ChkLibType( tcLibrary )&lt;BR&gt;*****************************************************************************&lt;BR&gt;LOCAL lcLibType&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;*** Checks for file extension on library name, and&lt;BR&gt;*** figures out what it should be if not supplied&lt;BR&gt;lcLibType = UPPER( JUSTEXT( tcLibrary ) )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;IF NOT EMPTY( lcLibType ) &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;lcLibType = IIF( FILE( tcLibrary ), lcLibType, '' )&lt;BR&gt;ELSE&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** See if we have a vcx here&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;lcLibType = IIF( FILE( FORCEEXT( tcLibrary,'VCX' ) ), 'VCX', '' )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;IF EMPTY ( lcLibType )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcLibType = IIF( FILE( FORCEEXT( tcLibrary,'PRG' ) ), 'PRG', '' )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;ENDIF&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;BR&gt;RETURN lcLibType&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;BR&gt;ENDDEFINE&lt;/FONT&gt;&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/o:p&gt;
&lt;P&gt;&lt;/P&gt;&lt;A HREF="/photos/andykramek/picture3872.aspx" target=_blank&gt;&lt;/A&gt;&lt;A HREF="/photos/andykramek/images/4509/original.aspx" target=_blank&gt;&lt;/A&gt;&lt;A HREF="/photos/andykramek/images/4509/original.aspx" target=_blank&gt;&lt;/A&gt;&lt;A HREF="/photos/andykramek/picture4509.aspx" target=_blank&gt;&lt;/A&gt;&lt;A HREF="/photos/andykramek/picture4510.aspx" target=_blank&gt;&lt;/A&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=4508" width="1" height="1"&gt;</description></item><item><title>SW Fox, An Endangered Species I fear!</title><link>http://weblogs.foxite.com/andykramek/archive/2007/06/24/4172.aspx</link><pubDate>Sun, 24 Jun 2007 10:30:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:4172</guid><dc:creator>andykr</dc:creator><slash:comments>6</slash:comments><comments>http://weblogs.foxite.com/andykramek/comments/4172.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/andykramek/commentrss.aspx?PostID=4172</wfw:commentRss><description>&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;Marcia and I have just returned from Prague, where we were lucky enough to be among the speakers for the third time. This was, and is, a &lt;I&gt;great&lt;/I&gt; conference and this year had over 300 attendees. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;However, the first time we went there (in 2002) they had 600+. Why do I mention this? &lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;Well, I am told that Advisor Devcon this year had about 35 attendees for the VFP Track (contrast that with Advisor DevCon 2000 in Miami where there were over 1200, and with Orlando in 1998 where there were more than 2000). &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;I also know that last year's Southwest Fox in Phoenix had only just over 100 attendees.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;It does seem to be a general phenomenon across the world that fewer and fewer people are going to IT Conferences these days and there are probably several reasons for this. Obvious ones are budgetary constraints and&amp;nbsp;increased pressure on deadlines that reduces 'training' time.&amp;nbsp;However, &amp;nbsp;I also think that the ever-expanding scope of freely available advice and help on line has, for some people (especially those not directly involved), reduced the perceived value of conferences. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;However I totally disagree with that viewpoint and consider that conferences offer three huge benefits that cannot be obtained in any other way:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;[1] Networking. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;In our business, as in any other, "what you know" is important, but often "who you know" is at least as important. How can you know someone unless you meet with them, talk with them and spend time with them? In some ways the actual conference sessions are the least important aspect of a conference. It is the opportunity to meet others who live in the same world as you do and who do the same things that you do, to talk with them and discuss common issues and problems that adds significant value. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;Of course you also have to make the effort of going and talking to people! I have never understood people who go to a conference, attend the sessions and then disappear back to their hotel room – they are missing the most important part – the evening chat sessions in lobby, or the bar, or wherever the VFP crowd are congregating&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;[2] Broadening Horizons. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;We each live our professional lives immersed in the day to day issues with which we are concerned. How often do we take the time out to investigate some new facet of VFP? Or to look at some programming technique or issue for which we have no immediate use? Not very often I would wager. This is the shortcoming that on-line forums and help sites cannot address. They are 'problem oriented' in that when a question is asked, the response is an answer to that question. What you do not get is the answers to unasked questions or general information. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;For example, in Prague this year I attended a session given by Alan Griver on "VB Futures". This is something that I would not normally spend time researching, or even reading casually about, but it was an immensely interesting and revealing session and I learned a lot. Will I use it '&lt;I&gt;today&lt;/I&gt;'? No! Is it worth knowing about? Definitely! &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;[3] Learning New Skills/Approaches&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;One of the most significant benefits that I see from conferences is the presentation of alternatives. VFP is an immensely rich and powerful language and no-one really knows it all. (There are over 1500 Commands, Functions, Properties, Events and Methods, and probably 10 times that number of variations on them). It is almost an axiom that there are at least two ways (and usually more) of doing anything in VFP. What most of us (including myself) do is learn one and stick with it. At conferences I get a chance to see other approaches to problems, other techniques for using VFP and its tools and other people's solutions to problems. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;For example, at Prague last week I was asked by someone whether I thought he should use BINTOC() when creating an index on DELETED() so as to minimize the index size and improve transmission over the network. This was something I had never considered, and I told him I didn't know. So we went and tried it out then and there and, you know what, it works fine! So there was something I learned that despite my more than 20 years working with Fox I had never come across before and about which I would never have dreamed of asking on line. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;What is the point of this blog? Simply this;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;This year we will have only one dedicated VFP Conference in the USA (Fox Forward, although VFP oriented, &lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;is, intentionally, much broader in scope) and I greatly fear that it could very well be the last ever 'true' VFP Conference on this side of the Atlantic unless people in the community show their support in a practical way – by going to Phoenix in October!&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;The conference is being held at the Arizona Golf Resort and Conference Center, Mesa, Arizona and starts with a keynote presentation at 7:30pm on Thursday 18 October. Formal sessions begin at 8:00am on Friday 19 October, finishing at &lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;1:00pm on Sunday 21 October. &lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;In addition there are a number of 'pre-conference' sessions (3-hour workshops) being held on Thursday 18 October. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Verdana color=#006400 size=4&gt;For full details, and costs, go NOW to &lt;/FONT&gt;&lt;A href="http://www.swfox.net/home.aspx"&gt;&lt;FONT face=Verdana color=#006400 size=4&gt;http://www.swfox.net/home.aspx&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Verdana color=#006400 size=4&gt; and REGISTER&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;SPAN&gt;&lt;FONT face=Verdana color=#ff0000 size=4&gt;And remember, if we don't use it, we'll lose it - there may not be a "next year"&amp;nbsp;unless we can all make "this year" a success&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=4172" width="1" height="1"&gt;</description></item><item><title>So, no more Visual FoxPro. Now what?</title><link>http://weblogs.foxite.com/andykramek/archive/2007/05/19/3815.aspx</link><pubDate>Sat, 19 May 2007 20:06:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:3815</guid><dc:creator>andykr</dc:creator><slash:comments>1</slash:comments><comments>http://weblogs.foxite.com/andykramek/comments/3815.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/andykramek/commentrss.aspx?PostID=3815</wfw:commentRss><description>&lt;P class=bodytext&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;It has been over a month since Microsoft formally announced that there would be no new version of Visual FoxPro and that support for the current version would be retired in 2015. The reaction from large parts of the community was, of course, entirely predictable. &lt;B&gt;&lt;I&gt;Oh my Gosh! The sky is falling!&lt;o:p&gt;&lt;/o:p&gt;&lt;/I&gt;&lt;/B&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;But what is the reality? &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;I have been deliberately silent on this topic to try and give the dust some time to settle and, also to take stock of my own position and intentions. So here, for what it's worth, is what I think about it all.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Emotionally, I am sad that Microsoft have decided not to invest in further development of Visual FoxPro. It is truly a great tool, way better than most people outside the dedicated user community, realize. It has been a mainstay of LAN based, desktop application development in all sorts of businesses for more than 20 years and as I (and many others) have been saying for years, it is also one of the best, if not the very best, tool for middle tier component development for use with all types of data-centric applications. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;However, I also recognize that Microsoft is a business. I suspect that the demise of Visual FoxPro has more to do with the FoxPro community than most people in that community would like to admit. It has been made abundantly clear, on numerous occasions over recent years, that Visual FoxPro was not paying its way. The main cause is, of course, that the Royalty Free distribution, and lack of database licensing, give it a poor (i.e. non-existent) on-going revenue model. The only real revenue from VFP is, therefore, sales of new versions and when you couple this with the reluctance of the FoxPro Community to actually go out and buy new versions (why else is VFP 6.0 still the most widely used version of Visual FoxPro?) it is not hard to see why Microsoft are not keen on tackling a major re-write of Visual FoxPro.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Now hang on there; where did that come from? &lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;Who said anything about a "&lt;B&gt;&lt;I&gt;major re-write&lt;/I&gt;&lt;/B&gt;"? &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Well, if you think about it, what else could we be talking about for a Version 10?&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;There are two key issues to consider here. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;First there is the question of 'features'. What new features could be added to Visual FoxPro in order to create a new version? Sure there are some little 'nice-to-have' things that could be added, but really the only things lacking in VFP are things that other Microsoft Products already provide. Even assuming it were possible, adding database features like integrated Security, Transaction Logging or extending the table size beyond the 2Gb limit, would only make Visual FoxPro a competitor for SQL Server. Similarly adding development features, like native Web Page capability, or CLR integration would only make it compete with Visual Studio. Why on earth would Microsoft want to do things like this for a product on which they don't make any money anyway?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Second there is the issue of technology. Whether we like it or not Visual FoxPro is bedded firmly in the technology of the 1980s and 90s. "Backward Compatibility' has always been one of Visual FoxPro's major strengths, but this is partly because it hasn’t really changed its core technology that much over the years. Now we are confronted with 64-bit, multiple processor hardware with more RAM than one would have dreamed of 5 years ago. Visual FoxPro was not built to run in such environments and changing it so that it can take advantage of the technology would surely be difficult and expensive. In fact I doubt if anything short of a total re-write from the ground up would suffice.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;So while I may not like the decision, I fully understand it. In fact, I am grateful that Microsoft have agreed to stand by the product until 2015 anyway. Not only that, they have committed to delivering Service Pack 2, and the Sedna patch to VFP 9.0 (that will enable VFP to run under, and take advantage of, the next generation of operating systems). &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;So, now that we are over that, what next? &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Well the first thing to consider is what does the announcement actually mean.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Microsoft have stated that VFP will not stop working – merely that they will not continue to support the product after 2015. This is perfectly normal and in line with their standard practice. Take a look at the product life cycle pages for any Microsoft Development tool and you will see the same pattern. You can find the web page here:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;A href="http://support.microsoft.com/default.aspx/gp/lifeselectdevtools"&gt;&lt;FONT face=Tahoma color=#800080 size=2&gt;http://support.microsoft.com/default.aspx/gp/lifeselectdevtools&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Here are the dates for all the versions of Visual FoxPro since VFP 6.0:&lt;/FONT&gt;&lt;/P&gt;
&lt;TABLE class=MsoTableGrid cellSpacing=0 cellPadding=0&gt;

&lt;TR&gt;
&lt;TD&gt;
&lt;P class=tablecolumnhead&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Version&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tablecolumnhead&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Released&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tablecolumnhead&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Mainstream Support Retired&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tablecolumnhead&gt;&lt;STRONG&gt;&lt;FONT face=Arial size=2&gt;Extended Support Retired&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;P class=tabletext&gt;&lt;FONT face=Arial size=2&gt;Visual FoxPro 6.0 Professional Edition&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;8/16/1998&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;9/30/2003&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;9/30/2004 &lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;P class=tabletext&gt;&lt;FONT face=Arial size=2&gt;Visual FoxPro 7.0 Professional Edition&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;9/29/2001&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;10/10/2006&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;10/14/2008 &lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;P class=tabletext&gt;&lt;FONT face=Arial size=2&gt;Visual FoxPro 8.0 Professional Edition&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;3/12/2003&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;4/8/2008&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;4/9/2013 &lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;P class=tabletext&gt;&lt;FONT face=Arial size=2&gt;Visual FoxPro 9.0 Professional Edition&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;12/22/2004&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;1/12/2010&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;1/13/2015 &lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;FONT face=Tahoma size=2&gt;And just for comparison, here are a couple of other tools…&lt;/FONT&gt;&lt;/P&gt;
&lt;TABLE class=MsoTableGrid cellSpacing=0 cellPadding=0&gt;

&lt;TR&gt;
&lt;TD&gt;
&lt;P class=tabletext&gt;&lt;FONT face=Arial size=2&gt;Visual Studio .NET 2003 Professional Edition&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;7/10/2003&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10/14/2008&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10/8/2013 &lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;P class=tabletext&gt;&lt;FONT face=Arial size=2&gt;Visual Basic .NET 2003 Standard Edition&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;7/10/2003&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10/14/2008&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10/8/2013 &lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;P class=tabletext&gt;&lt;FONT face=Arial size=2&gt;Visual Studio 2005 Team Suite&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;1/27/2006&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;4/12/2011&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;4/12/2016&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;P class=tabletext&gt;&lt;FONT face=Arial size=2&gt;Visual C++ 2005 Express Edition &lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;1/14/2006 &lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT face=Arial size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;4/12/2011&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD&gt;
&lt;P class=tabletext align=right&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;4/12/2016 &lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;As you can see, the pattern is standard. 5 years on "Mainstream" support plus a further 5 years on "Extended" support. For definitions of exactly what this means, see the details on the FAQ page here: &lt;/FONT&gt;&lt;A href="http://support.microsoft.com/gp/lifepolicy"&gt;&lt;FONT face=Tahoma color=#800080 size=2&gt;http://support.microsoft.com/gp/lifepolicy&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Basically once the mainstream support phase ends, Microsoft will no longer provide non-security related hotfixes, provide no-charge incident support or entertain Warranty claims or Feature/Enhancement requests.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;So what does that mean for you and I? Probably not much! It is pretty rare for the average developer to use "incident support" anyway, and for a mature and stable product like VFP it is even rarer.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;B&gt;&lt;I&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;But there won't be another version!&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;So what? What difference does that really make. Ask yourself the following questions:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Is VFP going to stop working on 1/13/2015 ? &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;(Hint: NO)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Is VFP's data &lt;SPAN&gt;handling and integration capability going to go away or be reduced&lt;/SPAN&gt;? &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;(Hint: NO)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Will the features that make VFP your &lt;SPAN&gt;development tool of choice change? &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;(Hint: NO)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Will you not be able create and distribute royalty free EXE data-based applications? &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;(Hint: NO)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Will the capabilities and extensibility that make VFP the most powerful desktop database change? &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;SPAN&gt;&lt;FONT face=Tahoma size=2&gt;(Hint: NO)&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Which is the most widely used version of Visual FoxPro in the world today? &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;(Hint: VFP 6.0! A product whose support expired almost 3 years ago…)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;In short, what will change? Answer, nothing at all! (Except, of course, for the vindication of the perception of the uninformed, marketing and buzz-word driven, benighted people who wouldn't dream of considering or using VFP anyway).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;So what I am I doing about it all? Nothing! My clients typically are small to medium size businesses who are looking for fast, cost-effective (i.e. cheap!) solutions to business problems. Mostly they require solutions that run on desk-top PCs over secure Local Area networks. Typically they couldn't care less what the solution is created with. What they require is results, not conformity to corporate strategic plans.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Of course I will continue to provide the best service I can for my clients; where that means using SQL Server for a database, I will. If it means developing a browser based application in ASP .NET and C# then I will do that (and indeed, I have done so). But when I need a middle tier, data aware COM component, or a simple desktop application that accesses only data held locally then I will still be turning to Visual FoxPro as my number one development tool.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=3815" width="1" height="1"&gt;</description></item><item><title>Are on-line technical forums breeding lazy developers?</title><link>http://weblogs.foxite.com/andykramek/archive/2007/02/19/3330.aspx</link><pubDate>Mon, 19 Feb 2007 12:36:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:3330</guid><dc:creator>andykr</dc:creator><slash:comments>15</slash:comments><comments>http://weblogs.foxite.com/andykramek/comments/3330.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/andykramek/commentrss.aspx?PostID=3330</wfw:commentRss><description>&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;As most of my readers will know, I spend a considerable amount of time trying to help other developers with technical issues in various on-line forums. I don’t do this because I am seeking some sort of kudos, or recognition, but because when I was starting out as developer back in the late 1980s I received a lot of help from other people. Most of them I had never heard of (but I have been very fortunate in that many of these ‘names’ I now count among my friends) but they were unfailingly helpful and always ready to offer advice, code and the benefit of their own experiences. Now I try to repay them by helping others who are just starting out, or who have hit a block of some sort.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;However, I have noticed a rather, disturbing (at least to me), trend recently. It seems that more and more developers are using the on-line forums as the FIRST place they go for solutions rather than, as has always been the case, the last resort – when you have exhausted all other resources. Here is a question I saw posted today (yes, this is real, and un-edited):&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=codefirstline&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;I would like to know what is wrong with the following statements:&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;DIMENSION cust[2]&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;cust[1] = "aaa"&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;cust[2] = "bbb"&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;CREATE CURSOR CUSTOMERS FROM ARRAY cust&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;STRONG&gt;&lt;FONT face="Courier New" size=2&gt;I get the error "No fields found to process". &lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;I simply cannot imagine why anyone would post a question like&amp;nbsp;this because the answer is immediately obvious from the help file topic for CREATE CURSOR where is states explicitly that:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=byline&gt;&lt;FONT face=Tahoma size=2&gt;&lt;EM&gt;FROM ARRAY &lt;SPAN&gt;ArrayName&lt;/SPAN&gt; &lt;BR&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;EM&gt;&lt;FONT face=Tahoma size=2&gt;Specifies the name of an existing array whose contents are the name, type, precision, and scale for each field in the temporary table. You can use the &lt;B&gt;FROM ARRAY&lt;/B&gt; clause instead of specifying individual fields. For the proper format of the contents of the array, see AFIELDS(&amp;nbsp;) Function. &lt;/FONT&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Wouldn't it be reasonable to expect that a developer, on getting an error like "No fields Found to Process" would jump into the Help File to check that the code is correct? If so, even a cursory check for syntax would have revealed that the array was just plain wrong! A moment’s thought, and a quick search for “From Array” would have revealed a number of options including "&lt;I&gt;APPEND FROM ARRAY&lt;/I&gt;" which obviously will do exactly what was wanted, but also "&lt;I&gt;REPLACE FROM ARRAY&lt;/I&gt;" and "&lt;I&gt;COPY TO ARRAY&lt;/I&gt;” which might have repaid a little further investigation and would have solved the problem in about 30 seconds.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Instead, the person posted a question, received an answer in 15 minutes, re-posted the “correct” question which was “&lt;I&gt;how can I append data from an array to a cursor&lt;/I&gt;” and (presumably) waited another quarter hour for an answer to that one!&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Or how about this one:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=codefirstline&gt;&lt;STRONG&gt;&lt;FONT face="Courier New" size=2&gt;How to use ReportListener with Top-Level form and what Enginerbehaviour and Reportbehaviour shuould set. Please Help &lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;What sort of question is that? This is on a par with “&lt;I&gt;How do I write an application in VFP?&lt;/I&gt;” or “&lt;I&gt;How long is a piece of string?&lt;/I&gt;”&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Maybe it’s me, but I get the feeling that people are getting lazy and expect, nay, even DEMAND, that others spoon-feed them answers to questions that really the questioner could have answered themselves with minimal effort and research. I actually replied to the person who asked the ReportListener question as follows:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;I&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Pardon me for jumping in here, but I think you are being very unreasonable. The first thing you need to do is to make some effort to do your own research, you can't expect others to do it all for you!&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;I&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Do you have the VFP Help file? If so, try looking in the help file under: "ReportListener Base Foundation Class". There is an example at the bottom of the page! &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;I&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;On the other hand, maybe just don't like the VFP Help files. So how about going to the VFP Website and looking at the "Technical Article" section? Maybe you could download Cathy Poutney's articles (which includes a load of examples):&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;I&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;What's New in the Visual FoxPro 9.0 Report Writer and Visual FoxPro 9.0 Report Writer In Action &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;I&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;There is also Doug Hennig's article on "Hyperlink Your Reports" and there are other useful links there too.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;I&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;On the other hand, maybe you don't like the Microsoft Web site either. So how about going to www.google.com and entering "VFP Report Listener Examples" - would you like me to list all 12,200 hits on that one for you (or can you manage to look at those by yourself)?&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;I&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;If you don't like that either, what about this forum's archives? There must be dozens of threads here discussing ReportListeners and absolutely chock full of good advice.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;I&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;Look, if you have a specific question, we are only too glad to help, but asking others to do your research work for you is unfair and unreasonable. Go and do some research and when you find something you can't understand, or can't cope with, come and ask by all means. But what you are doing now is just abusing the goodwill of the members of this forum. &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;And the last paragraph says it all – it seems to me that&amp;nbsp;this is a growing trend among some developers who seem to believe that there is no point in doing any research, or investigation, because you can just post the question on-line and someone else will do it for you. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Now, I &lt;I&gt;know&lt;/I&gt; that I don’t have to answer these sorts of questions, but the thing is that I really believe that the only way to become a better developer is to really understand what is going on and how your development tool works. But I don’t think you can get that sort of understanding without putting SOME effort of your own into acquiring it. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;So the point of this article is two-fold. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;[1] Am I being over-sensitive about this? Or are people really just getting lazier because it’s so easy to get answers on-line?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;[2] How can we (and maybe even &lt;EM&gt;SHOULD&lt;/EM&gt; we?) encourage people, especially neophytes, to appreciate the value of doing their own research before posting questions on line?&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;o:p&gt;&lt;FONT face=Tahoma size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=3330" width="1" height="1"&gt;</description></item><item><title>Design Patterns – The Fa&amp;#231;ade </title><link>http://weblogs.foxite.com/andykramek/archive/2007/01/21/3165.aspx</link><pubDate>Sun, 21 Jan 2007 21:02:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:3165</guid><dc:creator>andykr</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/andykramek/comments/3165.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/andykramek/commentrss.aspx?PostID=3165</wfw:commentRss><description>&lt;P class=firstparagraph&gt;&lt;FONT face=Tahoma size=2&gt;The façade is, perhaps, the second most commonly implemented design pattern. Just like the Bridge (probably the most widely used pattern of all, and certainly the most fundamental) it is usually implemented without a conscious decision having been made. Does this mean that it merely a statement of the obvious? Perhaps, but the pattern does have a very specific intent, and should definitely be taken seriously.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=subhead2&gt;&lt;STRONG&gt;&lt;FONT face=Arial&gt;What is a Façade?&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;The formal definition for Façade offered by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides is:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=noteoneline&gt;&lt;EM&gt;&lt;FONT face=Arial size=2&gt;Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use&lt;/FONT&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Succinct, but perhaps not quite so obvious after all. Consider the basic three tier architecture so widely used in software design. How should you define the middle tier? Potentially there are going to be many different objects in that middle tier. For example you may have any, or all, of the following types of object:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bulletfirst&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;·&lt;/FONT&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Data Validation objects&lt;BR&gt;&lt;/FONT&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;·&lt;/FONT&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Business Rule Objects&lt;BR&gt;&lt;/FONT&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;·&lt;/FONT&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Data Transformation Objects&lt;BR&gt;&lt;/FONT&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;·&lt;/FONT&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Data Access/Database Connection Objects&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;How is your Presentation Tier going to manage all the interactions with these individual objects? You could easily end up with a frightful mess where each object in the Presentation Tier must have detailed knowledge of each of the middle tier objects and has to handle them directly. The resulting system diagram looks horribly like that shown in Figure 1.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=figure&gt;&lt;FONT face=Tahoma size=2&gt;Not only is this aesthetically displeasing, it illustrates that we have a tightly coupled system which is, as always, prone to error when things change. Changes to any of the middle tier components must be reflected in all of the Presentation Tier components that access them! &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=figurecaption&gt;&lt;EM&gt;&lt;FONT face=Arial size=2&gt;&lt;IMG src="/photos/andykramek/images/3166/original.aspx" border=0&gt;&lt;/FONT&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P class=figurecaption&gt;&lt;EM&gt;&lt;FONT face=Arial size=2&gt;Figure 1: Cross-Tier interactions can get messy!&lt;/FONT&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;By implementing a Façade the system becomes much simpler as shown in Figure 2.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=figure&gt;&lt;FONT size=2&gt;&lt;FONT face=Tahoma&gt;&amp;nbsp;&lt;IMG src="/photos/andykramek/images/3167/original.aspx" border=0&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=figurecaption&gt;&lt;EM&gt;&lt;FONT face=Arial size=2&gt;Figure 2: Cross Tier Interactions with a Façade Object&lt;/FONT&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Not only is this aesthetically more pleasing but, obviously this is a much more robust design. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Notice that the Presentation Tier objects no longer need detailed knowledge of the individual components of the middle tier. Instead they only need to know how to access the Façade object which is then responsible for controlling all further interactions within the middle tier. This achieves a weakly coupled state that, in turn, means that we can change things at will in the lower level sub-systems without needing to make corresponding changes elsewhere. Providing that the interface exposed by the façade object does not alter, then its internal facing methods are the only places that changes to lower level systems can ever affect. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=subhead2&gt;&lt;STRONG&gt;&lt;FONT face=Arial&gt;When should we use a Facade?&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT face=Tahoma size=2&gt;The purpose of the façade is to provide a simple interface to a complex system. Although most of the examples in pattern literature talk about ‘sub-systems’ you must remember that a design pattern is not dependent upon the implementation but on the design problem which it addresses. So while it is may not be very common for us, as FoxPro developers to build “complex sub-systems”, we often create complex objects which expose many methods in their interface! So whenever we find ourselves having to call multiple methods on the same object we really should be thinking in terms of implementing a façade. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;The usual scenario occurs when we have to run some multi-step process or calculation. Usually our first instinct is to add the relevant methods directly to the object (usually the form!) that requires them. When this gets messy we may provide a ‘control’ method to call the various steps in the correct order and to evaluate results and act accordingly. The resulting code looks something like this: &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=codefirstline&gt;&lt;STRONG&gt;&lt;FONT face="Courier New" size=2&gt;LPARAMETERS tuInval&lt;BR&gt;llStatus = This.CheckParameters( tuInval )&lt;BR&gt;IF llStatus&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;luResult = This.FirstStep( tuInval )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;IF VARTYPE( luResult ) = “N” AND NOT EMPTY( luResult )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;llStatus = This.SecondStep( luResult )&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ELSE&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;llStatus = .F.&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;ENDIF&lt;BR&gt;RETURN llStatus&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;This will work perfectly well, of course, until some other object requires access to the code. Now we have a problem. The next stage is to abstract the code from our form and create a stand-alone object, but now we have to make multiple calls to that object – and from more than one place in our application – sound familiar? It should, because this is precisely the scenario that the façade pattern addresses.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;Our object should not actually expose all of its methods, instead it should expose a façade consisting of just a few very simple methods which then call other methods internally as needed. By designing things this way we achieve several things:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bulletfirst&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;·&lt;/FONT&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;The code can be called from any object&lt;BR&gt;&lt;/FONT&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;·&lt;/FONT&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;The process detail is hidden, callers only need to know the exposed interface&lt;BR&gt;&lt;/FONT&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;·&lt;/FONT&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Changes to the implementation are confined to the façade object&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=subhead2&gt;&lt;STRONG&gt;&lt;FONT face=Arial&gt;How can we implement a façade?&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=firstparagraph&gt;&lt;FONT face=Tahoma size=2&gt;The example given here is for a converter class, defined in Visual FoxPro, that can be implemented directly as a VFP application object, or as a COM component. The interface for this object is extremely simple, and consists of just TWO methods:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bulletfirst&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;·&lt;/FONT&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;Convert&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Which expects three parameters, a value and the appropriate From/To codes. This method returns the converted value or an error code&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bulletfirst&gt;&lt;SPAN&gt;&lt;FONT size=2&gt;·&lt;/FONT&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT face=Tahoma size=2&gt;GetErrors&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;Interrogates the object’s errors collection and returns either a VFP Error Object or a COM exception, depending on how the object was instantiated&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;In fact the object has a number of methods which are defined as “Protected” so that they do not even appear in the COM interface, and can only be called internally. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=bodytext&gt;&lt;FONT face=Tahoma size=2&gt;The first thing that this method does, is to pass the received parameters through a validation method to ensure that they are of the correct (expected) data type. We are not concerned, at this point, if the values are meaningful, just that they are expected. Since this method is the only entry point, once we have checked the parameters, we can assume that they are correct in all other places because the only way that values can be sent to another method is from this, or a subordinate, method. This is an additional benefit of the façade! &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=codefirstline&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;*** First thing to do is to ensure we have From/To parameters&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;IF NOT .ValidateParam( tuConvFm, "C" ) OR EMPTY( tuConvTo ) &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcErrText = "Invalid 'From' Parameter" + CRLF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;ENDIF&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;IF NOT .ValidateParam( tuConvTo, "C" ) OR EMPTY( tuConvTo ) &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;lcErrText = lcErrText + "Invalid 'To' Parameter" + CRLF&amp;nbsp;&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;ST