Skip to content

Commit fa84fb8

Browse files
committed
3장 완료
1 parent 56b172a commit fa84fb8

16 files changed

+151
-43
lines changed

example03/src/application/port/input/router-network.input-port.ts

+10-9
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,23 @@ import { RouterId } from 'src/domain/vo/router.id';
88
export class RouterNetworkInputPort implements RouterNetworkUseCase {
99
public constructor(private readonly _routerNetworkOutputPort: RouterNetworkOutputPort) {}
1010

11-
async addNetworkToRouter(routerId: RouterId, network: Network): Promise<Router> {
12-
const router = await this.fetchRouter(routerId);
13-
return await this.createNetwork(router, network);
11+
addNetworkToRouter(routerId: RouterId, network: Network): Router {
12+
const router = this.fetchRouter(routerId);
13+
14+
return this.createNetwork(router, network);
1415
}
1516

16-
private async fetchRouter(routerId: RouterId): Promise<Router> {
17-
return await this._routerNetworkOutputPort.fetchRouterById(routerId);
17+
private fetchRouter(routerId: RouterId): Router {
18+
return this._routerNetworkOutputPort.fetchRouterById(routerId);
1819
}
1920

20-
private async createNetwork(router: Router, network: Network): Promise<Router> {
21+
private createNetwork(router: Router, network: Network): Router {
2122
const newRouter = NetworkOperation.createNewNetwork(router, network);
2223

23-
return (await this.persistNetwork(router)) ? newRouter : router;
24+
return this.persistNetwork(router) ? newRouter : router;
2425
}
2526

26-
private async persistNetwork(router: Router): Promise<boolean> {
27-
return await this._routerNetworkOutputPort.persistRouter(router);
27+
private persistNetwork(router: Router): boolean {
28+
return this._routerNetworkOutputPort.persistRouter(router);
2829
}
2930
}

example03/src/application/port/output/router-network.output-port.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ import { Router } from 'src/domain/entity/router';
22
import { RouterId } from 'src/domain/vo/router.id';
33

44
export interface RouterNetworkOutputPort {
5-
fetchRouterById(routerId: RouterId): Promise<Router>;
6-
persistRouter(router: Router): Promise<boolean>;
5+
fetchRouterById(routerId: RouterId): Router;
6+
persistRouter(router: Router): boolean;
77
}

example03/src/application/usecase/router-network.usecase.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ export interface RouterNetworkUseCase {
1616
* - And CIDR이 유효하다
1717
* - Then 라우터에 네트워크를 추가한다
1818
*/
19-
addNetworkToRouter(routerId: RouterId, network: Network): Promise<Router>;
19+
addNetworkToRouter(routerId: RouterId, network: Network): Router;
2020
}

example03/src/domain/entity/router.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ import { RouterType } from 'src/domain/vo/router.type';
66
import { Predicate } from 'src/utils/types';
77

88
export class Router {
9-
private _networkSwitch: Switch;
10-
public constructor(private readonly _routerType: RouterType, private readonly _routerId: RouterId) {}
9+
public constructor(private readonly _routerType: RouterType, private readonly _routerId: RouterId, private _networkSwitch?: Switch) {}
1110

1211
public static filterRouterByType(routerType: RouterType): Predicate<Router> {
1312
return routerType === RouterType.CORE ? this.isCore : this.isEdge;
@@ -28,15 +27,21 @@ export class Router {
2827
public retrieveNetworks(): Network[] {
2928
return this._networkSwitch.getNetworks();
3029
}
30+
3131
public getRouterType(): RouterType {
3232
return this._routerType;
3333
}
3434

35+
public getRouterId(): RouterId {
36+
return this._routerId;
37+
}
38+
3539
public toString(): string {
3640
return `
3741
Router {
3842
type: ${RouterType[this._routerType]},
3943
id: ${this._routerId.toString()}
44+
networkSwitch: ${this._networkSwitch.toString()}
4045
}
4146
`;
4247
}

example03/src/domain/entity/switch.ts

+12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { IP } from 'src/domain/vo/ip';
22
import { Network } from 'src/domain/vo/network';
3+
import { Protocol } from 'src/domain/vo/protocol';
34
import { SwitchId } from 'src/domain/vo/switch.id';
45
import { SwitchType } from 'src/domain/vo/switch.type';
56

@@ -15,4 +16,15 @@ export class Switch {
1516
const copied = [...this._networks];
1617
return copied;
1718
}
19+
20+
public toString(): string {
21+
return `
22+
Switch {
23+
type: ${SwitchType[this._type]}
24+
id: ${this._id.toString()}
25+
address: ${this._address.address}(${Protocol[this._address.protocol]})
26+
network: ${this._networks.toString()}
27+
}
28+
`;
29+
}
1830
}

example03/src/domain/service/network.operation.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ import { Network } from 'src/domain/vo/network';
99
* 새로운 네트워크 객체를 생성하고 해당 객체를 라우터에 연결된 스위치에 추가
1010
*/
1111
export class NetworkOperation {
12-
public static createNewNetwork(router: Router, { address, name, cidr }: Network): Router {
13-
const availabilitySpec = new NetworkAvailabilitySpecification(address, name, cidr);
12+
public static createNewNetwork(router: Router, network: Network): Router {
13+
const availabilitySpec = new NetworkAvailabilitySpecification(network.address, network.name, network.cidr);
1414
const cidrSpec = new CIDRSpecification();
1515
const routerTypeSpec = new RouterTypeSpecification();
1616
const amountSpec = new NetworkAmountSpecification();
1717

18-
if (!cidrSpec.isSatisfiedBy(cidr)) throw new Error(`CIDR is below ${CIDRSpecification.MINIMUM_ALLOWED_CIRD}`);
18+
if (!cidrSpec.isSatisfiedBy(network.cidr)) throw new Error(`CIDR is below ${CIDRSpecification.MINIMUM_ALLOWED_CIRD}`);
1919

2020
if (!availabilitySpec.isSatisfiedBy(router)) throw new Error('Address already exist');
2121

22-
if (amountSpec.and(routerTypeSpec).isSatisfiedBy(router)) {
23-
const network = router.createNetwork(address, name, cidr);
24-
router.addNetworkToSwitch(network);
22+
if (amountSpec.isSatisfiedBy(router) && routerTypeSpec.isSatisfiedBy(router)) {
23+
const _network = router.createNetwork(network.address, network.name, network.cidr);
24+
router.addNetworkToSwitch(_network);
2525
}
2626

2727
return router;

example03/src/domain/specification/cidr.specification.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ export class CIDRSpecification extends AbstractSpecification<number> {
44
public static readonly MINIMUM_ALLOWED_CIRD = 8;
55

66
isSatisfiedBy(cidr: number): boolean {
7-
return Number.isInteger(cidr) && cidr > CIDRSpecification.MINIMUM_ALLOWED_CIRD;
7+
return Number.isInteger(cidr) && cidr >= CIDRSpecification.MINIMUM_ALLOWED_CIRD;
88
}
99
}

example03/src/domain/vo/network.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { IP } from 'src/domain/vo/ip';
2+
import { Protocol } from 'src/domain/vo/protocol';
23

34
export class Network {
45
public constructor(private readonly _address: IP, private readonly _name: string, private readonly _cidr: number) {
@@ -15,6 +16,16 @@ export class Network {
1516
}
1617

1718
get cidr(): number {
18-
return this.cidr;
19+
return this._cidr;
20+
}
21+
22+
public toString(): string {
23+
return `
24+
Network {
25+
address: ${this._address.address}(${Protocol[this._address.protocol]}),
26+
name: ${this._name},
27+
cird: ${this._cidr}
28+
}
29+
`;
1930
}
2031
}

example03/src/domain/vo/router.id.ts

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ export class RouterId {
1111
return new RouterId(UUID.randomUUID());
1212
}
1313

14+
public getId(): UUID {
15+
return this._id;
16+
}
17+
1418
toString(): string {
1519
return this._id.toString();
1620
}
+4-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
export enum SwitchType {}
1+
export enum SwitchType {
2+
LAYER2,
3+
LAYER3,
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { RouterNetworkInputPort } from 'src/application/port/input/router-network.input-port';
2+
import { RouterNetworkUseCase } from 'src/application/usecase/router-network.usecase';
3+
import { Router } from 'src/domain/entity/router';
4+
import { Network } from 'src/domain/vo/network';
5+
import { RouterId } from 'src/domain/vo/router.id';
6+
import { routerNetworkFileAdapter } from 'src/framework/adapter/output/router-network.file.adapter';
7+
8+
export class RouterNetworkCLIAdapter {
9+
private _routerNetworkUsecase: RouterNetworkUseCase;
10+
11+
constructor() {
12+
this.setAdapters();
13+
}
14+
15+
public addNetwork(routerId: RouterId, network: Network): Router {
16+
return this._routerNetworkUsecase.addNetworkToRouter(routerId, network);
17+
}
18+
19+
private setAdapters(): void {
20+
this._routerNetworkUsecase = new RouterNetworkInputPort(routerNetworkFileAdapter);
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { RouterNetworkOutputPort } from 'src/application/port/output/router-network.output-port';
2+
import { Router } from 'src/domain/entity/router';
3+
import { Switch } from 'src/domain/entity/switch';
4+
import { IP } from 'src/domain/vo/ip';
5+
import { Network } from 'src/domain/vo/network';
6+
import { RouterId } from 'src/domain/vo/router.id';
7+
import { RouterType } from 'src/domain/vo/router.type';
8+
import { SwitchId } from 'src/domain/vo/switch.id';
9+
import { SwitchType } from 'src/domain/vo/switch.type';
10+
11+
class RouterNetworkFileAdapter implements RouterNetworkOutputPort {
12+
private _routers: Router[];
13+
14+
constructor() {
15+
this._routers = [];
16+
this.createSampleRouter();
17+
}
18+
19+
private createSampleRouter(): void {
20+
const routerId = RouterId.withId('ca23800e-9b5a-11eb-a8b3-0242ac130003');
21+
const network = new Network(new IP('10.0.0.0'), 'HR', 8);
22+
const networkSwitch = new Switch(SwitchType.LAYER3, SwitchId.withoutId(), [network], new IP('9.0.0.9'));
23+
const router = new Router(RouterType.EDGE, routerId, networkSwitch);
24+
this._routers.push(router);
25+
}
26+
27+
public fetchRouterById(routerId: RouterId): Router {
28+
let retrievedRouter: Router;
29+
30+
for (const router of this._routers) {
31+
if (router.getRouterId().getId().equals(routerId.getId())) {
32+
retrievedRouter = router;
33+
break;
34+
}
35+
}
36+
37+
return retrievedRouter;
38+
}
39+
40+
public persistRouter(router: Router): boolean {
41+
return !!this._routers.push(router);
42+
}
43+
}
44+
45+
// for singlton
46+
export const routerNetworkFileAdapter = new RouterNetworkFileAdapter();

example03/src/main.ts

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { RouterType } from 'src/domain/vo/router.type';
2-
import { RouterViewCliAdapter } from 'src/framework/adapter/input/router-view.cli.adapter';
1+
import { IP } from 'src/domain/vo/ip';
2+
import { Network } from 'src/domain/vo/network';
3+
import { RouterId } from 'src/domain/vo/router.id';
4+
import { RouterNetworkCLIAdapter } from 'src/framework/adapter/input/router-network.cli.adapter';
35

4-
const cli = new RouterViewCliAdapter();
5-
// const routers = await cli.obtainRelatedRouters(RouterType.EDGE);
6-
// console.log(routers);
7-
8-
cli.obtainRelatedRouters(RouterType.EDGE).then((v) => console.log(v.toString()));
6+
const cli = new RouterNetworkCLIAdapter();
7+
const routerId = RouterId.withId('ca23800e-9b5a-11eb-a8b3-0242ac130003');
8+
const network = new Network(new IP('20.0.0.0'), 'Marketing', 8);
9+
const router = cli.addNetwork(routerId, network);
10+
console.log(router.toString());

example03/src/utils/specification/abstract.specification.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { AndSpecification } from 'src/utils/specification/and.specification';
21
import { Specification } from 'src/utils/specification/specification';
32

43
export abstract class AbstractSpecification<T> implements Specification<T> {
@@ -8,3 +7,14 @@ export abstract class AbstractSpecification<T> implements Specification<T> {
87
return new AndSpecification<T>(this, specification);
98
}
109
}
10+
11+
// 다른 파일에 생성시 순환 참조 문제가 발생하여 한 파일에 선언
12+
export class AndSpecification<T> extends AbstractSpecification<T> {
13+
constructor(private readonly _spec1: Specification<T>, private readonly _spec2: Specification<T>) {
14+
super();
15+
}
16+
17+
public isSatisfiedBy(t: T): boolean {
18+
return this._spec1.isSatisfiedBy(t) && this._spec2.isSatisfiedBy(t);
19+
}
20+
}

example03/src/utils/specification/and.specification.ts

-12
This file was deleted.

example03/src/utils/uuid.ts

+4
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,8 @@ export class UUID {
1717
public toString(): string {
1818
return this._uuid;
1919
}
20+
21+
public equals(target: UUID): boolean {
22+
return this._uuid === target._uuid;
23+
}
2024
}

0 commit comments

Comments
 (0)