here's another one that i get asked frequently. just how should you go about designing classes. of course, there is no single ‘right’ answer, but i have always found it helpful, when considering creating a new class, to ask myself three questions:

·       is the object going to be re-used?

·       will the class simplify the task of managing complexity?

·       is it worth the effort?

just for clarity, let me expand these a little:

re-usability

this is probably the commonest reason for creating a class and the achievement of re-usability is, after all, one of the primary goals of oop.  at its simplest level this can mean as little as setting up your own personal preferences for objects – font, color and style for example so that all objects of your class are created with the correct settings in place. things get a little trickier when you consider functionality.  how often, in practice, do you do exactly the same thing, in exactly the same way, to achieve exactly the same results, in exactly the same environment?  the answer is probably “not very often” and you may begin to wonder whether re-usability actually is so valuable after all.  this leads us neatly to the second criterion.

managing complexity

it is actually very rare that anything other than the simplest of functional classes can simply be re-used ‘as-is’.  there are almost always differences in the environment, the input or the output requirements and sometimes all of them.  this apparent complexity can sometimes obscure the issue, which is that the desired functionality remains constant, even though the implementation may differ in detail between applications.

by applying the rules for designing classes outlined in the next topic, it should be easier to decide whether using a class will ease the management of this complexity or not.  even if the creation of a class could ease the management of the complexity, we still have to consider our third criterion.

is it worth the effort

an object should be encapsulated so that it contains within itself all of the information needed to complete its task, and  indeed it is axiomatic that no object should ever rely on the internal implementation of another object.  clearly this can make life extremely difficult.  it may mean that your class will have to check dozens of possible conditions to determine (for itself) exactly what the state of the system is before it can perform its allotted function.  when considering the creation of a new class, it is important to be sure that it is actually worth the effort of doing so.

what sort of class do we want?

having decided that i really do want to create a new class, the next question to answer is “what type of class should i design?”. there are two fundamental models for class design which are the “real world” or concrete model and the “component” or abstract model. neither is inherently better than the other, they are just different.

real world (concrete) model

in this model classes are designed to deliver the required functionality in its entirety. business objects are usually based on this model. for example, we could define a “person” business object class that has the common characteristics (e.g.  properties for left eye, right eye, nose and so on) and behaviors of a person (e.g. methods for breathing, eating, etc). this person class can then be sub classed to model the functionality of special types of people such as “customers” or “friends”. it is readily apparent here that the real world model relies heavily on inheritance and, as a result, most of the functionality is explicitly defined at design time.

component (abstract) model

in this model classes deliver specific behaviors rather than functionality. each class defines a generic function or action and, in isolation, has limited usability. clearly there will be little reliance on inheritance, instead, the model depends upon aggregation (essentially a run-time operation) and composition (both design and run time). the equivalent of our real world person business object is a composite of separate objects: two instances of the eye class, one instance of the nose class, etc.

identifying responsibilities
having decided on the model to use, the next task is to be absolutely sure that you know what the class is actually going to do.  this may sound obvious, but there is a subtle trap here.  it is very easy to build so much into a class that, before you realize it, you have built something that is actually not re-usable because it does too much! the best approach is to identify, and categorize,  the ‘responsibilities’ of the class before you start writing any code. a responsibility can be defined, very simplistically, as some element of functionality which has to be completed.

categorizing responsibilities (the “must, could should” rules)
the purpose of the categorization is to ensure that i can correctly identify where, in the class hierarchy, each responsibility belongs. i do this by using three categories which i call “must do”, “could do” and “should be done”

responsibilities that fall into the first, 'must do', category are those things which an object derived from the class would have to do in every situation and which could not be done by any other object. they are, therefore, clearly the direct and sole responsibilities of the class. these must form part of the root class definition. for example, any object that moves the record pointer in a table, cursor or view, must check for eof() and bof() conditions. so this functionality belongs in the root class.

responsibilities which fall into the 'could do' category are indicators that the class may require one or more subclasses (or, possibly, the cooperation of objects of another class). in other words these are the things that it would be possible for the class to do, but which would not actually be required in every situation. typically it is the failure to recognize these 'could do' items early enough in the design process that leads to the inappropriate placement of functionality in the class hierarchy and which limits re-usability. for example, an object that displays a list could disable itself once a selection has been made. however, that is not essential to its function and is not behavior that would be required in every instance. it therefore belongs in a specialized sub-class.

the final (‘should be done’) category is very important indeed. this is the category that defines the 'assumptions' that a class must have fulfilled in order to function properly. items listed here are definitely not the sole responsibility of the class in question but must, nonetheless, be done somehow. for example, in order for a control to be bound to a data source, the data source should be opened before the control is instantiated. however, managing that operation clearly cannot be the responsibility of the control itself – if only because it must be done before the control is instantiated.

having defined and categorized the responsibilities of the new class, you can then define its public interface by deciding what properties and methods it will require, and how it will reveal itself to other objects with which it will interact. only when all this is done can you begin to think about the actual code and there are a couple of things to remember about this too.

code in methods, not events

when coding classes i believe firmly in avoiding placing code directly in native visual foxpro events whenever i can do so. instead, i create custom methods and call those from the event.  there is, admittedly, no requirement to do things this way, but i find it makes life easier for three reasons. 

·       it allows me to give meaningful names to method code. this may sound trivial, but really does make code easier to read and maintain when the code that produces some form of output is called by ‘this.generateoutput()’ rather than ‘thisform.pageframe1.page1.cmdbutton1.click()

·       it allows me to 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 me to break complex methods up into multiple, (and potentially re-usable) methods.  the event acts merely as the initiator for the associated code.

methods should do one thing and one thing only

methods that do “everything” are difficult to reuse. remember; 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 such monolithic methods up into smaller, better focused,  methods and use a control method to call them individually if necessary. (ask yourself how many times you have found yourself duplicating, within a method, a block of code that already exists as part of another method).

beware of putting functionality too high in the class hierarchy

this 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. one of the major benefits of the “must, could, should” approach is that it helps to avoid this trap.

use template methods for a consistent interface

i stated 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. by creating empty, or placeholder, methods at the highest level of the hierarchy i can ensure that all subclasses share a common interface. as long as subclasses share a common interface, they are interchangeable. even if an empty method gets called, it won’t hurt anything, because all visual foxpro methods return .t. by default – even when they contain no code.

8 Responses to Designing and Building Classes

  • Anonymous says:

    Hi Mr. Andy,

    Just looking at the title of this post, i immediately had it printed out cuz i know this will be very useful for me. i do this everytime i read your posts on foxite’s forum. this is the impression i have on you. every word that comes from you regarding vfp are very useful. i admire that! thank you for sharing it with all of us.

  • Anonymous says:

    Thank you Lucy. I hope I can at least give others some hints to help them avoid the errors that I have made and, since I have made a lot of those in my time I have a few hints to give 🙂

  • Anonymous says:

    I’ve found the most challening aspect of building classes is defining appropriate relationships between classes. I agree there is a tendancy to build too much into a class, which leads to Object Oriented "systems" with only a handful of classes.

    Most books on the subject do a good job of throwing around the terms aggregation, polymorphism, association, etc etc, but don’t do a good job of teaching someone how to apply them. To me the main way to become adept at desiging classes is to learn from an expert, either in your company or through a training class. You have some good advice, but it’s difficult to grasp the significance of the design portion unless its been demonstrated to you. The fact that there is no "right" answer means that you can’t create a design, then go to a book or article and see if your design is valid.

  • Anonymous says:

    The problem is that the topic is really too big for a Blog. It needs much more than 3/4 pages to dicuss in detail but this was intended to give a few clues rather than be the definitive answer.

    However, there is some information on this topic in a book – I wrote it! See Chapter 3 ("Design, Design, Design") of KiloFox (1001 Things You Wanted to Know About Visual FoxPro) for:

    Detailed explanations of "aggregation, polymorphism etc etc" as they apply in VFP and also for a worked Example (albeit a fairly simple one) of how to implement the process.

    There is also a detailed white paper on my website (www.tightlinecomputers.com) on implementing Design Patterns in VFP (and more information on this topic in my third book, MegaFox: 1002 Things You Wanted to Know About Extending VFP).

  • Anonymous says:

    Thank you for your useful blog.i have a question about classes.if i build an app from my class how i can compress it?

  • Anonymous says:

    I’m sorry I don’t understand the question. What do you mean by ‘compress’? What do you want to compress anyway? The App, a Class, the Class Library….?

  • Anonymous says:

    Hi Andy,

    I have a question about how controls locate their class libraries during runtime. If I have 2 exes (main.exe and module.exe) which use custom.vcx but the two custom.vcxs are not the same, how does VFP know which custom.vcx to use when running a form which has controls from custom.vcx of the module.exe?

    1. Does it matter whether the form is included or excluded in the project?

    2. Can we control how VFP locates the class libraries?

    Thanks,

    Peter

  • Thanks Andy !!

    You can find the Spanish version of this article at (Puede encontrar la versión en Español de este artículo en:)

    http://www.portalfox.com/modules.php?op=modload&name=Sections&file=index&req=viewarticle&artid=71

    Regards / Saludos,

    Ana

    http://www.amby.net

    http://www.PortalFox.com

Leave a Reply

Your email address will not be published. Required fields are marked *