Java
Rosetta.java
// Copyright (c) 2007 Art & Logic, Inc. All Rights Reserved.
// $Id: Rosetta.java,v 1.1 2010/01/26 22:08:56 bporter Exp $
// Above: [sf02], [sf03]
// a note on the stuff inside the square brackets:
// Each of the codes inside brackets is a reference to the rule(s) in the
// Style Guide that's being illustrated, as follows:
// [sf##] - StyleGuide/SourceFiles
// [cas##] - StyleGuide/ClassesAndStructures
// [nr##] - StyleGuide/NamingRules
// [cg##] - StyleGuide/Commenting
// [fmt##] - StyleGuide/Formatting
// Throughout: [fmt01]; all indentation done with space characters (0x20),
// three spaces per logical tab stop.
package com.ArtLogic.Rosetta;
// [sf05]
import java.io.File;
import java.lang.String;
import com.ArtLogic.util.AlTypes;
// [sf07], only one class declared/defined in this source file [redundant in Java]
// [cg02], comments useful to programmers who will use (but not necessarily
// maintain) this class are separated out into the header file, not in the
// implementation file. [redundant in Java]
/**
* @class ARosetta
* @brief Simple, but meaningless class to demonstrate Art+Logic programming
* style conventions as they are applied to the various programming languages
* we use. In several places, you're asked to imagine a block of useful code
* to avoid distracting you from the issues of formatting (etc) that are being
* demonstrated.
*
* As you've already seen above, the thing about to be shown in this file is
* called out in comments using the A+L-style markup '!!!'
*/
// [nr11], [nr18] class names prefixed with "A"
public class ARosetta
{
// [nr25] the 'q' prefix indicates that we are controlling conditional
// compilation [...or in Java, conditional execution]
private static final boolean qVerbose = true;
// [cas01] public member functions/methods listed first
// [nr08] new non-class types (enumerations, data structures, etc) are
// named with MixedCase and no special prefix
public enum EnumName
{
// [nr23] identifiers specifying constants for the program are always
// prefixed with a lowercase 'k'.
kSomeConstant,
kSomeOtherConstant;
};
/**
* Construct and initialize the Rosetta object.
* @param fileName The file to use as our data source
*/
public ARosetta(String fileName)
{
fFileName = fileName;
fInputFile = new File(fFileName);
fProcessResult = 0;
}
/**
* [nr07] In Java, class methods (other than a class' constructor) begin with
* a lowercase letter, and additional words in the method name are capitalized.
*/
public boolean memberFunctionWithMultipleWords()
{
boolean ok = true;
// [fmt02] -- labels used as the target of a break or continue are
// placed in column zero.
blockOfCode:
{
// [fmt08] -- formatting of a for() loop.
for (int i = 0; i < kSomeConstant; ++i)
{
for (int j = 0; j < kSomeOtherConstant; ++j)
{
// [fmt02] -- preprocessor directives
if(qVerbose)
{
System.out.printf("testing: %d, %d\n", i, j);
}
// [nr07] -- Calls to member functions of the current object are
// made through an explicit "this."
ok = this.test(i, j);
if (!ok)
{
System.out.printf("Fatal error testing: %d, %d\n", i, j);
break blockOfCode;
}
}
}
return true;
} // end blockOfCode:
// cleanup code here...
return false;
}
/**
* !!! Here's how we handle very long lines (i.e., longer than 79
* characters)
*/
public boolean longLineWrapping()
{
// [fmt03] -- source lines should be less than 80 characters long.
// [fmt04] -- break lines at the most logical point
// 1 2 3 4 5 6 7
//34567890123456789012345678901234567890123456789012345678901234567890123456789
retval = FunctionWithManyArguments(longArgumentName1, longArgumentName2,
longArgumentName3, longArgumentName4);
// alternative format #1
retval = FunctionWithManyArguments(longArgumentName1,
longArgumentName2,
longArgumentName3,
longArgumentName4);
// alternative format #2
retval = FunctionWithManyArguments(
longArgumentName1,
longArgumentName2,
longArgumentName3,
longArgumentName4);
// [fmt05] -- prefer to break after a comma
retval = anObject.someUsefulFunction(x.leftMargin() + x.rightMargin(),
x.topMargin() + x.bottomMargin() - 1);
// [fmt05] -- if that's not possible, break after an operator
retval = anObject.SomeUsefulFunction(x.leftMargin() + x.rightMargin() +
anObject.horizontalPadding(), x.topMargin() + x.bottomMargin() - 1);
}
/**
* !!! Loop formatting
*/
public void loops()
{
// [fmt08] -- for() loop; note the pre-incremented form of the loop control
for (int i = 0; i < kSomeConstant; ++i)
{
// loop code here...
}
// [fmt09]
while (someBoolean)
{
// useful code...
}
// [fmt09] -- while loop with an empty body makes the emptiness explicit
while (this.someFuncReturningBool())
{
// intentionally empty...
}
// [fmt10] -- do/while loop.
// [fmt18] -- exception to the bracing rule saying that braces should
// always be on a line by themselves
do
{
// loop code here..
} while (someBoolean);
}
// [cas01] Protected member functions declared after public
/**
* [nr03] parameters passed to functions are named using lowerCamelCase
*/
protected boolean test(int firstVal, int secondVal)
{
boolean retval = true;
// [fmt07] -- if/else formatting
if (firstVal < secondVal)
{
// [cg06] -- use '$$$' as a marker to indicate a request that the
// following block of code be reviewed before a change is considered
// complete
// $$$ before
// this->Process(secondVal);
// $$$ after
// Shouldn't this be processing the first value in this case?
this.process(firstVal);
// $$$ end
}
else if (secondVal > kSomeConstant)
{
this.process(secondVal);
}
else
{
// [fmt18] -- use curly braces even in cases where the language doesn't
// require it to prevent maintenance errors.
retval = false;
}
return retval;
}
// [cas01] Private member function declared after protected
/**
* Useful function to process something or other.
*/
private void process(int val)
{
// [cg05] -- use '!!!' as a marker to indicate a section of code that
// requires attention
// !!!... removing old hardcoded value
// fProcessResult = 131;
// ...!!!
int result = val;
while (--val)
{
result *= val;
}
this.fProcessResult = result;
}
/**
* Demonstrating the formatting of a switch statement.
*/
private void decide(char midiEventType)
{
// [fmt11] -- switch/case formatting.
switch (midiEventType)
{
// comments precede the case
case kNoteOn:
this.noteOn(now);
if (duration > 0)
{
this.noteOff(now + duration);
}
break;
case kNoteOff:
this.noteOff(now);
break;
case kPolyAfter:
after = channelValue;
// [fmt35] include, but comment out the break when falling through intentionally.
// break;
case kChannelAfter:
this.afterTouch(after);
break;
// [fmt36] no need to include a commented out break when falling through an empty case
case kPitchbend:
// blank line...
// [fmt12] -- switch statements should always have a default case.
default:
assert(false);
this.logError("Unsupported event type!");
break;
}
}
// [cas02] member variables declared in the same order: public
// (avoid in most languages), protected, private.
// [nr04], [nr19] Member variables are prefixed with a lowercase 'f', followed
// by an uppercase letter.
public String fFileName;
protected File fInputFile;
private int fProcessResult;
}