Rosettas‎ > ‎

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;
}

?>