[2주차] Class와 원시값 포장

toto9602·2022년 2월 21일
0

Re: 스터디

목록 보기
2/3

이 글을 쓰는 과정에서 [TypeScript] 인터페이스 (Interface) #2 포스팅을 참고했음을 밝힙니다! :)


스터디가 현재로서는 1주차에 작성했던 <학점 계산기>를 개선해 나가는 방향으로
진행되고 있어,

2주차는 1주차에 작성했던 <학점 계산기> 코드를 개선하는 방향으로 코드를 수정해 보았다!

코드 수정 방향은

  • Class 기반으로 옮기기
  • 계산에 활용되는 각 요소들을 원시값 포장하기 (optional)
  • 일급 컬렉션 만들기(optional)

정도였다.

사실 일급 컬렉션 만들기는, 과제 처음 할 당시에는 이해를 잘 못해서 구현을 못했었다..ㅠ
그래서 과제 초안에는...

  • Class 기반으로 옮기기

  • 원시값 포장하기


    정도만 반영을 했고, 이후에 다른 팀원분들의 코드를 구경하고, 피드백도 받으면서 코드를 수정했다!

    그리하여 작성된 2주차 과제!

#0. 파일 분리

week2
│   index.ts
│   
└───calculator
│   │   calculator.ts
│   │   grades.ts
│   
└───constants
│   │   gradeScore.ts 
│   
└───interface
│   │   grade.ts
│  
└───primitive
│   │   courseName.ts
│   │   credit.ts
│   │   score.ts

우선 다음과 같이 파일 구조를 분리하였다!

calculator.ts

import { Grade } from '../interface/grade'
import { Grades } from './grades';

//학점계산기
export class GradeCalculator {

    private _sampleGrade:Grade[];

    constructor(sampleGrade:Grade[]) {
        this._sampleGrade = sampleGrade;
    }

    public printResult():void {
        const grades = new Grades(this._sampleGrade, 0, 0, 0);
        grades.calc();
        const gradeResult = grades.getGradeResult();
        const totalCredit = grades.getTotalCredit();
        console.log(`${totalCredit}학점에 ${gradeResult}입니다.`)
    }
}

GradeCalculator(학점 계산기)를 Class로 만들어, calculator.ts로 따로 분리해 주었다.

Grade는 역시 따로 분리한 interface 디렉토리에 grade.ts에서 가져오는 방식으로 바꾸어 분리하였다.

P.S 관련 자료를 찾다 보니 인터페이스에 관해 정말 잘 정리해 주신 분이 계셔서
해당 글을 참고하면 좋을 것 같다!

참고자료: [TypeScript] 인터페이스 (Interface) #2

grades.ts

import { Grade } from "../interface/grade";
import { Score } from "../primitive/score";
import { Credit } from "../primitive/credit";
import {CourseName} from '../primitive/courseName';
import { GRADE_SCORE } from "../constants/gradeScore";

export class Grades {

    private _grades:Grade[];
    private _totalScore:number;
    private _totalCredit:number;
    private _gradeResult:number;

    constructor(grades:Grade[], totalScore:number, totalCredit:number, gradeResult:number) {
        this._grades = grades;
        this._totalScore = totalScore;
        this._totalCredit = totalCredit;
        this._gradeResult = gradeResult;
    }
  

    public calc():void {

        for (let {성적, 학점, 과목명} of this._grades) {
            const score = new Score(성적);
            const credit = new Credit(학점);
            const courseName = new CourseName(과목명);
            const validatedScore = score.validate();
            const validatedCredit = credit.validate();
            const validatedCourseName = courseName.validate();

            this._totalScore += GRADE_SCORE[validatedScore] * validatedCredit ;
            this._totalCredit += validatedCredit;
                }
                
        this._gradeResult = parseFloat((this._totalScore/this._totalCredit).toFixed(2));
    }

    public getGradeResult():number {
        return this._gradeResult;
    }

    public getTotalCredit():number {
        return this._totalCredit;
    }
}

피드백 + 다른 팀원분들의 코드를 참고해서..
grades.ts 파일로 일급 컬렉션을 만들어 보고자 했는데..

사실 추가 피드백을 받기 전이라 개념을 제대로 이해한 건지, 이게 맞는지는 잘 모르겠다..

Grades라는 일급 컬렉션을 만들어서,
계산의 책임을 일급 컬렉션에 옮기는 것이 핵심이었던 것 같긴 함!

그래서 계산 로직을 grades.ts로 옮기는 방향으로 우선 코드를 수정해 보았고,

const score = new Score(성적);
const credit = new Credit(학점);
const courseName = new CourseName(과목명);
const validatedScore = score.validate();
const validatedCredit = credit.validate();
const validatedCourseName = courseName.validate();

이 부분에서는 원시값 포장 개념을 적용하여 유효성을 검사하고자 해 보았다.

courseName.ts

export class CourseName {

    private _courseName:string;

    constructor(courseName:string) {
        this._courseName = courseName;
    }

    validate() {
        const regex = /[!@#$%^&*+=]/
        if (!(regex.exec(this._courseName))) {
            return this._courseName;
        } 
        throw new Error('강의명은 특수문자를 포함하지 않습니다.')
    }
}

credit.ts

export class Credit {

    private _credit:number;

    constructor(credit:number) {
        this._credit = credit;
    }

    validate() {
        if (this._credit > 0 && this._credit < 4) {
            return this._credit;
        } 
        throw new Error('학점은 1 ~ 3 까지의 값입니다.')
    }
}

score.ts

export class Score {

    private _grade:string;

    constructor(grade:string) {
        this._grade = grade;
    }

    validate() {
        const regex = /[ABCDF]\+?/;
        if (regex.test(this._grade)) {
            return this._grade;
        } 
        throw new Error('유효한 성적이 아닙니다.')
    }
}

위 세 개의 파일에서는 각각 강의명, 학점, 성적(A+ ~ F)를 원시값 포장하였다!

validate라고 이름지은 함수를 통해 유효성을 검사했는데,
학점과 강의명에서는 정규표현식을 사용해 보았다!

Typescript에서 정규표현을 사용해 본 것은 처음이었는데,
정규표현을 처음 배웠던 Python과 크게 다르진 않아서!
문법이 자잘하게 다른 부분 정도만 구글링해서 적용하였다.

참고자료: 정규표현식


index.ts

import { GradeCalculator } from "./calculator/calculator";
import {SAMPLE_GRADE_ONE, SAMPLE_GRADE_TWO, SAMPLE_GRADE_THREE} from '../mock/index'

const gradeResultOne = new GradeCalculator(SAMPLE_GRADE_ONE);
const gradeResultTwo = new GradeCalculator(SAMPLE_GRADE_TWO);
const gradeResultThree = new GradeCalculator(SAMPLE_GRADE_THREE)

gradeResultOne.printResult();
gradeResultTwo.printResult();
gradeResultThree.printResult();

뚝딱뚝딱 파일을 분리해서 만든 학점 계산기 Class를 가져와서
GradeCalculator 객체를 만들고 printResult 함수로 결과를 출력해 주는 것으로 마무리 ! :)


"개념"을 생각하면서 코드를 개선해 나가는 과정은 모르는 것도 많고 생각해야 할 것도 많아서 어려운 것 같다..!ㅠㅠ

그래도 그만큼 여러 가지를 배울 수 있는 과정이 되기를 바라며 :)

profile
주니어 백엔드 개발자입니다! 조용한 시간에 읽고 쓰는 것을 좋아합니다 :)

0개의 댓글