Personal tools
 
Document Actions

Guidelines for creating and packaging an application

This How-to applies to: Any version.
This How-to is intended for: Application Developer, Core Developer

Lack of standardization in packaging usually gives an unsatisfactory experience to the end user who tries to install them. These guidelines should help you create and package your applications more consistently.

This is a first draft, feel free to discuss your disagreements with these guidelines by posting comments below so we can end up with something that can be suitable for most of us.

Purpose

The goal of this document is to suggest to Tux Droid application authors how to "finish" an application. "Finishing" an application can be accomplished by creating a consistent set of SVN properties, packaging elements and documentation.

"Finished" products that conform to the packaging standards defined in this document could gain benefit from introspection that will be done by Tux Droid daemons or applications in the future about the contents of the application. For example, release information documents such as README, CHANGES can be used automagically by an aggregator or plugin manager that can display version numbers, changes and check for updates.

It's probable that "finished" Products will be given a special status on tuxisalive.com. Contributed applications that don't meet "finished" application criterion will (of course!) be accepted, but they won't be recognized as "first-class" applications and may be excluded some types of cataloging.

Mandatory Files

README

A 'README' document should contain a description of the application and a short description on how to get started to use it.


Versioning

How to set the version number of a project release or a tag on SVN?

The version numbers we use have the following structure:

major.minor.release-maturity

The choice as to whether a new version warrants a higher major version number or minor version number is fairly subjective, with no particular rule.
Release numbers are only used for small bug fixes or changes that generally do not affect the usability of the application and don't brake the compatibility.

For the code stored on SVN, the version number should be appended with "(SVN/UNRELEASED)". This will be removed when tagging and release a fixed version and helps differentiate a release from a development copy.

Maturity keywords can be: alpha, beta, rc (release candidate).
Examples:

0.0.1 (SVN/UNRELEASED)
0.0.1
0.1.0-alpha1
0.1.0-alpha2
0.1.0-beta1
0.1.0-rc1
0.1.0-rc2
0.1.0

When you want to tag a release from you trunk (SVN), you should name the tag folder with the version number as shown in the examples above.

Example: tagging the daemon with version 0.3.1

  • change the version number in version.h from "0.3.1 (SVN/UNRELEASED)" to "0.3.1"
  • tag the new version with the command "svn cp trunk tags/0.3.1"
  • change the version number in version.h from "0.3.1" to "0.3.2 (SVN/UNRELEASED)"

On python, you will use the variable

__version__ = '0.0.1'

Preferred coding-style for contributors:

These guidelines are for those interested in contributing code to SVN.

(Note: You may find some inconsistencies with this guidelines and the SVN code. We are working on it.
If you would like to accelerate the process,  pls submit a patch :-)

Python programmers may want to follow the excellent python guidelines.

Tabs vs Spaces

We (strongly :-) prefer use of spaces instead of tabs. Inconsistent mixing of tabs and spaces is inappropriate so we simply disabled commit of source files containing tabs on SVN.

Indentation

4 spaces. Period.

Comments

"Some people say code shouldn't need commenting, and the code itself should be enough." In a perfect world, that could be the case. I would say that commenting is necessary wherever it adds clarity to the code.

Add comments before the code. This looks better, especially for long comments:

/* this is a long comment this is a long comment this is a 
 * long comment this is a long comment */
code();

In your C code, don't use C++ style // one-line comments,
prefer /* comment blocks */.

For python code, use docstrings.

Function declarations

Each function should be preceded by a block comment prologue that gives the name and a short description of what the function does.

The type of the value returned and the function name should be on a single line. Formal parameters can be all on the same line if the line is not too long, or each on a single line (too many parameters, long names). In this case, either align the following lines to the opening parenthesis, or indent 2 levels.

The opening brace of the function body should be alone on a line beginning in column 1.

Recommended:

void prepare_coffee(int delay, int strength)
{
}

void repair_coffee_machine(int number_of_parts_missing,
int number_of_parts_included_in_the_kit)
{
}
or
void repair_coffee_machine(int number_of_parts_missing,
int number_of_parts_included_in_the_kit)

Not recommended:

void
prepare_coffee(
int delay,
int strength
)
{
}

void prepare_coffee(int delay, int strength) {
}

Function Calls

Space after commas in function calls. No space between function name and opening bracket.

    f(a, b);

Flow-control statements

There are 2 ways to place the opening and closing braces. Either each braces in a new line or the opening brace placed on same line as the flow control. Follow the project style already used if you're contributing code.

Each braces on a new line:
if (no_power)
{
}

Opening brace with the flow keyword:
if (no_power) {
}

Whitespace in Expressions and Statements

There's a very nice paragraph about this on the python guidelines: http://www.python.org/dev/peps/pep-0008/

For better readability, it is suggested that arithmetic and logical operator are preceded and followed by a space character. But avoid extraneous whitespace immediately inside parentheses, brackets or braces, immediately before a comma, semicolon, or colon.

Bad:
if ((a<b)||(b>c)&&(c>d))
{
do_strange_and_weird_things(a,b,c,d);
}

if ( ( a + b ) * ( b - c ) / ( c - d ) )
{
do_strange_and_weird_things ( a , b , c , d ) ;
}

Better:

if ((a < b) || (b > c) && (c > d))
{
do_plain_and_understandable_things(a, b, c, d);
}
if ((a + b) * ((b - c) / (c - d)))
{
do_plain_and_understandable_things(a, b, c, d);
}

Maximum line length

Limit all lines to a maximum of 79 characters.

There are still many devices around that are limited to 80 character lines; plus, limiting windows to 80 characters makes it possible to have several windows side-by-side. The default wrapping on such devices looks ugly. Therefore, please limit all lines to a maximum of 79 characters.

Naming conventions

Choose good variable names, descriptive variable names greatly enhance code readability, don't choose the name based on what type the variable is. "eyesPosition" is a better name than "eyp", "eyes", "eyesFlag", "boolean" or "flag".

The following naming styles can be freely used but don't mix them in the same software:
    - lower_case_with_underscores
    - CapitalizedWords (or CapWords, or CamelCase -- so named because
      of the bumpy look of its letters[4]).  This is also sometimes known as
      StudlyCaps.
      Note: When using abbreviations in CapWords, capitalize all the letters
      of the abbreviation.  Thus HTTPServerError is better than
      HttpServerError.
    - mixedCase (differs from CapitalizedWords by initial lowercase
      character!)

Good practices

Before committing your code, here are a couple of things you certainly want to check:
  • Remove trailing whitespaces.
    It is a problem for diffing (fills the diffs with lines that didn't change except a whitespace) and leads to more conflicts when using SVN.
  • Convert tabs to spaces.
  • Wrap lines longer than 79 characters.
  • Add comments wherever necessary.
  • Check the diff before committing, undo all changes you didn't intended to commit, like whitespace, blank lines, temporary test code, etc. Check for style consistency.

Documentation with Doxygen


Some codes use doxygen for generating the documentation. When contributing to such a code, use doxygen style comments. Usually, it's enough to cut & paste a comment from another function and change the comments. If you need more advanced keywords, have a look at doxygen's documentation.
An example of doxygen comments:
/**
 * \brief Performs a clean exit of the daemon.
 *
 * \param[in] sig  Signal (unused)
 *
 * Used to catch signals to exit properly.
 */
static void quit_handler(int sig)
{
exit(0);
}

Creating a release


In order to make a release, you should update the trunk of your repository so that it contains exactly what will be in the release, then tag it to the release version number and roll-up a new version number in the trunk.
Usually, that means applying the following steps:
  1. Check that your working directory is updated with the repository and check carefully the functionality of your application (it's a good idea to check it from a fresh checkout of the repository);
  2. Remove (SVN/UNRELEASED) from 'version.txt' and commit it;
  3. Create a tag (this is done by doing a 'svn copy TRUNK_URL TAG_URL' where TAG_URL ends with the version number you're creating, i.e. 'URL/my_application/tags/0.1.2' ;
  4. Copy the trunk to a new directory named with the base name of your repository;
  5. Add (SVN/UNRELEASED) to 'version.txt', update the version number to the next release of your roadmap and commit it; SVN is now ready for future developments;
  6. Change the owner of the copy you just made to root:root: 'chown -R root:root my_application';
  7. Create the archive file and append the version number to the name; i.e. 'tar -czf my_application-0.0.2-rc1.tar.gz my_application'
Notes:
- I'm not sure changing the owner to root is the right way but at least if someone extracts your application as root, he won't end up with your user name as owner of the files.

Documentation

References

  1. H. Spencer, "Indian Hill C Style and Coding Standards as amended for U of T Zoology Unix"
  2. C and C++ Style Guides 
by David Bourgeois last modified 2007-09-03 13:53
Contributors: neimad, srikanta

Control flow statements

Posted by Damien at 2007-04-01 14:23
I think that having control flow statements on a single line should be forbidden because their readability is awful. And, more generally, that there should be only *one* instruction per line.

Thus, the following, found in USBDaemon_command_tux.c in function tux_req_status():

if (portb.bits.PB0){result[1] = 1;}else{result[1] = 0;}

is evil and should instead be written as follows:

if (portb.bits.PB0)
result[1] = 1;
else
result[1] = 0;

(I also removed the unnecessary curly braces)

Indentation b0rked in previous comment

Posted by Damien at 2007-04-01 14:26
Dammit, the formatting ate up the indentation... Should read:

if (portb.bits.PB0)
....result[1] = 1;
else
....result[1] = 0;
You are here: Home Documentation How-tos Guidelines for creating and packaging an application

Powered by Plone CMS, the Open Source Content Management System