Skip to content

Commit

Permalink
[ts][step_shotgun_surgery-01_base] Add premature abstractions
Browse files Browse the repository at this point in the history
  • Loading branch information
santakadev committed Apr 18, 2021
1 parent 38215b3 commit 8488517
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import StepId from '../Domain/StepId'
import StepRepository from '../Domain/StepRepository'
import VideoStep from "../Domain/VideoStep";
import StepDurationCalculatorFactory from "../Domain/StepDurationCalculatorFactory";

class GetStepDuration {
constructor(private repository: StepRepository) {
}

execute(stepId: string): number {
const step = this.repository.find(new StepId(stepId))
return step instanceof VideoStep ?
step.getVideoDuration() :
step.totalQuestions;
return StepDurationCalculatorFactory.build().calculate(step)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Step from "./Step";
import * as StepEnums from "./StepEnums";

export function multiplierFor(step: Step): number {
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
Expand Up @@ -5,7 +5,7 @@ import {STEP_TYPE_QUIZ} from "./StepEnums";
class QuizStep extends Step {
constructor(
stepId: StepId,
public readonly totalQuestions: Number
public readonly totalQuestions: number
) {
super(stepId);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import StepId from "./StepId";

abstract class Step {

protected constructor(private readonly _id: StepId) {
}
protected constructor(private readonly _id: StepId) {}

abstract type();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Step from "./Step";

interface StepDurationCalculator {
supports(step: Step): boolean;
calculate(step: Step): number;
}

export default StepDurationCalculator
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import StepDurationCalculator from "./StepDurationCalculator";
import Step from "./Step";
import {STEP_TYPES} from "./StepEnums";

class StepDurationCalculatorChain implements StepDurationCalculator {
constructor(private calculators: Array<StepDurationCalculator>) {
}

supports(step: Step): boolean {
return STEP_TYPES.some(step.type);
}

calculate(step: Step): number {
if (!this.supports(step)) {
throw new Error(`Missing calculator for step type ${step.type()}`);
}

for (let calculator of this.calculators) {
if (calculator.supports(step)) {
return calculator.calculate(step);
}
}

throw new Error(`Missing calculator for step type ${step.type()}`);
}
}

export default StepDurationCalculatorChain
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import StepDurationCalculator from "./StepDurationCalculator";
import StepDurationCalculatorVideo from "./StepDurationCalculatorVideo";
import StepDurationCalculatorQuiz from "./StepDurationCalculatorQuiz";
import StepDurationCalculatorChain from "./StepDurationCalculatorChain";

class StepDurationCalculatorFactory {
static build(): StepDurationCalculator
{
// Remember to add the calculator!!
return new StepDurationCalculatorChain([
new StepDurationCalculatorVideo(),
new StepDurationCalculatorQuiz(),
]);
}
}

export default StepDurationCalculatorFactory
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import StepDurationCalculator from "./StepDurationCalculator";
import QuizStep from "./QuizStep";
import Step from "./Step";
import {multiplierFor} from "./DurationMultiplier";
import {QUIZ_QUESTION_DURATION} from "./StepEnums";

class StepDurationCalculatorQuiz implements StepDurationCalculator {
supports(step: Step): boolean {
return step instanceof QuizStep;
}

calculate(step: QuizStep): number {
return step.totalQuestions * QUIZ_QUESTION_DURATION * multiplierFor(step);
}
}

export default StepDurationCalculatorQuiz
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import StepDurationCalculator from "./StepDurationCalculator";
import VideoStep from "./VideoStep";
import Step from "./Step";
import {multiplierFor} from "./DurationMultiplier";

class StepDurationCalculatorVideo implements StepDurationCalculator {
supports(step: Step): boolean {
return step instanceof VideoStep;
}

calculate(step: VideoStep): number {
return step.videoDuration * multiplierFor(step);
}
}

export default StepDurationCalculatorVideo
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
export const STEP_TYPE_VIDEO = 'video';
export const STEP_TYPE_QUIZ = 'quiz';
export const STEP_TYPE_VIDEO: string = 'video';
export const STEP_TYPE_QUIZ: string = 'quiz';

export const STEP_DURATION_MULTIPLIER_VIDEO = 1.1;
export const STEP_DURATION_MULTIPLIER_QUIZ = 1.5;
export const STEP_DURATION_MULTIPLIER_VIDEO: number = 1.1;
export const STEP_DURATION_MULTIPLIER_QUIZ: number = 1.5;

export const QUIZ_QUESTION_DURATION = 5;
export const QUIZ_QUESTION_DURATION: number = 5;

// Important: don't forget to add here the type!!
export const STEP_TYPES = [
export const STEP_TYPES: Array<string> = [
STEP_TYPE_VIDEO,
STEP_TYPE_QUIZ
];
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,14 @@ import {STEP_TYPE_VIDEO} from "./StepEnums";
class VideoStep extends Step {
constructor(
stepId: StepId,
private videoDuration: number
public readonly videoDuration: number
) {
super(stepId)
}

type(): string {
return STEP_TYPE_VIDEO
}

getVideoDuration(): number {
return this.videoDuration
}
}

export default VideoStep
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ test('should get the video step duration', () => {
const stepId = new StepId('stepId')
const step = new VideoStep(stepId, 13)
const stepRepository = {
find: jest.fn((stepId: StepId) => step)
find: jest.fn(() => step)
}
const getStepDuration = new GetStepDuration(stepRepository)

expect(getStepDuration.execute(stepId.value())).toBe(13)
expect(getStepDuration.execute(stepId.value())).toBe(14.3)
});

test('should get the quiz step duration', () => {
const stepId = new StepId('stepId')
const step = new QuizStep(stepId, 5)
const stepRepository = {
find: jest.fn((stepId: StepId) => step)
find: jest.fn(() => step)
}
const getStepDuration = new GetStepDuration(stepRepository)

expect(getStepDuration.execute(stepId.value())).toBe(5)
expect(getStepDuration.execute(stepId.value())).toBe(37.5)
});

0 comments on commit 8488517

Please sign in to comment.