VFP's BASICS (Part 1)

Version: 1.00.21 - Last Update: Sunday, August 31, 2014 (updated the links to other blog posts)

Previous EntryBasics Home Basics (Part 2)


This thread is all about OOP BASICS

OOP Basics with VFPLatest additions are marked with a Added/Modified ... sign

Please notice: This is a work in progress!

I made the experience that many smart VFP guys out there don't know the whole OOP-story. I mean, they are pretty good in creating powerful classes, but they fail to explain what the real difference is between object behaviour and appearance. Do you?

According to my own OOP design rules all my classes have beside their native INIT() and DESTROY() methods at least additional START() and STOP() methods.

VFP's native classes don't have real constructor and destructor methods we could use to overwrite with our own improvements.
At the moment VFP passes control back to our code within the INIT() method, VFP's internal object construction was finished! VFP's INIT() method is something like a post-construction hook-function. Thus, it should only be used to help VFP to finalize its object construction in that the only code we might put there is something that dimensions arrays and fills properties with the right default values for example. When it comes to real encapsulation - I mean the real art of coding reusable classes - we have to reassure that every class instance is fully encapsulated just after its initialization is finished.

What is a proof of full encapsulation?

Well, full encapsulation means that at the unique "post-init" point in your object's lifecycle all its properties have to match the type and value (you coded in your class definition) exactly . I name that object appearance (object appearance:=the values of all object properties) the post-init appearance or initial appearance. Within this initial context no data or information that doesn't already exist inside your object should be assigned to any of its properties. In other words: If you intend to create fully encapsulated classes, you never must write class code that assigns any external value to a property before the class instance's INIT() returned. Never write INIT-code in your reusable classes that presumes something to be existent (or even predictable) outside your object at runtime at this early stage.

BTW: Go and have a look at VFP's own online help about topic: "Init event". You can read the following there:

To prevent a control from being created, return false (.F.) from the INIT`() event. The Destroy event will not be triggered. For example, the following code returns false (.F.) if the Invoice table is not available:

PROCEDURE INIT
  IF NOT FILE("INVOICE.DBF")
     ERROR 'Initialization Failed: File not found'
     RETURN .F.
  ELSE
     USE INVOICE IN 0 AGAIN
     THIS.WorkArea = SELECT()
  ENDIF
ENDPROC

Well, those guys are not only breaking all (my) rules of encapsulation there, they're also doing another big no-No-NO: they're returning a FALSE from INIT(). Doing so is a real evidence of incapacity to me! Why?

1st: The information FILE("INVOICE.DBF") definitely is external to the object at that time. Not only at that special INIT()-point in object's lifetime, but at almost every point in time – especially, when we are coding the class. Thus, the information about the existence of a dBase file called "Invoice.dbf" is a first class citizen of object-external information!
2nd: Another big point to know (and to live and to die for) is that any object in memory has the “damn right" to exist as long as all of its properties are valid! This is the OOP concept of object validity in contrast to object utility.
3rd: Every programmer should be able to write classes from which valid objects can be created at runtime - at least, encapsulated objects with a valid post-init state. Otherwise the class concept can be considered nothing but trash.

IMHO and according to my own OOP design rules, the VFP HELP crew must have had a class in mind that should be able to create valid instances of objects. Well, if no invoice table exists in VFP’s FILE()-function's search path the object isn't useful (seen from the perspective of other objects running in the same context). But, that must not hinder the object from staying in memory! Who knows, maybe the table in question will become available later!?


22 OOP Design Rules

Beside the idea to write a separate documentation about good (and poor) OOP design, here are 22 of my basic OOP design and development rules. I hope you will find them useful. At least this chapter can help you understand my implementations later ;-)

The classes of my framework I'm going to talk about are fully reusable/encapsulated. The rules I'm going to enumerate below apply to that kind of reusable classes. Naturally, there are exceptions to my rules, we will have to talk about that later.

Another very good source of information I would like to point you to Christof Wollenhaupt's Safe Base Classes document. Christof shows us a code-based approach to write bullet-proof (base) classes. Contrary to that, my own OOP rules show you a way less carved in stone; they seem to be more liberally to me. Maybe you tend to implement a mixture of both approaches. The outcome always should be the same. A good class design will always lead to bullet-proof class hierarchies that will instantiate stable running, well behaved objects at runtime.


Rule #01: If avoidable, never initialize static class fields dynamically!

I must admit, this rule sounds strange. Thus, let me translate: A property is also called a static class field - so far, so good. We all know that we can write something like the following in VFP's property editor:  ="My new Caption"
This is called a dynamic assignment, even if my example is a pretty simplistic one. We could create other assignment including function calls like this: = SYS(2015) The SYS(2015) function returns a unique procedure name. It sounds to be the perfect fit for attaching a unique ID to every class instance. Check it out - you will find that every instance you create has the same SYS(2015)-value! Strange? Well, not if you've read Christof's document (linked above). In fact, you are assigning the SYS(2015) result to VFP's internal class object only the first time you instantiate an object from that class! All successively created objects won't evaluate the SYS(2015) call again! VFP fetches the buffered value of its class object from its internal class cache instead! Thus, if you are not absolutely safe as houses about what you're doing, do not touch VFP's internal class object properties this way. Rule#01 leads us to the next rule of thumb...


Rule #02: Always use your objects' INIT() method to assign class field default values!

Now, this is pretty easy to grasp. The moment VFP hands over control to our INIT() method, the internal class object is fully created and all properties are initialized with the class defaults. From now on, when you write to your object properties, you can be sure you are writing to your current class instance and not VFP's class object. Thus, assigning some unique value using =SYS(2015) to a property from there will always yield an unique ID inside your property - as expected. BTW: As we will see in Part II its always a good idea to implement things like the property initialization and others in a discrete self-defined method and call that method from Init() or Destroy(), instead of putting all code in VFP's native methods!


Rule #03: If avoidable, do not pass information into VFP's INIT() methods!

There are plenty of good reasons for not using input parameters within VFP's INIT() methods. One of the more obvious ones is, that you might want to reuse your class instantiated inside another container later in the game. Within such a construct the INIT() of your inner object will fire before the INIT() of your outer/containing object and that's not what you want, because there will be no parameter-data available then! Another (OOP-design) reason is, that passing external information into your object at this early stage (before INIT() has finished!) breaks full object encapsulation (see below)! Data passed into an object always is something external seen from the object's point of view. Thus, don't start passing in external information before you're done with your internal (self-contained) initialization!

Lately, someone who noticed that my own classes do have an INIT() input parameter, asked me why I’m breaking my own rules! :-) Let me tell you, the only input parameter I do accept in all INIT() methods of my reusable super-classes looks like this: LPARAMETERS tlAutoStart AS BOOLEAN. The <tlAutoStart>-value is no external data (in terms of “something vitally important I must know”), but solely used as workflow control information. If <tlAutoStart> is TRUE, the object gets started automatically (Start() gets called from Init()). Otherwise, Init() finishes and control is passed back to the parental maker, which then may or may not start the object (sooner or later). Therefore, <tlAutoStart> is no external information, but belongs to object’s internal process control data, merely introduced at Init() dynamically.


Rule #04: Always try to achieve full object encapsulation!

The best reason to haunt for full object encapsulation is that this is the only bullet-proof way to achieve full class reusability. Full encapsulation is pretty easy to achieve. 1st: Never access any information outside your object boundaries from within your class instance. 2nd: Never pass in any information before your INIT() method was successfully completed (returned TRUE).


Rule #05: Go for strongly typed properties

VFP doesn't support strongly typed properties. It's up to you to fill this gap! Why? Because its the only way to find the correct answer to the question "Is this class instance valid?" Why should we ask this? Because any valid object should have the established right to stay in VFP's working memory! Only if an object renders invalid it must be removed (or repaired)! Strongly typed properties are one major building block of error-free, thus excellent, class design. The crucial question is: How can we implement such a feature transparently? The answer to this question is: USE _ASSIGN() and _ACCESS() methods (see below)!


Rule #06: Go for property validation

We can check the type of any property pretty easily using _ASSIGN() and _ACCESS() methods. But that's not enough to let you know if a property is valid! In addition to that you need to know the range of valid values the property may hold! Only if a property value has a given type AND is inside the valid range, the property is valid! Thus, we have to implement a pretty complex strategy to simulate strong typing!


Rule #07: Go for object validation

We know by now what a valid property looks like. Now we can expand this definition to fit for an entire object. If all properties of an object are valid, then (and only then!) the entire object is valid. If only one property renders invalid, the whole object will become invalid. An invalid object isn't allowed to stay in VFP's working memory!


Rule #08: Get the difference - Dynamic vs. Static class fields

Dynamic class field is another generalized term for methods. Static class fields are properties (we've learned). Some programming languages implement a feature called uniform access principle. VFP doesn't support this natively. The principle of accessing class field information uniformly is realized (for example in Eiffel) by using the same notation when getting class data either by querying a property directly or by calling a non-parameterized function. In VFP we have to distinguish between a property query and a function call syntactically - the latter uses parenthesis. The uniform access principle makes it easier for the reusing developer to access object information, because she doesn't have to know how the class field was implemented internally. Thus, there is an even more generalized categorization (see next rule).


Rule #09: Get the difference - Queries vs. Commands

Queries are all kinds of questions you can ask an object's interface. A query always returns a value (not two values or even more, but only one value!). In other languages (like Eiffel) the reusing developer doesn't have to know how an object query is implemented (thanks to the uniform access principle). Although, every VFP developer has to be aware of the correct type: is it a static query, then she will access an object's property. Is it a dynamic query, then she calls a non-parameterized function that returns a value as well. A dynamic query never changes the object's appearance! If a dynamic query fails it can signal it's own failure by returning a predefined error value (see query contracting)

Commands are all other object's methods that are no queries or events. In contrast to queries a command never returns any value but can change the object's appearance (and of coarse it's state, too). The only way a command can signal a broken contract is to raise an exception.


Rule #10: Get the difference - Incoming vs. Outgoing Messages

All commands and queries that are sent from one object to another are also called messages. Like in real life amongst humans we need at least two persons to start a dialogue/conversation. Very often there are many more persons/objects involved. Within VFP's runtime only two objects can communicate at the same a time. The relation established between them can be named "Sender/Receiver", "Guest/ Host" or other pairings like that. One part queries or commands the other. Messages sent are called incoming messages from the receiver's viewpoint, because they are coming from the "outside". The other group of messages called outgoing messages are AKA events. These messages never "leave" the object. They never will be sent to another reference by the object itself. There is no "call out" to a foreign object method, but a call to an own method only. That's why we say those methods are events that get raised! Because outgoing messages never will be sent to another class instance directly, we cannot "sit and wait" until we will be informed / hit by an incoming message. We have to get active ourselves and bind to any outgoing message we're interested in instead.


Rule #11: Get the difference - State vs. Appearance

Both terms, state and appearance, belong to the same part of my taxonomy. Both are meta class attributes describing two static aspects of all class instances at runtime. Let's use a VFP form class as an example. After you created an instance of the form like so:
loForm = CREATEOBJECT("Form") and made it visible
loForm.Show() you can see your new form object showing up in it's post-init appearance. Your form has a lot of properties. All of them, better: the values they have, make up the appearance of the object. BTW: a VFP object doesn't have to stem from a GUI class to have an appearance. Each object's appearance is the entirety of all property values at a given point in the object's lifetime. Moving or resizing our demo form for example will change it's appearance. Thus, our form object have an almost unlimited quantity of different appearances. As we've already learned, each single form property can be valid or invalid. Thus, if all properties are valid, we could state that the object appearance is valid, too. The term appearance relates pure quantity more closely. Therefore, we should use the term state instead, when describing the object quality of being valid or not (a Boolean value/quality). From object appearance follows object state, but not exactly vice versa!

BTW: The only object appearance you can describe in your class definition precisely is the one called post-init appearance if you've done it right and followed my rules so far!
If all of your objects' post-init appearances are completely self-contained, bearing no external references as described in your class definition, and if all of your property values were initialized explicitly (using code) then you can re-run that portion of code at any time to reset your entire object to it's post-init appearance. Do exactly that before you destroy your class instances and you will never see any dangling references again! In fact, it is sufficient if you reset all properties that (may) hold an object reference when destroying your instances.


Rule #12: Get the difference - Utility vs. Behavior

Both terms, utility and behavior, belong to the same part of my taxonomy. Both are meta class attributes describing two dynamic aspects of all class instances at runtime. Behavior is a collective term for all kinds of object functionality (all kinds of VFP methods). The big difference between behavior and appearance is, that any object that has one or more not so well-behaving methods, must not be "sentenced to death" at once. If all procedures work as expected and all functions return correct results then the entire object's utility is said to be useful. Every single object's behavior is acceptable if it produces what is defined in it's contract (see next rule). If only one function call returns an error value or one single procedure call raises an exception, then the overall object's utility is set to useless immediately! An object can have many useful and many useless behaviors, the overall utility is a Boolean object quality which can only be useful or not useful!

BTW: If you tend to think about realizing some kind of percentage object utility, maybe you better redesign your class! Why is it no good idea to create objects with sometimes 70% and maybe sometimes only 30% of overall utility? Well, classes with too much functionality tend to start up with more "broken" behavior due to their complexity than slim/compact ones. Overloading classes with behavior always bears the risk of adding disparate behavior, thus loosing desired tight coupling between data and functionality! Nobody needs the universal Swiss Army Knife class! An all-in-one object suitable for every purpose should be avoided like the plague if we still want to take advantage of the basic OOP principles!

Strange: Nobody ever asked me "How can you test the overall utility of your class instances at runtime?" Maybe because the answer is pretty trivial: "You cannot!", otherwise you would run a full Integration-test of your class! But what you can do is to check system prerequisites. For example, if some DBF file is missing that your object is going to open then you know that your instance is not useful. Or if you know that your instance needs some object reference(s) in one or more properties you know that your class is not useful as long as those references are missing. In all other cases you have to wait for an unfixable error to occur to set your object's utility to useless.

Question 1.) What if a record that your biz-object wants to modify is already locked by another user? Does this render your biz-object useless?
Question 2.) What if Type("This.Parent") == "O" is false but your object needs a parental reference ? Would this render your instance useless?

Answer 1.) NO! Dealing with locked records (and other multi-user related stuff) must be a vital function of  the data component of your biz-object.
Answer 2.) NO! The This.Parent reference belongs to the object's state. A missing This.Parent reference must render your instance invalid immediately (see Rule#11)!


Rule #13: Go for Contracts

Contracting between two objects can be compared to conclude an agreement in the real world. One object acts as the supplier the other is the acceptor/consumer. The consumer needs a service the supplier offers. Both parties have to agree upon what service should be interchanged and what the terms of contract are. Next, they have to communicate what should be done if one of them breaks the contract. The consumer can only break the contract by passing invalid parameters to the supplier. In that case the contract states, what the supplier has to do in that case (raise an exception or return a special error value?). If the consumer did everything right, the supplier may break the contract because of some internal malfunction. The contract should state in that case what the supplier has to do in such a case (return error value or raise an exception).
Carefully implemented contracting can save you a lot of headache! Although VFP misses some native language constructs to simplify contract coding even more, we have enough programming power at our fingertips to implement some full-blown version of our own.
Contracting can be seen as an extended assertion management as well as a generic parameter checking system (see below).


Rule #14: Separate Interface from Implementation smartly

A big question is: "How to implement a full-blown VFP contracting scheme?" Well, first of all - it is a good idea not to code against implementation but against an interface. But - what can we do within VFP? There is no such thing like an interface definition (like in the .NET languages). Okay, let's grow our own! We need some little tool that helps us setting up all needed interface classes (based on a lightweight VFP base class); we need another tool that may helps us transferring our old parameter checking code from our implementation classes into our new interface classes (or do it by hand:-).
We will end up with implementation classes freed from the overhead of parameter checking code but extended with an additional bridging scheme to link them to their corresponding interface classes.
Creating our own interface classes brings us a high level assertion management. We will be able to reassure that no object can break a contract we've defined inside our interface objects. Later in the game, we can disable the extended contract assertions to get more speed. Finally, it could be possible to remove all interface objects and link the implementation objects together directly. A process comparable to deep-freezing the current application development state into an "ultra fast" end user EXE.

BTW: We didn't talk about possible further enhancements! There are other extensions worth looking at. If we choose to create and maintain separate interface classes for each of our reusable classes then we have room to add more than only one interface class to each of our classes! Different interfaces could expose different sets of commands and queries. We could implement security-relevant interfaces and add them on the fly at runtime subject to the logged-in user.
We could think about a special messaging matrix that only holds our interface objects. The parent-child relations established there would then represent our application's workflow hierarchy and more. I mean, a set of standardized interface objects is easier to handle within an unified messaging concept than a whole bunch of different implementation classes.
Our implementation objects could also be updated and/or changed transparently in the background during runtime! The flexibility we would gain using such a concept is enormous!


Rule #15: Go for START() and STOP()

No object can do all the work. No reusable class should be that complex! Objects have to be collaborative and communicative. But we've learned that all reusable classes should be designed to create valid objects that are encapsulated, self-contained, not knowing/assuming anything about the "world outside" after their INIT() has run.

At this point every object has to be valid (otherwise our factory would have removed it), but in most of the cases these objects aren't of big help - they render useless, because so much external information still is missing. This is the moment to run the object's Start() method.
Starting an object means to bring in all information from the outside needed to make the instance render useful! Stopping an object means to reset all properties to their post-init state!
In my framework the Start() method may be called from an object's INIT() depending on a property called .lAutoStart As Boolean. The Stop() method is called from the (self-defined) RELEASE() method or from the DESTROY() method automatically. Both methods are also responsible for any event binding/releasing that should be made.


Rule #16: Get the difference - Start/Stop vs. Init/Destroy

While INIT() and DESTROY() are native VFP event methods Start() and Stop() aren't, although they could have been!
Within your INIT() code you take care of the objects initial appearance - your INIT() makes the object an exact and therefore valid copy of your class blueprint. Init() is a function. You can return Success or Failure. (Within all of my base classes I flagged VFP's INIT() function as PROTECTED!)
Within your DESTROY() code  you should do any additional housekeeping necessary. (Within all of my base classes I flagged VFP's DESTROY() procedure as PROTECTED!)
Within your START() code you take care of the objects initial utility - your Start() method takes input parameters that can be used to pass in all external information and references your object needs to collaborate and communicate. After having started your objects property .lUseful should be set to TRUE. Start() is a command, thus never returns any value. Start() also takes care of any kind of native event binding.
Within your STOP() code you reset the object's appearance to exact the same state it has before your Start() method ran the first time - including VFP's native event binding.


Rule #17: Get the difference - Parent- vs. Child Objects

What came first the chicken or the egg?
It is always wise to differentiate between a parent object and its children! A VFP form object hosts instances of let's say VFP's TextBox- and CommandButton classes. The form is the parent, the contained controls are the children. These are my rules of thumb you might want to apply in a similar scenario, too:
A child should never know anything about its parent. A parent object should always know all and everything about its children! A child should never send a message to its parent directly using VFP's specialty: parental reference keywords like PARENT, THISFORM or THISFORMSET. Any child should only communicate with the outside either by using references that were passed in during Start() or by raising events. During startup a parent may send its own reference (or others) to any of it's children's START() methods or may bind to any of its children's events.

All of my statements apply to reusable, encapsulated classes only! In other words: if you don't intend to create a reusable super-class (let’s say, to include it in your personal framework) then you might code and use everything you like - go and query any parent information like
THIS.WIDTH = THISFORM.WIDTH-10 it is up to you.
BUT: If you code something like THIS.WIDTH = THIS.PARENT.WIDTH in one of your framework's control classes you might get into troubles, because later in the game you may try to put your control some levels deeper into a containment hierarchy. THIS.PARENT references a different object then! Thus, it is a good idea to add your own parent reference property to all of your base classes. Set this reference during Start() and you cannot loose anymore!


Rule #18: Get the difference - OOP vs. PROCEDURAL

Another fundamental question always is: "Where should I store a needed functionality?" There are two basically different options to choose from. 1st: Create a class and implement it as a class feature (OOP). 2nd: Add it to one of your procedure libraries (PRGs). The first objectifies your function by adding a new object at runtime, the latter enhances your VFP language through adding another verb to the language, a so called procedure that can be called when needed. Both approaches have their pros and cons! On the one hand it is always faster to call a function directly from a procedure file than to first instantiate an object before one can use its functionality. On the other hand classes have these nice inheritance and polymorphism features and can persist values between calls within their properties.

Many other development languages have no procedures and functions like VFP has but are building their whole universe upon classes. VFP is a typical hybrid language supporting both concepts! Let's have a short look on C# or VB.net where we can find class methods that are marked as STATIC (in VB SHARED). These class methods come close to VFP's procedural concept, because they can be used/called directly without instantiating an object first. Instead of an "ObjectName.MethodName" combination we have to write "ClassName.MethodName" here to get access directly.

Any data that is needed has to be passed into a procedure/function. Thus a function/procedure relates to the verb in a sentence, whereas an object (a class instance) maps to the noun in a sentence more closely. Its up to you to decide what you want to extend: VFP's language with your own verbs, or VFP's base class list with your own sub classes. Anyway, there are some rules of thumb we can use to guide our design decisions:
1st: If we do not use any properties of an object, the methods of such a class could also be placed inside a procedure file. If there is no coupling between object's data and functionality AND there is no special need for inheritance because the functionality is very special or finalized, we can drop the wrapping with as class saving some instantiation time at runtime!
Have a look at the following function. Would it make sense to you to wrap it into a class just to call it as a method? I don't think so! This function itself is a wrapper to make VFP's SKIP command a little bit more reliable, thus decorating a command/verb. It doesn't make much sense to change Skipping() to oSkipper.Skipping()!

FUNCTION Skipping(tnSkip AS INTEGER) AS BOOLEAN 
	LOCAL llSuccess 
	ASSERT VARTYPE(m.tnSkip) == "N" ; 
	MESSAGE "wrong parameter type" 
	IF RECCOUNT() > 0 
		IF m.tnSkip < 0 AND NOT BOF() 
			SKIP m.tnSkip 
			IF BOF() 
				GO TOP
ELSE llSuccess = .T. ENDIF ENDIF IF m.tnSkip = 0 IF EOF() GO BOTTOM ELSE IF BOF() GO TOP ELSE GO (RECNO()) ENDIF ENDIF llSuccess = .T. ENDIF IF m.tnSkip > 0 AND NOT EOF() SKIP m.tnSkip IF EOF() GO BOTTOM ELSE llSuccess = .T. ENDIF ENDIF ENDIF RETURN m.llSuccess ENDFUNC

Another example to show what I mean is the following class definition

DEFINE CLASS cTextManager AS Custom 
	FUNCTION MakeNice(tcText AS STRING,; 
		tlOption AS BOOLEAN,; 
		tnOption AS INTEGER) AS STRING 
		*\\ here code to reformat the text 
	   RETURN m.tcText 
	ENDFUNC 
	FUNCTION PrintText(tcText AS STRING,; 
		tlOption AS BOOLEAN,; 
		tnOption AS INTEGER) AS BOOLEAN 
		*\\ here code to print the text 
	   RETURN .T. 
	ENDFUNC 
	FUNCTION ConvertText(tcText AS STRING,; 
		tlOption AS BOOLEAN,; 
		tnOption AS INTEGER) AS STRING 
		*\\ here code to convert the text 
	   RETURN m.tcText 
	ENDFUNC 
ENDDEFINE

Obviously there are three methods (functions) that neither share nor use any property values at all. The text to process is always passed in on method invocation together with some (maybe optional) other control values. Okay, we call the class a "Text Manager" but his three functions could be placed inside a simple procedure file as well!


Added September 2009Rule #19: Get the big difference between Public, Protected and Hidden

Sounds easy enough, does it? But what are the consequences you have to deal with? First off all, here is my own preferred strategy: “Keep all and everything PUBLIC…” as long as there is no very good reason to PROTECT a classes’ PEM, and: “Never hide anything…” until you feel “forced by class design” to do so!

PUBLIC PEMs define the classes’ public interface. This means they define the TYPE of your class. This is true for the reusing developer at design time, as well as for other class instances sending messages or querying your object at runtime. If you are someone who is using a contracting mechanism (see rule#14), you belong to the lucky guys! The contracts you implement will protect your class instance from becoming useless or even worse, invalid. If you don’t implement contracts you have to watch your property values and the signatures of messages sent carefully not to get trapped by other misbehaving objects. In other words: You have to implement _ASSIGN() methods and comprehensive parameter checking.

PROTECTED PEMs define the classes’ internal interface. Right you are! There is no such thing like an “internal interface” seen from the viewpoint of other objects at runtime. The “internal interface” is the reusing developer’s interface she can code against. Protected PEMs will be inherited and can be reused in subclasses. But they cannot be accessed from the outside. Thus, changing the visibility of a native VFP-PEM from PUBLIC to PROTECTED will not change the BASETYPE of your class at design time, but at runtime! And that may lead you into trouble! PEM protection also leads to worse testability of your class instances! Thus, the preferred way to protect your objects’ properties is to shield them using _ASSIGN() and _ACCESS() methods, and a well designed contracting scheme to check the parameter values when your methods get called.

HIDDEN PEMs are taken out of VFP’s inheritance completely! They are not visible / accessible from the outside at runtime and no reusing developer can use them in her own subclasses! Thus, changing the visibility of a native VFP-PEM from PUBLIC or PROTECTED to HIDDEN will change the BASETYPE of that class at design time as well as at runtime! You must have a damn good design reason for hiding any PEMs in your classes (taking them out of inheritance, making them un-reusable, inaccessible and not testable). Ask yourself, is-a container still of type “Container” if you hide VFP’s “Control”, “ControlCount” and “Objects” properties? One could say that hiding any VFP native property is like deep-freezing that class into a new base class, right? I will show you my one and only design reason to set a method to HIDDEN in a minute.

Good reasons

If a method is a pure internal helper function that is not intended to be overwritten / changed in subclasses, it may be a protected one. If you want to keep it testable you should protect it not before the next descendant class level! That way you can run a unit-test on the implementing class (with the still unprotected method) in your testing environment still having the needed protection at runtime through the additional subclass level (where protection takes place). BTW: A protected method does not need any parameter checking, which would slow down performance otherwise!

My own (one and only) reason to set a method to hidden is to fake a new VFP base class! Yes, you read it right! This also is one of my “little dirty tricks” I like best :-) Let me explain that using a simple example: “The Top-Level-Form Base Class”.

All you have to do to make a VFP Form class a top level form class is to set the Form.ShowWindow property to 2. Okay, let’s say you stored a subclass in your framework class library named “TopLevelForm” and added some useful code relying on the fact that every instance of that class has set This.ShowWindow to 2. Well, next you might add another ShowWindow_ASSIGN() method to protect that property. In this very “cheap” example that’s all you would have to do. But, if you have a lot of PEMs to protect that way it would be easier simply to set their visibility to PROTECTED. This (we talked about it) in turn would change the classes’ TYPE at runtime (or even the BASETYPE, if you’re dealing with native PEMs). Your VFP FORM no longer is-a FORM but now is-a TOPLEVELFORM! By your own definition a TOPLEVELFORM does not have a ShowWindow property exposed in its public interface. AND: As with all other VFP base classes your new TOPLEVELFORM base class cannot be redefined to another base class!
Now, let’s add a HIDDEN BaseClass_ACCESS() method returning the new base class name “Toplevelform”. That’s all it takes to make a Form pretend to be something different, a brand new VFP base class! Please notice that I did not used “Formtoplevel” as the new base class name. There is a good reason not to do so. Keeping the real base class name as the first part of the new name expression indeed won’t break any existing code that queries the Form.BaseClass property like so: If oItem.BaseClass = “Form”. But that would be a real source of confusion, because our new TL-Form no longer is-a FORM, but is-a TOPLEVELFORM! (Tip, I always query BaseClass properties using code like this: If oItem.BaseClass == “Container” (with double quotes and Proper() formatted string which runs a tiny little bit faster than single quote comparison).

Finally, no reusing developer can change the base class expression returned at runtime because she even will not see the _Access() method any longer. The new base class type name is deep-frozen into the class at your framework level. Of course, you have to document your new “base class feature” well, and you must keep in mind, that VFP’s debugger always shows the old (and only) real base class name.


Added September 2009 Rule #20: Get the difference - Instance Programming vs. Role Assignments

VFP supports instance programming. That is: drop a control on a form (or any other container) at design time, open for example the click method of that control and put some code in it. Sounds familiar to you, I bet.

You’ve just programmed an instance! In VFP the control (now containing your click event code) inside the containing class is no CLASS in VFP’s class designer but the INSTANCE of a VFP class. This concept is NOT supported in many other languages. Some of them support the class-in-class concept instead. If you are going for VFP classes that are easy to migrate to other OOP-languages, and can be extended by sub-classing them, never do instance programming!

Assigning values to controls hosted within other controls at design time is NO instance programming, although you’re assigning these values to the same inner class instance as above. A value assignment does not change instance behavior, but only instance appearance. That’s why it is not called “programming” but “assignment”. VFP’s instance assignments can be translated into any other OOP-language easily.

What is a ROLE?

Well, the role concept is no specific OOP feature, but a more generic concept. Any role an object may play at runtime is a combination of appearance and specific behavior of that class instance. We all know the typical “Close”-Button placed on a form. The role of that button is the combination of the button’s caption set to “Close” and some Click handler code maybe like this: Thisform.Release(). The button’s Caption defines the appearance part, the Click() code defines the behavior part of the role in this example. Indeed, this is a very simplistic one. Think about much more complex business objects and you will find that they also follow the same concept.

How to assign roles to a class or instance

As we knew by now, value assignments to properties (the appearance part) are a no-brainer. Thus, let’s concentrate on the behavioral part of the concept. The roles concept should always be adapted using sub-classing at design time if we want to avoid instance programming. Of course, sub-classing needs more work to be done creating all distinct descendant classes. Instance programming can be coded faster but on the other hand, leads to source code that is harder to find/maintain, and does NOT support inheritance. It can be real fun to implement roles if our super classes are carefully designed to fully support that concept. There are many roads we can take implementing roles. To name the most common ones, there are: value driven execution, hooks & templates, dependency injection and event binding.

Value driven execution

The easiest way to vary object behavior is to control it through values of one or more properties. Let’s say, our business object super class has properties called cMainTable, cMainAlias and cMainTag. All we have to code in the corresponding OpenMainTable() method is something like this:
Use (This.cMainTable) In 0 Order Tag (This.cMainTag) Alias This.cMainAlias
In our descendant implementation classes we only have to fill in the property values, that’s all! Or we may want to branch the execution path based on a (property) value. The beauty of value driven execution is that object’s behavior controlled that way can be varied at runtime, too! Downside of this approach is that classes can become bulky (overloaded with properties). Methods implementing execution branching very often get complex and long (an endless list of IF THEN ELSE, or DO CASE statements) and therefore are hard to maintain.

Hooks & Templates

These patterns should be a developer’s best friends ! Typically there are PROTECTED Before-, Do- and After- Hook methods that are called from the PUBLIC entry-point which is a Template method. Let’s say, we need a PUBLIC MakeCursor() method that will be called at runtime if a given cursor still not exists. The MakeCursor() method is a template method implemented in our super class that calls the three other methods like this:
Local llSuccess As Boolean
llSuccess = .T.
If This.MakeCursorBefore(@llSuccess)
    llSuccess = This.MakeCursorDo(@llSuccess)
Endif
This.MakeCursorAfter(@llSuccess)
Return m.llSuccess

In this super class all of the PROTECTED methods above have the same signature:
LParameters tlSuccess As Boolean@

This concept lets us implement basic functionality in the super classes of our framework (in our example in the .MakeCursorDo() method). Naturally, the reusing developer is free to overwrite our …Do() method with her own implementation but, often enough, she only wants to add a little bit of behavior before, or after our original code was executed. Now, she can implement (for example) additional indexing in the …After() method, or disabling our basic behavior completely through returning FALSE from her …Before() method.

Dependency Injection

The most sophisticated way to dynamically add behavior at runtime is achieved through object reference injection (AKA Dependency Injection). Instead of implementing the behavior inside the class that will expose it at runtime, we code our desired behavior into another flyweight class. Let’s take the last example from above. Now, our biz-object super class has a new property named “oCursorMaker”. The code in our This.InitDo() method might look like this:
This.oCursorMaker = CreateObject("MakeCrs_CustomerTemp")
Return Vartype(This.oCursorMaker) == "O
"

The code in our This.MakeCursorDo() method will look like this:
Return This.oCursorMaker.MakeCursor()

The “CursorMaker” class can be considered as a FACTORY although it doesn’t produce an object in this case but a cursor. Anyway, instances of that special factory class can be used everywhere in our applications. If we need to change the structure of the temporary customer cursor created by this cursor factory we have to code it only once and in one place: the MakeCursor() method. Because the functionality is wrapped in a classes’ method it can be altered, or extended using sub-classing. Take the “Hooks & Template Method” code above and put it into our “CursorMaker” class for example.

Alas, our solution still isn’t perfect because the behavior of our biz-object class cannot be altered without touching the source code, and it cannot be unit-tested without instantiating the real “MakeCrs_CustomerTemp” class, too.

It is time to create some real Dependency Injection which is also (more generally) called Inversion of Control (IoC) in the context of other strongly typed languages. An IoC-Container holding our biz-objects would precisely know what cursor factory instance each of those biz-objects need. It is the hosting IoC-Container who now calls our biz-object’s MakeCursor() method passing in a reference to the proper cursor factory instance. Our biz-objects’ MakeCursor() methods now could look like this:

Lparameters toCursorMaker As CursorFactory of Factories.vcx
Local llSuccess As Boolean
llSuccess = Vartype(m.toCursorMaker) == “O” And;
            m.toCursorMaker.BaseClass == “Cursormaker” 
IF This.MakeCursorBefore(@llSuccess, m.toCursorMaker)
    llSuccess = This.MakeCursorDo(@llSuccess, m.toCursorMaker)
Endif
This.MakeCursorAfter(@llSuccess, m.toCursorMaker)
Return m.llSuccess

Now we can store all of our cursor factory instances in one distinct place (maybe inside the IoC-Container itself) and get their references from there when we need them! Each of our biz-objects’ MakeCursorDo() methods contains productive code that looks like this:

Lparameters tlSuccess As Boolean@,toCursorMaker As CursorFactory of Factories.vcx
Return m.tlSuccess And ;
   m.toCursorMaker.Class == “CustomerTemp” And;
   m.toCursorMaker.MakeCursor()

Dependency Injection supports the vital design principle of Separation of Concerns (SoC) that is, separating a Class into distinct section classes so that each section class addresses a separate concern. This leads to a higher modularity of our class design which in turn gives us back better reusability.
Unit-testing the biz-object is easy now, because we can send a mock object reference to the MakeCursor() method.
Last but not least this approach is highly customizable at runtime. If requirements change (maybe we have to use SQL-Server for our temp cursors one fine day) we can switch to another cursor factory class in no time without touching a single line of code in our biz-objects.

Event Binding

VFP has a very cool event binding. We can add almost every behavior we need at runtime using VFP's Bindevent() functionality. Go and read my blog post Cool VFP Event Binding.


Added September 2009Rule #21: Go for a good Object Factory

The Design Pattern Abstract Factory belongs to the group of Object Creational patterns. The intent of the Abstract Factory pattern is to provide an interface for creating families of related or dependent objects without the need of specifying their concrete classes.

The really cool thing about using a factory instead of coding object creational code directly into our methods is that we don’t have to change that code all over the place if we have to change the classes’ name or library.

Example

Instead of coding this:
This.oGui = NewObject(“MyTLForm”, “Gui.Vcx”)

we may use this redirection instead:
This.oGui = m.goApp.oFactory.MakeObject([MY_TOPLEVEL_FORM])

If the “MyTLForm” class was moved into another class library, if it was renamed, or got outdated we have to look up each reference in code and fix it. “No big deal for my GoFish Search & Replace tool” you might think. But be warned, even when using the most sophisticated tools there is a rest of uncertainty when running bulk replaces in VFP! Always!

Before we dive into the real thing let’s look at the first line of code above. There are two things we can change to improve it! If I have to write code without a factory instance I would code it so:
This.oGui = NewObject([MyTLForm], [GUI]) 
I removed the “.Vcx” extension, and I replaced the double quotations marks with square brackets. There is no need to specify a “.Vcx” extension because VFP will add it automatically. But that’s not the point. What I did is to shorten the class library expression to its minimum (one word, not dot). The cool thing about denoting strings with square brackets is that these strings will be processed by VFP’s preprocessor!
Now, as long as we do not use an include file with our class that redefines the two expressions above there will be no difference between [MyTLForm] and “MyTLForm”, or [GUI] and “Gui.Vcx”. VFP will search along its search path to locate our Gui.Vcx class library and then will instantiate our MyTLForm top level form.
What if we have changed the name of our class library (which always is a pretty bad idea) and the name of our top level form class all together? Assuming that we have a global include file for our project that is also linked into all of our class libraries, we now can go there and redefine the expressions as follows:

#DEFINE MyTLForm    MyTopLevelForm
#DEFINE
GUI         Forms.Prg

After rebuilding our project VFP will instantiate the PRG-based “MyTopLevelForm” class from the “Forms.Prg” class library. Thus, using square brackets saves us the work defining those two lines already at the beginning of our coding work like so:

#DEFINE MY_TLFORM  “MyTLForm
#DEFINE
GUI        “Gui.Vcx

This.oGui = NewObject(MY_TLFORM, GUI)

The bottom line is: Denoting strings with square brackets within our CreateObject(), NewObject() and Set ClassLib To functions introduces a first level of redirection. This redirection is available at design time only because it requires include file driven preprocessing. Please keep in mind that VFP’s preprocessor does NOT process value assignments we typed into the Class Designer’s Property Editor. We may type in something like  = [MY_FORM_CAPTION] into the caption textbox of the form's property sheet but it will never be substituted! The only thing we can do is placing the assignment in the Form.Init() method editor window like so: This.Caption = [MY_FORM_CAPTION]

Back to the golden thread

The basic approach of a Factory design in VFP(!) should always be a table-driven design. The driving table should be small enough to be held in memory by VFP completely, and indexed well to get maximum performance. The lookup column of the table will be filled with the static class names like "BIZ_CUSTOMER", or "FORM_CUSTOMER". These are the class name tokens we use in our code when calling the Factory to get back a reference. Class name tokens must never change again. If we changed a class name or location, the only thing we have to do is to modify the corresponding record of the factory table.

A good basic Factory design in VFP should also attend to the following VFP-specialties:
1.) VFP's NewObject() function runs up to 20 times slower compared to the older CreateObject() function! Thus, internally a good VFP Factory should always use the latter one! From this it follows that the Factory also has to handle all Set ClassLib To settings, including class library alias names!
2.) If we need to create a member object to add it to an existing container instance we must call the container's CreateObject() method. A good VFP Factory should be able to do this.
3.) In VFP all objects are created not only into VFP's working memory but they also "inherit" the active data session! A good VFP Factory (running in its own private data session) must be able to create instances in any other valid data session!

Using a table-driven approach frees us from creating lots of Factory classes (one for each class family). In other languages we would end up having one form factory, one biz-object factory, and many others. Our driving table may be extended to hold some parent-child relation between class definitions. This information could then be used to automatically instantiate member objects of the main container object without any additional calls. I am using this technique to create and add all needed Smart Interfaces (see Rule#14) to my class instances in one go!

A table-driven Factory is an invaluable valuable module that should always be integrated in all of your projects! With the help of a little sync-tool the maintenance overhead (updating of the driving table) can be kept minimal.


Previous EntryBasics HomeBasics (Part 2)

3 comments:

  1. Great article! I'm waiting for the next part. Cheers :-)
    Andrzej

    ReplyDelete
  2. Thanx. Still busy adding NEXT topics to this thread. Stay tuned:-)

    ReplyDelete
  3. Great job ... can't wait for next part of this ...

    ReplyDelete