-
Notifications
You must be signed in to change notification settings - Fork 5
Conventions
Well since we are several developers on the project and others might want to contribute to the project so I decided to set down a convention that all code should conform to in order to make it a consistent.
The convention I've decided on is based on reading, it's a little more to write but I want it to be as easy as possible to work with even if the code isn't written by you and hopefully letting you code without having to look up what this code actually means or does but that the current context of it let's you assume what will happen.
Al right so to the code. I will be going with PascalCase for the internal C++ code on classes, namespaces and functions. The name should describe the function but if the name becomes way too long then you should think again. And you are never allowed to remove namespaces. Namespaces are there for a reason so if there is a namespace then you have to use it. Even if the compiler can deduct what namespace the function is in for you, you still have to write it so the developer easier can see which version of the function/variable you mean.
The argument names of functions are to be prefixed with the letter 'a'. This letter can be replaced to make reading the variable more natural. For instance it can be replaced with 'an', 'some' or 'the'. There is an exception to the rule where if you are only allowed to pass one specific value and should always be the same then you don't have to. This exception is applied to global ruby module and classes. Like the SFML module and the like. This is better than providing a global variable reference in my opinion. This also don't apply to the arguments argc or argv as I want them to be reserved like keywords. But only of course if they are used in co-junction with each others of course. Member variables are to be prefixed with 'my' and global variables with 'global'. If the global variable is local to this file only, it's declared static then it is to have the prefix 'local'. Spaces inside parenthesis and index operators but not before a parenthesis. Spaces also between operands and operators. One letter variables are never allowed either. No i, j, k and so on.
Example code:
SomeType globalVariable;
static AnotherType localVariable;
class FooBar
{
public:
FooBar( VALUE SFML );
~FooBar();
void SomeFunction( DataClass[] someData, int anAmount );
VALUE AnotherFunction( int argc, VALUE[] args, VALUE aSelf );
private:
SomeType myMemberVariable;
};At all times avoid complicating code. If you can resolve something without using pointers then do so. If you are writing "complicated" code then you are probably doing something wrong.
The wrappers should be written in the same manner to make it easier for developers to dive into them if there is a bug or something like this. Here is a basic template:
/* rbSFML
* Copyright (c) 2012 Henrik Valter Vogelius Hansson - groogy@groogy.se
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef MODULE_CLASS_HPP
#define MODULE_CLASS_HPP
#include <ruby.h>
#include <rbSFML.hpp>
/* Required includes */
#include </* ... */>
namespace rbClass
{
static inline SomeType PublicFunction( SomeType anArgument );
#if defined( MODULE_CLASS_CPP ) // <- Define in the implementation source file.
VALUE Class; // <- MUST BE NAMED CLASS!
#else
extern VALUE Class;
#endif
#if defined( RBSFML_MODULE ) // <- Defined whne compiling the specific module.
void Init( VALUE SFML );
#endif
#if defined( MODULE_CLASS_CPP )
// Class#function_name( argument )
static VALUE FunctionName( VALUE aSelf, VALUE anArgument );
// Class#memory_usage
static VALUE GetMemoryUsage( VALUE aSelf ); // <- All classes must implement this!
#endif
};
SomeType rbClass::PublicFunction( SomeType anArgument )
{
/* Insert code here */
}
#endif // MODULE_CLASS_HPP/* rbSFML
* Copyright (c) 2012 Henrik Valter Vogelius Hansson - groogy@groogy.se
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
#define MODULE_CLASS_CPP
/* Internal Includes */
#include </* ... */>
/* External includes */
#include <SFML/Module/Class.hpp>
#include </* ... */>
void rbClass::Init( VALUE SFML )
{
rbClass::Class = rb_define_class_under( SFML, "Class", rb_cObject );
// Class methods
rb_define_alloc_func( rbClass::Class, rbMacros::Allocate< sf::Class> );
// Instance methods
rb_define_method( rbClass::Class, "function_name", rbClass::FunctionName, 1 );
rb_define_method( rbClass::Class, "memory_usage", rbClass::GetMemoryUsage, 0 );
// Instance aliasses
// aliases here if any
}
// Class#function_name( argument )
VALUE rbClass::FunctionName( VALUE aSelf, VALUE anArgument )
{
return Qnil;
}
// Class#memory_usage
VALUE rbClass::GetMemoryUsage( VALUE aSelf )
{
return SIZET2NUM( sizeof( sf::Class ) );
}As you can see this template gives two interfaces when being compiled. One internal within the module and one outwards. If you want something to be show outwards then implement it as the PublicFunction, otherwise implement it as FunctionName. If you need to use something internally defined which means compilation would fail with static/inline modifier then you are of course free to remove them and implement the code in the source file instead.
Well with external code I am talking about the actual code written in ruby. More to come here but just assume the ruby standard.
In order to deal with both the garbage collector and making sure that we always work against the same Ruby instance of the wrapper we have to save a reference to an object if an object can point to another. Prime example is resource objects here. A sprite points to a texture object. Here we have to keep a reference back to the texture in ruby. This is done very simple. Just save a reference to it in an instance variable. There is one rule though to make it clear that the variable is "private" so that you don't accidentally overwrite it. They all must start with the prefix "_ref_". This means that for sprite this variable is called "@__ref__texture".