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;

}


?>