Just a reminder that session proposals for Southwest Fox 2012 are due by 8 AM EDT this Friday, March 23. If you’re interested in speaking, please download the Call for Speakers and the proposal application from http://www.swfox.net/CallForSpeakers.aspx. We look forward to hearing from you.
Monday, March 19, 2012
Tuesday, March 06, 2012
Southwest Fox 2012
Save the dates for Southwest Fox and Southwest Xbase++ 2012! The conferences take place October 18-21, 2012.
This year we have two conferences as one great event at the same location. Southwest Fox has always served Visual FoxPro developers an opportunity to learn and extend their skills, and network with fellow developers. Alaska Software is working on PolarFox, a product that keeps the Visual FoxPro language alive in their next generation tool. You get two conferences for the price of one!
The conferences take place at the San Tan Elegante Conference and Reception Center, the same great location as last year.
If you’re interested in presenting at Southwest Fox 2012, please visit http://www.swfox.net/callforspeakers.aspx, read the complete Call for Speakers document (linked from that page), and download the proposal submission application. Session proposals are due by March 23.
Finally, if there are any topics you hope will be covered this year, please send them to info@swfox.net, right away.
Friday, February 10, 2012
Automatic Property Testing
Suppose you have a class that looks like this:
public class Person : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
private string _Phone;
public string Phone
{
get
{
return _Phone;
}
set
{
if (_Phone != value)
{
_Name = value;
OnPropertyChanged("Phone");
}
}
}
private string _Name;
public string Name
{
get
{
return _Name;
}
set
{
if (_Name != value)
{
_Name = value;
}
}
}
}
It’s a simple person class with Name and Phone properties. Because it implements INotifyPropertyChanged, the setter for every property should raise the PropertyChanged event. However, there are two bugs in this class:
- The setter for Phone sets _Name rather than _Phone.
- The developer forgot to raise PropertyChanged in the setter for Name.
We want to write some unit tests for this class. We need at least two tests for every property: one ensuring the value stored to the property is the one read from it and one ensuring that storing a value raises PropertyChanged. Here’s an example of the tests for Phone:
private string changedProperty;
public void PropertyChanged(object sender,
System.ComponentModel.PropertyChangedEventArgs e)
{
changedProperty = e.PropertyName;
}
[TestMethod()]
public void Phone_ValueTest()
{
Person target = new Person();
string expected = "555-555-5555";
target.Phone = expected;
string actual = target.Phone;
Assert.AreEqual(expected, actual);
}
[TestMethod()]
public void Phone_RaisesPropertyChanged()
{
Person target = new Person();
target.PropertyChanged += new
PropertyChangedEventHandler(PropertyChanged);
target.Phone = "555-555-5555";
string actual = changedProperty;
string expected = "Phone";
Assert.AreEqual(expected, actual);
}
As you can guess, it’s quickly going to get tedious writing these tests, especially if you have a lot of properties. Let’s automate this.
ClassTester is a project on CodePlex (http://classtester.codeplex.com) that automatically tests every property to ensure the value written is the value read and, if the class implements INotifyPropertyChanged, writing to the property raises PropertyChanged. Using ClassTester couldn’t be easier: replace all of the property test methods with this one simple method:
[TestMethod()]
public void AutomaticPropertyChangedTest()
{
PropertyTester tester = new PropertyTester(new Person());
tester.TestProperties();
}
Nice and (almost) generic: we can use this test forevery class; the only change we have to make is the name of the class to test.
When run, this test fails with the error “The get value of the 'Phone' property on the type 'AutomaticPropertyTesting.Person' did not equal the set value”. That points out the first bug, so we fix that by changing “_Name” to “_Phone” in the setter for Phone. (If this seems far-fetched, I actually ran into that today; the hazards of copy and paste coding!) Running the test again still gives a failure: “The property 'Name' on the type 'AutomaticPropertyTesting.Person' did not throw a PropertyChangedEvent”. Adding OnPropertyChanged(“Phone”) to the setter for Name doesn’t fix the problem; only the correct OnPropertyChanged(“Name”) allows the test to pass.
Let’s make the class a little more complex by adding an ID property that’s automatically set to a new Guid value when the class is instantiated. Note that the setter is private so only this class can change the value, such as when a person is loaded from a database, and that it doesn’t raise PropertyChanged because of this.
private Guid _id = Guid.NewGuid();public Guid ID
{
get
{
return _id;
}
private set
{
_id = value;
}
}
Now the test fails again: “The property 'ID' on the type 'AutomaticPropertyTesting.Person' did not throw a PropertyChangedEvent”. Fortunately, ClassTester has a mechanism to ignore certain properties: you can add this to the test method:
tester.IgnoredProperties.Add("ID");Of course, you’d have to do that for every property you don’t want automatically tested (not only for this reason, but some others described on the Codeplex site, such as when a property’s type is an interface or a class with a non-default constructor). That can get a little tedious too. So, I created a couple of classes to further automate this.
The first class is a new attribute:
public class DontAutomaticallyTestAttribute : Attribute {}
The second class is a façade for PropertyTester. What it brings to the table is automatically adding properties marked with the DontAutomaticallyTest attribute to the IgnoredProperties list.
public class PropertyTest
{
private object _toBeTested;
public PropertyTest(object toBeTested)
{
_toBeTested = toBeTested;
}
public void TestProperties()
{
PropertyTester tester = new PropertyTester(_toBeTested);
PropertyInfo[] props = _toBeTested.GetType().GetProperties(
BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in props)
{
if (DontTest(prop))
{
tester.IgnoredProperties.Add(prop.Name);
}
}
tester.TestProperties();
}
private bool DontTest(PropertyInfo property)
{
return property.GetCustomAttributes(
typeof(DontAutomaticallyTestAttribute), false).Length > 0;
}
}
Now you change the line of code in AutomaticPropertyChangedTest to use the new class:
PropertyTest tester = new PropertyTest(new Person());
and add the DontAutomaticallyTest attribute to those properties you don’t want automatically tested (you will write manual tests, won’t you?):
[DontAutomaticallyTest]
public Guid ID
Of course, you also have to add a reference to the project holding these two classes to both the project for your classes and your test project. However, for a couple of minutes work, you can now save tons of time creating tests for all the properties in your classes.
Sunday, February 05, 2012
Updating the VFPX ReportBuilder.APP
There are a couple of bugs in the VFP 9 Service Pack 2 version of ReportBuilder.APP, which provides the Report Designer dialogs and event handlers. I discussed the first bug, which causes the Printer Environment setting for a report to be turned on when you click the font button in the Field or Label Properties dialogs, in an earlier blog post. The other is a small one: using code like:
do (_reportbuilder) with 3, "TablePath.DBF"
to specify a custom registry table causes DELETED to be set off. The fix for this is simple: save the current setting of DELETED in FRXBuilder.PRG before setting it off and restore the setting near the end.
Several people suggested I actually implement these fixes in the copy of ReportBuilder.APP (and the corresponding source code) available on VFPX, so I did so today.
Thursday, December 08, 2011
Using Google Translate from VFP
Stonefield Query is a localizable application: all strings displayed to the user are stored in a resource file and we provide a resource editor that allows a developer to translate the strings into other languages. This means that someone has to do the translation into a particular language and keep it update to date when we release a new version, which as you can guess is a lot of work.
Inspired by Christof Wollenhaupt’s Googlefy Your Apps session at Southwest Fox 2011, I looked at using the Google Translate API to automate the translation process and allow us to translate into more languages than have currently been done. It actually turned out to be pretty easy.
First, you have to sign up for a Google account. The Translate API isn’t free but it isn’t very expensive: $20 for 1 million characters. After you’ve enabled the API, you’re assigned a key that has to be passed to the API on every call.
The API uses REST, which is a fancy of way of saying that the parameters are passed as part of a URL. Here’s an example:
https://www.googleapis.com/language/translate/v2?key=INSERT-YOUR-KEY&q=hello%20world&source=en&target=de
This tells the API to translate “hello world” (the encoded text in the “q” parameter) from English (“en” in the source parameter) to German (“de” in the target parameter). It returns the result as JSON:
{ "data": { "translations": [ { "translatedText": "Hallo Welt" } ] } }
To access the API from VFP code, use Craig Boyd’s VFPConnection library. Below is a function that does all the work. Pass it the text to translate and the source and target languages (spelled out, such as “English” and “German”) and it returns either the translated text if it succeeded, null if the language is invalid, or blank if the translation failed. This function supports all of the languages the Translate API supports. Note: replace the assignment to lcKey with your Google API key.
Automatic translation may not be quite as good as manual translation because it doesn’t necessarily use the same colloquialisms a native speaker would. However, it’s an excellent starting point; someone can use the Resource Editor to tweak any strings to the proper translation.
lparameters tcPhrase, ;
tcFromLanguage, ;
tcToLanguage
local lcKey, ;
lcPhrase, ;
lcFromLanguage, ;
lcToLanguage, ;
lcURL, ;
lcResult, ;
lcTranslate
* Specify the Google API key.
lcKey = 'PUT YOUR KEY HERE'
* HTML encode the phrase to translate.
lcPhrase = Encode(tcPhrase)
* Get the language codes.
lcFromLanguage = GetLanguage(tcFromLanguage)
if empty(lcFromLanguage)
return .NULL.
endif empty(lcFromLanguage)
lcToLanguage = GetLanguage(tcToLanguage)
if empty(lcToLanguage)
return .NULL.
endif empty(lcToLanguage)
* Set up VFPConnection.
set library to VFPConnection.FLL
* Call Google Translate and return the result.
lcURL = 'https://www.googleapis.com/language/translate/v2' + ;
'?key=' + lcKey + ;
'&q=' + lcPhrase + ;
'&source=' + lcFromLanguage + ;
'&target=' + lcToLanguage
lcResult = HTTPSToStr(lcURL)
lcTranslate = ''
if not empty(lcResult)
lcTranslate = strconv(strextract(lcResult, '"translatedText": "', '"'), 11)
endif not empty(lcResult)
return lcTranslate
function Encode(tcString)
local lcString
lcString = strtran(tcString, '<', '<')
lcString = strtran(lcString, '>', '>')
lcString = strtran(lcString, '"', '"')
lcString = strtran(lcString, '&', '&')
lcString = strtran(lcString, ' ', '%20')
lcString = strtran(lcString, '?', '%3F')
return lcString
procedure GetLanguage(tcLanguage)
local laLanguages[52, 2], ;
lnLanguage, ;
lcLanguage
laLanguages[ 1, 1] = 'Afrikaans'
laLanguages[ 1, 2] = 'af'
laLanguages[ 2, 1] = 'Albanian'
laLanguages[ 2, 2] = 'sq'
laLanguages[ 3, 1] = 'Arabic'
laLanguages[ 3, 2] = 'ar'
laLanguages[ 4, 1] = 'Belarusian'
laLanguages[ 4, 2] = 'be'
laLanguages[ 5, 1] = 'Bulgarian'
laLanguages[ 5, 2] = 'bg'
laLanguages[ 6, 1] = 'Catalan'
laLanguages[ 6, 2] = 'ca'
laLanguages[ 7, 1] = 'Chinese Simplified'
laLanguages[ 7, 2] = 'zh-CN'
laLanguages[ 8, 1] = 'Chinese Traditional'
laLanguages[ 8, 2] = 'zh-TW'
laLanguages[ 9, 1] = 'Croatian'
laLanguages[ 9, 2] = 'hr'
laLanguages[10, 1] = 'Czech'
laLanguages[10, 2] = 'cs'
laLanguages[11, 1] = 'Danish'
laLanguages[11, 2] = 'da'
laLanguages[12, 1] = 'Dutch'
laLanguages[12, 2] = 'nl'
laLanguages[13, 1] = 'English'
laLanguages[13, 2] = 'en'
laLanguages[14, 1] = 'Estonian'
laLanguages[14, 2] = 'et'
laLanguages[15, 1] = 'Filipino'
laLanguages[15, 2] = 'tl'
laLanguages[16, 1] = 'Finnish'
laLanguages[16, 2] = 'fi'
laLanguages[17, 1] = 'French'
laLanguages[17, 2] = 'fr'
laLanguages[18, 1] = 'Galician'
laLanguages[18, 2] = 'gl'
laLanguages[19, 1] = 'German'
laLanguages[19, 2] = 'de'
laLanguages[20, 1] = 'Greek'
laLanguages[20, 2] = 'el'
laLanguages[21, 1] = 'Hebrew'
laLanguages[21, 2] = 'iw'
laLanguages[22, 1] = 'Hindi'
laLanguages[22, 2] = 'hi'
laLanguages[23, 1] = 'Hungarian'
laLanguages[23, 2] = 'hu'
laLanguages[24, 1] = 'Icelandic'
laLanguages[24, 2] = 'is'
laLanguages[25, 1] = 'Indonesian'
laLanguages[25, 2] = 'id'
laLanguages[26, 1] = 'Irish'
laLanguages[26, 2] = 'ga'
laLanguages[27, 1] = 'Italian'
laLanguages[27, 2] = 'it'
laLanguages[28, 1] = 'Japanese'
laLanguages[28, 2] = 'ja'
laLanguages[29, 1] = 'Korean'
laLanguages[29, 2] = 'ko'
laLanguages[30, 1] = 'Latvian'
laLanguages[30, 2] = 'lv'
laLanguages[31, 1] = 'Lithuanian'
laLanguages[31, 2] = 'lt'
laLanguages[32, 1] = 'Macedonian'
laLanguages[32, 2] = 'mk'
laLanguages[33, 1] = 'Malay'
laLanguages[33, 2] = 'ms'
laLanguages[34, 1] = 'Maltese'
laLanguages[34, 2] = 'mt'
laLanguages[35, 1] = 'Norwegian'
laLanguages[35, 2] = 'no'
laLanguages[36, 1] = 'Persian'
laLanguages[36, 2] = 'fa'
laLanguages[37, 1] = 'Polish'
laLanguages[37, 2] = 'pl'
laLanguages[38, 1] = 'Portuguese'
laLanguages[38, 2] = 'pt'
laLanguages[39, 1] = 'Romanian'
laLanguages[39, 2] = 'ro'
laLanguages[40, 1] = 'Russian'
laLanguages[40, 2] = 'ru'
laLanguages[41, 1] = 'Serbian'
laLanguages[41, 2] = 'sr'
laLanguages[42, 1] = 'Slovak'
laLanguages[42, 2] = 'sk'
laLanguages[43, 1] = 'Slovenian'
laLanguages[43, 2] = 'sl'
laLanguages[44, 1] = 'Spanish'
laLanguages[44, 2] = 'es'
laLanguages[45, 1] = 'Swahili'
laLanguages[45, 2] = 'sw'
laLanguages[46, 1] = 'Swedish'
laLanguages[46, 2] = 'sv'
laLanguages[47, 1] = 'Thai'
laLanguages[47, 2] = 'th'
laLanguages[48, 1] = 'Turkish'
laLanguages[48, 2] = 'tr'
laLanguages[49, 1] = 'Ukrainian'
laLanguages[49, 2] = 'uk'
laLanguages[50, 1] = 'Vietnamese'
laLanguages[50, 2] = 'vi'
laLanguages[51, 1] = 'Welsh'
laLanguages[51, 2] = 'cy'
laLanguages[52, 1] = 'Yiddish'
laLanguages[52, 2] = 'yi'
lnLanguage = ascan(laLanguages, tcLanguage, -1, -1, 1, 15)
if lnLanguage > 0
lcLanguage = laLanguages[lnLanguage, 2]
else
lcLanguage = ''
endif lnLanguage > 0
return lcLanguage
Monday, December 05, 2011
Southwest Fox 2012
Southwest Fox 2011 was a great success. Now we’re trying to figure out what form next year’s event will take. You can help us by answering a few questions about your preferences. Please take the survey at https://www.surveymonkey.com/s/VCCKNDG, so we can include your input.
Whether you attended Southwest Fox this year, or it’s been a few years, or you never attended Southwest Fox, your input will really help us figure out what direction to take next year and in the years to come.
Tuesday, November 08, 2011
Southwest Fox 2011, Day 4
I planned on attending a couple of sessions Saturday morning, but ended up having a long chat with Toni Feltman and Steve Bodnar about .Net development, unit testing, version control, and other stuff. Again, this is one of the special things about conferences in general—discussions with other developers to help get a fresh perspective on things, solve problems, and spark new ideas—but especially SWFox: since we require all speakers to provide detailed white papers for their sessions, you still get the full benefit of all sessions whether you attend them or not. That makes the networking opportunities at SWFox even more valuable.
The one session I couldn’t miss, of course, was my own: the repeat of my ActiveX controls session. This time, I took special care to not miss any steps in my demo, so the attendees were cheated out of the opportunity to see a speaker squirm and learn from their mistakes. Sorry, guys!
The closing session was short but sweet. One of the things we discussed was 2012.
As many people suspected, this was a tough, scary year for us. By mid-August, we were in full panic mode, as we were so far below breakeven that it looked like a five-figure loss for us. Fortunately, a larger-than-usual number of people signed up after September 1; that combined with an increase in sponsorship this year took us over the top. However, we’re really concerned about next year: if the trend of decreasing attendance continues, 2012 could be a disaster.
So, one of the questions on our conference evaluation form was what type of format would attendees like for a future event: the traditional SWFox format, a less expensive “Code Camp” style (volunteer speakers, no food provided or perhaps sponsored food), an even less expensive one-track format (all sessions in a single room), etc. The reason for asking this question is to try to find out what we can do to minimize our risk. If we get the same number of people registered for 2012 as 2011 but they all register in June or July, there’s no panic and we can have the same format we’ve always had. But if the attendance goes down or people defer registration until fall like happened this year, we have to make adjustments so we don’t face an enormous loss. We don’t know what the answer to this is yet, but the takeaway from the closing session is that we did make a commitment to host an event in 2012.
Of course, asking people who paid a premium price to attend a premium conference doesn’t necessarily mean you’ll get the same answers as you do from those who didn’t attend for whatever reason. So, in the next month or so, we’re going to ask the community what kind of conference they’d like us to put on. When it comes time, please respond to the survey so we can get an accurate feel for what folks want us to do.
One other thing I’d ask: if you love SWFox like we do, and want to see it continue, do us a favor and register early next year. That would take out the panic for us and allow us to plan for the type of conference we really want to host.
I really felt that this was the best SWFox ever. The mood was upbeat, the sessions were amazing, the food was great, the conference center was wonderful … It wasn’t just me: I heard from lots of other people that they felt the same way.
The closing session ended with us giving away thousands of dollars in prizes provided by our sponsors, including some goodies like T-shirts that we threw into the audience (Tamar wisely counseled us against throwing the pins!).
After cleaning up the session rooms, we had lunch with Sharon, our main contact at the hotel and conference center, to do a post-mortem on the conference. We discussed the few things that didn’t work (Internet access and temperature control in the rooms) and the great number of things that did (dedication and hard work of the staff, the food, and the other things that make this a great venue). We also discussed some potential dates for next year.
After that meeting, Rick, Therese, Tamar, Marshal and I had our own meeting to talk a little about 2012, then met a few others (Bo Burban and his son and Steve Bodnar) for dinner. We went to Kona Grill, where Rick and I had some of the best sushi I’ve ever had.
Then it was time for the main event: the long-standing tradition of indoor go-kart racing. About 20 of us showed up at Octane Racing (formerly F1 Race Factory) to compete for the title of fastest racer. With Rick Strahl not driving this year, first place was up for grabs. I thought I did really well, but both Paul Mrozowski and my former employee Rob Eisler (just kidding, Rob!) beat me. In the second race, I finished behind Bo but ahead of Paul. See the Geeks & Gurus Facebook page for photos.
We got back to the hotel by about 11:30, too jazzed up to call it a night yet. Besides, there was still two jumbo bottles of champagne to drink. Which we, of course, did, sitting around the pool. I finally called it a night at about 1:30.
Sunday was kind of anti-climatic, as usual: a nice breakfast with the Schummers and Granors followed by a long day of travel home. I slept almost the entire flight from Phoenix to Minneapolis, something I rarely do.
Thanks to everyone who came to SWFox and made it the best one ever. We’ll see you next year for sure!
Southwest Fox 2011, Day 3
After breakfast, I presented my session on creating ActiveX controls for VFP using .Net. This was a fun session to do because it shows some cool techniques for greatly expanding the list of controls available to VFP applications. This session is pretty complex, so I started by suggesting folks not worry about the details (the white paper has cookbook-like instructions) but focus more on the overview. The session has a lot of complex steps, and sure enough, I missed a step a couple of times and got myself into a little demo trouble. I figured out the first one myself but thank goodness Paul Mrozowski was there to point out the problem with the second one. The audience was very gracious with my gaffes, and someone even pointed out later that they were glad I’d done that so they could see what to do if they missed a step. Of course, I planned that!
I next went to see Kevin Ragsdale’s UI session. I was a little late because, as usual, I was chatting with folks between sessions. Wow, another great session by Kevin. He showed some UI problems common to VFP applications and then showed how to fix them, resulting in a more comprehensible and easier-to-use application. I have a strong feeling I’ll be handing the Best Speaker trophy to Kevin at next year’s conference.
I then went to see Jim Nelson’s session on Thor. If you haven’t seen Thor, a new VFPX project, you’re missing a huge productivity boost in your development efforts. Thor provides a framework for IDE tools, but even more importantly, provides a huge set of such tools to do things such as rename objects, change base classes, and go to the definition of a class, method, procedure, or constant. Jim did a nice job of showing how to install Thor, how the UI works, how some of the included tools work, and how to add your own tools to Thor.
After a nice lunch of hamburgers and hotdogs with all the fixings, I went to Rick Borup’s session on Mercurial. I don’t think Rick knows this, but we call him “The Professor” because his sessions are incredibly well-researched, prepared, and presented. I was thinking later on about how I would’ve done this session and I wouldn’t have done half as well as he did. I’ve been using Mercurial for about six months so I went to this session hoping to have some gaps filled and wasn’t disappointed. Afterward, Toni Feltman expressed amazement that I was finally using a version control system, because she’s been after me for years about it. I think Rick also inspired Tamar to give Mercurial a shot.
Next up was the repeat of my Windows 7 session. Like the first session, I spent some time going over why virtualization (a misnamed term: it refers to redirecting reads and writes to protected locations to “virtual stores” rather than virtual machines as the term is commonly known today) is bad for your health. This led to one of the most gratifying parts of the conference: helping someone resolve a problem. Steve Bodnar mentioned to me after the session that he had a huge problem with a customer system crashing whenever they tried to output to PDF. He suspected the FFC Report Listener class library had somehow become corrupted but replacing it with a fresh version didn’t resolve the problem. During my discussion of virtualization, he realized that it wasn’t the FFC version of the library that was corrupted but the virtualized copy. Sure enough, as soon as he deleted the copy, the application worked as expected. Steve was so happy he Tweeted that he was going to kiss me full on the lips, so I ducked him the rest of the day and evening (just kidding, Steve).
I was beat, so rather than attending a session during the last timeslot of the day, I hung out at the Servoy booth drinking wine with Yvo Boom and Jon Madden of Servoy, Ken Levy, Chick Bornheim of MicroMega, and Chick’s friend Gary, who was attending his first SWFox.
Next it was time for the conference dinner party. Last year, we’d planned on holding the party out on the veranda but a sudden dust storm forced us to quickly move indoors. Fortunately, the weather was in our favor this year, and the dinner was magnificent: superb food and a really nice dark atmosphere. (I would’ve called it “romantic” except my wife wasn’t there and I don’t think Walt Krzystek and the guys from Matrix would’ve appreciated my expressing that point of view.)
At 8:30, the bonus sessions started. I attended the Show Us Your Apps session, which featured six VFP developers showing the crowd an application they’ve developed that they’re proud of. And proud they should be—there were some very cool apps and techniques on display! I was especially impressed by the fact that for several of the presenters, English was not their native language. It takes a lot of courage to get up and speak before a group of technical people, but even more so in a foreign language! Kudos to all those who took the time to show us what VFP is capable of.
The other bonus session was for independent developers, an idea that Rick Borup came up with a few months ago. I heard a lot of great comments about this session, so we may have to do it again next year.
We once again ended up at the hotel bar, this time enjoying some of the leftover cake and champagne from last night’s celebration.
Southwest Fox 2011, Day 2
Thursday started at my usual time of 5 am. After setting out sign boards for the session rooms and registering a few newly-arrived attendees, I had breakfast and went to the first session, Eric Selje’s Lightswitch for VFP Developers. Eric did a great job explaining what Lightswitch is (a tool for rapidly developing Silverlight applications) and showing the basics of developing a Lightswitch application.
I was going to go to Steve Bodnar’s jQueryUI session next but ended up chatting with a couple of the new exhibitors, Basis and Alpha Five, about their products. Fortunately, I’d seen Steve present this session in January. In fact, his presentation inspired me to add new features to the SWFox web site, including the menu and the accordion control on the session pages.
My Developing VFP Applications for Windows 7 session was next. The first half of the session was similar to the Windows Vista session I presented four years earlier, but updated for Windows 7 and with more things I’ve learned about Windows security and virtualization since then. The second half focused on how to implement Windows 7 features in your VFP application, especially related to the Windows 7 Taskbar. I showed how I’ve implemented these features in a real-world application (Stonefield Query) using Steve Ellenoff’s Win7TLib VFPX project, including the actual code to implement those features.
After a very tasty lunch (the food at the Legado is so good, several people commented on Twitter recently about how much weight they gained!), I went to Steve Black’s Looking Back session. Although I don’t work on the type of applications Steve does, it was still interesting hearing his perspective on software development and process management techniques.
At every conference, a common phrase you’ll hear is “that session (or tip) paid for my conference”. Last year, it was Steve Ellenoff’s Win7TLib session for me. This year, it was Kevin Ragsdale’s Easy Multi-Threading session. Kevin is a great speaker: funny, great examples, and well-paced. He showed how to use a DLL created by Christof Wollenhaupt to add multi-threading to VFP applications. Like Steve’s session last year, my mind was abuzz with ideas about where in my applications I can make use of this technique. I know others felt the same way because that was a major point of discussion at every meal I had for the rest of the conference, and even on the taxi ride back to the airport on Sunday. You know you struck a chord when someone as advanced as Rick Strahl is inspired!
By a very happy coincidence, Jody Meyer’s session on ParallelFox immediately followed Kevin’s session. ParallelFox uses a different technique—out-of-process EXE servers rather than in-process COM objects—but has a similar purpose: allowing multiple tasks to be performed simultaneously to take advantage of multi-core processors common in today’s computers. The combination of these two techniques was on everyone’s mind and I saw a lot of very excited people after seeing these two sessions.
The speaker dinner was Thursday night. It’s our small way of thanking the speakers for the enormous amount of time and effort they put into preparing sessions and white papers. As Tamar pointed out at both the keynote and closing sessions, without them, there would be no conference. I had the pleasure of sitting with Rick Borup and his wife, Eric Selje, Menachem Bazian, Steve Ellenoff, and Kevin Ragsdale. Kevin was uncharacteristically quiet; I think he was still in a daze after the dynamite presentation he did in the afternoon. Menachem and Steve were like a tag-team comedy duo; rumor has it they’ll be playing Vegas soon. The food at the Gordon Biersch Brewery at the San Tan Mall was outstanding, as was the hand-crafted beer I tried. Good company, good food, good times.
As usual, we headed back to the hotel bar. Toni Feltman had planned an informal party to celebrate Cathy Pountney marrying Jim Knight this summer. However, she also found out that Alan Griver had recently married Allie (hope that’s the correct spelling) so she quickly picked up a second cake. There was tons of champagne and apple cider to celebrate with. I had an 8:30 session to present in the morning so I headed up just before midnight.
Southwest Fox 2011, Days 0 and 1
I was up early on Tuesday, October 25, to catch a 7:00 am flight to Phoenix. Rick Schummer’s wife Therese picked up Rob Eisler, a co-worker, and me at the airport and we met Rick at the hotel to start assembling conference bags. Normally we arrive on Tuesday when the conference starts on Thursday, but with it starting on Wednesday this year, we’re actually a day later because, in our fifth year of hosting this conference, we’ve got the preparation down to a science. Tamar and Marshal Granor arrived a little later, and we all met with the conference center staff late in the afternoon to finalize preparations. After setting up projectors and power strips in the session rooms, we went out for dinner at Brio, a nice Italian restaurant at the nearby San Tan Mall, then came back to the hotel and hung out in the bar for a while with some friends.
Wednesday morning, I was up at my usual 6 am, only I was in Phoenix, so that made it 5 am. That way pretty much the way the conference went: up really early and to bed late. Definitely in full conference mode. After getting the registration room set up, we were open for business at 8:00. Registration is always a fun time, because it’s a chance to see old friends again and put faces to the names of new attendees. Pre-conference sessions started at 9:00 so we were fairly busy until then. During quiet periods, I chatted with Rick, Tamar, and people coming to register, and catch up on email. During lunch, I had a chance to meet Dimiter from Bulgaria and talk about software development and the economy in his country. To me, that’s one of the best things about going to a conference: meeting new people and finding out what they do and where they’re from, as well as renewing and strengthening friendships.
The afternoon was similar to the morning: greeting attendees as they came to register and chatting with folks. I had a long chat with Ken Levy about a variety of things, including the fact that he and Randy Brown thought it was a surprise than Randy was coming to SWFox, but in fact Rick had already made up a badge for Randy because he saw his name on the hotel room list. Rick, Tamar, and I also finalized who was going to do what in the keynote that evening.
After the pre-con sessions ended, we held a short speaker meeting to go over logistics with everyone. This also gave us a chance to meet the new guy, Tuvia Vinitsky, and for everyone to say hi to Steven Black, who hasn’t been a SWFox for several years. (Sorry we didn’t give you a chance to say hi to everyone before we started, Steve, but we were on a tight schedule.)
Tamar, Marshal, Therese, and I went to Paradise Café at the San Tan Mall for a quick dinner because we had to be back before 7:00 for the keynote. Rick, as usual, did not accompany us because he can’t eat before the conference starts.
We had a few surprises at the keynote this year. First, we awarded the VFPX Administrators’ Award to Joel Leach for his work with FoxTabs and ParallelFox. This turned out to be fortuitous, because ParallelFox ended up being a huge part of SWFox this year. The second surprise was the announcements of the 2011 FoxPro Lifetime Achievement Award recipients. I almost blew the surprise for this: during the setup, while there were fortunately a small number of people in the room, I connected my laptop to the projector and navigated to the folder where the keynote PowerPoint presentation was located. In that same folder were photos of Drew Speedie, Steven Black, and Toni Feltman, and it wouldn’t take a rocket scientist to figure out why. I was horrified when I realized that (shades of the infamous “Babe of the Day” incident from years past) and quickly pulled the plug before anyone else saw the evidence on the big screen.
Our part of the keynote went smoothly and quickly. We then introduce Steve to do the keynote presentation on Niche Marketing. What a bang-up job did! I suspect many attendees had never heard Steve speak before and were blown away by his session. That’s OK: the rest of us were too. I heard attendees talk about his session for the rest of the conference.
After the keynote, we held a reception in the trade show area. It looked like the exhibitors had their hands full with all of the attendees coming to find out about their products. I had a great chat with Frank Perez and Paul Mrozowski over a few Coronas.
After the reception closed, many people headed to the hotel bar. I had a fun time catching up with Phil Feltman and reliving the good times of past conferences. Joel Leach said his face hurt from laughing so much.
I hit the bed about midnight and took all of 4 seconds to fall asleep.