MlView C++ coding standards.
//////////////////////////////

Initial Author: Dodji Seketeli.

I) Style
==========

Class and namespace names
-------------------------------
Class names are in the form "FooClassName", with the first letter in big cap.
Namespace names are in the form "fooNamespace", with the first letter in
small cap.

Methods names
------------------
Class and instance methods are in the form FooClassName::first_member_name ();
The actual member name is in small cap and made of words separated by
underscores. There should be a space between the method name and the
left bracket. 

For example, style FooClassName::bad_style() is bad style, whereas 
FooClassName::good_style () is good style.  FooClassName::anotherBadStyle ()     
is also bad style.

Methods definition layout
-------------------------
The Method return type should be alone on a line, starting at the begining of
the line.
The Fully qualified method name should be on the next line, right after
the return type line, starting at the begining of the line.
The curly bracket starting the method body should come on the next line and
be at the begining of the line.

e.g:

bool
FooClass::is_the_method_good ()
{
}

Variable names
-------------------
Variable names are all in small caps, made of words separated by small caps.
e.g: variable_names.

Methods parameters start with 'a_'.

e.g: 

void
FooClass::method_bar (int a_parameter) 
{
} 

Indentation 
-------------------
Indentation is made of tabs that are 4 space deep(\t).

A block indentation 1 tab deep. 

If, switch case etc layout
-------------------------

If/else etc should be indented like:

e.g:
if (condition) {
	do_something () ;
} else if (another_condition) {
	do_something_else () ;
} else {
	do_something_again () ;
}
Note the use of white spaces after the if, else keywords etc.

II) classes organisation 
=================================

mlview namespace
------------------
All the MlView code is in the 'mlview' namespace.
Class names don't need to start with MlView then, like MlViewApp.
Naming the class App is fine as it ends up being refered to as mlview::App.

source files
-------------
At most, we try to keep the rule "one source file, one class" as true as possible.Of course, classes that are not 'public' are defined in the source file 
of the relevant public class they are related to.
Source files should have names in small cap, made of words separating by
dashes (-). NO SOURCE FILE SHOULD CONTAIN UNDERSCORE ! Every source file name
should be prefixed by "mlview-".

e.g: the source file of the class mlview::App is mlview-app.cc .

inheritance
------------
All the "public" Classes should derive from the mlview::Object class.
That class itself derives from the Glig::Object class. 

All the "public" interface should derive from the mlview::Iface class.

III)API/ABI compatibility
=========================

A lot of classes of the MlView project will _maybe_ be used by other modules.
Therefore, we must get prepared to ensure forward API/ABI compatibility.

Are are a couple of rules to achieve this.

Only one class member
---------------------
All the classes in the project should have only one private member called
m_priv. That m_priv should be a pointer. The m_priv should be allocated
by the constructor of the class. The type of m_priv should be forward declared
in the declaration header and defined in the definition source file.

e.g:
// in mlview-foo.h file
struct FooPriv ;
class Foo {
	FooPriv *m_priv ;

	public:

	Foo () ;
	Foo (Foo &a_foo) ;
	virtual ~Foo () ;
} ;

//in mlview-foo.cc file
struct FooPriv {
	//members go here
} ;

Foo::Foo ()
{
	m_priv = new FooPriv () ;
}
Foo::~Foo ()
{
	if (m_priv) {
		delete m_priv ;
		m_priv = NULL ;
	}
}

No inline methods
-----------------
No inline method should be defined in the *.h  headers. All the methods
must be defined in *.cc files.

IV) Error logging, assertions, Exceptions
==========================================

People are greatly invited to use assert like macros in the mlview code.
These macros are there to check that logical conditions are meet at
various well choosen positions in the program.
For example, before dereferencing a pointer, one shoud *always* make sure
the pointer is not NULL.
The assert macros to use are defined in src/mlview-exception.h are 
called like THROW_IF_FAIL(), etc.

e.g:

AFooClass *ptr = get_pointer () ;
THROW_IF_FAIL2 (ptr != NULL, "argh, got a NULL pointer") ;
if (ptr->is_what_i_want ()) {
	do_this () ;
} else {
	do_that () ;
}
.

The THROW_IF_FAIL2(condition, message) macro throws an instance of 
mlview::Exception if the condition is not met. The message of the exception
is 'message'. Using this macro is useful because it logs in the console
_where_ the THROW_IF_FAIL2() was actually called. This is of an invaluable
use in debugging conditions.

Similarly, people should use the THROW (message) macros instead of
writting 'throw FooException ("blah"), because this macro logs the place
where the throw actually occured. Again, this helps a lot for debugging.

Also, please, do not define you own exception class unless you really can't
do otherwise. Why ? because the proliferation of exception classes usually
turn into a mess for the application writers. In short, people end up
asking themselves "what type of exception should I throw here ?".
In the case of mlview, the answer is short. Write something like:

THROW ("fonction foo() returned an error") ;

This simple macro will dump a trace of the file/linenumber/method name/
of *where* the exception was thrown from, and you'll get an instance
of mlview::Exception. It is simple and easily debuggable.
Let's keep it like that for now.

V) Exceptions and safe pointers
=============================

A common problem we face when we use exceptions is ressource leaking.

look at this code:

Foo* foo_ptr = allocate_foo () ;
do_this () ;
free_foo (foo_ptr) ;

Now, if do_this() throws an exception, foo_ptr will not
bee freed, so the application will be leaking.
A naive approach toward that is to enclose all the function
call in try/catch blocks. In practise, this approach appears to
be heavy and doesn't even completely solve the problem.

This is where the SafePtr template class of MlView comes into play.
You use it like this:

SafePtr<Foo, FooRef, FooUnref> foo_ptr ;
foo_ptr = allocate_foo () ;
do_this () ;

Note that you don't need to call free_foo() anymore.
Actually, SafePtr is a smart pointer. It lets the user perform almost
all the assignation operations it can perform on a Foo* (*, ->, etc...)
and it is responsible of the pointer lifetime.
The template class SafePtr is defined in mlview-safe-ptr.h and the
FooRef/FooUnref types are functors responsible of referencing, and unreferencing
Foo. These functors are defined in mlview-safe-ptr-utils.h .

You are strongly encouraged to use SafePtr each time you deal with pointers
*and* you want to take care of their lifetime. To do so, you just need to
include mlview-safe-ptr-utils.h . If the type of pointer you need doesn't have
a defined set of Ref/Unref functor, you can add a it to mlview-safe-ptr-utils.h.
