5.25 Namespace Pollution


5.25 Namespace Pollution

One problem with creating libraries with a lot of different modules is namespace pollution. A typical library module will have a #include file associated with it that provides external definitions for all the routines, constants, variables, and other symbols provided in the library. Whenever you want to use some routines or other objects from the library, you would typically #include the library's header file in your project. As your libraries get larger and you add declarations in the header file, it becomes likely that the names you've chosen for your library's identifiers will conflict with names you want to use in your current project. This is known as namespace pollution: Library header files pollute the namespace with names you typically don't need in order to gain easy access to the few routines in the library you actually use. Most of the time those names don't harm anything — unless you want to use those names for your own purposes.

HLA requires that you declare all external symbols at the global (program/unit) level. You cannot, therefore, include a header file with external declarations within a procedure. As such, there will be no naming conflicts between external library symbols and symbols you declare locally within a procedure; the conflicts will only occur between the external symbols and your global symbols. While this is a good argument for avoiding global symbols as much as possible in your program, the fact remains that most symbols in an assembly language program will have global scope. So another solution is necessary.

HLA's solution, is to put most of the library names in a namespace declaration section. A namespace declaration encapsulates all declarations and exposes only a single name (the namespace identifier) at the global level. You access the names within the namespace by using the familiar dot notation (see the discussion of namespaces in the previous chapter). This reduces the effect of namespace pollution from many dozens or hundreds of names down to a single name.

Of course, one disadvantage of using a namespace declaration is that you have to type a longer name in order to reference a particular identifier in that name space (i.e., you have to type the namespace identifier, a period, and then the specific identifier you wish to use). For a few identifiers you use frequently, you might elect to leave those identifiers outside of any namespace declaration. For example, the HLA Standard Library does not define the symbols malloc, free, or nl (among others) within a namespace. However, you want to minimize such declarations in your libraries to avoid conflicts with names in your own programs. Often, you can choose a namespace identifier to complement your routine names. For example, the HLA Standard Library's string copy routine was named after the equivalent C Standard Library function, strcpy. HLA's version is str.cpy. The actual function name is cpy; it happens to be a member of the str namespace, hence the full name str.cpy, which is very similar to the comparable C function. The HLA Standard Library contains several examples of this convention. The arg.c and arg.v functions are another pair of such identifiers (corresponding to the C identifiers argc and argv).

Using a namespace in a header file is no different than using a namespace in a program or unit, though you do not normally put actual procedure bodies in a namespace. Here's an example of a typical header file containing a namespace declaration:

 // myHeader.hhf - // // Routines supported in the myLibrary.lib file. namespace myLib;      procedure func1; @external;      procedure func2; @external;      procedure func3; @external; end myLib; 

Typically, you would compile each of the functions (func1..func3) as separate units (so each has its own object file and linking in one function doesn't link them all). Here's what a sample unit declaration for one of these functions:

 unit func1Unit; #includeonce( "myHeader.hhf" ) procedure myLib.func1; begin func1;      << code for func1 >> end func1; end func1Unit; 

You should notice two important things about this unit. First, you do not put the actual func1 procedure code within a namespace declaration block. By using the identifier myLib.func1 as the procedure's name, HLA automatically realizes that this procedure declaration belongs in a namespace. The second thing to note is that you do not preface func1 with "myLib." after the begin and end clauses in the procedure. HLA automatically associates the begin and end identifiers with the procedure declaration, so it knows that these identifiers are part of the myLib namespace and it doesn't make you type the whole name again.

Important note: When you declare external names within a namespace, as was done in func1Unit previously, HLA uses only the function name (func1 in this example) as the external name. This creates a namespace pollution problem in the external namespace. For example, if you have two different namespaces, myLib and yourLib and they both define a func1 procedure, the linker will complain about a duplicate definition for func1 if you attempt to use functions from both these library modules. There is an easy work-around to this problem: Use the extended form of the @external directive to explicitly supply an external name for all external identifiers appearing in a namespace declaration. For example, you could solve this problem with the following simple modification to the myHeader.hhf file above:

 // myHeader.hhf // // Routines supported in the myLibrary.lib file. namespace myLib;      procedure func1; @external( "myLib_func1" );      procedure func2; @external( "myLib_func2" );      procedure func3; @external( "myLib_func3" ); end myLib; 

This example demonstrates an excellent convention you should adopt: When exporting names from a namespace, always supply an explicit external name and construct that name by concatenating the namespace identifier with an underscore and the object's internal name.

The use of namespace declarations does not completely eliminate the problems of namespace pollution (after all, the namespace identifier is still a global object, as anyone who has included stdlib.hhf and attempted to define a "cs" variable can attest), but namespace declarations come pretty close to eliminating this problem. Therefore, you should use namespace everywhere practical when creating your own libraries.




The Art of Assembly Language
The Art of Assembly Language
ISBN: 1593272073
EAN: 2147483647
Year: 2005
Pages: 246
Authors: Randall Hyde

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