====================================== FoxPro Developers Network of San Diego ====================================== FoxDev TipsLetter #99-4 APRIL 28, 1999 Website: Editor: ---------------------------------------------------------------------- CONTENTS: * Calendar * More About the May Meeting * Erratum Dan Covill * Peter Butterfield's Framework Art Bergquist * Tech Tips: Sub-classing Grid Components Dan Freeman More on Rushmore Navigation Bill Heitstuman VFP 6 Threading Problem Steve Settimi * Other Stuff: Consulting Solutions Group * Administrivia ====================================================================== CALENDAR: May 5 Tim Daly, one of our new members will show us a VFP6 7:00 pm Network Management System which he developed. June 2 Eric Lendvai will talk about Builders. July 7 Barbara Peisch will report on what happened at DEVCON Meetings are at 6450 Lusk Blvd (NOT 6540), in the PS business center. From the Lusk Blvd driveway, go straight back to the furthest corner of the rear bldg and park. The conference room is upstairs over the Fitness Center. The meeting is at 7:00 pm. ====================================================================== MORE ABOUT THE MAY MEETING Tim Daly's application is deployed on an intranet as an active document. A navigational tool displays a small map of the United States with all of the network elements (nodes) plotted on it. The user clicks on the map at a desired location and a small red rectangle encloses the area which is displayed on the rest of the screen. The nodes and the links between them are laid out on the screen, and the user may click on any item to get detail. Some technical hurdles and solutions: When several links (line objects) overlap, how do you determine which link the user is selecting? How do you display the nodes when they span such a large area like the United States? How is navigation through the network accomplished? How was the application deployed on the intranet? Come to the meeting and find out. ---------------------------------------------------------------------- ERRATUM In last month's review of Bill Heitstuman's Solutions Framework, I got an attack of the stupids while describing Bill's neat trick. I said: "We asked how he could optimize "goto bottom" using a filter. Bill's simple answer; set order to _descending_ and "goto top"!" Well, of course, that doesn't work, and it's not what he said, either! Bill kindly pointed that out, with the corrected statement: "We asked how he could optimize "goto bottom" using a filter. Bill's simple answer; Switch the order direction (ie. Asc to Desc), issue a Locate command, switch order direction back again." Mea culpa! Dan Covill, (sloppy) editor ---------------------------------------------------------------------- Peter Butterfield's Framework by Art Bergquist On April 9, we had a special Friday meeting of the FoxPro Developers Network of San Diego. Peter Butterfield came down from Los Angeles to share, with the small group of developers assembled, various insights about his (latest) application framework. Peter first summarized for us the benefits of OOP: - testability - re-usability - scalability - maintainability - encapsulation Above all else, Peter wants you to understand that the key to a good framework is a balance between (1) minimal coupling and (2) maximum utility. The tighter the coupling, the more the opportunity for introducing bugs when maintaining code; we therefore want the least coupling possible to maximize the "bug-free"ness of our code (my term, not Peter's). He indicated that global variables are the most flagrant (ergo, tightest) coupling. In a 2-tier model, there is tight coupling between the UI and the Business Rules that reside on the front-end. A 3-tier model, on the other hand, "decouples" the business rules from the UI by placing that application logic in the middle tier (the UI remaining on the front-end and the data on the back-end). Peter then showed us parts of his "user-interface" framework, so named because it is more of a textbook example rather than a complete application framework (as are commercially available). In his framework, he separates (decouples) the navigation toolbar from his forms. One nice tip that Peter made during his presentation was that each object should have a SUSPEND method. This will enable you to interrogate an object's protected properties from the Watch window. Let me demonstrate. Peter created a sample program called (very appropriately) SAMPLE.PRG: DEFINE CLASS MyClass AS Line PROTECTED x1, x2, x3 x1 = 1 x2 = 2 x3 = 3 FUNCTION Suspend SUSPEND ENDFUNC ENDDEFINE From the Command Window, he then issued the following commands: oa = NewObject('MyClass', 'sample.prg') oa.Suspend() In the Watch window, he then typed in the following three (3) properties: oa.x1 oa.x2 oa.x3 which responded with the three (3) following values respectively: 1 2 3 Alternatively, you can type the following three (3) lines in the Command Window: ?oa.x1 ?oa.x2 ?oa.x3 and you will see the aforementioned three (3) values displayed in the active window. Peter rounded out his presentation with an impressive display of the power of a collection class he has developed. ====================================================================== TIPS ====================================================================== SUBCLASSING GRID COMPONENTS by Dan Freeman (You Can Do That!) Midwest Fox Pros User Group A frequently asked question online is how to subclass grid components. For example, you may want a header that responds to a click event in a particular way. You can copy/paste code into each header's click methods at design time, but this approach is hardly taking advantage of the inheritance model. Another disadvantage is that you can no longer rely on a grid's ability to unfurl itself at runtime, automatically providing the right number of columns for the underlying data source. If you're goint to put code in each header, you have to hard-code the number of columns in the grid. This problem is made more thorny by the fact that the visual class designer does not support grid components (columns or headers), or many other components of container classes (page frames, option groups, command groups). Still, Header is one of FoxPro's base classes and can be subclassed like any other - you just can't create your subclass visually. You must do it in code, using something like the following: DEFINE CLASS MyHeader AS Header PROCEDURE click WAIT WINDOW NOWAIT this.parent.name ; + " " + this.name + " Click" ENDPROC ENDDEFINE The only problem now is finding a way to use this class in your grid at runtime. For that, we'll take advantage of the grid's 'containership model'. Remember that the grid is a container which can only contain Columns. Columns, in turn, are containers too. Like every other container object in FoxPro, grids contain an internal collection that provides references to each column and a count property to find out how many columns there are as well as AddObject() and RemoveObject() methods. So, if we're not happy about the default header that Visual FoxPro gives us, we can just remove the existing header and add one of our own making! The VFP 5/6 code would look something like this in the grid's INIT() method: FOR EACH loColumn IN this.columns WITH loColumn .RemoveObject("Header1") .AddObject("Header1", "MyHeader") ENDWITH ENDFOR This works even when we're relying on the column to unfurl itself because of the way FoxPro builds containers inside out. Each of the controls in a column is constructedc, followed by the column itself, and finally the grid is constructed after all the columns have finished. (This code assumes that the class MyHeader exists in a program file you installed with SET PROCEDURE TO.) For VFP3, the "for each" construct doesn't exist, so use this instead: FOR lnCount = 1 to this.ColumnCount WITH this.Columns[lnCount] .RemoveObject("Header1") .AddObject("Header1", "MyHeader") ENDWITH ENDFOR In both cases, I've used the WITH/ENDWITH construct, because chances are good that I'll want to "remember" some of the properties of the existing header (font, caption, alignment, etc.) and set the new header to match. As you make more and more references to any objects, WITH/ENDWITH will improve performance because Visual FoxPro only needs to fetch the object reference once. This technique works equally well with grid columns, option buttons, pages in a page frame, and command groups, although each has its own bit of strange behavior. (from Fox Prose, newsletter of the Atlanta FoxPro Users Group) [Editor's note: I've been doing my header diddling with a builder, based on Miriam Liskin's articles in FoxPro Advisor. I think this way looks cleaner, but haven't tried it yet. The problem I see is that you're building all these objects twice at run time. Oh well, VFP is only supposed to be fast on data! DC] ---------------------------------------------------------------------- MORE ON RUSHMORE NAVIGATION Bill Heitstuman Here is some sample code for Rushmore-optimized navigating. Moving to the last record (with or without a filter): * Reverse Direction Select "Customers" If "Desc" $ Set("Order") Then Set Order To Order() Ascending Else Set Order To Order() Descending EndIf * Find First Record (Actually Last) Locate * Reset Direction If "Desc" $ Set("Order") Then Set Order To Order() Ascending Else Set Order To Order() Descending EndIf This Code will move to the last record in a filtered or unfiltered cursor. If the filtered fields have been indexed, the last records will be found almost immediately. In addition, if you use the continue commands for 'Next' and 'Previous' navigation it will enhance performance greatly. All of these enhancements can be found in the FoxSolutions framework. [Editor's note: Did you know you could put "then" on an if statement? I didn't. Thanks again, Bill. DC] ---------------------------------------------------------------------- VFP 6.0 THREADING PROBLEM by Steve Settimi Taken from Rick Stahl's new book, "Internet Applications with Visual FoxPro 6.0" "....VFP 6 unlike VFP 5.0 does support Apartment Model Threading, but it blocks access to the same server while another call to that same server is executing. The server is blocked at the component level which means that the components actually start up on a new thread, but have to wait for a blocking lock to clear before it can enter the processing code. What this means is that if two users are hitting a page that uses the same COM server (remember a server can contain multiple objects) the requests will queue up one after the other. If you have a 10 second and 1 second request following it the 1 second request may have to wait up to 11 seconds to get its result returned. That's very limiting for an Active Server Page or any other multi-threaded client on a busy Web server that may have hundreds or even thousands of simultaneously active users! An interim release to the rescue: This blocking behavior is addressed in a forthcoming interim release of Visual FoxPro (release date unknown at this time, but expected in early 1999). This release provides a new multi-threaded runtime that handles thread isolation and does not block simultaneous method calls. I'm currently using an early beta version of this release and it's possible to get unlimited instances of your server to fire up simultaneously. ..." ====================================================================== OTHER STUFF ====================================================================== SOLUTIONS CONSULTING GROUP Solutions Consulting Group, at 6540 Lusk Blvd, is the host for our meetings. But who are they, and what do they do? "Since its inception in 1993, Solutions Consulting Group has grown to more than 40 employees with over 65 active clients throughout Southern California. We are a Microsoft Certified Solution Provider Partner and a member of the Oracle Business Alliance Program." They do: Corporate Application Development Data Warehousing Network Services They work in FoxPro, VFP, VB, Access, SQL, and Oracle. They are looking for more employees and they do use contractors as well; contact Armando Andrade at if you're interested. For More Information... --------------------------Administrivia------------------------------- This newsletter is a service to members of the FoxPro Developers Network of San Diego (FPDN). The editor (Dan Covill) is solely responsible for the content, Barbara Peisch does the distribution. E-mail the editor YOUR tips, comments, complaints, and rebuttals. Editor: Dan Covill 619-272-2448 Board of Directors: Eric Lendvai - President 760-439-6617 Art Bergquist - Vice Pres 760-740-0428 Claude Nikula - Secretary 619-615-6318 Barbara Peisch - Treasurer 760-729-9607 Randy Barber - Director 619-670-7542 Steve Settimi - Director 619-262-5883 ----------------------------------------------------------------------