2002-08-02 21:53:23 +04:00
|
|
|
Synergy Developer and Porting Guide
|
|
|
|
===================================
|
|
|
|
|
|
|
|
This document is under development.
|
|
|
|
|
|
|
|
Code Organization
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
The synergy source code organization is:
|
|
|
|
|
|
|
|
. -- root makefiles, some standard documentation
|
|
|
|
cmd -- program source code
|
|
|
|
synergy -- synergy client
|
|
|
|
synergyd -- synergy server
|
|
|
|
config -- stuff for autoconf/automake
|
|
|
|
dist -- files for creating distributions
|
|
|
|
rpm -- files for creating RPMs
|
|
|
|
doc -- placeholder for documentation
|
|
|
|
examples -- example files
|
|
|
|
lib -- library source code
|
|
|
|
base -- simple utilities
|
|
|
|
client -- synergy client library
|
|
|
|
http -- simple http tools
|
|
|
|
io -- I/O
|
|
|
|
mt -- multithreading
|
|
|
|
net -- networking
|
|
|
|
platform -- platform dependent display/window/event stuff
|
|
|
|
server -- synergy server library
|
|
|
|
synergy -- synergy shared client/server code library
|
|
|
|
|
|
|
|
Note how the utility code required by the programs is placed into
|
|
|
|
separate library directories. This makes the makefiles a little
|
|
|
|
more awkward but makes for a cleaner organization. The top level
|
|
|
|
directory has only the standard documentation files and the files
|
|
|
|
necessary to configure and build the rest of the project.
|
|
|
|
|
|
|
|
|
|
|
|
Coding Style Guide
|
|
|
|
------------------
|
|
|
|
|
|
|
|
Synergy uses many coding conventions. Contributed code should
|
|
|
|
following these guidelines.
|
|
|
|
|
2002-08-12 02:43:07 +04:00
|
|
|
- Symbol Naming
|
|
|
|
Names always begin with a letter (never an underscore). The first
|
|
|
|
letter of interior names are always capitalized. Acronyms should
|
|
|
|
be all uppercase. For example: myTextAsASCII.
|
|
|
|
|
|
|
|
Names come it two flavors: leading capital and leading lowercase.
|
|
|
|
The former have the first character capitalized and the latter
|
|
|
|
don't. In the following table, leading capital names are indicated
|
|
|
|
by `Name' and leading lowercase names by `name'.
|
|
|
|
|
|
|
|
The naming convention for various things are:
|
|
|
|
|
|
|
|
* Exceptions -- X + Name XMyException
|
|
|
|
* Interfaces -- I + Name IMyInterface
|
|
|
|
* Template Classes -- T + Name TMyTemplate<>
|
|
|
|
* Other Classes -- C + Name CMyClass
|
|
|
|
* Enumerations -- E + Name EMyEnumeration
|
|
|
|
* Constants -- k + Name kMyConstant
|
|
|
|
* Data Members -- m_ + name m_myDataMember
|
|
|
|
* Methods -- name myMethod
|
|
|
|
* Functions -- name myFunction
|
|
|
|
* Variables -- name myVariable
|
|
|
|
|
|
|
|
Exceptions are types that get thrown and are generally derived
|
|
|
|
(possibly indirectly) from XBase. Interfaces are derived (possibly
|
|
|
|
indirectly) from IInterface and have only pure virtual functions.
|
|
|
|
Other classes are classes that aren't exceptions or interfaces.
|
|
|
|
Constants include global constants and enumerants.
|
|
|
|
|
|
|
|
Method names should usually have the form `verbObject'. For example:
|
|
|
|
* isGameOn()
|
|
|
|
* getBeer()
|
|
|
|
* pressPowerButton()
|
|
|
|
* setChannel()
|
|
|
|
In general, use `get' and `set' to read and write state but use `is'
|
|
|
|
to read boolean state. Note that classes that contain only `is',
|
|
|
|
`get', and `set' are probably plain old data; you might want to
|
|
|
|
consider using public data members only or, better, refactor your
|
|
|
|
design to have classes that actually do something more than just
|
|
|
|
hold data.
|
|
|
|
|
|
|
|
- File Naming
|
|
|
|
Each class should have one source and one header file. If the
|
|
|
|
class is named `CMyClass' then the source file should be named
|
|
|
|
`CMyClass.cpp' and the header file `CMyClass.h'.
|
|
|
|
|
|
|
|
Headers files not containing a class should have some meaningful
|
|
|
|
name with a leading capital (e.g. `Version.h').
|
|
|
|
|
|
|
|
Source files without a header file have a leading lowercase name.
|
|
|
|
Only files containing the entry point for an application should
|
|
|
|
lack a header file.
|
|
|
|
|
2002-08-02 21:53:23 +04:00
|
|
|
- Dependencies
|
|
|
|
* No circular library dependencies
|
|
|
|
Library dependencies form an acyclic graph. Conceptually
|
|
|
|
libraries can be arranged in layers where each library only
|
2002-08-12 02:43:07 +04:00
|
|
|
references libraries in layers below it, not in the same layer
|
|
|
|
or layers above it. The makefiles build the lowest layer
|
|
|
|
libraries first and work upwards.
|
2002-08-02 21:53:23 +04:00
|
|
|
|
|
|
|
* Avoid circular uses-a relationships
|
|
|
|
When possible, design classes with one-way uses-a relationships
|
|
|
|
and avoid cycles. This makes it easier to understand the code.
|
|
|
|
However, sometimes it's not always practical so it is permitted.
|
|
|
|
|
2002-08-12 02:43:07 +04:00
|
|
|
* Included files in headers
|
|
|
|
Headers should #include only the necessary headers. In
|
|
|
|
particular, if a class is referenced in a header file only as a
|
|
|
|
pointer or a reference then use `class COtherClass;' instead of
|
|
|
|
`#include "COtherClass.h".'
|
|
|
|
|
|
|
|
* #include syntax
|
|
|
|
Non-synergy header files must be included using angle brackets
|
|
|
|
while synergy header files must be included using double quotes.
|
|
|
|
#include "CSynergyHeader.h"
|
|
|
|
#include <systemheader.h>
|
|
|
|
The file name in a #include must not be a relative path unless
|
|
|
|
it's a system header file and it's customary to use a relative
|
|
|
|
path, e.g. `#include <sys/types.h>'. Use compiler options to
|
|
|
|
add necessary directories to the include search path.
|
|
|
|
|
|
|
|
* Included file ordering
|
|
|
|
Files should be included in the following order:
|
|
|
|
* Header for source file
|
|
|
|
The first include for CMyClass.cpp must be CMyClass.h.
|
|
|
|
* Other headers in directory, sorted alphabetically
|
|
|
|
* Headers for each library, sorted alphabetically per library
|
|
|
|
Include headers from the library closest in the dependency graph
|
|
|
|
first, then the next farthest, etc. sort alphabetically within
|
|
|
|
each library.
|
|
|
|
* System headers
|
|
|
|
|
2002-08-02 21:53:23 +04:00
|
|
|
- C++
|
|
|
|
* C++ features
|
|
|
|
Synergy uses the following more recent C++ features:
|
|
|
|
* bool
|
|
|
|
* templates
|
|
|
|
* exceptions
|
|
|
|
* mutable
|
|
|
|
* new scoping rules
|
|
|
|
* the standard C++ library
|
|
|
|
|
|
|
|
Do not use the following C++ features:
|
|
|
|
* dynamic_cast
|
|
|
|
* run time type information
|
|
|
|
* namespaces and using (use std:: where necessary)
|
|
|
|
|
|
|
|
The new scoping rules say that the scope of a variable declared
|
|
|
|
in a for statement is limited to the for loop. For example:
|
|
|
|
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
// i is in scope here
|
|
|
|
}
|
|
|
|
// i is not in scope here
|
|
|
|
|
|
|
|
for (int i = -10; i < 0; ++i) {
|
|
|
|
// an entirely new i is in scope here
|
|
|
|
}
|
|
|
|
// i is not in scope here
|
|
|
|
|
|
|
|
This is used routinely in synergy, but only in for loops. There
|
|
|
|
is a macro for `for' in lib/base/common.h when building under
|
|
|
|
Microsoft Visual C++ that works around the fact that that compiler
|
|
|
|
doesn't follow the new scoping rules. Use the macro if your
|
|
|
|
compiler using the old scoping rules.
|
|
|
|
|
|
|
|
* Standard C++ library
|
|
|
|
The standard C++ library containers should always be used in favor
|
|
|
|
of custom containers wherever reasonable. std::string is used
|
|
|
|
throughout synergy but only as the CString typedef; always use
|
|
|
|
CString, never std::string. Synergy avoids using auto_ptr due to
|
|
|
|
some portability problems. Synergy makes limited use of standard
|
|
|
|
algorithms and streams but they can be freely used in new code.
|
|
|
|
|
|
|
|
* Limited multiple inheritance
|
|
|
|
Classes should inherit implementation from at most one superclass.
|
|
|
|
Inheriting implementation from multiple classes can have unpleasant
|
|
|
|
consequences in C++ due to it's limited capabilities. Classes can
|
|
|
|
inherit from any number of interface classes. An interface class
|
|
|
|
provides only pure virtual methods.
|
|
|
|
|
|
|
|
Synergy breaks this rule in two places. First is that IInterface
|
|
|
|
implements the virtual destructor. However, it's just an empty
|
|
|
|
method so it doesn't really count. Second is MXErrno which provides
|
|
|
|
implementation for exceptions that use the global errno variable.
|
|
|
|
|
|
|
|
* No globals
|
|
|
|
Avoid global variables. All global variables must be static, making
|
|
|
|
it visible only with its source file. Most uses of global variables
|
|
|
|
are better served by static data members of a class. Global
|
|
|
|
constants are permitted in some circumstances.
|
|
|
|
|
|
|
|
Also avoid global functions. Use public static member functions in
|
|
|
|
a class instead.
|
|
|
|
|
|
|
|
These rules are violated by the main source file for each program
|
|
|
|
(except that the globals are still static). They could easily be
|
|
|
|
rewritten to put all the variables and functions into a class but
|
|
|
|
there's little to be gained by that.
|
|
|
|
|
|
|
|
* Private data only
|
|
|
|
If a class is plain-old-data (i.e. it has no methods) all of its
|
|
|
|
data members should be public. Otherwise all of its data members
|
|
|
|
should be private, not public or protected. This makes it much
|
|
|
|
easier to track the use of a member when reading code. Protected
|
|
|
|
data is not allowed because `protected' is a synonym for `public
|
|
|
|
to my subclasses' and public data is Bad Thing. While it might
|
|
|
|
seem okay in this limited situation, the situation is not at all
|
|
|
|
limited since an arbitrary number of classes can be derived,
|
|
|
|
directly or indirectly, from the class and any of those classes
|
|
|
|
have full access to the protected data.
|
|
|
|
|
2002-08-12 02:43:07 +04:00
|
|
|
* Plain old data
|
|
|
|
A class that merely contains data and doesn't perform operations
|
|
|
|
on that data (other than reads and writes) is plain old data (POD).
|
|
|
|
POD should have only public data members and non-copy constructors.
|
|
|
|
It must not have any methods other than constructors, not even a
|
|
|
|
destructor or assignment operators, nor protected or private data.
|
|
|
|
|
|
|
|
* Avoid using friend
|
|
|
|
Avoid declaring friend functions or classes. They're sometimes
|
|
|
|
necessary for operator overloading. If you find it necessary to
|
|
|
|
add friends to some class C, consider creating a utility class U.
|
|
|
|
A utility class is declared as the only friend of C and provides
|
|
|
|
only static methods. Each method forwards to a private method on
|
|
|
|
an object of C type (passed as a parameter to the U's method).
|
|
|
|
This makes maintenance easier since only U has friend access to C
|
|
|
|
and finding any call to U is trivial (they're prefixed by U::).
|
|
|
|
|
2002-08-02 21:53:23 +04:00
|
|
|
* Don't test for NULL when using `delete' or `delete[]'
|
|
|
|
It's unnecessary since delete does it anyway.
|
|
|
|
|
2002-08-12 02:43:07 +04:00
|
|
|
- Makefiles
|
|
|
|
Automake's makefiles (named Makefile.am) have a few requirements:
|
|
|
|
* Define the following macros at the top of the file:
|
|
|
|
NULL =
|
|
|
|
DEPTH = <relative-path-to-top-level>
|
|
|
|
VDEPTH = ./$(VPATH)/$(DEPTH)
|
|
|
|
<relative-path-to-top-level> is `..', `../..', `../../..', etc,
|
|
|
|
whichever references the top directory of the synergy tree. For
|
|
|
|
example, for a subdirectory of the top level use `..', for a
|
|
|
|
subdirectory of a subdirectory of the top level use `../..'.
|
|
|
|
* Lists should have one item per line and end in $(NULL). For
|
|
|
|
example:
|
|
|
|
EXTRA_DIST = \
|
|
|
|
kiwi.txt \
|
|
|
|
mango.cpp \
|
|
|
|
papaya.h \
|
|
|
|
$(NULL)
|
|
|
|
Indentation must use tabs in a makefile. Line continuations
|
|
|
|
(backslashes) should be aligned using tabs.
|
|
|
|
* Lists of files should be sorted alphabetically. Lists of
|
|
|
|
subdirectories must be in the desired build order.
|
|
|
|
|
|
|
|
- Source Formatting
|
2002-08-02 21:53:23 +04:00
|
|
|
Every project has its own formatting style and no style satisfies
|
|
|
|
everyone. New code should be consistent with existing code:
|
|
|
|
|
2002-08-12 02:43:07 +04:00
|
|
|
* All files should include the copyright and license notice
|
2002-08-02 21:53:23 +04:00
|
|
|
* Use tabs to indent
|
|
|
|
* Tabs are 4 columns
|
2002-09-02 21:14:21 +04:00
|
|
|
* Lines should not extend past the 80th column
|
2002-08-02 21:53:23 +04:00
|
|
|
* Open braces ({) go on same line as introducing statement
|
|
|
|
`for (i = 0; i < 10; ++i) {' not
|
|
|
|
for (i = 0; i < 10; ++i)
|
|
|
|
{
|
|
|
|
* Close braces line up with introducing statement
|
|
|
|
* Open brace for function is on a line by itself in first column
|
|
|
|
* Close brace for function lines up with open brace
|
|
|
|
* Always use braces on: if, else, for, while, do, switch
|
|
|
|
* `else {' goes on it's own line
|
|
|
|
* Always explicitly test pointers against NULL
|
|
|
|
e.g. `if (ptr == NULL)' not `if (ptr)'
|
|
|
|
* Put spaces around binary operators and after statements
|
|
|
|
e.g. `if (a == b) {' not `if(a==b){'
|
|
|
|
* C'tor initializers are one per line, indented one tab stop
|
|
|
|
* Other indentation should follow existing practice
|
|
|
|
* Use Qt style comments for extraction by doxygen
|
|
|
|
* Mark incomplete or buggy code with `FIXME'
|
|
|
|
|
2002-09-02 21:14:21 +04:00
|
|
|
- Other
|
|
|
|
* calls to log() should always be all on one line (even past column 80)
|
|
|
|
|
2002-08-12 02:43:07 +04:00
|
|
|
|
2002-08-02 21:53:23 +04:00
|
|
|
Class Relationships
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
The doxygen documentation can help in understanding the relationships
|
|
|
|
between objects. Use `make doxygen' in the top level directory to
|
|
|
|
create the doxygen documentation into doc/doxygen/html. You must have
|
|
|
|
doxygen installed, of course.
|
|
|
|
|
|
|
|
FIXME -- high level overview of class relationships
|
|
|
|
|
|
|
|
|
|
|
|
Portability
|
|
|
|
-----------
|
|
|
|
|
|
|
|
FIXME -- information about porting to new platforms
|