PHP
Rosetta.php
<?php
// Copyright (c) 2008 Art & Logic, Inc. All Rights Reserved.
// $Id: Rosetta.php,v 1.3 2008/02/27 15:00:11 dgrant 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.
define("kVerbose", TRUE);
// [sf07], only one class declared/defined in this source file.
// [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.
/**
* 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"
class ARosetta
{
/**
* Construct and initialize the Rosetta object.
* @param string fileName Name of the file to use as our data source.
*/
public function __construct($fileName)
{
$this->fileName = $fileName;
$this->inputFile = fopen($fileName, "r");
}
/**
* Destroy the Rosetta object, performing any needed cleanup.
*/
public function __destruct()
{
fclose($this->inputFile);
}
/**
* Demonstrates various code concepts.
* @return boolean TRUE for success, FALSE otherwise.
*/
// [nr07] Member functions are named using CamelCase, with a leading upper
// case letter.
public function MemberFunctionWithMultipleWords()
{
$ok = TRUE;
// [fmt08] -- formatting of a for() loop.
for ($i = 0; $i < self::kSomeConstant; ++$i)
{
for ($j = 0; $j < self::kSomeOtherConstant; ++$j)
{
if (kVerbose)
{
echo sprintf("testing: %d, %d\n", $i, $j);
}
// [nr07] -- Calls to member functions of the current object are
// made through an explicit $this-> pointer.
$ok = $this->Test($i, $j);
if (!$ok)
{
error_log(sprintf("Fatal error testing: %d, %d\n", $i, $j));
// !!! PHP: - no "goto" mechanism.
// Could use "break 2;" to break out of both for loops.
return FALSE;
}
}
}
return TRUE;
}
/**
* !!! Here's how we handle very long lines (i.e., longer than 79
* characters)
* @return mixed Result of performing various operations.
*/
public function LongLineWrapping()
{
$retval = NULL;
// [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->SomeFunction($x->LeftMargin() + $x->RightMargin(),
$x->TopMargin() + $x->BottomMargin() - 1);
// [fmt05] -- if that's not possible, break after an operator
$retVal = $anObject->SomeFunction($x->LeftMargin() + $x->RightMargin() +
$anObject->HorizontalPadding(),
$x->TopMargin() + $x->BottomMargin() - 1);
return $retVal;
}
/**
* !!! Loop formatting
*/
public function Loops()
{
// [fmt08] -- for() loop; note the pre-incremented form of the loop
// control.
for ($i = 0; $i < self::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);
}
/**
* Performs some tests.
*/
// [nr03] parameters passed to functions are named using lowerCamelCase.
protected function Test($firstVal, $secondVal)
{
$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 > self::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;
}
/**
* Useful function to process something or other.
*/
private function Process($val)
{
// [cg05] -- use '!!!' as a marker to indicate a section of code that
// requires attention.
// !!!... removing old hardcoded value
// $this->processResult = 131;
// ...!!!
$result = $val;
while (--$val)
{
$result *= $val;
}
$this->processResult = $result;
}
/**
* Demonstrating the formatting of a switch statement.
*/
private function Decide($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.
// !!! PHP: has no enum facility, use consts or arrays instead.
const kSomeConstant = 50;
const kSomeOtherConstant = 100;
private $fileName;
private $inputFile;
private $processResult = 0;
}
?>