$Id$

AbiSource Programmer Guidelines

Copyright (C) 1999 AbiSource, Inc. All Rights Reserved.

Eric W. Sink, eric@abisource.com

AbiSource, Inc.

$Date$

1. Generally, we use Hungarian notation and mixed-case names for variables. Prefix integer variables with an i and pointer variables with a p. For example, iNumColumns.

2. Class member variables should be prefixed with m_. For example, m_pBlockLayout. Static member variables should be prefixed with s_.

3. We use C++, but we use it carefully. We generally follow the C++ Portability Guide document at www.mozilla.org. Don't use templates, exceptions, RTTI, or namespaces. Avoid multiple inheritance. The C++ filename suffix is .cpp.

4. C is allowed (but strongly discouraged), but if you're writing new code, we'd prefer that you change the suffix to .cpp and compile it as C++. :-) The type checking is stronger that way. If you do use C, do not use C++ style comments (// this is a comment). In C++ code, prefer C++ style comments where appropriate.

5. We care about compiler warnings. Turn on the highest warning level of your compiler which is reasonable and fix everything it complains about. Our goal is to have a warning-free build. In practice, we usually come very close to that goal.

6. We care about proper resource allocation and maintenance. Please be very careful about freeing any resources you allocate. If you don't, someone will probably make you aware of the error of your ways.

7. Cross-platform (XP) code is very important to us. Remember that XP code must compile on a wide variety of platforms. Don't put platform-specific stuff in XP files. Don't put platform #ifdefs in XP files. Don't put any code which could be XP in a platform-specific file. At the time of this writing, AbiWord is approximately 90% XP code, based on line count. We'd like to keep it that way.

8. Use the portability types in abi/src/util. For example, don't use unsigned long, use UT_uint32 instead. If there is no possibility of overflow on any supported platform, int can be used as loop index.

9. Keep an eye on Bugzilla. We believe in the "fix bugs as you go" approach. Don't let the bug count ever get too high. When you fix a bug, update Bugzilla to reflect the change in state.

10. When you check something in, send email about it. Put the word 'commit' in the subject line of the message.

11. Design and implement AbiSuite for users, not for programmers. We're fanatical about developing software which normal people will like to use. This is more than just the usual cliches about user friendliness. If you are a programmer, you are definitely not normal. Quite often, we refer to the example target user as "the church secretary". When coding a feature, ask yourself if you designed it such that your Mom will like to use it. If your Mom is a geek too, then refer to someone else's Mom.

12. Prefix the names of protected or private methods with an underscore.

13. The curly brace goes on the next line, and is indented to the same position as the starting position of the expression it belongs to, i.e.

if(x)

{

14. Indents are 4 spaces or 1 tab. Tabs are 4 spaces.

15. Use asserts liberally. We've provided the UT_ASSERT macro for just this purpose. Asserts are good -- they provide you an opportunity to make your assumptions explicit.

16. Don't use C++ iostreams. "I consider the use of C++ iostreams to be a bug and will log it." -- Jeff Hostetler, 27 January 1999. :-)

17. Don't break the tree. This is a Big One. Some Open Source projects seem to be very forgiving about checking in code which doesn't compile or causes instant crashes. We're not. Around here, when someone breaks the tree, we require them to buy donuts.

18. Don't declare variables in the declaration of a 'for' loop of 'if' conditional and expect them to work outside the scope of the block of code. This is required by ANSI/ICO C++ rules. Metrowerks CodeWarrior is unforgiving about this; such variables are restricted to the scope of the conditional or loop. For example, CodeWarrior will refuse to compile the following code:

for (int i = 0; i > 10; i++)

{

printf("i is %d \n", i);

}

printf("i is now %d \n", i);

'i' is used after the for loop, where it is not in variable scope. Write portable cross-platform code like this:

int i;

for (i = 0; i > 10; i++)

{

printf("i is %d \n", i);

}

printf("i is now %d \n", i);

This is part of the more general principle of using only ANSI standard C++, and only those parts of it that are portable.

19. On a subsequent note, don’t do multiple declarations of loop variables inside the loop in XP code because the win32 compiler (CL) is stupid and non-conformant:

for (UT_uint32 i = 0; i < 10; i++)

{

// do something 1

}

for (UT_uint32 i = 0; i < 100; i++)

{

// do something loop #2
}

20. Use of protected member variables is strongly discouraged. Please use private member variables, using properly-scoped getter/setter methods to access and set their values.

21. Use constructor initializers. Do do this:

Foo::Foo (int a, int b)

: m_a(a), m_b(b)

{
}

Do not do this:

Foo:Foo (int a, int b)

{

m_a = a;

m_b = b;
}

22. static_cast<> and const_cast<> are your friends. Avoid dynamic_cast<> at all costs.

23. Don’t use templates in your code. We have lots of utility classes in src/af/util/xp which are meant to supplant the STL. These classes themselves may conditionally use the STL as their backend.