Documentation/CodeConventions

General Formatting Conventions

Red5's formatting convention begins with Sun's Code Conventions for the Java Programming Language which you will find here:  http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html

The follwing rules used by Red5 may differ Sun's standard:

  • Maximum line length is 120 characters
  • Use spaces instead of tabs
  • Indendation size is 4 spaces
  • Use fully qualified import statements, i.e. do not use asterisks
  • Do not insert a new line before opening brace. Insert a new line before closing brace
    //This is the way we want it!
    public void correctBlock() {
    }
    
    //Not like this
    public void badBlock() 
    {
    }
    
  • The conditional part of if and while statements should not use the equality operator for testing true or false values.
    //Do this
    if (foo)
    
    //Do NOT do this
    if (foo==true)
    
  • Always use the short form of the classname in code. Certain exception do apply where the fully qualified classname is required such as when java.sql.Date and java.util.Date are used in the same class. Otherwise, you should always import the class and use the short name.
    //Do this
    try {
    } catch (IOException e) {
    }
    
    //Do NOT do this
    try {
    } catch (java.io.IOException e) {
    }
    

Javadoc

Provide documentation to your methods in addition to providing notes within the method to help readers follow the flow. Internal method comments should be blocked by "//" and not "/*" even if they cover more than one line. If your code is in response to a bug report, add the tracking number to the comment.

Add your name and email (optional) to the class or method @author tag if you make a sugnificant contribution. This provides recognition as well as providing a point of contact for the modification.

Use @todo as a reminder of what needs to be done at a later time.

Unit Tests

All new classes and methods should have a corresponding unit test.

  • Use the naming scheme *Test.java for unit tests
  • Do not define public static Test suite() or constructor methods, the build system will automatically do the right thing without them

Logging

  • Use SLF4J org.slf4j.Logger rather than Log4j, JCL, or Java logging (JULI)
  • Log as much as necessary for someone to figure out what broke
  • Do not log throwables that you throw - leave it to the caller
  • Use SLF4J varargs {} expansion
  • If your logging call includes a loop, put it inside an isDebugEnabled() or isTraceEnabled() block

Levels

  • Use trace level for detailed/diagnostic logging
  • Use debug level for things an application developer would need to know
  • Use info level for things an administrator would need to know
  • Use warn level for things indicating an application or transient problem
  • Use error level for things indicating a problem with the server itself

Exceptions

  • A situation is only exceptional, if the program can not handle it with reasonably effort. Wrong input data should be an expected situation of the regular code, that could be handled gracefully.
  • The intention of exception-handling is to separate real error-handling from the regular part of the code, so don't force the caller to mix it with unnecessary exceptions.
  • Only if your code really has a problem to continue e.g., when a parameter is invalid, feel free to throw an exception!
  • Do NOT throw an exception, if you only suppose the caller of your code could have a problem with a special result. Try to return a special result value instead e.g., null, and let the caller decide with a regular if-else-statement. If the caller really has a problem, HE WILL throw an exception on his own.
  • But if your code throws an exception, even though it has no real problem and it could continue without an exception and return a special result value, you forestall the decision of the caller, whether the special result is really an error or not.
  • If you throw an exception, where the caller would decide that it is no error in the context of the caller, you force the caller to write an exception handler in his regular part or to abort i.e., you force the caller to mix regular code with exception handling. That is the opposite of the intentention of exception handling.
    //Bad example
    java.lang.Class.forName(String) throws ClassNotFoundException
    
  • In most programs/situations it is an error if this method does not find the class, therefore it throws an exception and forestalls the decision of the caller.
  • But maybe there is a program that should check a list of class names, whether the classes are present or not. Such a program is forced to mix its regular code with error handling of an exception, that is no error at all in that context.
  • The method should return a special result value instead: null. Many callers of that method have expected that situation and therefore are not in an unexpected situation/exceptional state. They could decide the situation on their own.
  • Only throw checked exceptions (not derived from RuntimeException), if the caller has a chance to handle it.
  • Exceptions that signal programming errors or system failures usually cannot be handled/repaired at runtime -> unchecked exception.
  • If your code really has a problem to continue e.g., when a parameter is invalid, throw an unchecked exception (derived from RuntimeException) and do NOT throw a checked exception, because if not even your code can handle the problem, in the very most cases the caller has no chance to handle the problem, too. Instead there maybe somebody somewhere in the highest layers who catches all RuntimeException's, logs them and continues the regular service.
  • Only if it is not possible to return special result values cleanly, use checked exceptions to force the caller to decide the situation. The caller should deescalate the situation by catching and handling one or more checked exceptions, e.g. with special result values(?) or by escalating with an unchecked exception, because the situation is an error, that can not be handled.
  • Checked exceptions are an official part of the interface, therefore do not propagate checked exceptions from one abstraction layer to another, because usually this would break the lower abstraction. E.g. do not propagate SQLException to another layer, because SQLExceptions are an implementation detail, that may change in the future and such changes should not affect the interfaces and their callers.
  • Never throw NullPointerException or RuntimeException. Use either IllegalArgumentException, or NullArgumentException (which is a subclass of IllegalArgumentException anyway). If there isn't a suitable subclass available for representing an exception, create your own.

Eclipse Users

Formatter Profile

The profile can be downloaded from here -  red5_codeformat.xml

Window -> Preferences
Java -> Code Style -> Formatter
Click on import and select the red5_codeformat.xml file downloaded above
Press OK after importing

Code Template

The latest version with the required header format can be downloaded here -  red5_codetemplate.xml

Window -> Preferences
Java -> Code Style -> Code Templates
Click on import and select the red5_codetemplate.xml file downloaded above
Press OK after importing

Submitting a Patch

If you make changes to Red5, and would like to contribute the to the project, you should create a patch via svn and post it to the Red5 users list or via Trac. To create a patch, simply execute the following command:

$> svn diff > your-changes.patch

Note: You may also use Eclipse to create a patch (Team -> Create Patch...), but this may require committers to modify the patch to match their project layout (workspace per branch or all branches in one workspace) and some committers may not be using Eclipse/Subclipse.