=================================== |Coding Guide Lines for Planeshift| =================================== (a) Coding Precautions: Please follow these simple precautions to make sure that your code is safe. ============================================================================= 1. Test for NULL pointers: If you are using some function that returns a pointer to some object, then make sure that the pointer returned is not NULL, before using it. Example: Don't do this: psserver->GetConnectionSet()->FindClient(29)->GetCharData(); Do this: ConnectionSet* connSet = psserver->GetConnectionSet(); if (!connSet) { Error1("ConnSet doesn't exist yet!"); return; } Client* client29 = connSet->FindClient(29); if (client29) .... ... .. If a pointer must exist, and it's a serious error for it to be NULL at this point, use an assert instead of a regular NULL check. The program will stop and the stack can be examined to find the error. Example: void class::function(gemItem * obj) { if (!obj) return; psItem* item = obj->GetItem(); CS_ASSERT(item != NULL); // All gemItems must have a psItem .... ... .. 2. Keep track of scope: // This won't do anything to obj outside of this scope void class::function(gemItem * obj) { obj = newptr; } // This will change what obj is pointed to after it's called void class::function(gemItem * & obj) { obj = newptr; } Make sure you use the one you need for each situation. For example, if you delete the passed object then set the pointer to NULL, don't forget the '&' in the function prototype! 3. Avoid including many Header files: Please avoid using any header file into other files if there's no need of it, as including many header files will considerably increase the re-build time even if you change little code. (b) Coding Convention: ====================== 1. Introduction: Every programmer has his own coding style, however when multiple programmers are working on the same project it's a good idea to use a common coding style. Before starting with planeshift style. Like most of other coding standard documents I present some links to other docs at the end. 2. The Planeshift style: a) Indentation: -4 chars are used for indentation. -Tab characters are forbidden! -Brackets are used in the following format: if (foo == bar) { bar++; } PLEASE, use them also when if/else/whatever is followed just by one line of code. Don't using them makes the code hard to read and it is easier to create errors. -Lines are no longer than 78 chars unless it makes sense to keep them long If you have to break a line in a strange place to get it in 78 characters then leave it as a long line. b) Comments: First of all: USE THEM!! Especially when introducing new functions, code that is not clear, but also in every step that for you is trivial and for others might not be. -1 line comments are // -Multiline comments are /* */ -We use doxygen (http://www.stack.nl/~dimitri/doxygen/ ) for documenting classes and functions, so inside the header files you should use /// and /** before commenting classes/functions. (doxygen has more feature you can use of course, read the documentation on doxygen page for it). Doxygen uses a system of tags to comment the code. Here is a brief example of some of the more common tags. /** Your brief class description here, should be about 1 line and end in a period. * Your more detailed description is placed here where you describe the class in full * detail. */ class MyTestClass { public: bool MyTestFunction( int x, int y, int& val ); /** A simple description of the function ending in a period. * A more detailed description here. Can be on multiple lines. * Following we have information on the parameters and return values. * Empty line between detailed description and start of param statements * just makes it easier to read. * * @param x: Description of x * @param y: Description of y * @param val: [CHANGES] Is set to be equal to some value. * @return bool Describe return state. * * Additional tags for more detail. * @remark Key remarks about this function. * @see MyTestFunction2() */ /// A one line comment. void Set(); /** Multiline comments should look like this. * */ }; You can also use some HTML code in the comments to do lists if needed. Lists are also handled by doxygen easily using - or -# for example: /** * Following this will be a list. * - List element 1 * - List element 2 * -# Numbered list 1 * -# Numbered list 2 * -# Numbered list 3 * . * This is more text added to List element 2. * - List element 3 * . */ c) File Organization: Each file should start with the following header to make licensing clear: (things in [] brackets are optional) /** Filename * * Copyright (C) 200x Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * [ - author YourName yourSurname youremail ] * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * [short description about what is inside the file] */ -Some people want to separate functions in cpp files, use the following line for it: //--------------------------------------------------------------------------- d) Naming style: - Classes very tailored to the Planeshift game (not the generic engine) should start with a "ps" in front of their name and should use uppercase for each new word in them, e.g. psMyClass An exception are classes/functions that are only used internally in a .cpp file. For datatypes it depends, if they are big structs you should use the "ps"Name style. - Classes that deal with the gui should start with 'paws' - Functions should have a capital letter at the beginning of each word, e.g. MyFunction - Variables start with lowercases, e.g. int myVariable; psEngine* psengine; - To explicitely mention it: We don't use hungarian name convention. - Underscores should only be used for constants - Constants and enums use ONLY capital letters, e.g. CONSTANT, PLAYER_COUNT - You should normally put 1 class in 1 file and name the file like the class in it. Ee use ONLY lower case letters (and underscores) for filenames and extensions are .cpp, .h and .inc, e.g. psmyclass.h psmyclass.cpp initcs.inc - Multiple classes in one source file are acceptable if the 2ndary classes are essentially private to the main class in the file or the data seems like it belongs together. e) Code in #defines is prohibited if that code is doing meaningful work. Things like declaring standard factory classes or logging error message expansion are fine. Doing things with if statements and multiple C statements in them is not fine. f) Classes which have any form of persistence (db, file, network) should in general be responsible for marshaling their own members. g) Portability Issues: Avoid to use printf or cout. Crystal Space offers several tools for showing errors, therefore use them! For errors, use "ErrorN" where N can vary depending from the amount of arguments. For debug information, use "DebugN" where N depends from the amount of arguments. You can check the other possible tools in /src/common/util/log.h Don't forget libc headers. They could be included inderectly on your system, for example I I can include in linux and is included inderectly by iostream.h so it compiles for me. But on other systems this won't work 3. Using cvs early and often: - For those of you with write access, if you are not committing code to cvs at least every day or so (on the days you work on PS), you are probably defining your task too broadly. Don't interpret your task as "Implement new GUI system for Spells" but as "Make button which displays icon", "Make Spellbook Parent window", etc. - PLEASE, TEST YOUR CODE as much as possible before committing! At least test that the client can STILL connect to the server and that there are no major problems! - After completing each step, re-update your cvs to merge everyone else's changes into yours, rebuild, make sure there are no problems and commit your step with a note in the history about the step and what the next steps are until you are finished your task. If something is partially completed and will not work right if someone tries it, don't let that stop you from committing the part that does work. Just note in history.txt what NOT to try. - If what are you committing is a fix for a bug in the bugtracker, specify in the history.txt the number of the bug and briefly, what was the bug about. - Write as many comments as possibile: what it is obvious to you might be unclear for some body else and it can become really hard to solve problems if you are not available if the code is hard to understand! 4. Implementing coding style in Vim: Here are some tips to automate some things from the coding style above: a) unix with vim - make 2 template files with the general header in them - Setup your vimrc to automate indentation (this is only a part of my vim configuration that covers indentation and syntax highlighting) set nocompatible autocmd FileType cpp call PSStyle() autocmd FileType h call PSStyle() autocmd FileType inc call PSStyle() function PSStyle() set cindent set shiftwidth=4 set tabstop=8 set softtabstop=4 set textwith=78 so ${VIMRUNTIME}/syntax/syntax.vim endfunction filetype on 5 Some other coding styles: http://pcroot.cern.ch/TaligentDocs/TaligentOnline/DocumentRoot/1.0/Docs/books/WM/WM_3.html This is a complicated document, while some general advises are good, the naming convention are just another braindamaged thing like the old hungarian name conventions... http://www.gnu.org/prep/standards_toc.html This also covers more than indentation and naming. I personally like the this style as it's succesfull used in LOTS of projects howevere the authors don't like c++ :(, and the document enforces you a bit too lot I think (style for a changelog?!?) http://developer.gnome.org/doc/guides/programming-guidelines/book1.html Some more general advices and nearly some indentation/naming style as gnu uses http://purists.org/linux/ To present something different to gnu, here's linus view of coding style , also a good read, you should especially look at the "functions" and "commenting" sections. http://crystal.sourceforge.net/docs/online/manual/cs_263.html#SEC619 The style of Crystal Space our 3d engine. We're using their naming conventions as it's the only way not to end up with 2 naming styles in our application. Howevere we use another indentation style and change some other things. Compared with all these docs the planeshift coding convention is poor and lets you much room, if you have more questions/additions feel free to contact Planeshift team on IRC: irc.freenode.net, channel #planeshift-build