The old version of this document is also Available in PDF format
$PTII/util/testsuite/ptspell *.java
$PTII/util/testsuite/chkjava *.java
$PTII/adm/bin/fix-files *.java
/* One line description of the class. copyright notice */ package MyPackageName; // Imports go here, in alphabetical order, with no wildcards. ////////////////////////////////////////////////////////////////////////// //// ClassName /** Describe your class here, in complete sentences. What does it do? What is its intended use? @author yourname @version $Id: codingStyle.tex,v 1.15 2010/03/31 23:33:07 cxh Exp $ @see classname (refer to relevant classes, but not the base class) @since Ptolemy II x.x @Pt.ProposedRating Red (yourname) @Pt.AcceptedRating Red (reviewmoderator) */ public class ClassName { /** Create an instance with ... (describe the properties of the * instance). Use the imperative case here. * @param parameterName Description of the parameter. * @exception ExceptionClass If ... (describe what * causes the exception to be thrown). */ public ClassName(ParameterClass parameterName) throws ExceptionClass { } /////////////////////////////////////////////////////////////////// //// public variables //// /** Description of the variable. */ public int variableName; /////////////////////////////////////////////////////////////////// //// public methods //// /** Do something... (Use the imperative case here, such as: * "Return the most recently recorded event.", not * "Returns the most recently recorded event.") * @param parameterName Description of the parameter. * @return Description of the returned value. * @exception ExceptionClass If ... (describe what * causes the exception to be thrown). */ public int publicMethodName(ParameterClass parameterName) throws ExceptionClass { return 1; } /////////////////////////////////////////////////////////////////// //// protected methods //// /** Describe your method, again using imperative case. * @see RelevantClass#methodName() * @param parameterName Description of the parameter. * @return Description of the returned value. * @exception ExceptionClass If ... (describe what * causes the exception to be thrown). */ protected int _protectedMethodName(ParameterClass parameterName) throws ExceptionClass { return 1; } /////////////////////////////////////////////////////////////////// //// protected variables //// /** Description of the variable. */ protected int _aProtectedVariable;
/////////////////////////////////////////////////////////////////// //// private methods //// // Private methods need not have Javadoc comments, although it can // be more convenient if they do, since they may at some point // become protected methods. private int _privateMethodName() { return 1; } /////////////////////////////////////////////////////////////////// //// private variables //// // Private variables need not have Javadoc comments, although it can // be more convenient if they do, since they may at some point // become protected variables. private int _aPrivateVariable; }The key points to note about this organization are:
Copyright (c) 1999-2010 The Regents of the University of California. All rights reserved. Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. PT_COPYRIGHT_VERSION_2 COPYRIGHTENDKEYThis style of copyright is often referred to the community as a "BSD" copyright because it was used for the "Berkeley Standard Distribution" of Unix. It is much more liberal that the commonly used "GPL" or "GNU Public License," which encumbers the software and derivative works with the requirement that they carry the source code and the same copyright agreement. The BSD copyright requires that the software and derivative work carry the identity of the copyright owner, as embodied in the lines:
Copyright (c) 1999-2010 The Regents of the University of California. All rights reserved.The copyright also requires that copies and derivative works include the disclaimer of liability in BOLD. It specifically does not require that copies of the software or derivative works carry the middle paragraph, so such copies and derivative works need not grant similarly liberal rights to users of the software. The intent of the BSD copyright is to maximize the potential impact of the software by enabling uses of the software that are inconsistent with disclosing the source code or granting free redistribution rights. For example, a commercial enterprise can extend the software, adding value, and sell the original software embodied with the extensions. Economic principles indicate that granting free redistribution rights may render the enterprise business model untenable, so many business enterprises avoid software with GPL licenses. Economic principles also indicate that, in theory, fair pricing of derivative works must be based on the value of the extensions, the packaging, or the associated services provided by the enterprise. The pricing cannot reflect the value of the free software, since an informed consumer will, in theory, obtain that free software from another source. Software with a BSD license can also be more easily included in defense or national-security related applications, where free redistribution of source code and licenses may be inconsistent with the mission of the software. Ptolemy II can include other software with copyrights that are different from the BSD copyright. In general, we do not include software with the GNU General Public License (GPL) license, because provisions of the GPL license require that software with which GLP'd code is integrated also be encumbered by the GPL license. In the past, we have made an exception for GPL'd code that is aggregated with Ptolemy II but not directly combined with Ptolemy II. For example cvs2cl.pl was shipped with Ptolemy II. This file is a GPL'd Perl script that access the CVS database and generates a ChangeLog file. This script is not directly called by Ptolemy II, and we include it as a "mere aggregation" and thus Ptolemy II does not fall under the GPL. Note that we do not include GPL'd Java files that are compiled and then called from Ptolemy II because this would combine Ptolemy II with the GPL'd code and thus encumber Ptolemy II with the GPL. Another GNU license is the GNU Library General Public License now known as the GNU Lesser General Public License (LGPL). We try to avoid packages that have this license, but we on occasion we have included them with Ptolemy II. The LGPL license is less strict than the GPL - the LGPL permits linking with other packages without encumbering the other package. In general, it is best if you avoid GNU code. If you are considering using code with the GPL or LGPL, we encourage you to carefully read the license and to also consult the GNU GPL FAQ at http://www.gnu.org/licenses/gpl-faq.html. We also avoid including software with proprietary copyrights that do not permit redistribution of the software. The date of the copyright for newly created files should be the current year:
Copyright (c) 2010 The Regents of the University of California. All rights reserved.If a file is a copy of a previously copyrighted file, then the start date of the new file should be the same as that of the original file:
Copyright (c) 1999-2010 The Regents of the University of California. All rights reserved.Ideally, files should have at most one copyright from one institution. Files with multiple copyrights are often in legal limbo if the copyrights conflict. If necessary, two institutions can share the same copyright:
Copyright (c) 2010 The Ptolemy Institute and The Regents of the University of California. All rights reserved.Ptolemy II includes a copyright management system that will display the copyrights of packages that are included in Ptolemy II at runtime. To see what packages are used in a particular Ptolemy configuration, do Help - About - Copyright. Currently, URLs such as about: and about:copyright are handled specially. If, within Ptolemy, the user clicks on a link with a target URL of about:copyright, then we eventually invoke code within
import ptolemy.kernel.CompositeEntity; import ptolemy.kernel.Entity; import ptolemy.kernel.Port; import ptolemy.kernel.util.IllegalActionException; import ptolemy.kernel.util.Locatable; import ptolemy.kernel.util.NameDuplicationException;in particular, we do not use the wildcards supported by Java, as in:
import ptolemy.kernel.*; import ptolemy.kernel.util.*;The reason that we discourage wildcards is that the full class names in import statements makes it easier find classes that are referenced in the code. If you use an IDE such as Eclipse, it is trivially easy to generate the import list in this form, so there is no reason to not do it. Imports are ordered alphabetically by package first, then by class name, as shown above.
/** In this actor, inputs are read from the <i>input</i> port ... */The Javadoc program gives extensive diagnostics when run on a source file. Our policy is to format the comments until there are no Javadoc warnings. Private members and methods need not be documented by Javadoc comments. The doccheck tool from
@author Claudius Ptolemaus, Contributor: Tycho BraheIf you are creating a new file that is based on an older file, move the authors of the older file towards the end:
@author Copernicus, Based on Galileo.java by Claudius Ptolemaus, Contributor: Tycho BraheThe general rule is that only people who actually contributed to the code should be listed as authors. So, in the case of a new file, the authors should only be people who edited the file. Note that all the authors should be listed on one line. Javadoc will not include authors listed on a separate line.
bash-3.2$ svn proplist README.txt Properties on 'README.txt': svn:keywords svn:eol-style bash-3.2$ svn propget svn:keywords README.txt Author Date Id Revision bash-3.2$ svn propget svn:eol-style README.txt nativeTo set the properties on a file:
svn propset svn:keywords "Author Date Id Revision" filename svn propset svn:eol-style native filenameFor details about properly configuring your Subversion environment, see
@since Ptolemy II 8.1Adding an @since tag to a new class is optional, we usually update these tags by running a script when we do a release. However, authors should be aware of their meaning. Note that the @since tag can also be used when a method is added to an existing class, which will help users notice new features in older code.
@Pt.ProposedRating blue ptolemy @Pt.AcceptedRating green ptolemyThe intent of the code rating is to clearly identify to readers of the file the level of maturity of the contents. The Ptolemy Project encourages experimentation, and experimentation often involves creating immature code, or even "throw-away" code. Such code is red. We use a lightweight software engineering process documented in "Software Practice in the Ptolemy Project,"[1] to raise the code to higher ratings. That paper documents the ratings a:
/** Mark the object invalid, indicating that when a method * is next called to get information from the object, that * information needs to be reconstructed from the database. */ public void invalidate() { _valid = false; }By contrast, here is a poor method comment:
/** Set the variable _valid to false. */ public void invalidate() { _valid = false; }While this certainly describes what the method does from the perspective of the coder, it says nothing useful from the perspective of the user of the class, who cannot see the (presumably private) variable _valid nor how that variable is used. On closer examination, this comment describes how the method is accomplishing what it does, but it does not describe what it accomplishes. Here is an even worse method comment:
/** Invalidate this object. */ public void invalidate() { _valid = false; }This says absolutely nothing. Note the use of the imperative case in all of the above comments. It is common in the Java community to use the following style for documenting methods:
/** Sets the expression of this variable. * @param expression The expression for this variable. */ public void setExpression(String expression) { ... }We use instead the imperative case, as in
/** Set the expression of this variable. * @param expression The expression for this variable. */ public void setExpression(String expression) { ... }The reason we do this is that our sentence is a well-formed, grammatical English sentence, while the usual convention is not (it is missing the subject). Moreover, calling a method is a command "do this," so it seems reasonable that the documentation say "Do this." The use of imperative case has a large impact on how interfaces are documented, especially when using the listener design pattern. For instance, the java.awt.event.ItemListener interface has the method:
/** Invoked when an item has been selected or deselected. * The code written for this method performs the operations * that need to occur when an item is selected (or deselected). */ void itemStateChanged(ItemEvent e);A naive attempt to rewrite this in imperative tense might result in:
/** Notify this object that an item has been selected or deselected. */ void itemStateChanged(ItemEvent e);However, this sentence does not capture what the method does. The method may be called in order to notify the listener, but the method does not "notify this object". The correct way to concisely document this method in imperative case (and with meaningful names) is:
/** React to the selection or deselection of an item. */ void itemStateChanged(ItemEvent event);The above is defining an interface (no implementation is given). To define the implementation, it is also necessary to describe what the method does:
/** React to the selection or deselection of an item by doing... */ void itemStateChanged(ItemEvent event) { ... implementation ... }Comments for base class methods that are intended to be overridden should include information about what the method generally does, plus information that a programmer may need to override it. If the derived class uses the base class method (by calling super.methodName()), but then appends to its behavior, then the documentation in the derived class should describe both what the base class does and what the derived class does.
/** The fire() method is called when ... */The parentheses are empty even if the method takes arguments. The arguments are not shown. If the method is overloaded (has several versions with different argument sets), then the text of the documentation needs to distinguish which version is being used. Other methods in the same class may be linked to with the @link ... Javadoc tag. For example, to link to a foo() method that takes a String:
* Unlike the {@link #foo(String)} method, this method ...Methods and members in the same package should have an octothorpe (# sign) prepended. Methods and members in other classes should use the fully qualified class name:
{@link ptolemy.util.StringUtilities.substitute(String, String, String)}Links to methods should include the types of the arguments. To run Javadoc on the classes in the current directory, run make docs, which will create the HTML javadoc output in the doc/codeDoc subdirectory. To run Javadoc for all the common packages, run cd $PTII/doc; make docs. The output will appear in $PTII/doc/codeDoc. Actor documentation can be viewed from within Vergil, right clicking on an actor and selecting View Documentation.
* @exception MyException If such and such occurs.Notice that the body always starts with "If", not "Thrown if", or anything else. Just look at the Javadoc output to see why. In the case of an interface or base class that does not throw the exception, use the following:
* @exception MyException Not thrown in this base class. Derived * classes may throw it if such and such happens.The exception still has to be declared so that derived classes can throw it, so it needs to be documented as well.
// FIXME: The following cast may not always be safe. Foo foo = (Foo)bar;By default, Eclipse will highlight FIXMEs.
if (container != null) { Manager manager = container.getManager(); if (manager != null) { manager.requestChange(change); } }Closing brackets should be on a line by themselves, aligned with the beginning of the line that contains the open bracket. Please avoid using the Tab character in source files. The reason for this is that code becomes unreadable when the Tab character is interpreted differently by different programs. Your text editor should be configured to react to the Tab key by inserting spaces rather than the tab character. To set up Emacs to follow the Ptolemy II indentation style, see $PTII/util/lisp/ptemacs.el. To set up Eclipse to follow the Ptolemy II indentation style, see the instructions in $PTII/doc/coding/eclipse.htm. Long lines should be broken up into many small lines. The easiest places to break long lines are usually just before operators, with the operator appearing on the next line. Long strings can be broken up using the + operator in Java, with the + starting the next line. Continuation lines are indented by 8 characters, as in the throws clause of the constructor in figure 1.
Right: foo(a, b); Wrong: foo(a,b);Use spaces around operators such as plus, minus, multiply, divide or equals signs, after semicolons and after keywords like if, else, for, do, while, try, catch and throws:
Right: a = b + 1; Wrong: a=b+1; Right: for(i = 0; i < 10; i += 2) Wrong: for (i=0 ;i<10;i+=2) Right: if ( a == b) { Wrong: if(a==b)Note that the Eclipse clean up facility will fix these problems, see
throw IllegalActionException(this, "Cannot append an object of type: " + obj.getClass().getName() + " because " + "it does not implement Cloneable.");Note that the exception not only gives a way to identify the objects that caused the exception, but also why the exception occurred. There is no need to include in the message an identification of the "this" object passed as the first argument to the exception constructor. That object will be identified when the exception is reported to the user. If an exception is caught, be sure to use exception chaining to include the original exception. For example:
String fileName = foo(); try { // Try to open the file } catch (IOException ex) { throw new IllegalActionException(this, ex, "Failed to open '" + fileName + "'"); }
# Makefile for the Java classes used to implement the Ptolemy kernelEach makefile has a one line description of the purpose of the makefile.
# # @Authors: Christopher Hylands, based on a file by Thomas M. Parks #The authors for the makefile. # @version $Id: makefile 56450 2009-12-06 06:54:56Z eal $ The version control version. We use $Id$, which gets expanded by Subversion to include the revision number, the date of the last revision and the login of the person who made the last revision.
# @Copyright (c) 1997-2010 The Regents of the University of California.The copyright year should be the start with the year the makefile file was first created, so when creating a new file, use the current year, for example "Copyright (c) 2010 The Regents . . ."
# All rights reserved. # # Permission is hereby granted, without written agreement and without # license or royalty fees, to use, copy, modify, and distribute this # software and its documentation for any purpose, provided that the # above copyright notice and the following two paragraphs appear in all # copies of this software. # # IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES # ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF # THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE # PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF # CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, # ENHANCEMENTS, OR MODIFICATIONS. # # PT_COPYRIGHT_VERSION_2 # COPYRIGHTENDKEYThe new BSD copyright appears in each makefile.
ME = ptolemy/kernel/utilThe makefile variable ME is set to the directory where that includes the makefile. Since this makefile is in ptII/ptolemy/kernel/util, ME is set to that directory. The ME variable is primarily used by make to print informational messages.
DIRS = testThe DIRS makefile variable lists each subdirectory in which make is to be run. Any subdirectory that contains a makefile should be listed in DIRS.
# Root of the Ptolemy II directory ROOT = ../../..The ROOT makefile variable is a relative path to the $PTII directory. This variable is relative so as to avoid problems if the $PTII environment variable is not set or is set to a different version of Ptolemy II.
CLASSPATH = \$(ROOT)Set the Java classpath to the value of the ROOT makefile variable, which should be the same as the $PTII environment variable. Note that if this makefile contains Java files that require third party software contained in jar files not usually found in the Java classpath, then CLASSPATH would be set to include those jar files, for example CLASSPATH = $(ROOT)$(CLASSPATHSEPARATOR)$(DIVA_JAR) would include ptII/lib/diva.jar, where the DIVA_JAR makefile variable is defined in ptII.mk
# Get configuration info CONFIG = $(ROOT)/mk/ptII.mk include $(CONFIG)The above includes $PTII/mk/ptII.mk The way the makefiles work is that the $PTII/configure script examines the environment, and then reads in the
# Flags to pass to javadoc. (Override value in ptII.mk) JDOCFLAGS = -author -version -public $(JDOCBREAKITERATOR) $(JDOCMEMORY) $(JDOCTAG)Directory specific makefile variables appear here. This variable sets JDOCFLAGS, which is used if "make docs" is run in this directory. JDOCFLAGS is not often used, we include it here for completeness.
# Used to build jar files PTPACKAGE = util PTCLASSJAR = $(PTPACKAGE).jarPTPACKAGE is the directory name of this directory. In this example, the makefile is in ptolemy/kernel/util, so PTPACKAGE is set to util. PTPACKAGE is used by PTCLASSJAR to name the jar file when make install is run. For this file, running make install will create util.jar. If a directory contains subdirectories that have source files, then PTCLASSJAR is not set and PTCLASSALLJAR and PTCLASSALLJARS is set, see below.
JSRCS = \ AbstractSettableAttribute.java \ Attribute.java \ BasicModelErrorHandler.java \And so on . . .
ValueListener.java \ Workspace.javaA list of all the .java files to be included. The reason that each Java file is listed separately is to avoid shipping test files and random kruft. Each file that is listed should follow this style guide.
EXTRA_SRCS = $(JSRCS)EXTRA_SRCS contains all the source files that should be present. If there are files such as icons or .xml files that should be included, then OTHER_FILES_TO_BE_JARED is set to include those files and the makefile would include:
# Sources that may or may not be present, but if they are present, we don't # want make checkjunk to barf on them. # Don't include demo or DIRS here, or else 'make sources' will run 'make demo' MISC_FILES = $(DIRS) # make checkjunk will not report OPTIONAL_FILES as trash # make distclean removes OPTIONAL_FILES OPTIONAL_FILES = \ doc \ 'CrossRefList$$1.class' \ 'CrossRefList$$CrossRef.class' \And so on . . .
'Workspace$$ReadDepth.class' \ $(PTCLASSJAR)MISC_FILES and OPTIONAL_FILES are used by the make checkjunk command. The checkjunk target prints out the names of files that should not be present. We use checkjunk as part of the release process. MISC_FILES should not include the demo directory or else running make sources will invoke the demos. To determine the value of OPTIONAL_FILES, run make checkjunk and add the missing .class files. Since the inner classes have $ in their name, we need to use single quotes around the inner class name and repeat the $ to stop make from performing substitution.
JCLASS = $(JSRCS:%.java=%.class)JCLASS uses a make macro to read the value of JSRCS and substitute in .class for .java. JCLASS is used to determine what .class files should be created when make is run.
all: jclass install: jclass $(PTCLASSJAR)The all rule is the first rule in the makefile, so if the command make is run with no arguments, then the all rule is run. The all rule runs the jclass rule, which compiles the java files. The install rule is run if make install is run. The install rule is like the all rule in that the java files are compiled. The install rule also depends on the value of PTCLASSJAR makefile variable, which means that make install also creates util.jar
# Get the rest of the rules include $(ROOT)/mk/ptcommon.mkThe rest of the rules are defined in ptcommon.mk
DIRS = util attributes undo testDIRS contains each subdirectory in which make will be run
# Used to build jar files PTPACKAGE = kernel PTCLASSJAR =Note that in ptolemy/kernel/util, we set PTCLASSJAR, but here it is empty.
# Include the .class files from these jars in PTCLASSALLJAR PTCLASSALLJARS = \ attributes/attributes.jar \ undo/undo.jar \ util/util.jarPTCLASSALLJARS is set to include each jar file that is to be included in this jar file. Note that we don't include test/test.jar because the test directory contains the test harness and test suites and is not necessary at run time
PTCLASSALLJAR = $(PTPACKAGE).jarPTCLASSALLJAR is set to the name of the jar file to be created, which in this case is kernel.jar.
install: jclass jarsThe install rule depends on the jars target. The jars target is defined in ptcommon.mk. The jars target depends on PTCLASSALLJAR, so if PTCLASSALLJAR is set, then make unjars each jar file listed in PTCLASSALLJARS and creates the jar file named by PTCLASSALLJAR
bash-3.2$ svn co svn+ssh://source.eecs.berkeley.edu/chess/svntest A svntest/README.txt Checked out revision 7. bash-3.2$ cd svntestbash-3.2$ echo '$Id$' > testfile.txt
bash-3.2$ svn add testfile.txt A testfile.txt bash-3.2$ svn commit -m "A test for svn keywords: testfile.txt " testfile.txt Adding testfile.txt Transmitting file data . Committed revision 8. bash-3.2$ cat testfile.txt@version $Id: testfile.txt 1.1 2010-03-31 18:18:22Z cxh $
bash-3.2$ svn proplist testfile.txt Properties on 'testfile.txt': svn:keywords svn:eol-styleNote that testfile.txt had $Id$ properly substituted. If testfile.txt had only $Id$ and not something like
bash-3.2$ svn proplist README.txt Properties on 'README.txt': svn:keywords svn:eol-style bash-3.2$ svn propget svn:keywords README.txt Author Date Id Revision bash-3.2$ svn propget svn:eol-style README.txt nativeSee $PTIII/doc/coding/releasemgt.htm for information about how to use
svn propset svn:keywords "Author Date Id Revision" MyClass.java svn propset svn:eol-style native MyClass.java svn commit -m "Fixed svn keywords" MyClass.java
svn propget svn:ignore . > /tmp/iIf the directory has svn:ignore set, then /tmp/i will contain the files to be ignored. If the directory does not have svn:ignore set, then /tmp/i will be ignored. Edit /tmp/i and add files to be ignored:
*.class bar.jarThen run
svn propset svn:ignore -F /tmp/i . svn commit -N -m "Added *.class and bar.jar to svn:ignore" .We use the -N option to commit just the directory.
@author @version @since @Pt.ProposedRating @Pt.AcceptedRating
make sources make make install
$PTII/adm/bin/mkpackagehtml ptolemy.foo.bar cd $PTII/ptolemy/foo/bar svn add README.txt package.html