How to Contribute to GUF

Copyrights

If you contribute code, you must grant copyright of that code to Kenton Varda (me). There are many reasons for this:

  • If, at some future date, it becomes necessary to change the licensing terms on the code, it will be nearly impossible to do so if many people hold copyrights on various bits of the code. The code will *always* be open source. If I change the license on the code, it will be to some other OSI-approved open source license.
  • Most governments (especially that of the United States) have little respect for unregistered copyrights. However, registering a copyright to multiple holders around the world would be very difficult. At some point, I will need to register GUF's copyright, and the only way I can do that is if I own the code.
  • If a third party violates the license on the code, it will be very hard for me to bring a legal suit against them if I am not the copyright holder of the code in question. I am (somewhat) prepared to bring suit against those who violate the license (having three uncles who are lawyers, at least one of which deals in intellectual property, helps). Wouldn't you like me to do that work for you? :)
  • Note that I will NOT take credit for writing your code. You get to keep that. :) I just need legal ownership. Authors of code will be clearly indicated at the top of every source file and in various documentation.
  • The Free Software Foundation asks the same of their contributors.

Readings

Required reading:

  • All general coding documents (including this one).
  • Documentation on all core GUF classes, especially smart pointers.
  • At least some GUF code (to get the feel of it).

Highly recommended reading. I owe all of my C++ programming skill to these books (and a lot of practice):

  • Effective C++ and More Effective C++ by Scott Meyers
  • Large Scale C++ Software Design by John Lakos
  • Design Patterns by Gamma et al.

Writing a New Module

When writing a new module, you will want to start out by copying the header and cpp templates found in the templates directory of the source tree. These will start you off quickly with a framework consistent with the rest of the library. The next few steps depend on the type of class you are writing.

  • Pass-by-value

    Pass-by-value classes generally represent new data types, and have little functionality other than storing and performing basic operations on that data.

    If you are writing a pass-by-value class, you'll want to remove some stuff provided by the templates. The templates are designed for pass-by-smart-pointer classes, since those are the most used. Some things you will want to remove include:

    • The inheritance of the class from GObject. Pass-by-value classes should not use inheritance.
    • The smart pointer type declaration in the header.
    • The insulated implementation class in the source file (pass-by-value classes can't be insulated).

    You will then want to start writing your class. Keep the following in mind when you do:

    • Keep the amount of member data to a minimum. Pass-by-value classes are supposed to be custom data types. Keep your class under 16 bytes in size.
    • Avoid allocating memory. Most data type classes shouldn't even deal with pointers.
    • Try to keep functions short, and inline them when appropriate.
    • Copy constructors, assignment operators, and destructors should be as fast as possible. Remember, pass-by-value types are passed by value. Thus, copy constructors, destructors, and assignments will be used heavily. If you find you have to allocate or free memory in these functions, consider using reference counting to minimize the performance hit. (See GString for an example of a pass-by-value class that uses reference counting.)
    • Use overloaded operators where they make sense.
    • If your data type has a logical "null" value, consider integrating it with GUF's "null" keyword. "null" is actually an object of type "GNullType". All you have to do to make your class compatible is write a constructor which takes an operator of type "GNullType" and constructs a null object (this function should be as fast as a copy constructor, or faster). Be careful when assigning a "null" value for you type, however. A null variable should have no other purpose than being null. For example, a null pointer is a pointer to zero. A pointer to zero is never valid. On the other hand, a 3D vector class can have the value (0, 0, 0). Should this value be considered null? No! (0, 0, 0) is a valid vector and could mean something other than null. 3D vectors have no "null" value.
    • Generally, pass-by-value classes should not throw exceptions.

  • Pass-by-smart-pointer

    Pass-by-smart-pointer classes are larger classes that represent large data sets or some sort of functional object. Most classes in GUF are of this type. There are some things to keep in mind here, too:

    • First and foremost, think about the interface for your module. Is there an existing abstract interface which your module could logically implement? If so, implement it! If you create a new interface or add to an existing one, think about your custom functions. Might another module want to implement the same interface? If so, you may want to separate your interface into a separate module, so other classes can implement the same interface.
    • Keep the interface of your class separate from the implementation. The templates are set up to help you with this. Your header file should declare an abstract interface only! This means all virtual functions and no member variables. In addition, this interface may have a static member function named "New". This function should return a smart pointer to an implementation of your class. That implementation should be fully defined in the implementation file of your module (the cpp file).

Submitting Code

When your code is complete, send it to temporal@gauge3d.org. It will then be reviewed by myself and possibly one or two others. In all likelyhood, I'll reply with a list of things that need to be fixed, possibly accompanied by a modified version of your code. Do not be discouraged by this -- I throw out my own code all the time! :)

Once the code is reasonably clean and functional, it will be added to GUF's CVS repository, marking its official addition to the project.