wxWindows Programmer Style Guide

by Vadim Zeitlin

This guide is intended for people who are (or intending to start) writing code for wxWindows class library.

The guide is separated into two parts: the first one addresses the general compatibility issues and is not wxWindows-specific. The advises in this part will hopefully help you to write programs which compile and run on greater variety of platforms. The second part details the wxWindows code organization and its goal it to make wxWindows as uniform as possible without imposing too many restrictions on the programmer.

Acknowledgements: This guide is partly based on C++ portability guide by David Williams.

### General C++ Rules

- New or not widely supported C++ features

1. Don't use C++ templates
2. Don't use C++ exceptions
3. Don't use RTTI
4. Don't use namespaces
5. Don't use STL
6. Don't declare variables inside `for()`
7. Don't use nested classes
8. Don't use new logical operators keywords

- Other compiler limitations

1. Use ternary operator ?: carefully
2. Don't use initializers with automatic arrays
3. Always have at least one constructor in a class with destructor

- General recommendations

1. No C++ comments in C code>
2. No global variables with constructor
3. Turn on all warnings and eradicate them
4. Don't rely on `sizeof(int) == 2`...
5. No assignments in conditional expressions
6. Use `#if 0` rather than comments to temporarily disable blocks of code
7. Avoid overloaded virtual functions
8. Don't use extra semi-colons on top level

- Unix/DOS differences

1. Use .cpp for C++ source file extension
2. Don't use backslash ('\\') in #includes
3. Avoid carriage returns in cross-platform code
4. Use only lower letter filenames
5. Terminate the files with a new-line
6. Avoid globals differing by case only

- Style choices

1. Naming conventions: use `m_` for members
2. Don't use `void` for functions without arguments
3. Don't use `const` for non pointer/reference arguments

### wxWindows Rules

- Files location and naming conventions

1. File locations
2. Include guards
3. Precompiled headers

- File layout and indentation

1. wxWindows standard header
2. Indent your code with 4 spaces (no tabs!)
3. Order of parts in a class declarations

- More about naming conventions

1. Use wx or WX prefix for all public symbols
2. Use WXDLLEXPORT with all classes/functions in wxMSW/common code
3. Use Set/Get prefixes for accessors
4. wxNAMING_CONSTANTS

- Miscellaneous

1. Use forward declarations whenever possible
2. Use debugging macros

### General C++ Rules

- New or not widely supported C++ features

The usage of all features in this section is not recommended for one reason: they appeared in C++ relatively recently and are not yet supported by all compilers. Moreover, when they're supported, there are differences between different vendor's implementations. It's understandable that you might love one (or all) of these features, but you surely can write C++ programs without them. Where possible, workarounds to compensate for absence of your favourite C++ abilities are indicated.

Just to suppress any doubts that there are compilers which don't support these new features, you can think about Win16 (a.k.a. Win 3.1) compilers, none of which supports any feature from the list below.

1. Don't use C++ templates

Besides the reasons mentioned above, template usage also makes the program compile much slower (200%-300% is not uncommon) and their support even in the compilers which have had it for a long time is far from perfect (the best example is probably gcc).

Workaround: The things you would like to use templates for are, most commonly, polymorphic containers (in the sense that they can contain objects of any type without compromising C++ type system, i.e. using `void *` is out of question). wxWindows provides dynamic arrays and lists which are sufficient in 99% of cases - please don't hesitate to use them. Lack of template is not a reason to use static arrays or type-less (passing by `void *`) containers.

2. Don't use C++ exceptions

The C++ exception system is an error-reporting mechanism. Another reasons not to use it, besides portability, are the performance penalty it imposes (small, but, at least for current compilers, non-zero), and subtle problems with memory/resource deallocation it may create (the place where you'd like to use C++ exceptions most of all are the constructors, but you need to be very careful in order to be able to do it).

Workaround: there is no real workaround, of course, or the exceptions wouldn't have been added to the language. However, there are several rules which might help here:

1. Every function returns an integer (or at least boolean) error code.

   There is no such thing as a function that never fails - even if it can't fail now, it might do it later, when modified to be more powerful/general. Put the `int` or `bool` return type from the very beginning!

2. Every function you call may fail - check the return code!

   Never rely on the function's success, always test for a possible error.

3. Tell the user about the error, don't silently ignore them.

   Exceptions are always caught and, normally, processed when they're caught. In the same manner, the error return code must always be processed somehow. You may choose to ignore it, but at least tell the user that something wrong happened using `wxLogError` or `wxLogWarning` functions. All wxWindows functions (must) log the error messages on failure - this can be disabled by using wxLogNull object before calling it.

   Examples:

   - Wrong:

         void ReadAddressBookFile(const wxString& strName)
         {
           wxFile file;

           if ( !file.Open(strFile) )
             return;

           ...process it...
         }

   - Correct:

         // returns false if the address book couldn't be read
         bool ReadAddressBookFile(const wxString& strName)
         {
           wxFile file;

           if ( !file.Open(strFile) ) {
             // wxFile logged an error because file couldn't be opened which
             // contains the system error code, however it doesn't know what
             // this file is for and an error message "can't open $GLCW.ADB"
             // can be quite confusing for the user. Here we say what we mean.
             wxLogError("Can't read address book from '%s'!",
         	       strName.c_str());
             return false;
           }

           ...process it...

           return true;
         }

     or, if it's not an error if file doesn't exist (here we could just check its existence, but let's suppose that there is no `wxFile::Exists()`) we can also write:

         // returns false if address book file doesn't exist
         bool ReadAddressBookFile(const wxString& strName)
         {
           wxFile file;

           // start a block inside which all log messages are suppressed
           {
             wxLogNull noLog;
             if ( !file.Open(strFile) )
               return false;
           }

           ...process it...

           return true;
         }

3. Don't use RTTI

RTTI stands for Run-Time Type Information and there is probably no other reason not to use it except the portability issue and the fact that it adds `sizeof(void *)` bytes to any class having virtual functions (at least, in the implementations I'm aware of).

Workaround: use wxWindows RTTI system which allows you to do almost everything which the new C++ RTTI, except that, of course, you have to use macros instead of the (horrible looking, BTW) `dynamic_cast`.

4. Don't use namespaces

This topic is subject to change with time, however for the moment all wxWindows classes/functions live in the global namespace.

Workaround: None.

5. Don't use STL

STL is the new C++ standard library, proposing all kinds of template containers and generic algorithm implementations. Templates are the heart (and almost everything else) of the library, so its usage is out of question. Besides, even with the compilers which do support templates, STL has many of its own problems, there are many "not 100% standard compatible" vendor implementations, none of existing debuggers understands its complicated data structures, ... the list can go on (almost) forever.

Workaround: Use wxString, dynamic arrays and lists and other wxWindows classes. wxString has many of the most often used functions of std::string STL class (typedef to be precise).

6. Don't declare variables inside `for()`

The scope of a variable declared inside `for()` statement changed several years ago, however many compilers still will complain about second declaration of `i` in the following code:

      for ( int i = 0; i < 10; i++ ) {
        ...
      }

      ...

      for ( int i = 0; i < 10; i++ ) {
        ...
      }

even though if it's perfectly legal now.

Workaround: write this instead:

      int i;
      for ( i = 0; i < 10; i++ ) {
        ...
      }

      ...

      for ( i = 0; i < 10; i++ ) {
        ...
      }

or, even better, use different names for the variables in the different for loops (in particular, avoid mute variable names like `i`above) - then you can declare them in the loop statement and don't pollute the outer name space with local loop variables.

7. Don't use nested classes

Nested classes are, without doubt, a very good thing because they allow to hide "private" (in the sense that they're used only inside the library) classes and, generally, put the related things together.

Unfortunately, some compilers have trouble understanding them, so we must sacrifice the ideals of software design to get a working program in this case.

Workaround: instead of

      // in the header
      class PublicLibClass {
      ...
      private:
        class PrivateLibClass { ... } m_object;
      };

you can try the following:

      // in the header
      class PrivateLibClass; // fwd decl
      class PublicLibClass {
      ...
      private:
       class PrivateLibClass *m_pObject;
      };

      // in the .cpp file
      class PrivateLibClass { ... };

      PublicLibClass::PublicLibClass()
      {
        m_pObject = new PrivateLibClass;

        ...
      }

      PublicLibClass::~PublicLibClass()
      {
        delete m_pObject;
      }

A nice side effect is that you don't need to recompile all the files including the header if you change the PrivateLibClass declaration (it's an example of a more general interface/implementation separation idea).

8. Don't use new logical operators keywords

The C++ standard has introduced the following new reserved words: `or`, `and`, `not`, `xor`, `bitand`, `bitor`, `compl`, `and_eq`, `or_eq`, `not_eq`, `or_eq` which can be used instead of the usual C operations &&, ||, ~ etc.

This wonderful (and not backwards compatible in addition to being absolutely useless) new feature means that these new keywords should not be used as the variable names - even if current compilers usually will accept this, your code will break in the future. For most of the keywords, using them as variable names is quite unlikely, but `or` and `compl` were used in the wxWindows sources which seems to indicate that they are the most likely candidates.

It goes without saying that these new keywords should not be used instead of the tradional C operators neither both because most compilers don't accept them and because using them in C code makes it less readable.

``

- Other compiler limitations

This section lists the less obvious limitations of the current C++ compilers which are less restrictive than the ones mentioned in the previous section but are may be even more dangerous as a program which compiles perfectly well on some platform and seems to use only standard C++ featurs may still fail to compile on another platform and/or with another compiler.

1. Use ternary operator ?: carefully

The ternary operator `?:` shouldn't be used with objects (i.e. if any of its operands are objects) because some compilers (notably Borland C++) fail to compile such code.

Workaround: use `if/else` instead.

        wxString s1, s2;

        // Borland C++ won't compile the line below
        wxString s = s1.Len() < s2.Len() ? s1 : s2;

        // but any C++ compiler will compile this
        wxString s;
        if ( s1.Len() < s2.Len() )
            s = s1;
        else
            s = s2;

2. Don't use initializers with automatic arrays

The initializers for automatic array variables are not supported by some older compilers. For example, the following line

        int daysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

will fail to compile with HP-UX C++ compiler.

Workaround: either make the array static or initialize each item separately: in the (stupid) example above, the array should be definitely declared as `static const` (assuming that the leap years are dealt with elsewhere somehow...) which is ok. When an array is really not const, you should initialize each element separately.

3. Always have at least one constructor in a class with destructor

It is a good rule to follow in general, but some compilers (HP-UX) enforce it. So even if you are sure that the default constructor for your class is ok but it has a destructor, remember to add an empty default constructor to it.

- General recommendations

While the recommendations in the previous section may not apply to you if you're only working with perfect compilers which implement the very newest directives of C++ standard, this section contains compiler- (and language-) independent advice which must be followed if you wish to write correct, i.e. working, programs. It also contains some C/C++ specific remarks in the end which are less important.

1. No C++ comments in C code>

Never use C++ comments in C code - not all C compilers/preprocessors understand them. Although we're mainly concerned with C++ here, there are several files in wxWindows sources tree which are compiled with C compiler. Among them are `include/wx/setup.h` and `include/wx/expr.h`. Another thing related to C vs C++ preprocessor differences is that some old C preprocessors require that all directives start in the first column (while it's generally allowed to have any amount of whitespace before them in C++), so you should start them in the beginning of the line in files which are compiled with C compiler.

2. No global variables with constructors

In C++, the constructors of global variables are called before the `main()` function (or `WinMain()` or any other program entry point) starts executing. Thus, there is no possibility to initialize anything before the constructor call. The order of construction is largely implementation-defined, meaning that there is no guarantee that one global object will be initialized before another one (except if they are both defined in the same translation unit, i.e. .cpp file). Most importantly, no custom memory allocation operators are installed at the moment of execution of global variables constructors, so a (less restrictive) rule is that you should have no global variables which allocate memory (or do anything else non-trivial) in the constructor. Of course, if an object doesn't allocate memory in its constructor right now, it may start making it later, so you can only be sure about this if you don't use any variables of object (as opposed to simple: `int`, ...) types. Example: currently, wxString doesn't allocate memory in its default constructor, so you might think that having a global (initially) empty wxString is safe. However, if wxString starts allocating some minimal amount of memory in its default constructor (which doesn't look unreasonable), you would have all kinds of problems with `new` and `delete` operators (overloaded in wxWindows), especially because the first `new` called is the standard one (before wxWindows overloads them) and `delete` will be the overloaded operator.

3. Turn on all warnings and eradicate them

Give the compiler a chance to help you - turn on all warnings! You should always use the maximum available warning level of your compiler and understand and correct each of them. If, for whatever reasons, a compiler gives a warning on some perfectly legal line of code and you can't change it, please insert a comment indicating it in the code. Most oftenly, however, all compiler warnings may be avoided (not suppressed!) with minimal changes to your code.

4. Don't rely on `sizeof(int) == 2`...

You should never assume any absolute constraints on data type sizes. Currently, we have 16-bit, 32-bit and 64-bit machines and even inside each class data type sizes are different. A small table illustrates it quite well:

Architecture/OS | sizeof(short) | sizeof(int) | sizeof(long) | sizeof(void *)
i386/Windows 3.1 | 2 | 2 | 4 | 2 or 4
i386/Windows 95 | 2 | 4 | 4 | 4
Merced/Win64 | 2 | 4 | 4 | 8
Alpha/Linux | ??? | ??? | ??? | ???

5. No assignments in conditional expressions

Although close to the heart of many C programmers (I plead guilty), code like classical `if ( (c = getchar()) != EOF )` is bad because it prevents you from enabling "assignment in conditional expression" warning (see also above) which is helpful to detect common mistypes like `if ( x = 2 )` instead of `if ( x == 2 )`.

6. Use `#if 0` rather than comments to temporarily disable blocks of code

If you have to temporarily disable some code, use

      #if 0 // VZ: I think this code is unneeded, it probably must be removed
        ...
      #endif // 0

instead of

      /*
        ...
      */

The reason is simple: if there are any `/* ... */` comments inside `...` the second version will, of course, miserably fail.

7. Avoid overloaded virtual functions

You should avoid having overloaded virtual methods in a base class because if any of them is overriden in a derived class, then all others must be overriden as well or it would be impossible to call them on an object of derived class. For example, the following code:

        class Base
        {
        public:
            virtual void Read(wxFile& file);
            virtual void Read(const wxString& filename);
        };

        class Derived : public Base
        {
        public:
            virtual void Read(wxFile& file) { ... }
        };

        ...

        Derived d;
        d.Read("some_filename");    // compile error here!

will fail to compile because the base class function taking `filename` is hidden by the virtual function overriden in the derived class (this is known as [virtual] function name hiding problem in C++).

The standard solution to this problem in wxWindows (where we have such situations quite often) is to make both `Read()` functions not virtual and introduce a single virtual function `DoRead()`. Usually, it makes sense because the function taking a filename is (again, usually) implemented in terms of the function reading from a file anyhow (but making only this functions not virtual won't solve the above problem!).

So, the above declarations should be written as:

        class Base
        {
        public:
            void Read(wxFile& file);
            void Read(const wxString& filename);

        protected:
            virtual void DoRead(wxFile& file);
        };

        class Derived : public Base
        {
        protected:
            virtual void DoRead(wxFile& file) { ... }
        };

This technique is widely used in many of wxWindows classes - for example, `wxWindow` has more than a dozen of `DoXXX()` functions which allows to have many overloaded versions of commonly used methods such as `SetSize()`

8. Don't use extra semi-colons on top level

Some compilers don't pay any attention to extra semicolons on top level, as in

      class Foo { };;

while others complain loudly about it. Of course, you would rarely put 2 semicolons yourself, but it may happen if you're using a macro (`IMPLEMENT_something`, for example) which already has a ';' inside and put another one after it.

- Unix/DOS differences

Two operating systems supported by wxWindows right now are (different flavours of) Unix and Windows 3.1/95/NT (although Mac, OS/2 and other ports exist/are being developed as well). The main differences between them are summarized here.

1. Use .cpp for C++ source file extension

There is, unfortunately, no standard exceptions for C++ source files. Different people use .C, .cc, .cpp, .cxx, .c++ and probably several others I forgot. Some compilers don't care about extension, but there are also other ones which can't be made to compile any file with "wrong" extension. Such compilers are very common in DOS/Windows land, that's why the .cpp extension is the least likely to cause any problems - it's the standard one under DOS and will probably be accepted by any Unix compiler as well (any counter examples?). The extension for the header files is .h.

2. Don't use backslash ('\\') in #includes

Although it's too silly to mention, please don't use backslashes in `#include` preprocessor statement. Even not all Windows compilers accept it, without speaking about all other ones.

3. Avoid carriage returns in cross-platform code

This problem will hopefully not arise at all, with CVS taking care of this stuff, however it's perhaps not useless to remember that many Unix compilers (including, but not limited to, gcc) don't accept carriage returns (= = '\r') in C/C++ code.

4. Use only lower case filenames

DOS/Windows 3.1 isn't case sensitive, Windows 95/NT are case preserving, but not case sensitive. To avoid all kinds of problems with compiling under Unix (or any other fully case-sensitive OS), please use only lower case letters in the filenames.

5. Terminate the files with a new-line

While DOS/Windows compilers don't seem to mind, their Unix counterparts don't like files without terminating new-line. Such files also give a warning message when loaded to vim (the Unix programmer's editor of choice :-)), so please think about terminating the last line.

6. Avoid globals differing by case only

The linker on VMS is case-insensitive. Therefore all external variables and functions which differ only in case are not recognized by the linker as different, so all externals should differ in more than the case only: i.e. `GetId` is the same as `GetID`.

- Style choices

All wxWindows specific style guidelines are specified in the next section, here are the choices which are not completely arbitrary, but have some deeper and not wxWindows-specific meaning.

1. Naming conventions: use `m_` for members

We all know how important it is to write readable code. One of the first steps in this direction is the choice of naming convention. It may be quite vague or strictly define the names of all the variables and function in the program, however it surely must somehow allow the reader to distinguish between variable and functions and local variables and member variables from the first glance.

The first requirement is commonly respected, but for some strange reasons, the second isn't, even if it's much more important because, after all, the immediate context usually allows you to distinguish a variable from a function in C/C++ code. On the other hand, you cannot say what `x` in the following code fragment is:

      void Foo::Bar(int x_)
      {
        ...

        x = x_;

        ...
      }

It might be either a local variable (unluckily the function is too long so you don't see the variable declarations when you look at `x = x_` line), a member variable or a global variable - you have no way of knowing.

The wxWindows naming convention gives you, the reader of the code, much more information about `x`. In the code above you know that it's a local variable because:

1. global variables are always prefixed with `g_`
2. member variables are always prefixed with `m_`
3. static variables are always prefixed with `s_`

Examples:

      extern int g_x; // of course, 'x' is not the best name for a global...

      void Bar()
      {
        int x;
      }

      class Foo {
        public:
          void SetX(int x) { m_x = x; }
        private:
          int m_x;
      };

As you see, it also solves once and for all the old C++ programmer's question: how to call `SetX()` parameter? The answer is simple: just call it `x` because there is no ambiguity with `Foo::m_x`.

The prefixes can be combined to give `ms_` and `gs_` for static member (a.k.a. class) variables and static global variables.

The convention is, of course, completely worthless if it is not followed: nothing like being sure that `x` is a local variable in the code fragment above and discovering later the following lines in the header:

      class Foo {
        ...
        int x;  // I don't like wxWindows naming convention
      };

Please do use these prefixes, they make your code much easier to read. Also please notice that it has nothing to do with the so-called Hungarian notation which is used in wxMSW part of wxWindows code and which encodes the type of the variable in its name - it is actually quite useful in C, but has little or no sense in C++.

2. Don't use `void` for functions without arguments

In ANSI C, `void Foo()` takes an arbitrary number of arbitrarily typed arguments (although the form `void Foo(...)` is preferred) and `void Foo(void)` doesn't take any arguments. In C++, however, the situation is different and both declarations are completely equivalent. As there is no need to write `void` in this situation, let's not write it - it can only be confusing and create an impression that it really means something when it's not at all the case.

3. Don't use `const` for non pointer/reference arguments

In both C and C++ an argument passed by value cannot be modified - or, more precisely, if it is modified in the called function, only the local copy is really changed, not the caller's variable. So, semantically speaking, there is no difference between `void Foo(int)` and `void Foo(const int)`. However, the `const` keyword is confusing here, adds nothing to the code and even cannot be removed if `Foo()` is virtual and overridden (because the names are mangled differently). So, for arguments passed by value you shouldn't use `const`.

Of course, it doesn't apply to functions such as `void PrintMessage(const char *text)` where `const` is mandatory.

### wxWindows rules

- File location and naming conventions

File locations

The wxWindows files for each supported platform have their own subdirectories in "include" and "src". So, for example, there is "src/msw", "include/gtk" etc. There are also two special subdirectories called "common" and "generic". The common subdirectory contains the files which are platform independent (wxObject, wxString, ...) and the generic one the generic implementations of GUI widgets, i.e. those which use only other wxWindows classes to implement them. For the platforms where the given functionality cannot be implemented natively, the generic implementation is used and the native one is used for the others. As I feel that it becomes a bit too confusing, here is an example: wxMessageBox function is implemented natively under Windows (where it just calls MessageBox API), but there is also a generic implementation which is used under, for example, GTK. A generic class should normally have a name that distinguishes it from any platform-specific implementation. A #define will allow wxGenericMessageDialog to be wxMessageDialog on some platforms, for example.

This scheme applies not only for the .cpp files, but also for the headers. However, as the program using wxWindows should (ideally) not use any "`#ifdef <platform>`" at all, the headers are always included with "`#include <wx/msgdlg.h>`" (for example). This file, in turn, includes the right header for given platform. Any new headers should conform to this setup as well to allow including `<wx/foo.h>` on any platform.

Note that wxWindows implementation files should use quotes when including wxWindows headers, not angled brackets. Applications should use angled brackets. This ensures that the dependencies are correctly handled by the compiler.

Include guards

To minimize the compile time C++ programmers often use so called include guards: for example, in the header file foo.h you might have

    #ifndef _FOO_H_
    #define _FOO_H_

    ... all header contents ...

    #endif
     //_FOO_H_

In this way, the header will only be included once for the compilation of any .cpp (of course, it still will be included many times for the compilation of the whole project, so it has nothing to do with precompiled headers). wxWindows is no exception and also uses include guards which should use the above form, except for top-level headers which include files with identical names, in which case you should use _FOO_H_BASE_.

Precompiled headers

The precompiled headers greatly (we're speaking about orders of hundreds of percent here) reduce the compilation time. wxWindows uses them if the target compiler supports them (it knows about MS Visual C++, Borland C++ and g++). You should include all the headers included from `` only inside "`#if !USE_PRECOMP`" to avoid unnecessary overhead in the case when the precompiled headers are used.

The start of a cpp implementation file after the heading might look like this:

    #ifdef __GNUG__
    #pragma implementation "bitmap.h"
    #endif

    // For compilers that support precompilation, includes "wx.h".
    #include "wx/wxprec.h"

    #ifdef __BORLANDC__
    #pragma hdrstop
    #endif

    #ifndef WX_PRECOMP
    #include <stdio.h>
    #include "wx/setup.h"
    #include "wx/list.h"
    #include "wx/utils.h"
    #include "wx/app.h"
    #include "wx/palette.h"
    #include "wx/bitmap.h"
    #include "wx/icon.h"
    #endif

    #include "wx/msw/private.h"
    #include "assert.h"

Any header file should containg the following lines:

    #ifdef __GNUG__
      #pragma interface "foo.h"
    #endif

and the corresponding .cpp file:

    #ifdef __GNUG__
      #pragma  implementation "foo.h"
    #endif

for g++ compilation.

- File layout and indentation

wxWindows standard header here. The copyright holder is the original author. It is assumed the author does not assert copyright, under the terms of the wxWindows licence. This is a legal interpretation of the informal usage 'public domain' (the copyright holder does not assert the copyright).

Indent your code with 4 spaces (no tabs!)

Order of parts in a class declarations

- More about naming conventions

Use wx or WX prefix for all public symbols. wx should be used for functions and classes, WX for macros.

2. Use WXDLLEXPORT with all classes/functions in wxMSW/common code The title says it all - every public (in the sense that it is not internal to the library) function or class should have WXDLLEXPORT macro in its declaration to allow compilation of wxWindows as shared library. For example:

       bool WXDLLEXPORT wxYield(void);
       class WXDLLEXPORT MyClass;  // (for forward declarations and real declarations)
       WXDLLEXPORT_DATA(extern wxApp*) wxTheApp;

   The reason for the strange syntax for data is that some compilers use different keyword ordering for exporting data.

Use Set/Get prefixes for accessors

There is a convention in wxWindows to prefix the accessors (i.e. any simple, in general, inline function which does nothing else except changing or returning the value of a member variable) with either `Set` or `Get`.

wxNAMING_CONSTANTS

The constants in wxWindows code should be defined using `enum` C++ keyword (and not with `#define` or `static const int`). They should be declared in the global scope (and not inside class declaration) and their names should start with a `wx` prefix. Finally, the constants should be in all capital letters (except the first 2) to make it easier to distinguish them from the variables with underscores separating the words.

For example, file-related constants should be declared like this:

    enum
    {
        wxFILEOPEN_READ,
        wxFILEOPEN_WRITE,
        wxFILEOPEN_READWRITE
    };

- Miscellaneous

Use forward declarations whenever possible

It's really a trivial piece of advice, but remember that using forward declarations instead of including the header of corresponding class is better because not only does it minimize the compile time, it also simplifies the dependencies between different source files.

On a related subject, in general, you should try not to include other headers from a header file.

Use debugging macros

wxWindows provides the debugging macros `wxASSERT, wxFAIL` and `wxCHECK_RET` in `` file. Please use them as often as you can - they will never do you any harm but can greatly simplify the bug tracking both for you and for others.

Also, please use `wxFAIL_MSG("not implemented")` instead of writing stubs for not (yet) implemented functions which silently return incorrect values - otherwise, a person using a not implemented function has no idea that it is, in fact, not implemented.

As all debugging macros only do something useful if the symbol `__WXDEBUG__` is defined, you should compile your programs in debug mode to profit from them.

Please send any comments to Vadim Zeitlin.