This code challenge covered the typical inheriting Shapes topic, RegEx, and some elements of the SOLID principles.

View on Gist.

<?php

/****************************************************************************
 * 1. Create classes that will properly represent the following constructs: *
 ****************************************************************************/

/** Details **
 * 1. Define a Shape object, where the object is any two dimensional figure, and has the
 * following characteristics: a name, a perimeter, and a surface area.
 * 2. Define a Circle, retaining and accurately outputting the values of the aforementioned
 * characteristics of a Shape.
 * 3. Define a Triangle. This time, the name of the triangle should take into account if it is
 * equilateral (all 3 sides are the same length), isosceles (only 2 sides are the same length), or scalene (no 2 sides are the same).
 */

abstract class Shape
{
    protected $name;
    protected $perimeter;
    protected $surfaceArea;

    abstract function getName();
    abstract function getPerimeter();
    abstract function getSurfaceArea();
}

class Circle extends Shape
{
    private $radius;

    public function __construct(float $radius)
    {
        $this->name = 'Circle';
        $this->radius = $radius;
    }

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * @return float
     */
    public function getPerimeter(): float
    {
        if (! $this->perimeter) {
            $this->perimeter = (2 * pi() * $this->radius);
        }

        return $this->perimeter;
    }

    /**
     * @return float|null
     */
    public function getSurfaceArea()
    {
        if (! $this->surfaceArea) {
            $this->surfaceArea = (pi() * ($this->radius * $this->radius));
        }

        return $this->surfaceArea;
    }
}

class Triangle extends Shape
{
    private $sideA;
    private $sideB;
    private $sideC;

    public function __construct(float $sideA, float $sideB, float $sideC)
    {
        $this->sideA = $sideA;
        $this->sideB = $sideB;
        $this->sideC = $sideC;

        $this->determineName();
    }

    private function determineName()
    {
        if ($this->sideA == $this->sideB && $this->sideB == $this->sideC) {
            $this->name = 'Equilateral';
        } elseif ($this->sideA == $this->sideB || $this->sideA == $this->sideC || $this->sideB == $this->sideC) {
            $this->name = 'Isocoles';
        } else {
            $this->name = 'Scalene';
        }
    }

    public function getName()
    {
        return $this->name;
    }

    public function getPerimeter()
    {
        if (! $this->perimeter) {
            $this->perimeter = $this->sideA + $this->sideB + $this->sideC;
        }

        return $this->perimeter;
    }

    public function getSurfaceArea()
    {
        if (! $this->surfaceArea) {
            $s = ($this->sideA + $this->sideB + $this->sideC) / 2;
            $x = ($s * ($s - $this->sideA) * ($s - $this->sideB) * ($s - $this->sideC));
            $this->surfaceArea = sqrt($x);
        }

        return $this->surfaceArea;
    }
}

/************************************************
 * 2. What problems do you see in this example? *
 ************************************************/

/** Notes **
 * I'm not sure how deep to go, but the items I see are:
 *  - Username/Password hardcoded, would end up in repo.
 *  - Violates Single-Responsibility (handles DB connection AND query) and Dependency Inversion Principles (MySQL dependence, vs DBConnection Interface) of SOLID.
 *  - Using variables in the query could result in SQL injection. Prepared statements are the solution.
 *  - Visibility isn't explicitly declared on the method.
 *  - The method would be better named `createNewStudent` or something similar.
 *  - No failure is returned/exception thrown.
 */

/*************************************************************************************************************************************************
 * 3. How would you extract an order number with 6 or more digits (432987 in these snippets) that would work with any of the following snippets? *
 *************************************************************************************************************************************************/

/** Notes **
 * https://regex101.com/r/gwhrEM/1
 * This regex would do it: `[0-9]{6,}`, though it would capture any 6+ digit number.
 * If I knew that there could be other
 * 6-digit, non-order numbers, I would write it to capture after 'PO#', before
 * '-IRC', or between <td></td>. This would cause issues with snippet #4, however,
 * as there is nothing to search for other than the digits.
 */

/**************************************************************************
 * 4. Which of the following classes do you prefer? Why do you prefer it? *
 **************************************************************************/

/** Notes **
 * FooBar practices dependency injection, so probably that one as you could create
 * a Scrambler interface and pass in an implementation without being tied to a
 * particular one.
 */

/***************************************************************************************************************************************************************
 * 5. Giving the following class, write a unit test which covers the behavior of the getFoo() method, independent of the behavior of StringScramblerInterface. *
 ***************************************************************************************************************************************************************/

/** Notes **
 * This assumes that the scramble method, whichever implementation is used, changes
 * the input in some way. The second test may not be required, as perhaps a
 * reverse could be considered a scramble.
 */

class FooTest extends TestCase
{
    private $fooBar;

    public function setUp()
    {
        $this->fooBar = new FooBar(new StringScramblerImplementation());
    }

    /**
     * Ensure returned value does NOT equal our input value, or the result of strrev();
     *
     * @test
     */
    public function getFoo()
    {
        $testText = 'TestText';

        $fooResult =  $this->fooBar->getFoo($testText);

        $this->assertNotEquals($testText, $fooResult);
        $this->assertNotEquals(strrev($testText), $fooResult);
    }
}
Tagged in:
,