208 lines
8.1 KiB
Plaintext
208 lines
8.1 KiB
Plaintext
|
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.
|
||
|
|
||
|
- Dependencies
|
||
|
* No circular library dependencies
|
||
|
Library dependencies form an acyclic graph. Conceptually
|
||
|
libraries can be arranged in layers where each library only
|
||
|
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.
|
||
|
|
||
|
* 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.
|
||
|
|
||
|
- 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.
|
||
|
|
||
|
* Don't test for NULL when using `delete' or `delete[]'
|
||
|
It's unnecessary since delete does it anyway.
|
||
|
|
||
|
- 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.
|
||
|
|
||
|
- Formatting
|
||
|
Every project has its own formatting style and no style satisfies
|
||
|
everyone. New code should be consistent with existing code:
|
||
|
|
||
|
* Use tabs to indent
|
||
|
* Tabs are 4 columns
|
||
|
* 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'
|
||
|
|
||
|
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
|