Skip to content

Commit

Permalink
Add base code for Shotgun Surgery illustration
Browse files Browse the repository at this point in the history
  • Loading branch information
Dani Santamaría committed Apr 8, 2021
1 parent e372902 commit 12ea6eb
Show file tree
Hide file tree
Showing 18 changed files with 1,009 additions and 342 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
}
],
"require": {
"php": "^7.2"
"php": "^7.4"
},
"require-dev": {
"jakub-onderka/php-parallel-lint": "^1.0",
Expand Down
970 changes: 708 additions & 262 deletions examples/php/php-step_shotgun_surgery-01_base/composer.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Application;

use CodelyTv\StepShotgunSurgery\Domain\StepDurationCalculatorFactory;
use CodelyTv\StepShotgunSurgery\Domain\StepRepository;

class GetStepDuration
{
private StepRepository $steps;

public function __construct(StepRepository $steps)
{
$this->steps = $steps;
}

public function __invoke(string $stepId): float
{
$step = $this->steps->find($stepId);
return StepDurationCalculatorFactory::build()->calculate($step);
}
}
29 changes: 0 additions & 29 deletions examples/php/php-step_shotgun_surgery-01_base/src/Codelyber.php

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Domain;

class DurationMultiplier
{
public static function multiplierFor(Step $step): float
{
if ($step->type() === StepEnums::STEP_TYPE_VIDEO) {
return StepEnums::STEP_DURATION_MULTIPLIER_VIDEO;
}

if ($step->type() === StepEnums::STEP_TYPE_QUIZ) {
return StepEnums::STEP_DURATION_MULTIPLIER_QUIZ;
}

return 1.0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Domain;

class Question
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Domain;

final class QuizStep extends Step
{
private array $questions;

public function __construct(string $id, Question ...$questions)
{
parent::__construct($id);
$this->questions = $questions;
}

public function type(): string
{
return StepEnums::STEP_TYPE_QUIZ;
}

public function videoDuration(): int
{
throw new Exception('Ques doesn\'t contain any video.');
}

public function questionCount(): int
{
return count($this->questions);
}
}
26 changes: 26 additions & 0 deletions examples/php/php-step_shotgun_surgery-01_base/src/Domain/Step.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Domain;

abstract class Step
{
private string $id;

public function __construct(string $id)
{
$this->id = $id;
}

public function id(): string
{
return $this->id;
}

abstract function type(): string;

abstract function videoDuration(): int;

abstract function questionCount(): int;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Domain;

interface StepDurationCalculator
{
public function supports(Step $step): bool;

public function calculate(Step $step): float;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Domain;

class StepDurationCalculatorChain implements StepDurationCalculator
{
/** @var StepDurationCalculator[] */
private array $calculators;

public function __construct(StepDurationCalculator ...$calculators)
{
$this->calculators = $calculators;
}

public function supports(Step $step): bool
{
return in_array($step->type(), StepEnums::STEP_TYPES);
}

public function calculate(Step $step): float
{
foreach ($this->calculators as $calculator) {
if ($calculator->supports($step)) {
return $calculator->calculate($step);
}
}

throw new RuntimeException("Missing calculator for step type {$step->type()}");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Domain;

class StepDurationCalculatorFactory
{
public static function build(): StepDurationCalculator
{
// Remember to add the calculator!!
return new StepDurationCalculatorChain(
new StepDurationCalculatorVideo(),
new StepDurationCalculatorQuiz()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Domain;

class StepDurationCalculatorQuiz implements StepDurationCalculator
{
public function supports(Step $step): bool
{
return $step instanceof QuizStep;
}

public function calculate(Step $step): float
{
return $step->questionCount() * StepEnums::QUIZ_QUESTION_DURATION * DurationMultiplier::multiplierFor($step);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Domain;

class StepDurationCalculatorVideo implements StepDurationCalculator
{
public function supports(Step $step): bool
{
return $step instanceof VideoStep;
}

public function calculate(Step $step): float
{
return $step->videoDuration() * DurationMultiplier::multiplierFor($step);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Domain;

final class StepEnums
{
const STEP_TYPE_VIDEO = 'video';
const STEP_TYPE_QUIZ = 'quiz';

const STEP_DURATION_MULTIPLIER_VIDEO = 1.1;
const STEP_DURATION_MULTIPLIER_QUIZ = 1.5;

const QUIZ_QUESTION_DURATION = 5;

# Important: don't forget to add here the type!!
const STEP_TYPES = [
self::STEP_TYPE_VIDEO,
self::STEP_TYPE_QUIZ
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Domain;

interface StepRepository
{
public function find(string $id): Step;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace CodelyTv\StepShotgunSurgery\Domain;

final class VideoStep extends Step
{
private int $videoDuration;

public function __construct(string $id, int $videoDuration)
{
parent::__construct($id);
$this->videoDuration = $videoDuration;
}

function type(): string
{
return StepEnums::STEP_TYPE_VIDEO;
}

function videoDuration(): int
{
return $this->videoDuration;
}

function questionCount(): int
{
throw new Exception('Video doesn\'t contain any quiz questions.');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types = 1);

namespace CodelyTv\StepShotgunSurgery\Tests\Application;

use CodelyTv\StepShotgunSurgery\Application\GetStepDuration;
use CodelyTv\StepShotgunSurgery\Domain\StepRepository;
use CodelyTv\StepShotgunSurgery\Domain\VideoStep;
use PHPUnit\Framework\TestCase;

final class GetStepDurationTest extends TestCase
{
/** @test */
public function shouldReturnVideoStepDuration()
{
$steps = $this->createMock(StepRepository::class);
$steps
->method('find')
->willReturn(new VideoStep('videoId', 10));

$getStepDuration = new GetStepDuration($steps);

$duration = $getStepDuration->__invoke('videoId');

$this->assertSame(11.0, $duration);
}
}
Loading

0 comments on commit 12ea6eb

Please sign in to comment.