[ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ]

Appendices

Appendix A:
A short but pertinent digression

Colin and I have been using a strategy that seems to work very well for different types of clients: we design our applications as out-of-process (EXE) COM objects, but also give them a command-line usage. This strategy does not have to be adjusted or re-implemented for each application. For example, we typically allow only one command line argument, and it always does the same thing.

The command line argument is a filename. We stipulate that the format of this file is a set of lines in the format property = value. The main program associated with EXE does the following:


    * instantiates the COM object
    * invokes the COM object’s .LoadFile method , passing it this argument
    * invokes the COM object’s .Run or .Execute method.

Internally, the .LoadFile method simply validates the filename and converts the contents of a file to a string, which it sends to a .LoadString method.

The .LoadString method goes line by line (normalizing whitespace, and using CRs, CRLFs, or LFs as line terminators) through the string:

    * check each line for a potential property=value statement.
    * subject each possible property to a PEMSTATUS() test
    * if appropriate, STORE a type-transformed version of the value to
    (“THIS.”+ property).

One beauty of this system is that the .Run, .LoadString, and .LoadFile methods are also available to the COM object. By calling.LoadFile or .LoadString – whichever suits you – followed by .Run, a COM client can make efficient use of a VFP server, with the fewest possible number of COM calls. This is great for performance reasons as well as giving consistent functionality between your command-line and COM clients.

We find that some early binding versus late binding COM clients have different needs with regard to passing Fox parameters. Some client environments must pass the arguments (no argument can be optional), others have difficulty with methods that require arguments (all arguments must be optional).

With strong typing in VFP 7, this problem may be somewhat alleviated. To date, however, to serve these differently-abled clients equally, we usually have something like a .cParameter property. If an exposed method such as .LoadString expects an argument and does not receive it, it looks to this property for an alternate source of the required information. A client that has trouble passing VFP parameters uses this property.

Although it is true that not every system has a single process easily defined, to be invoked by a .Run or .Execute call, this is usually solved with an “action” property the client can set, like any other, in the set of properties processed by .LoadString.

I highly recommend this practice. I guess it has nothing explicitly to do with XML, on the face of it! However, it is all part of giving equal access to different types of clients, creates efficient COM applications, and works very well with XML-enabled applications in general.

Appendix B:
A sneak preview of new Coverage engine PEMs in VFP7

Stack XML enhancements to Coverage in VFP7 include the following new PEMs for the cov_engine class in COVERAGE.VCX. They are shown here with the PEM descriptions added to each member as part of the VCX, with a little extra explanation in some cases. Note: cov_standard (the interface class) was not touched in this enhancement.
.cSavedStackXML

Holds the name of the saved Coverage stacklevel analysis in XML form, after this file has been saved to disk. Set back to default ("") when you load a new log.

.lStackXMLExtendedTree

If .T., generates more extensive StackXML, so Profiling of each branch can assess effects of args and other factors for different invocations of a module. Defaults to .F. but if COV_LOAD_STACK_FROM_DBF is .T., this more extensive XML is always gen'd.

.ShowStackXML(tcLog)

Calls GetStackXML(tcLog) and DisplayStackXML(tcXMLFile) to run coverage analysis figures against a specific VFP project set of files. tcLog argument ignored if DEFINEd COV_LOAD_STACK_FROM_DBF is .T. Returns .T. if successful.
(like ShowProjectStatisics)

.GetStackXML(tcLog)

Generates Stack Analysis XML from tcLog, defaulting to current Coverage source log. tcLog argument ignored if DEFINEd COV_LOAD_STACK_FROM_DBF is .T. Returns .T. if successful.
(like GetProjectStatistics, this is the one that does the real work)

.DisplayStackXML(tcXMLFile)

Displays XML file, defaulting to the current Stack Analysis filename indicated by the cSavedStackXML property. Returns .T. if no error occurs.
(like DisplayProjectStatistics, except that, instead of being abstract in the engine, cov_engine.DisplayStackXML does a ShellExecuteA)

.ToggleStackXMLExtendedTree()

Toggles .lStackXMLExtendedTree. Designed to be augmented in subclasses to reflect this switch in the UI, change default XSLT on this basis, etc. Returns .T. if no error occurs.
(like ToggleCoverageProfileMode)

.cStackXSLT

Holds filename providing default XSL Transformation stylesheet to be applied by default to the generated Stack XML analysis document, when TransformStackXML is called.

.TransformStackXML(tcXSLT, tcXMLIn, tcXMLOut, tlNoShow)

Applies tcXSLT (default to .cStackXSLT) to tcXMLIn (default .cSavedStackXML, GetStackXML called if empty). Saves result to tcXMLOut (defaults to tcXMLIn-based generated name w/ HTM ext). If ! tlNoShow, calls DisplayStackXML. Returns .T. if successful.

Additional Coverage changes in VFP 7 not shown here to support this enhancement include various existing methods updated to account for the new Stack piece. For example, cov_engine.Init(..) has been adjusted to call GetStackXML() if the engine is instantiated in unattended mode, along with creating and saving the target dbf and skipped files dbf.

Interface changes in the COV_OPTIONSDIALOG class (see figure) and COV_LOCS.H localization message file as well as the shortcut menu expose the Stack features.

New bottom section of Coverage Options dialog allows you to set Stack options and defaults.

New tune-able options in COV_TUNE.H to support the Stack feature include the following:
* the first two represent element node prefixes
#DEFINE COV_STACKROOT "VFPCallStackLog"
#DEFINE COV_STACK_ONEVENT_TAG event
* the next items are used to help identify the XML and HTM files written
* to disk as being generated from this particular process.
#DEFINE COV_STACKXML_SUFFIX "_STACK"
#DEFINE COV_STACKXMLEXT_SUFFIX "_STACKX"
#DEFINE COV_TRANSFORM_SUFFIX "_XSL"
* the next item indicates whether lines are loaded from the Coverage
* source workfile dbf or gathered directly by reading the original
* text log. The former has a very slight speed advantage but will
* not include ON... events, since those lines are ignored by Cov workfiles
#DEFINE COV_LOAD_STACK_FROM_DBF .F.
* the vars in the next item have the same meaning as the columns of the
* same name in the Coverage source workfile DBF -- equivalents for these
* items are read in from the source text log when COV_LOAD_STACK_FROM_DBF
* is .F.,and this expression stays the same. You can change it as long as
* you ensure that the result will never be empty except for ON... events.
* Load a log into COVERAGE.APP, SET DATASESSION TO _oCoverage.DataSessionID,
* and refer to the source workfile (by default, its alias is FromLog) for
* some indication on the possible contents of these columns.
#DEFINE COV_STACKEXPR ALLTR(IIF(INLIST(FileType,".fxp",".mpx",".qpx",".spx"), ;
IIF(EMPTY(ObjClass),IF(NOT EMPTY(Executing),ALLTR(Executing),""),;
IIF(LEFT(Executing,1)=".",ALLTR(ObjClass),"")+ALLTR(Executing)), ;
ALLTR(Executing)))
 

[ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ]