프라이D
프라이Develog(❁´◡`❁)
프라이D
전체 방문자
오늘
어제
  • ALL (378)
    • TDD, Cleancode with JavaScr.. (5)
    • 프로젝트 (32)
      • work (3)
      • 직접 만드는 기술 블로그 (2)
      • 데일리 옥션 (19)
      • 모락모락 (8)
    • Computer Science (1)
    • Algorithm & 자료구조 (94)
      • 알고리즘 w.JavaScript (53)
      • 자료구조 (5)
      • (인프런) 자바스크립트 알고리즘 문제풀이 (34)
    • JavaScript (45)
      • JavaScript (41)
      • 모던 자바스크립트 Deep Dive (4)
    • WEB (13)
    • 회고 (12)
    • TIL (109)
    • WIL (7)
    • Stacks (20)
      • React.js (6)
      • Next.js (1)
      • Redux (3)
      • Node.js (2)
      • GIT (2)
      • SAP (1)
    • 15일 메이킹 프로젝트 (15)
    • 이전 기록 (14)
    • ETC. (5)
    • ---------------2021 (6)
      • 내일배움단-웹개발 5주 (2)
      • 정보처리기사 (4)

블로그 메뉴

  • 홈
  • 태그
  • 미디어로그
  • 위치로그
  • 방명록

공지사항

인기 글

태그

  • JavaScript
  • nomadcoder
  • MySQL
  • 알고리즘
  • 자바스크립트알고리즘
  • 2023 인프콘 후기
  • 국비지원
  • 자바스크립트비트마스크
  • 내일배움카드
  • nomadcoders
  • 모던자바스크립트딥다이브
  • 내일배움단
  • vanilaJS
  • 스파르타코딩클럽
  • 비트마스크
  • 투포인터알고리즘
  • 코딩프로젝트
  • 자바스크립트
  • Til
  • 코드스테이츠

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
프라이D

프라이Develog(❁´◡`❁)

TIL

[TIL] 2023-0924 : 유연하고 확장되기 쉽고 교체되기 쉬운 코드를 작성하자.

2023. 9. 25. 03:37

Facts

- 미완성 상태긴 하지만 영화 리뷰 STEP1 PR을 올렸다.

- 로또 미션 STEP 3 리팩토링 진행

 

Feelings

- 어쨌든 PR 을 올렸다는 것 자체가 마음을 조금 편하게 해줌.

- 한 번 재미있다고 생각하면 또 너무 재밌어서 계속 하고 싶음

- 날씨가 좋아서 기분이 좋았다.

 

Findings

- 오늘 받은 피드백 중에는 '다른 서비스가 여러 플랫폼에 서비스를 제공하기 위해 어떤 노력을 할지 고민해보면 많은 공부가 될 것이다' 라는 내용이 있었다. 이미 성장한 큰 서비스가 어떻게 생겨먹었고 굴러가는지 관심을 가지고 인사이트를 얻는 것도 큰 공부가 되겠음...

- 지난 PR 에서는 일단 로또 게임이 웹 UI 에서 돌아가게 만드는 것에 초점을 맞춰서 메서드고 코드 정리고 하나도 하지 않았었는데, 어찌저찌 돌아가기는 하지만 이를 다시 이해하는데 약간의 시간이 걸렸다. 복잡하니까 더 쳐다보기 싫은 그런 현상이 있었음...

- Controller 로직을 두고 여기서 view 를 주입받는 방식으로 구현하려고 했는데, 그러면 이미 view 에 너무 많은 의존성을 가진 Controller 의 메서드들이 web UI 에 해당하는 view 에서 사용하기 까다롭게 되어있어서 이를 리팩토링 하고 있다.

 

부끄럽지만 아래가 나의 기존 코드

class LottoGameController {
  #view;
  #vendingMachine;
  #winningCalculator;

  // ... 

  async purchaseAndIssueLottos() {
    // 🤔 이미 이 메소드 안에서 view 의 메소드를 호출하고 있어서, view 의 구현에 영향을 받는다.
    const purchaseAmount = await this.#view.getPurchaseAmount();

    this.#vendingMachine.purchase(purchaseAmount);
    const purchasedLottoList = this.#vendingMachine.lottos;
    
    // 👀 여기도
    this.#view.printPurchasedLottos(purchasedLottoList);

    return purchasedLottoList;
  }

  async setWinningNumbers() {
    // 👀 여기도
    const { selectedNums, extraNum } =
      await this.#view.getLottoWinningNumbers();

    return new LottoWinningNumbers({
      selectedNums: selectedNums,
      extraNum,
    });
  }

  // ... and more ...
}

controller 의 로직이 이렇게 되어있다보니, 주입받는 view 로직도 controller 의 구현에 맞춰야 해서 아래와 같이 이상하고 복잡한 코드가 등장했다. 

class LottoGameViewWeb extends LottoGameView {
  // ... 
  
  // controller 에서 이미 view 의 이 메서드를 비동기도 다루고 있어서 불필요한 promise 가 사용되었다.
  async getPurchaseAmount() {
    return new Promise(async (resolve, reject) => {
      const button = document.getElementById('purchase-button');

      button.addEventListener('click', async () => {
        const input = document.getElementById('purchase-amount-input');
        const purchaseAmount = input.value;
        
        resolve(purchaseAmount);
      });
    });
  }

 
  // 여기도... 메서드명도 이 지경이다 보니 도대체 뭘 하는 메서드인지 나도 모르겠음 😏 
  #createButtonClickPromise() {
    return new Promise((resolve) => {
      const button = document.querySelector('.open-result-modal-button');
      button.addEventListener('click', () => {
        // 일반 번호들 가져오기
        const selectedNumsElements =
          document.querySelectorAll('.selected-number');
        const selectedNums = Array.from(selectedNumsElements).map((input) =>
          Number(input.value)
        );

        // 보너스 번호 가져오기
        const extraNumInput = document.querySelector('.bonus-number');
        const extraNum = Number(extraNumInput.value);

        // 입력된 번호 컨트롤러로 전달
        resolve({ selectedNums, extraNum });

        // 모달창 열기 
        const modal = document.querySelector('.modal');
        modal.classList.add('open');
        
        // 😅 그리고 이해가 잘 안되니까 이렇게 과도하게 친절한 주석도 추가된 것 같음...
      });
    });
  }

 // ... and more ...
}

- 그래서 방식을 바꿔 controller 는 외부에서 데이터를 인자로 받아 도메인 모델들에게 전달해 게임의 기능을 수행시키고 다시 그 값을 반환해 외부에서 핸들링 하도록 수정했음... 그렇게 하니 controller 의 역할도 조금 가벼워졌고 view는 어떻게 구현되든 controller 를 잘 활용해 콘솔 기반이든 웹 UI 기반이든 동작하도록 만들 수 있어서 유연성이 증가했다. 내 생각보다 함수, 메서드의 단위를 더 잘게 쪼개야 하는듯. 이렇게 리팩토링을 시작하기 전에는 view 와 강결합이 되어있다는 생각 자체를 못했었음. 

- 처음엔 아예 갈아엎을까 생각도 했지만, 만약 이게 실무라면 그렇게 할 수는 없을테니까 최대한 있는 코드에서 변경을 최소화 하면서 바꾸려고 노력하고있다. 

 

- 그래서 아래와 같은 방식으로 변경을 해보았음... 이거는 웹 UI 에서 로또 게임을 돌리는 로직인데, 더이상 유저의 입력을 비동기로 처리하기 위해 Prmoise, resolve 를 활용할 필요가 없어짐 (그래도 연습은 했다) 

- 에러 핸들링의 경우 이벤트 리스너의 콜백 함수가 비동기이다 보니, 상위 메서드인 run 에서 try catch 로 핸들링이 어려웠고... 일단 콜백 함수 내에서 then 과 catch 로 핸들링 하도록 만들었는데 조금 더 추상화해서 정리할 수 있을 것 같다. 

class App {
  #view;
  #controller;

  constructor() {
    this.#view = new LottoGameViewWeb();
    this.#controller = new LottoGameController();
  }

  run() {
    try {
      this.step1();
      this.step2();
    } catch (error) {
      alert(error.message);
    }
  }

  /**
   * 구매 버튼을 클릭해 유저가 입력한 금액만큼 로또를 발행한다.
   */
  step1() {
    const $purchaseButton = document.getElementById('purchase-button');
    const $purchaseInput = document.getElementById('purchase-amount-input');

    $purchaseButton.addEventListener('click', () => {
      const purchaseAmount = $purchaseInput.value;

      this.#controller
        .purchaseAndIssueLottos(purchaseAmount)
        .then((purchasedLottoList) =>
          this.#view.printPurchasedLottos(purchasedLottoList)
        )
        .catch((error) => alert(error.message));
    });
  }

  // ... 
}

 

Feedback

- 과제 리뷰 기한은 끝났는데 그래도 어찌저찌 마무리 해보겠다고 노력한 점은 잘했음

- 마음에 안든다고 갈아 엎지 않고 점진적으로 개선하려고 하는 점은 스스로 칭찬해주고 싶음

- 역시 새벽에 하는 코딩이 잘 됨. 시간을 조정해서 새벽시간에 공부를 할 수 있게 조절하는 것도 좋을 것 같다. 건강엔 나쁠 것 같지만...

 

Future Action

- 리팩토링 마무리 후 다시 블로깅

저작자표시 (새창열림)

'TIL' 카테고리의 다른 글

[TIL] 2023-0926 테스트  (0) 2023.09.27
[TIL] 2023-0925 점진적 과부하  (4) 2023.09.26
[TIL] 2023-0922  (0) 2023.09.24
[TIL] 2023-0921  (1) 2023.09.21
[TIL] 2023-0126 : 새 프로젝트 / 딥다이브 스터디 / 과제  (3) 2023.01.27
    'TIL' 카테고리의 다른 글
    • [TIL] 2023-0926 테스트
    • [TIL] 2023-0925 점진적 과부하
    • [TIL] 2023-0922
    • [TIL] 2023-0921
    프라이D
    프라이D
    틀린내용 정정 및 개선사항은 언제든지 댓글 달아주세요 :D

    티스토리툴바