SlideShare une entreprise Scribd logo
1  sur  4
Télécharger pour lire hors ligne
T
HE MOTIVATION FOR NAMESPACES IN C++
is twofold and easy to sketch out: to
reduce the scope, quite literally, for name
clashes at the global level and to indicate
the origin, ownership and conceptual grouping of
a global identifier. However, it turns out that
while the motivation and core mechanism are
fairly straightforward, their effective use is more
of a challenge. As with so many things in
programming, having a rough idea and a piece of
syntax is rarely enough. Let’s go back to first
principles.
The clash
Consider a common-or-garden date class. Reasonable
names for such a type include date and Date.
Indeed, unless someone is wilfully ignoring received
wisdom on writing good C++—such as choosing
DATE, which uses the macro-naming convention,
or _Date, which uses a name reserved for use by the
compiler and standard library—that pretty much
exhausts the available options for the most obvious
name.
What happens if someone else has chosen the
same name for a type? If you are working on
your own and are not linking in third party code,
the odds are that the problem of name clashes will
not affect you. However, a lot of software is
developed by teams of programmers building on
existing code, developed both in-house and
externally (‘out-house’, given the quality of some
of what is available both freely and commercially).
While you don’t expect name clashes to be a daily
occurrence, when they happen they are tedious and
wasteful. Someone has to make a change. The
chances are that it will be you. You have to start
thinking laterally for a solution if the problem occurs
between code from two libraries over which you
have no control. And don’t think that the problem
manifests itself only in the source at compile time
when you include two headers with the clashing
names: the problem can manifest itself at link time,
or even at run time as a bug.The compiler may detect
duplicate symbols, such as two definitions for
the default constructor, date::date(). If the clash
is with templates or inline functions, the problem
can be more subtle. Your code may link, but at run
time strange things start to happen.
For most compilers, template or inline function
code that the compiler chooses not to inline
(remember, inline is a suggestion, not a command)
is generated out of line in each translation unit in
which it is used. For you to end up with a single,
unique definition in the final executable image, the
linker has to discard such duplicates. In this case,
the baby and bathwater may well go out together,
so that programmer-generated duplicates are
thrown out with the compiler-generated ones.
This means that in the final image the ‘wrong’ one
may be called, hence bugs.
There are a number of creative solutions for
compile- and link-time clashes, including preprocessor
surgery or hiding the combatant names from one
another by strictly segregating their usage across
separate DLLs. This isn’t a strategy, it is post hoc
firefighting.
What needs fixing?
Before addressing how clashes can be resolved more
intentionally, it is perhaps worth pausing for a
moment to consider what exactly needs solving.
First of all, the problem concerns clashes in the
global namespace, i.e. the top-level names in
your program. Local variables and class members
are not the problem and the plain scope-resolution
operator (::) has always been able to resolve
such issues. Second, clashes related to the use of
the preprocessor are of a different kind. The
q Name collisions between classes or
constants are more annoying than
they are common.
q Using identifier prefixes or nesting
names inside a struct is a step in the
right direction,but only a small step.
q C++ namespaces introduce named,
extensible scopes with all the right
collision avoidance properties.
q In choosing a good name for a
namespace,pick on something stable.
Don't use department names,
company names or domain names.
FACTS AT A GLANCE
C++ WORKSHOP
At the very least, C++ namespaces do what they say. The idea of namespaces is
quite simple, but their sensible application is not always obvious. Kevlin Henney
explains how to avoid getting lost in namespace
What’s in a name?
40 APPLICATION DEVELOPMENT ADVISOR q www.appdevadvisor.co.uk
MARCH–APRIL 2003 41
solution to such problems is quite simply to stop abusing the
preprocessor. Not exactly a complex solution, but, as with any
wasting addiction, the habit may be hard for some C++
programmers to break. Third, clashing global variables, i.e.
non-const data visible to a whole program, tend to suggest
that a body of code has much deeper problems than its authors
either recognise or are prepared to admit.
Therefore, reasonably, non-nested type names can clash and
constant names can clash (most likely, enum constants). What about
function names? It turns out that they rarely clash. Overloading
tends to take them out of each other’s way. It is rare that two functions
with the same name and argument count will match exactly because
they will typically work on separate types: that is, types that are
specific to their library or subsystem.
With a traditional object-oriented style, you will not find that
many functions floating around the global namespace, so function
name clashes effectively disappear off the radar. Most functions
will be clearly associated with classes as static or, most commonly,
non-static members.The most common non-member functions
in a C++ OO program will be overloaded operators, and these will
be associated with the type they operate on, so they are already uniquely
qualified and in no need of clash protection.
What about templates? For class templates clashes are as much
a problem as they are for ordinary type names. Function templates,
however, fall between the two poles. They may clash with other
function templates that are similarly parameterised. For instance,
two function templates with the same name taking a single
argument of parameterised type will be indistinguishable from
one another in the eyes of the compiler and linker, and will therefore
clash. However, if they have either different argument counts or
more specific argument types, such as a non-templated type
from their library of origin, they will pass by one another without
interference.
Some traditional approaches
Before namespaces were added to C++, there were basically two
proactive approaches that could be taken to avoiding name
clashes: You could either use a common prefix ahead of all
identifiers, or use structs or classes to provide a mini-namespace.
The problem with the first approach is that, in practice, most
choices for prefixes are one or two characters in length. Much more
than this is normally considered a chore, and it tends to hide the
real part of the name unless suitable spacing or separation is used,
which in practice means an underscore character. However,
there is not a lot of useful informational bandwidth in a couple
of characters. The chances that the abbreviations are both clearly
meaningful and suitably collision-proof are typically low. As a general
solution, there seem to be genuine practical and cognitive
problems with identifier prefixes of any length.
Another problem with prefixes is that many programmers
already use them for other purposes. It is true that in most such
cases the practice is not a particularly effective one (e.g. restating
the blindingly obvious by using C to prefix class names or the more
general T to prefix type names), but programmers nevertheless persist
in their use. You could end up with prefix soup if an uncritical
programmer fell for all the possible name mangling fashions.
Name mangling is really the responsibility of the language and
compiler. Compilers already mangle function names to include
class membership and argument type information. A common
pre-namespace idiom was to use empty classes or structs to wrap
typedefs or enum types. For expressing regular procedural functions,
some programmers also enclosed otherwise ordinary functions
in a scope, making them static members rather than ordinary
member functions.
As far as it goes, this technique is OK, but it doesn’t actually
go that far. Yes, it does reduce the chance of name collision, especially
between constants, such as enumerators. And yes, the use of the
scope-resolution operator is a visibly distinct separator between
the name of the scope and the name that is being enclosed. However,
to use any enclosed name always requires the fully qualified
name. There is no discounted concession or reasonable short cut
for frequent users. You wanted a distinct name, you got it and you’re
stuck with it. Perhaps more significantly, the enclosing scope is
in practice limited to a single header file. A class scope is a
closed construct: the scope cannot be extended to embrace new
content and it cannot span multiple header files. This makes the
technique useless for anything except simple modular wrapping.
Namespace, the final frontier
The C++ namespace construct was introduced to address all of the
issues outlined so far, and potentially more. If you are already familiar
with namespaces, the article has so far acted as a revision and reminder
of the motivation. It has possibly also pointed out a couple of things
that are not normally mentioned, such as the low priority that
should be attached to anticipating function name collisions.
A namespace is in some ways like a class and in many ways not:
q A namespace acts to introduce a scope that contains features
such as classes and functions. That scope can be opened and
closed in any file.
q A class can have a private section, but the contents of a
namespace are always public.
q Namespaces can nest only inside one another. They cannot be
nested inside classes or functions.
q A namespace cannot have the same name as another type defined
at the same level.
q Unlike a class, a namespace does not have a terminating
semi-colon.
q A namespace that has no name is both formally and obviously
an unnamed namespace. It allows you to keep names private
to a translation unit, displacing (and deprecating) a similar role
of static. Where static applies only to functions and data,
an unnamed namespace applies also to types.
q The global namespace is the scope outside of any named or
unnamed namespace. It is effectively the root and default
namespace.
q Entities with linkage that are enclosed in a namespace will have
their linkage name affected by the namespace.This means that
you cannot simply take some headers for a precompiled
library and wrap those headers in an alternative namespace:
the result won’t link because the original code was compiled
with the identifiers in the global namespace.
Directory listings revisited
To demonstrate a couple of these features in practice, let’s revisit
the directory listing classes described in two previous columns1, 2
.
Two classes, dir_stream and dir_iterator, were defined.The common
prefix seems to be crying out for some better factoring, and a
namespace offers a suitable approach. In the header defining the
stream we would have:
C++ WORKSHOP
42 APPLICATION DEVELOPMENT ADVISOR q www.appdevadvisor.co.uk
namespace dir
{
class stream
{
public:
explicit stream(const std::string &);
~stream();
operator const void *() const;
stream &operator>>(std::string &);
...
};
}
And in the header for the iterator:
namespace dir
{
class stream;
class iterator : public std::iterator<
std::input_iterator_tag, std::string>
{
public:
iterator();
explicit iterator(stream &);
~iterator();
const std::string &operator*() const;
const std::string &operator->() const;
iterator &operator++();
iterator operator++(int);
bool operator==(const iterator &) const;
bool operator!=(const iterator &) const;
...
};
}
The member function definitions appear in the same namespace.
For instance, the iterator’s postincrement operator defined in terms
of the preincrement operator:
namespace dir
{
...
iterator iterator::operator++(int)
{
iterator old = *this;
++*this;
return old;
}
...
}
Notice that names declared in the same namespace can be referred
to directly, without any scope resolution, when accessed elsewhere
in the same namespace.
Using declarations to your advantage
There are a number of different approaches to using a name from
a named namespace. The simplest is just using the fully qualified
name. Alternatively, there is a using declaration that imports a
specific name as a more local declaration, and then there is the
more sweeping using directive that imports all the names from
namespace for unqualified use:
using namespace std;
void list_dir(const string &name)
{
typedef ostream_iterator<string> out;
using dir::stream;
stream directory(name);
dir::iterator begin(directory), end;
copy(begin, end, out(cout, "n"));
}
using declarations and directives can appear at either global or
local scope. In the code example, a wholesale usage of the std
namespace is made at the global level, allowing unqualified use
of std::string, std::ostream_iterator, std::copy and std::cout.
A using declaration imports dir::stream for local use, whereas
dir::iterator is fully named for its use.
The usage in the fragment is contrived and more than a little
inconsistent. It demonstrates syntax and basic concepts, but
not necessarily best practice. There are different opinions as to
what constitutes best practice. Some advocates always use fully
qualified names and never employ using directives, whereas
others see no harm in them. In spite of the variation, there are
some valuable and general points that can be made.
Be consistent in how a particular namespace is pulled into code.
For example, because the std namespace is effectively part of the
common platform, some developers like to pull it all in with a
using directive in their source files.This is fine, so long as it is done
consistently. Inconsistently using a directive in one source file and
fully qualifying in another serves no useful development purpose.
As with other practices in software development, anything that’s
not useful should not be used.
Never use namespace using directives or declarations as a
convenience in header files, even for namespace std. In the
privacy of your own source file you can do what you want
without affecting other source files. Placing a using directive in
a header instantly floods any file that #includes it with a host of
unwanted and unnecessary names, pre-empting any policy that
file may have on namespace usage and roundly defeating the whole
point of namespaces. This is a frequent bad habit in a lot of
commercial code that I have seen, suggesting that even though
the idea of namespaces is quite simple, some programmers can
be even simpler.Therefore, always declare features in headers using
fully qualified names. If a function definition appears in a
header, because it is either inlined or templated, and fully
qualified names are considered too cumbersome in the function
body, place the using at the beginning of the function body, not
outside it. Such careful scoping ensures that headers are properly
self-contained.
What and how to name
This is all good, but when would you actually define namespaces
in your own code? It is one thing to say you have a language
mechanism, but quite another to say that you have a method that
makes sense of it.
A reasonable enough starting point would be to consider
defining a namespace when you might otherwise have been
tempted to use a common prefix on identifiers.The dir namespace
was an example of this.
C++ WORKSHOP
Another reasonable starting point would be to consider a
namespace when a class or struct seems only to have public members
that are types, constants or static member functions. An
exception to this is where the type in question defines a trait, a
policy or both
3
. In the current language, namespaces cannot be
templated or used as template parameters, so a struct is really the
most suitable expression of such designs.
In search of stability
I will leave you with one final recommendation to consider: make
sure that your namespace names are stable and long lived. If a name
is not stable, it means that you will have to change the namespace
name and therefore any code that depends on it when the name
is no longer applicable, even though all the namespace contents
are otherwise unaffected. An architecture should be structured
so that stable concepts depend on more stable, not less stable,
concepts.
What, specifically, have I got in mind? Organisational structure
is the main offender. What at first seems like a good idea—enclosing
your code in a namespace that corresponds to your company or
department—turns out to be quite the opposite. It is a superficially
good idea that lacks any sound reasoning or depth when you scratch
the surface.
Department or division partitioning is generally far less stable
than code for an installed system. Companies reorganise themselves
internally whenever they need to be seen to be doing something
by their customers or shareholders, or simply when they’re
bored. The reorganisation may be as simple as renaming a few
departments or it may involve relocations, regional restructuring
and redundancies. Experience suggests that such events are more
frequent than they are effective, but whichever way you look at
it, an organisation’s internal structure is clearly not a bellwether
of stability.
Likewise, anyone who has been in software development for
more than a few minutes will know that company names are as
unstable as transuranic elements. Companies merge, demerge, spin-
off, acquire, rebrand and debrand, add a dot-com suffix or
remove a dot-com suffix with a regularity that keeps industry
commentators employed, but does little for anyone else. Even worse
is to base a namespace on a company’s domain name, an even less
stable concept. Source code is more likely to outlive any specific
incarnation of its sponsor. So, choose cautiously and wisely;
namespaces are easier in theory than in practice. s
References/bibliography:
1. Kevlin Henney, “Promoting polymorphism”, Application
Development Advisor, October 2001
2. Kevlin Henney, “The perfect couple”, Application
Development Advisor, November-December 2001
3. Kevlin Henney, “Flag waiving”, Application Development
Advisor, April 2002
Kevlin Henney is an independent software development consultant
and trainer. He can be reached at www.curbralan.com
C++ WORKSHOP
ADA's free e-mail newsletter
for software developers
By now many of you will have had a free on-line newsletter which is a service to
readers of ADA and packed with the very latest editorial for software and
application developers. However, some of our readers don't get this free service.
If you don't get your free newsletter it's for one of two good reasons.
b
Even though you subscribed to ADA,
you haven't supplied us with your e-mail address.
c
You ticked the privacy box at the time you subscribed
and we can't now send you our newsletter.
Sign up for this free service at www.appdevadvisor.co.uk/subscribe.htm
www.appdevadvisor.co.uk/subscribe.htm

Contenu connexe

Tendances

Coding standards for java
Coding standards for javaCoding standards for java
Coding standards for javamaheshm1206
 
Standards For Java Coding
Standards For Java CodingStandards For Java Coding
Standards For Java CodingRahul Bhutkar
 
.NET Coding Standards For The Real World (2012)
.NET Coding Standards For The Real World (2012).NET Coding Standards For The Real World (2012)
.NET Coding Standards For The Real World (2012)David McCarter
 
WordCamp US: Clean Code
WordCamp US: Clean CodeWordCamp US: Clean Code
WordCamp US: Clean Codemtoppa
 
Clean Code summary
Clean Code summaryClean Code summary
Clean Code summaryJan de Vries
 
Standard coding practices
Standard coding practicesStandard coding practices
Standard coding practicesAnilkumar Patil
 
Creating Stable Assignments
Creating Stable AssignmentsCreating Stable Assignments
Creating Stable AssignmentsKevlin Henney
 
Mark asoi ppt
Mark asoi pptMark asoi ppt
Mark asoi pptmark-asoi
 
Systematic error management - we ported rudder to zio
Systematic error management - we ported rudder to zioSystematic error management - we ported rudder to zio
Systematic error management - we ported rudder to ziofanf42
 
Desenvolvendo um Framework com TDD - Um Diário de Bordo - Agile Trends 2014
Desenvolvendo um Framework com TDD - Um Diário de Bordo - Agile Trends 2014Desenvolvendo um Framework com TDD - Um Diário de Bordo - Agile Trends 2014
Desenvolvendo um Framework com TDD - Um Diário de Bordo - Agile Trends 2014eduardomg23
 
Listen and look at your PHP code
Listen and look at your PHP codeListen and look at your PHP code
Listen and look at your PHP codeGabriele Santini
 
Journey's diary developing a framework using tdd
Journey's diary   developing a framework using tddJourney's diary   developing a framework using tdd
Journey's diary developing a framework using tddeduardomg23
 
Introduction to BDD (Behavior-Driven Development)
Introduction to BDD (Behavior-Driven Development)Introduction to BDD (Behavior-Driven Development)
Introduction to BDD (Behavior-Driven Development)Juan Rodríguez
 
Coding standards and guidelines
Coding standards and guidelinesCoding standards and guidelines
Coding standards and guidelinesbrijraj_singh
 

Tendances (20)

Coding standards for java
Coding standards for javaCoding standards for java
Coding standards for java
 
Standards For Java Coding
Standards For Java CodingStandards For Java Coding
Standards For Java Coding
 
.NET Coding Standards For The Real World (2012)
.NET Coding Standards For The Real World (2012).NET Coding Standards For The Real World (2012)
.NET Coding Standards For The Real World (2012)
 
WordCamp US: Clean Code
WordCamp US: Clean CodeWordCamp US: Clean Code
WordCamp US: Clean Code
 
Bb Tequila Coding Style (Draft)
Bb Tequila Coding Style (Draft)Bb Tequila Coding Style (Draft)
Bb Tequila Coding Style (Draft)
 
Clean Code summary
Clean Code summaryClean Code summary
Clean Code summary
 
Metaprogramming
MetaprogrammingMetaprogramming
Metaprogramming
 
Standard coding practices
Standard coding practicesStandard coding practices
Standard coding practices
 
Creating Stable Assignments
Creating Stable AssignmentsCreating Stable Assignments
Creating Stable Assignments
 
Codings Standards
Codings StandardsCodings Standards
Codings Standards
 
Mark asoi ppt
Mark asoi pptMark asoi ppt
Mark asoi ppt
 
Systematic error management - we ported rudder to zio
Systematic error management - we ported rudder to zioSystematic error management - we ported rudder to zio
Systematic error management - we ported rudder to zio
 
Cursus phpunit
Cursus phpunitCursus phpunit
Cursus phpunit
 
Desenvolvendo um Framework com TDD - Um Diário de Bordo - Agile Trends 2014
Desenvolvendo um Framework com TDD - Um Diário de Bordo - Agile Trends 2014Desenvolvendo um Framework com TDD - Um Diário de Bordo - Agile Trends 2014
Desenvolvendo um Framework com TDD - Um Diário de Bordo - Agile Trends 2014
 
Listen and look at your PHP code
Listen and look at your PHP codeListen and look at your PHP code
Listen and look at your PHP code
 
Journey's diary developing a framework using tdd
Journey's diary   developing a framework using tddJourney's diary   developing a framework using tdd
Journey's diary developing a framework using tdd
 
Refactoring 2 The Max
Refactoring 2 The MaxRefactoring 2 The Max
Refactoring 2 The Max
 
Introduction to BDD (Behavior-Driven Development)
Introduction to BDD (Behavior-Driven Development)Introduction to BDD (Behavior-Driven Development)
Introduction to BDD (Behavior-Driven Development)
 
Coding standards and guidelines
Coding standards and guidelinesCoding standards and guidelines
Coding standards and guidelines
 
Code Smell
Code SmellCode Smell
Code Smell
 

Similaire à What's in a Name?

C# and java comparing programming languages
C# and java  comparing programming languagesC# and java  comparing programming languages
C# and java comparing programming languagesShishir Roy
 
A Catalog Of Common Bugs In C Programming
A Catalog Of Common Bugs In C   ProgrammingA Catalog Of Common Bugs In C   Programming
A Catalog Of Common Bugs In C ProgrammingAllison Koehn
 
Migrating From Cpp To C Sharp
Migrating From Cpp To C SharpMigrating From Cpp To C Sharp
Migrating From Cpp To C SharpGanesh Samarthyam
 
GoF Design patterns I: Introduction + Structural Patterns
GoF Design patterns I:   Introduction + Structural PatternsGoF Design patterns I:   Introduction + Structural Patterns
GoF Design patterns I: Introduction + Structural PatternsSameh Deabes
 
If I Had a Hammer...
If I Had a Hammer...If I Had a Hammer...
If I Had a Hammer...Kevlin Henney
 
why c++11?
why c++11?why c++11?
why c++11?idrajeev
 
4 pillars of OOPS CONCEPT
4 pillars of OOPS CONCEPT4 pillars of OOPS CONCEPT
4 pillars of OOPS CONCEPTAjay Chimmani
 
C# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringC# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringEyob Lube
 
10 things you're doing wrong in Talend
10 things you're doing wrong in Talend10 things you're doing wrong in Talend
10 things you're doing wrong in TalendMatthew Schroeder
 
10 things you're doing wrong in Talend
10 things you're doing wrong in Talend10 things you're doing wrong in Talend
10 things you're doing wrong in TalendDatalytyx
 
Design patterns in_c_sharp
Design patterns in_c_sharpDesign patterns in_c_sharp
Design patterns in_c_sharpCao Tuan
 
c-for-c-programmers.pdf
c-for-c-programmers.pdfc-for-c-programmers.pdf
c-for-c-programmers.pdfSalar32
 
A Program Transformation Technique to Support Aspect-Oriented Programming wit...
A Program Transformation Technique to Support Aspect-Oriented Programming wit...A Program Transformation Technique to Support Aspect-Oriented Programming wit...
A Program Transformation Technique to Support Aspect-Oriented Programming wit...Sabrina Ball
 

Similaire à What's in a Name? (20)

The Perfect Couple
The Perfect CoupleThe Perfect Couple
The Perfect Couple
 
C# and java comparing programming languages
C# and java  comparing programming languagesC# and java  comparing programming languages
C# and java comparing programming languages
 
A Catalog Of Common Bugs In C Programming
A Catalog Of Common Bugs In C   ProgrammingA Catalog Of Common Bugs In C   Programming
A Catalog Of Common Bugs In C Programming
 
Migrating From Cpp To C Sharp
Migrating From Cpp To C SharpMigrating From Cpp To C Sharp
Migrating From Cpp To C Sharp
 
Bp301
Bp301Bp301
Bp301
 
GoF Design patterns I: Introduction + Structural Patterns
GoF Design patterns I:   Introduction + Structural PatternsGoF Design patterns I:   Introduction + Structural Patterns
GoF Design patterns I: Introduction + Structural Patterns
 
NamingConvention
NamingConventionNamingConvention
NamingConvention
 
If I Had a Hammer...
If I Had a Hammer...If I Had a Hammer...
If I Had a Hammer...
 
C# interview
C# interviewC# interview
C# interview
 
why c++11?
why c++11?why c++11?
why c++11?
 
4 pillars of OOPS CONCEPT
4 pillars of OOPS CONCEPT4 pillars of OOPS CONCEPT
4 pillars of OOPS CONCEPT
 
C# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoringC# coding standards, good programming principles & refactoring
C# coding standards, good programming principles & refactoring
 
Scala a case4
Scala a case4Scala a case4
Scala a case4
 
10 things you're doing wrong in Talend
10 things you're doing wrong in Talend10 things you're doing wrong in Talend
10 things you're doing wrong in Talend
 
10 things you're doing wrong in Talend
10 things you're doing wrong in Talend10 things you're doing wrong in Talend
10 things you're doing wrong in Talend
 
Design patterns in_c_sharp
Design patterns in_c_sharpDesign patterns in_c_sharp
Design patterns in_c_sharp
 
c-for-c-programmers.pdf
c-for-c-programmers.pdfc-for-c-programmers.pdf
c-for-c-programmers.pdf
 
C++ book
C++ bookC++ book
C++ book
 
Oops index
Oops indexOops index
Oops index
 
A Program Transformation Technique to Support Aspect-Oriented Programming wit...
A Program Transformation Technique to Support Aspect-Oriented Programming wit...A Program Transformation Technique to Support Aspect-Oriented Programming wit...
A Program Transformation Technique to Support Aspect-Oriented Programming wit...
 

Plus de Kevlin Henney

The Case for Technical Excellence
The Case for Technical ExcellenceThe Case for Technical Excellence
The Case for Technical ExcellenceKevlin Henney
 
Empirical Development
Empirical DevelopmentEmpirical Development
Empirical DevelopmentKevlin Henney
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that LetterKevlin Henney
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that LetterKevlin Henney
 
Solid Deconstruction
Solid DeconstructionSolid Deconstruction
Solid DeconstructionKevlin Henney
 
Procedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went AwayProcedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went AwayKevlin Henney
 
Structure and Interpretation of Test Cases
Structure and Interpretation of Test CasesStructure and Interpretation of Test Cases
Structure and Interpretation of Test CasesKevlin Henney
 
Refactoring to Immutability
Refactoring to ImmutabilityRefactoring to Immutability
Refactoring to ImmutabilityKevlin Henney
 
Turning Development Outside-In
Turning Development Outside-InTurning Development Outside-In
Turning Development Outside-InKevlin Henney
 
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Kevlin Henney
 
Thinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation QuadrantThinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation QuadrantKevlin Henney
 
The Error of Our Ways
The Error of Our WaysThe Error of Our Ways
The Error of Our WaysKevlin Henney
 

Plus de Kevlin Henney (20)

Program with GUTs
Program with GUTsProgram with GUTs
Program with GUTs
 
The Case for Technical Excellence
The Case for Technical ExcellenceThe Case for Technical Excellence
The Case for Technical Excellence
 
Empirical Development
Empirical DevelopmentEmpirical Development
Empirical Development
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
 
Lambda? You Keep Using that Letter
Lambda? You Keep Using that LetterLambda? You Keep Using that Letter
Lambda? You Keep Using that Letter
 
Solid Deconstruction
Solid DeconstructionSolid Deconstruction
Solid Deconstruction
 
Get Kata
Get KataGet Kata
Get Kata
 
Procedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went AwayProcedural Programming: It’s Back? It Never Went Away
Procedural Programming: It’s Back? It Never Went Away
 
Structure and Interpretation of Test Cases
Structure and Interpretation of Test CasesStructure and Interpretation of Test Cases
Structure and Interpretation of Test Cases
 
Agility ≠ Speed
Agility ≠ SpeedAgility ≠ Speed
Agility ≠ Speed
 
Refactoring to Immutability
Refactoring to ImmutabilityRefactoring to Immutability
Refactoring to Immutability
 
Old Is the New New
Old Is the New NewOld Is the New New
Old Is the New New
 
Turning Development Outside-In
Turning Development Outside-InTurning Development Outside-In
Turning Development Outside-In
 
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
Clean Coders Hate What Happens To Your Code When You Use These Enterprise Pro...
 
Thinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation QuadrantThinking Outside the Synchronisation Quadrant
Thinking Outside the Synchronisation Quadrant
 
Code as Risk
Code as RiskCode as Risk
Code as Risk
 
Software Is Details
Software Is DetailsSoftware Is Details
Software Is Details
 
Game of Sprints
Game of SprintsGame of Sprints
Game of Sprints
 
Good Code
Good CodeGood Code
Good Code
 
The Error of Our Ways
The Error of Our WaysThe Error of Our Ways
The Error of Our Ways
 

Dernier

Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 

Dernier (20)

Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 

What's in a Name?

  • 1. T HE MOTIVATION FOR NAMESPACES IN C++ is twofold and easy to sketch out: to reduce the scope, quite literally, for name clashes at the global level and to indicate the origin, ownership and conceptual grouping of a global identifier. However, it turns out that while the motivation and core mechanism are fairly straightforward, their effective use is more of a challenge. As with so many things in programming, having a rough idea and a piece of syntax is rarely enough. Let’s go back to first principles. The clash Consider a common-or-garden date class. Reasonable names for such a type include date and Date. Indeed, unless someone is wilfully ignoring received wisdom on writing good C++—such as choosing DATE, which uses the macro-naming convention, or _Date, which uses a name reserved for use by the compiler and standard library—that pretty much exhausts the available options for the most obvious name. What happens if someone else has chosen the same name for a type? If you are working on your own and are not linking in third party code, the odds are that the problem of name clashes will not affect you. However, a lot of software is developed by teams of programmers building on existing code, developed both in-house and externally (‘out-house’, given the quality of some of what is available both freely and commercially). While you don’t expect name clashes to be a daily occurrence, when they happen they are tedious and wasteful. Someone has to make a change. The chances are that it will be you. You have to start thinking laterally for a solution if the problem occurs between code from two libraries over which you have no control. And don’t think that the problem manifests itself only in the source at compile time when you include two headers with the clashing names: the problem can manifest itself at link time, or even at run time as a bug.The compiler may detect duplicate symbols, such as two definitions for the default constructor, date::date(). If the clash is with templates or inline functions, the problem can be more subtle. Your code may link, but at run time strange things start to happen. For most compilers, template or inline function code that the compiler chooses not to inline (remember, inline is a suggestion, not a command) is generated out of line in each translation unit in which it is used. For you to end up with a single, unique definition in the final executable image, the linker has to discard such duplicates. In this case, the baby and bathwater may well go out together, so that programmer-generated duplicates are thrown out with the compiler-generated ones. This means that in the final image the ‘wrong’ one may be called, hence bugs. There are a number of creative solutions for compile- and link-time clashes, including preprocessor surgery or hiding the combatant names from one another by strictly segregating their usage across separate DLLs. This isn’t a strategy, it is post hoc firefighting. What needs fixing? Before addressing how clashes can be resolved more intentionally, it is perhaps worth pausing for a moment to consider what exactly needs solving. First of all, the problem concerns clashes in the global namespace, i.e. the top-level names in your program. Local variables and class members are not the problem and the plain scope-resolution operator (::) has always been able to resolve such issues. Second, clashes related to the use of the preprocessor are of a different kind. The q Name collisions between classes or constants are more annoying than they are common. q Using identifier prefixes or nesting names inside a struct is a step in the right direction,but only a small step. q C++ namespaces introduce named, extensible scopes with all the right collision avoidance properties. q In choosing a good name for a namespace,pick on something stable. Don't use department names, company names or domain names. FACTS AT A GLANCE C++ WORKSHOP At the very least, C++ namespaces do what they say. The idea of namespaces is quite simple, but their sensible application is not always obvious. Kevlin Henney explains how to avoid getting lost in namespace What’s in a name? 40 APPLICATION DEVELOPMENT ADVISOR q www.appdevadvisor.co.uk
  • 2. MARCH–APRIL 2003 41 solution to such problems is quite simply to stop abusing the preprocessor. Not exactly a complex solution, but, as with any wasting addiction, the habit may be hard for some C++ programmers to break. Third, clashing global variables, i.e. non-const data visible to a whole program, tend to suggest that a body of code has much deeper problems than its authors either recognise or are prepared to admit. Therefore, reasonably, non-nested type names can clash and constant names can clash (most likely, enum constants). What about function names? It turns out that they rarely clash. Overloading tends to take them out of each other’s way. It is rare that two functions with the same name and argument count will match exactly because they will typically work on separate types: that is, types that are specific to their library or subsystem. With a traditional object-oriented style, you will not find that many functions floating around the global namespace, so function name clashes effectively disappear off the radar. Most functions will be clearly associated with classes as static or, most commonly, non-static members.The most common non-member functions in a C++ OO program will be overloaded operators, and these will be associated with the type they operate on, so they are already uniquely qualified and in no need of clash protection. What about templates? For class templates clashes are as much a problem as they are for ordinary type names. Function templates, however, fall between the two poles. They may clash with other function templates that are similarly parameterised. For instance, two function templates with the same name taking a single argument of parameterised type will be indistinguishable from one another in the eyes of the compiler and linker, and will therefore clash. However, if they have either different argument counts or more specific argument types, such as a non-templated type from their library of origin, they will pass by one another without interference. Some traditional approaches Before namespaces were added to C++, there were basically two proactive approaches that could be taken to avoiding name clashes: You could either use a common prefix ahead of all identifiers, or use structs or classes to provide a mini-namespace. The problem with the first approach is that, in practice, most choices for prefixes are one or two characters in length. Much more than this is normally considered a chore, and it tends to hide the real part of the name unless suitable spacing or separation is used, which in practice means an underscore character. However, there is not a lot of useful informational bandwidth in a couple of characters. The chances that the abbreviations are both clearly meaningful and suitably collision-proof are typically low. As a general solution, there seem to be genuine practical and cognitive problems with identifier prefixes of any length. Another problem with prefixes is that many programmers already use them for other purposes. It is true that in most such cases the practice is not a particularly effective one (e.g. restating the blindingly obvious by using C to prefix class names or the more general T to prefix type names), but programmers nevertheless persist in their use. You could end up with prefix soup if an uncritical programmer fell for all the possible name mangling fashions. Name mangling is really the responsibility of the language and compiler. Compilers already mangle function names to include class membership and argument type information. A common pre-namespace idiom was to use empty classes or structs to wrap typedefs or enum types. For expressing regular procedural functions, some programmers also enclosed otherwise ordinary functions in a scope, making them static members rather than ordinary member functions. As far as it goes, this technique is OK, but it doesn’t actually go that far. Yes, it does reduce the chance of name collision, especially between constants, such as enumerators. And yes, the use of the scope-resolution operator is a visibly distinct separator between the name of the scope and the name that is being enclosed. However, to use any enclosed name always requires the fully qualified name. There is no discounted concession or reasonable short cut for frequent users. You wanted a distinct name, you got it and you’re stuck with it. Perhaps more significantly, the enclosing scope is in practice limited to a single header file. A class scope is a closed construct: the scope cannot be extended to embrace new content and it cannot span multiple header files. This makes the technique useless for anything except simple modular wrapping. Namespace, the final frontier The C++ namespace construct was introduced to address all of the issues outlined so far, and potentially more. If you are already familiar with namespaces, the article has so far acted as a revision and reminder of the motivation. It has possibly also pointed out a couple of things that are not normally mentioned, such as the low priority that should be attached to anticipating function name collisions. A namespace is in some ways like a class and in many ways not: q A namespace acts to introduce a scope that contains features such as classes and functions. That scope can be opened and closed in any file. q A class can have a private section, but the contents of a namespace are always public. q Namespaces can nest only inside one another. They cannot be nested inside classes or functions. q A namespace cannot have the same name as another type defined at the same level. q Unlike a class, a namespace does not have a terminating semi-colon. q A namespace that has no name is both formally and obviously an unnamed namespace. It allows you to keep names private to a translation unit, displacing (and deprecating) a similar role of static. Where static applies only to functions and data, an unnamed namespace applies also to types. q The global namespace is the scope outside of any named or unnamed namespace. It is effectively the root and default namespace. q Entities with linkage that are enclosed in a namespace will have their linkage name affected by the namespace.This means that you cannot simply take some headers for a precompiled library and wrap those headers in an alternative namespace: the result won’t link because the original code was compiled with the identifiers in the global namespace. Directory listings revisited To demonstrate a couple of these features in practice, let’s revisit the directory listing classes described in two previous columns1, 2 . Two classes, dir_stream and dir_iterator, were defined.The common prefix seems to be crying out for some better factoring, and a namespace offers a suitable approach. In the header defining the stream we would have: C++ WORKSHOP
  • 3. 42 APPLICATION DEVELOPMENT ADVISOR q www.appdevadvisor.co.uk namespace dir { class stream { public: explicit stream(const std::string &); ~stream(); operator const void *() const; stream &operator>>(std::string &); ... }; } And in the header for the iterator: namespace dir { class stream; class iterator : public std::iterator< std::input_iterator_tag, std::string> { public: iterator(); explicit iterator(stream &); ~iterator(); const std::string &operator*() const; const std::string &operator->() const; iterator &operator++(); iterator operator++(int); bool operator==(const iterator &) const; bool operator!=(const iterator &) const; ... }; } The member function definitions appear in the same namespace. For instance, the iterator’s postincrement operator defined in terms of the preincrement operator: namespace dir { ... iterator iterator::operator++(int) { iterator old = *this; ++*this; return old; } ... } Notice that names declared in the same namespace can be referred to directly, without any scope resolution, when accessed elsewhere in the same namespace. Using declarations to your advantage There are a number of different approaches to using a name from a named namespace. The simplest is just using the fully qualified name. Alternatively, there is a using declaration that imports a specific name as a more local declaration, and then there is the more sweeping using directive that imports all the names from namespace for unqualified use: using namespace std; void list_dir(const string &name) { typedef ostream_iterator<string> out; using dir::stream; stream directory(name); dir::iterator begin(directory), end; copy(begin, end, out(cout, "n")); } using declarations and directives can appear at either global or local scope. In the code example, a wholesale usage of the std namespace is made at the global level, allowing unqualified use of std::string, std::ostream_iterator, std::copy and std::cout. A using declaration imports dir::stream for local use, whereas dir::iterator is fully named for its use. The usage in the fragment is contrived and more than a little inconsistent. It demonstrates syntax and basic concepts, but not necessarily best practice. There are different opinions as to what constitutes best practice. Some advocates always use fully qualified names and never employ using directives, whereas others see no harm in them. In spite of the variation, there are some valuable and general points that can be made. Be consistent in how a particular namespace is pulled into code. For example, because the std namespace is effectively part of the common platform, some developers like to pull it all in with a using directive in their source files.This is fine, so long as it is done consistently. Inconsistently using a directive in one source file and fully qualifying in another serves no useful development purpose. As with other practices in software development, anything that’s not useful should not be used. Never use namespace using directives or declarations as a convenience in header files, even for namespace std. In the privacy of your own source file you can do what you want without affecting other source files. Placing a using directive in a header instantly floods any file that #includes it with a host of unwanted and unnecessary names, pre-empting any policy that file may have on namespace usage and roundly defeating the whole point of namespaces. This is a frequent bad habit in a lot of commercial code that I have seen, suggesting that even though the idea of namespaces is quite simple, some programmers can be even simpler.Therefore, always declare features in headers using fully qualified names. If a function definition appears in a header, because it is either inlined or templated, and fully qualified names are considered too cumbersome in the function body, place the using at the beginning of the function body, not outside it. Such careful scoping ensures that headers are properly self-contained. What and how to name This is all good, but when would you actually define namespaces in your own code? It is one thing to say you have a language mechanism, but quite another to say that you have a method that makes sense of it. A reasonable enough starting point would be to consider defining a namespace when you might otherwise have been tempted to use a common prefix on identifiers.The dir namespace was an example of this. C++ WORKSHOP
  • 4. Another reasonable starting point would be to consider a namespace when a class or struct seems only to have public members that are types, constants or static member functions. An exception to this is where the type in question defines a trait, a policy or both 3 . In the current language, namespaces cannot be templated or used as template parameters, so a struct is really the most suitable expression of such designs. In search of stability I will leave you with one final recommendation to consider: make sure that your namespace names are stable and long lived. If a name is not stable, it means that you will have to change the namespace name and therefore any code that depends on it when the name is no longer applicable, even though all the namespace contents are otherwise unaffected. An architecture should be structured so that stable concepts depend on more stable, not less stable, concepts. What, specifically, have I got in mind? Organisational structure is the main offender. What at first seems like a good idea—enclosing your code in a namespace that corresponds to your company or department—turns out to be quite the opposite. It is a superficially good idea that lacks any sound reasoning or depth when you scratch the surface. Department or division partitioning is generally far less stable than code for an installed system. Companies reorganise themselves internally whenever they need to be seen to be doing something by their customers or shareholders, or simply when they’re bored. The reorganisation may be as simple as renaming a few departments or it may involve relocations, regional restructuring and redundancies. Experience suggests that such events are more frequent than they are effective, but whichever way you look at it, an organisation’s internal structure is clearly not a bellwether of stability. Likewise, anyone who has been in software development for more than a few minutes will know that company names are as unstable as transuranic elements. Companies merge, demerge, spin- off, acquire, rebrand and debrand, add a dot-com suffix or remove a dot-com suffix with a regularity that keeps industry commentators employed, but does little for anyone else. Even worse is to base a namespace on a company’s domain name, an even less stable concept. Source code is more likely to outlive any specific incarnation of its sponsor. So, choose cautiously and wisely; namespaces are easier in theory than in practice. s References/bibliography: 1. Kevlin Henney, “Promoting polymorphism”, Application Development Advisor, October 2001 2. Kevlin Henney, “The perfect couple”, Application Development Advisor, November-December 2001 3. Kevlin Henney, “Flag waiving”, Application Development Advisor, April 2002 Kevlin Henney is an independent software development consultant and trainer. He can be reached at www.curbralan.com C++ WORKSHOP ADA's free e-mail newsletter for software developers By now many of you will have had a free on-line newsletter which is a service to readers of ADA and packed with the very latest editorial for software and application developers. However, some of our readers don't get this free service. If you don't get your free newsletter it's for one of two good reasons. b Even though you subscribed to ADA, you haven't supplied us with your e-mail address. c You ticked the privacy box at the time you subscribed and we can't now send you our newsletter. Sign up for this free service at www.appdevadvisor.co.uk/subscribe.htm www.appdevadvisor.co.uk/subscribe.htm