So I direct my query to you VFP consultants in Foxite land: What are the common coding practices that newbies make that I should avoid to make your consulting life easier?Look for PatternsMuch has been said, elsewhere and by better qualified people than me, about Patterns. For the moment let me leave it by saying that Design Patterns can be just as relevant in the context of designing classes as they are to application design. When designing your own classes it is important to look for patterns in your requirements so that your classes themselves can reflect the patterns that you will use when they are deployed. Probably the best reference for getting to grips with Design Patterns is: “Design Patterns – Elements of Reusable Object Oriented Software” by Gamma, Helm, Johnson and Vlissides (Published by Addison Wesley, ISBN 0-201-63361-2)
Code in Methods, not EventsWhen coding your classes avoid placing code directly in native Visual FoxPro events. Instead, create custom methods and call those from your events. There is, admittedly, no requirement to do things this way, but it will make your life easier for (yet again) three reasons.
• It allows you to give meaningful names to your method code. This may sound trivial, but it really does make maintenance easier when code that produces output is called by ‘This.GenerateOutput()’ rather than ‘Thisform.Pageframe1.Page1.CmdButton1.Click()’
• It allows you change the interface, if necessary, by simply re-locating the single line of code which calls the method instead of having to cut and paste functional code.
• It allows you to break complex code up into multiple, (and potentially re-usable) methods. The Event method then acts merely as the initiator and controller for calling the associated code.
Beware of putting functionality too high in the class hierarchyThis is a trap that I have fallen into many times over the years and still occasionally stub my toe on. You will generally know when you have placed functionality too high because you will spend a lot of time in you subclasses trying to over-ride all the great functionality that you put in the root class. Let me give you an example of how not to do it from bitter personal experience.
I once had a method called SetInputMask() as a method in my root textbox class. It seemed to me that I wanted all my text boxes to have such functionality. This method, called from the text box’s Init(), looked at the ControlSource of the text box and used it to construct an InputMask for the control if one was not specified. It seemed like a good idea at the time because it would eliminate numeric overflow errors that would occur when an InputMask was not supplied for bound numeric fields. It would also stop endless support calls from my end users asking me why, when they typed “Supercalifragilisticexpialidotious” into a text box on the form, all that got saved was “Supercalifragilistic”.
So what was wrong with this idea? The answer is that this behavior did not belong in the root class text box. It was too high in the hierarchy. You can just imagine what happened the first time I dropped one of my custom textboxes into a grid column whose ControlSource was:
( IIF( MyRecordSource.MyField, ‘Yes’, ‘No’ ) )
The form blew up! It would have been a simple matter to set an InputMask for the column and its contained text box, but why should I have to? Each time a form with a grid blew up and I had to go back and determine the reason why and then set an InputMask cost several valuable minutes of my time. A much better idea would have been to have SetInputMask as a custom method of a subclass of my root class text box.
Had I applied the “Must, Could, Should” rule to this situation, it never would have happened. Placing code too high in the class hierarchy is probably the most frequent trap that we all, as developers, fall into. At least I know that it has been the bane of my existence.
Methods should do one thing and one thing onlyMethods that do “everything” are difficult to reuse. Remember this: “a single line of code is always reusable”. If I have to hit PAGE DOWN more than once to view my method code, the method is probably too long and trying to do too many things. The solution is to break the monolithic method up into smaller, better focused, methods and use a control method to call them individually.
Use template methods for a consistent interfaceI stated earlier that we need to avoid placing functionality too high in the hierarchy. However, this doesn’t mean that we shouldn’t define template methods in our root class. These empty methods at the highest level of the hierarchy ensure that all subclasses share the same interface. As long as sub-classes share a common interface, they are interchangeable.
Defining a common interface for subclasses by using template methods in the root class will not hurt anything. Remember, all Visual FoxPro methods return .T. even when they contain no code. Defining the entire interface in the root class makes it much easier to program to interface rather than implementation.
Regards,
Marcia G. Akins
Tightline Computers, Inc.