6.2 Coding standards

Coding standards

Coding standards and naming conventions are topics that are treated religiously rather than objectively. However, most people (including myself) find them very useful. Naming conventions are supposed to make source code easier to read, easier to maintain and easier to debug.

I do not intend to re-specify all the details of standards such as Hungarian Notation. Instead I'll focus on conventions concerned with object technology.

The notations I present here are based on standards used by Microsoft as well as many other companies, including Flash Creative Management. Yair Alan Griver described similar standards in his Visual FoxPro 3.0 Codebook. The wide acceptance of these standards is one of their great strengths. Nevertheless, programmers can still alter these standards to make them match their own needs. I added a couple of variations to these standards that serve my needs very well. Regardless, one of the advantages of standards is the fact that everybody knows them. Altered standards that seem to have some advantages might not work that well after all, since they can cause major confusion that outweighs all the gained advantages.

I'd like to discuss the original standards suggested by Microsoft and Flash Creative Management, as well as some of my own variations. You can decide for yourself whether or not these variations make sense or if you feel it's smarter to stick with the original version.

Object naming conventions

The original conventions suggest that all objects have to be named according to a single scheme. This scheme is based on notations used in other languages like Visual Basic. It suggests that every object name should have a three-letter prefix that specifies the base class.

It seems that very few people actually stick to this convention; they differentiate between two different groups of object names instead. One uses the three-letter prefix while the other one is more along the lines of variable naming conventions that I'll discuss in a moment.

Contained objects

Contained objects have a clearly defined ownership they belong to the objects that contain them. Often, these objects are composed using instance programming and pseudo-subclassing. Usually, they are created during design time (early composition), using drag and drop in the class designer. Sometimes they are assembled at runtime (late composition), usually due to some implementation issues like using classes that can't be modified in the Visual Class Designer. Contained objects are always members of other objects and cannot exist by themselves.

This is the kind of object name that uses the three-letter prefix to indicate the base class. The prefix is always lowercase, while the actual name begins with an uppercase character. The name doesn't contain underscores. If the name is a composition of multiple words, each word starts with an uppercase character. Here is a list of all prefixes used for object bases on FoxPro classes:

FoxPro class

Prefix

Example

ActiveDocument

acd

acdInvoiceApplet

CheckBox

chk

chkItemIsActive

Column (Grid-Column)

col or grc

colCustomerName
grcLineItemNumber

ComboBox

cbo or cmb

cobLanguagecmbCustomerGroup

CommandButton

cmd

cmdApply

Container

cnt

cntCustomerInfo

Control

ctl

ctlAddressField

Custom

cus

cusBehavior

EditBox

edt or txt

EdtMemo
txtComment

Form

frm, doc or dlg

frmCustomer
docContract
dlgOpenTable

FormSet

frs

frsPayroll

Grid

grd

grdLineItems

Header (Grid-Header)

grh or hea

grhCaption
heaDescription

Hyperlink

hyp or lnk

hypEMailAddress
lnkHomePage

Image

img or pic

imgWizard
picLogo

Label

lbl

lblName

Line

lin

linHorizontal

ListBox

lst

lstStyles

OLEControl (ActiveX Control)

ole or acx

oleTreeView
acxListView

OLEBoundControl

ole or olb

oleQuickTime
olbEmbeddedObject

OptionButton

opt

optYes

OptionGroup

ogr or opg

ogrOutput
opgDestination

Page

pag

pagStep1

PageFrame

pgf

pgfWizard

ProjectHook

pjh

pjhVisualWebBuilderProject

Separator

sep

sepDocument

Shape

shp

shpRectangle

Spinner

spn

spnPercentage

TextBox

txt

txtName

Timer

tmr

tmrObserver

Toolbar

tbr

tbrNavigation

Keep in mind that these conventions are meant to be helpful, not a burden. For this reason, some of the prefixes aren't used very often. ProjectHooks, for instance, are usually used at design time only. Unless you are creating a tool you want to give away, you probably won't want to bother with these conventions. Some objects like the separator simply don't do a whole lot; for this reason, many people don't even go through the hassle of defining a name. That's fine.

The only personal variation I added is the txt prefix for edit boxes. Even though this prefix is already used for regular text boxes, I found that I often end up replacing edit boxes with text boxes or vice versa. The special naming convention for the edit boxes became a major hassle because I had to go through all my code and replace the name. After all, edit boxes are just specialized text boxes that allow longer text.

Stand-alone objects

The second group of objects are stand-alone objects. Most of the contained objects are used for the user interface. For this reason, there are more stand-alone objects than contained ones. Stand-alone objects are created using CreateObject() or NewObject() functions rather than by .AddObject() or .NewObject() methods. Typically, the ownership of these objects is not clearly defined. An object can create a reference to an existing object and keep it alive even though the previous owner has already released it.

Naming of stand-alone objects is very similar to naming variables. They have a scope and a type, which is always "o." Keep in mind that references to stand-alone objects are just variables. The other issues attached to stand-alone objects are discussed in the "Variable naming conventions" section.

Names for stand-alone objects are always chosen in source code, just as you define variable names.

Class naming conventions

Just as we have naming conventions for objects, we also have conventions for the classes they are based on. Unlike the conventions for object naming, these conventions are simple and straightforward. Typically, classes have a lowercase, one-letter prefix indicating whether a class is concrete or abstract.

Class type

Prefix

Example

Abstract

a

aDialog

Concrete

c

cPrintDialog

Originally, people used "c" to indicate a class. This doesn't make a whole lot of sense, though, because classes can be easily identified as such. Therefore, no special indication is needed. Whether a class is abstract or concrete is valuable information. There is no other simple way to specify that a class is abstract, which makes this simple naming convention a powerful and elegant solution.

 

Variable naming conventions

This topic is not entirely related to object-oriented technology, but since object references are just variables with fancy names, I have a good excuse to discuss variable naming conventions as well.

Variables typically have a two-letter lowercase prefix that indicates their scope and type. Each word of the actual name starts with an uppercase letter. No underscores are used.

Scope

Prefix

Example

Public (Global)

<none> or g

gcUserName
oApplication

Private

p

pcHTMLOutput

Local

l

lcLine

Parameter

t, p or l

tcItemId
lcCustomerId
pcCustomerName

Property (Attribute)

<none> or a

Customer.cName
Invoice.acItemId

The scope is quite straightforward. One of my variations is to use an "l" or "p" for parameters instead of the "t". I don't think the "t" adds a whole lot, but it hides the actual scope. In Visual FoxPro, parameters can be private or local. It wasn't like that in FoxPro 2.x since there were no local variables. However, the "t" is a dinosaur brought over from the old days and it takes away the information that "l" or "p" provides.

Object references are treated a little differently than regular variables. Whenever they are public (global), the notation doesn't require a scope, so you'll see oApp, but not goApp. Why? Well, I don't know, but it doesn't seem to hurt anything since global object references are the only variables that don't have a scope.

Another special case is properties. Their scope is automatically determined by the object they belong to. Some people add an "a" for "attribute" (that's what C++ people call properties). I don't have a problem with that, but I don't see a real advantage either. Others use an "s" for "static," because properties fulfill the requirements for a static variable, at least when it comes to object lifetime and visibility. I don't agree with that, since this is only true when the property is protected; a property is not just a regular variable after all. Also, there is no such a thing as a "static property." FoxPro doesn't support that, but I still try to avoid the confusion who knows what new features Visual FoxPro 7.0 will have? The same is true for real static variables. I do like the idea of adding the visibility to the property names, though. This has saved me many times from trying to access a property that was protected and therefore not visible. The following table demonstrates these prefixes:

Scope

Prefix

Example

Public (Global)

g

THISFORMSET.gnToolbars

Protected

p

THIS.pcUserName

Hidden

h

THIS.hcPassword

The following is a list of all variable types used in Visual FoxPro:

Type

Prefix

Example

Array

a

laItems(1,1)

Character

c

GcUserName

Collection

a or e

laForms(1,1)
peForms(1,1)

Currency

y

lyPrice

Date

d

LdLastModified

DateTime

t

ltTimestamp

Double

b

pbValue

Float

f

lfTotal

General

g

lgVideo

Integer

i

liCounter

Logical

l

llActive

Memo

m

pmComments

Numeric

n

lnLineNumber

Object

o

oApplication

Variant

v

lvReturnValue

These variables are pretty straightforward. The only one that requires some extra explanation is the collection. Collections are either treated like regular arrays, or they use the letter "e". I guess this was the only letter of the word "collection" that wasn't taken by another variable type. I don't see a real advantage to using the "e" instead of the simpler and more intuitive "a". Array collections aren't real collections anyway, so it doesn't really matter.

Field naming conventions

There is no special naming convention for table fields. It's obvious that fields can't really have a scope, since they're always visible throughout the current data session. Indicating the scope in the field name would be pointless. Not quite as obvious is the reason for dropping the field type. Let's discuss that in a little more detail.

One reason for adding the type to variables is the fact that FoxPro treats all variables as "semi-variants." Variables do have a certain type, but you can change that type simply by assigning a new value. This is powerful, but also dangerous. The naming convention makes it obvious if somebody assigns a value of the wrong type to a variable.

Fields, on the other hand, aren't variants. Therefore, the danger of assigning an invalid value isn't as great; and even if it happens, you'll get an error message right away. This helps to avoid hard-to-find bugs and anomalies, and the naming convention isn't really necessary.

One might argue that the field type is still a helpful hint, especially when scattering data to objects, and I have to agree. But hey! Nobody says you can't add the type in your field names if you want to.

Method naming conventions

For some mystical reason, nobody so far has come up with naming conventions for methods. There would be some good reasons to do so. Methods have return values of certain types. They also request a specific number of parameters some by value and others by reference. We have to figure out all these issues by ourselves. However, I have to admit that it would be pretty weird to pack all this information into a naming convention, but adding the visibility and the return type couldn't hurt.

The following tables show some suggestions:

Scope

Prefix

Example

Public (Global)

g or none

THISFORMSET.glRefreshToolbars()
THISFORM.cGetOriginalCaption()

Protected

p

THIS.pcGetName()

Hidden

h

THIS.hlValidatePassword()

The return type of a method is very similar to its variable type. However, there are some differences in the details, mostly because not every field type can be a return type as well.

Return Type

Prefix

Example

Character

c

THIS.gcGetUserName()

Currency

y

THIS.pyGetPrice()

Date

d

THIS.hdGetLastModifiedDate()

DateTime

t

oApplication,gtGetTimestamp()

Logical

l

loInvoice.plIsActive()

Memo

m or c

THIS.pmGetComments()
loHTML.gcGetOutput()

None

x or none

loMail.SendMail
oApplication.xRefreshAllForms()

Numeric

n

THIS.gnGetCurrentLineNumber()

Object

o

goDataService.gpGetRecord()

Variant

v

THISFORM.txtPhone.gvGetNumber()

Methods that are visible throughout an application and don't have a return value are about as close as you can get to defining your own commands in Visual FoxPro. Whenever I create a method that does something I'd really like to see as a native Visual FoxPro command, I don't add any prefixes to it.

A note about parentheses: I don't add them, because I don't think using them with methods adds a whole lot. The danger of confusing methods and properties is minimal, especially when using proper naming conventions. The only scenario where methods could be confused with properties is when they are used to assign a value to another variable or property, as in the following example:

lcCaption = THISFORM.Caption

lcCaption = THISFORM.GetCaption()

The first line refers to a property and the second one calls a method. In this case, the parentheses are required anyway. In all the other scenarios, it's obvious whether the code represents a property or a method.

Keep in mind that this is not part of the original conventions. However, I don't see a good reason to use naming conventions for properties and variables but not for methods.

 

Other conventions

There are a number of other conventions that we haven't discussed. Some are concerned with coding style, others with table naming, and so on. Other conventions take an approach that's quite different from the Hungarian Notation I discussed in this chapter.

This book is not the place to discuss all of these. Other people have done an outstanding job doing that, so I decided to stick to the topic and talk about object-oriented programming instead.

Advantages and disadvantages of naming conventions

As mentioned above, the question of whether one wants to use naming conventions or not is rather religious and hardly ever objective. As a believer, I'm in danger of treating the topic the same way, but I'll still try to look at the downsides from an objective point of view.

One concern with using naming conventions is that one might lose the advantage of alphabetically sorted lists. Properties that have a prefix will not show up sorted correctly in property sheets and in the Class Browser. I don't see a major problem with that, especially since user-defined properties are always at the bottom of the list anyway, and therefore aren't sorted properly. I guess everyone has to decide for himself whether this is a disadvantage or not. If it bothers him, I have to grant him a point.

Another concern is the readability of source code. My opinion is that prefixes don't affect readability very much. It might take a little time to get used to it, but then it shouldn't be an issue anymore. The information you can get out of the prefix should outweigh the disadvantages by far. But again: If one doesn't like it, I couldn't argue with him. After all, this is all based on personal opinion.

As with most techniques described in this book, the advantages don't come for free if you just blindly follow the guidelines. The actual naming of variables, properties and methods is at least equally important as following the actual notation. The variable name "lnX", for instance, is a lot worse than using "Counter", even though the latter doesn't follow the naming convention. The obvious solution would be to use "lnCounter", which combines the standard with an intuitive name.

Other examples are even more obvious. Using "lnLine" and "lcLine" is a good one. I use these often, especially when iterating through lines of a memo field.

Sometimes, a name that seems to be intuitive is not as obvious as it first seems. Let's consider "Number," for instance. How could we know if "TelephoneNumber" is numeric or alphanumeric? What about "CustomerNumber"? Using "lcTelephoneNumber" and "lnCustomerNumber" instead clarifies the situation.

Hungarian Notation also makes debugging a lot easier. If you treat properties and memvars as if they were not variants and all of a sudden "lnCount" is character, you have valuable information about what's gone wrong.

Naming conventions in interfaces

Naming conventions should not be used in programming interfaces provided for other programmers. Imagine using a third-party class library that uses a naming convention you are not familiar with. This could end up being a major disaster, since you start mixing different conventions and therefore lose the advantages of either one. It's far better to use a component that doesn't use any conventions at all. In this case you lose the advantage of conventions in that component, but it doesn't hurt your own conventions. If not having the convention is a problem for you, you could always create a wrapper that uses your conventions.

Take the Visual FoxPro base classes, for example. None of them follows Hungarian Notation, even though Microsoft promotes that idea in the Visual FoxPro documentation. Keep in mind that all those conventions are just suggestions. Forcing someone to use a notation he doesn't like does more damage than good.



Advanced Object Oriented Programming with Visual FoxPro 6. 0
Advanced Object Oriented Programming with Visual FoxPro 6.0
ISBN: 0965509389
EAN: 2147483647
Year: 1998
Pages: 113
Authors: Markus Egger

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net