Skip to content

Commit 8488517

Browse files
committed
[ts][step_shotgun_surgery-01_base] Add premature abstractions
1 parent 38215b3 commit 8488517

File tree

12 files changed

+115
-23
lines changed

12 files changed

+115
-23
lines changed

examples/typescript/ts-step_shotgun_surgery-01_base/src/Application/GetStepDuration.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
import StepId from '../Domain/StepId'
22
import StepRepository from '../Domain/StepRepository'
3-
import VideoStep from "../Domain/VideoStep";
3+
import StepDurationCalculatorFactory from "../Domain/StepDurationCalculatorFactory";
44

55
class GetStepDuration {
66
constructor(private repository: StepRepository) {
77
}
88

99
execute(stepId: string): number {
1010
const step = this.repository.find(new StepId(stepId))
11-
return step instanceof VideoStep ?
12-
step.getVideoDuration() :
13-
step.totalQuestions;
11+
return StepDurationCalculatorFactory.build().calculate(step)
1412
}
1513
}
1614

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import Step from "./Step";
2+
import * as StepEnums from "./StepEnums";
3+
4+
export function multiplierFor(step: Step): number {
5+
if (step.type() === StepEnums.STEP_TYPE_VIDEO) {
6+
return StepEnums.STEP_DURATION_MULTIPLIER_VIDEO;
7+
}
8+
9+
if (step.type() === StepEnums.STEP_TYPE_QUIZ) {
10+
return StepEnums.STEP_DURATION_MULTIPLIER_QUIZ;
11+
}
12+
13+
return 1.0;
14+
}

examples/typescript/ts-step_shotgun_surgery-01_base/src/Domain/QuizStep.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {STEP_TYPE_QUIZ} from "./StepEnums";
55
class QuizStep extends Step {
66
constructor(
77
stepId: StepId,
8-
public readonly totalQuestions: Number
8+
public readonly totalQuestions: number
99
) {
1010
super(stepId);
1111
}

examples/typescript/ts-step_shotgun_surgery-01_base/src/Domain/Step.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import StepId from "./StepId";
22

33
abstract class Step {
4-
5-
protected constructor(private readonly _id: StepId) {
6-
}
4+
protected constructor(private readonly _id: StepId) {}
75

86
abstract type();
97
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import Step from "./Step";
2+
3+
interface StepDurationCalculator {
4+
supports(step: Step): boolean;
5+
calculate(step: Step): number;
6+
}
7+
8+
export default StepDurationCalculator
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import StepDurationCalculator from "./StepDurationCalculator";
2+
import Step from "./Step";
3+
import {STEP_TYPES} from "./StepEnums";
4+
5+
class StepDurationCalculatorChain implements StepDurationCalculator {
6+
constructor(private calculators: Array<StepDurationCalculator>) {
7+
}
8+
9+
supports(step: Step): boolean {
10+
return STEP_TYPES.some(step.type);
11+
}
12+
13+
calculate(step: Step): number {
14+
if (!this.supports(step)) {
15+
throw new Error(`Missing calculator for step type ${step.type()}`);
16+
}
17+
18+
for (let calculator of this.calculators) {
19+
if (calculator.supports(step)) {
20+
return calculator.calculate(step);
21+
}
22+
}
23+
24+
throw new Error(`Missing calculator for step type ${step.type()}`);
25+
}
26+
}
27+
28+
export default StepDurationCalculatorChain
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import StepDurationCalculator from "./StepDurationCalculator";
2+
import StepDurationCalculatorVideo from "./StepDurationCalculatorVideo";
3+
import StepDurationCalculatorQuiz from "./StepDurationCalculatorQuiz";
4+
import StepDurationCalculatorChain from "./StepDurationCalculatorChain";
5+
6+
class StepDurationCalculatorFactory {
7+
static build(): StepDurationCalculator
8+
{
9+
// Remember to add the calculator!!
10+
return new StepDurationCalculatorChain([
11+
new StepDurationCalculatorVideo(),
12+
new StepDurationCalculatorQuiz(),
13+
]);
14+
}
15+
}
16+
17+
export default StepDurationCalculatorFactory
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import StepDurationCalculator from "./StepDurationCalculator";
2+
import QuizStep from "./QuizStep";
3+
import Step from "./Step";
4+
import {multiplierFor} from "./DurationMultiplier";
5+
import {QUIZ_QUESTION_DURATION} from "./StepEnums";
6+
7+
class StepDurationCalculatorQuiz implements StepDurationCalculator {
8+
supports(step: Step): boolean {
9+
return step instanceof QuizStep;
10+
}
11+
12+
calculate(step: QuizStep): number {
13+
return step.totalQuestions * QUIZ_QUESTION_DURATION * multiplierFor(step);
14+
}
15+
}
16+
17+
export default StepDurationCalculatorQuiz
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import StepDurationCalculator from "./StepDurationCalculator";
2+
import VideoStep from "./VideoStep";
3+
import Step from "./Step";
4+
import {multiplierFor} from "./DurationMultiplier";
5+
6+
class StepDurationCalculatorVideo implements StepDurationCalculator {
7+
supports(step: Step): boolean {
8+
return step instanceof VideoStep;
9+
}
10+
11+
calculate(step: VideoStep): number {
12+
return step.videoDuration * multiplierFor(step);
13+
}
14+
}
15+
16+
export default StepDurationCalculatorVideo
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
export const STEP_TYPE_VIDEO = 'video';
2-
export const STEP_TYPE_QUIZ = 'quiz';
1+
export const STEP_TYPE_VIDEO: string = 'video';
2+
export const STEP_TYPE_QUIZ: string = 'quiz';
33

4-
export const STEP_DURATION_MULTIPLIER_VIDEO = 1.1;
5-
export const STEP_DURATION_MULTIPLIER_QUIZ = 1.5;
4+
export const STEP_DURATION_MULTIPLIER_VIDEO: number = 1.1;
5+
export const STEP_DURATION_MULTIPLIER_QUIZ: number = 1.5;
66

7-
export const QUIZ_QUESTION_DURATION = 5;
7+
export const QUIZ_QUESTION_DURATION: number = 5;
88

99
// Important: don't forget to add here the type!!
10-
export const STEP_TYPES = [
10+
export const STEP_TYPES: Array<string> = [
1111
STEP_TYPE_VIDEO,
1212
STEP_TYPE_QUIZ
1313
];

examples/typescript/ts-step_shotgun_surgery-01_base/src/Domain/VideoStep.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,14 @@ import {STEP_TYPE_VIDEO} from "./StepEnums";
55
class VideoStep extends Step {
66
constructor(
77
stepId: StepId,
8-
private videoDuration: number
8+
public readonly videoDuration: number
99
) {
1010
super(stepId)
1111
}
1212

1313
type(): string {
1414
return STEP_TYPE_VIDEO
1515
}
16-
17-
getVideoDuration(): number {
18-
return this.videoDuration
19-
}
2016
}
2117

2218
export default VideoStep

examples/typescript/ts-step_shotgun_surgery-01_base/tests/Application/GetStepDuration.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@ test('should get the video step duration', () => {
77
const stepId = new StepId('stepId')
88
const step = new VideoStep(stepId, 13)
99
const stepRepository = {
10-
find: jest.fn((stepId: StepId) => step)
10+
find: jest.fn(() => step)
1111
}
1212
const getStepDuration = new GetStepDuration(stepRepository)
1313

14-
expect(getStepDuration.execute(stepId.value())).toBe(13)
14+
expect(getStepDuration.execute(stepId.value())).toBe(14.3)
1515
});
1616

1717
test('should get the quiz step duration', () => {
1818
const stepId = new StepId('stepId')
1919
const step = new QuizStep(stepId, 5)
2020
const stepRepository = {
21-
find: jest.fn((stepId: StepId) => step)
21+
find: jest.fn(() => step)
2222
}
2323
const getStepDuration = new GetStepDuration(stepRepository)
2424

25-
expect(getStepDuration.execute(stepId.value())).toBe(5)
25+
expect(getStepDuration.execute(stepId.value())).toBe(37.5)
2626
});

0 commit comments

Comments
 (0)