[레벨1 - 미션2] 1단계 로또 피드백

Nine·2022년 3월 5일
1

💪공통

똑같은 실수를 반복하지

  • EOL, 선언형 지향, 불필요한 주석, 요구사항...

왜 매번 고치지를 못하니...! 이전에 받은 피드백은 확실하게 지키도록 해봅시다!


내가 짠 코드는 책임을 끝까지 집시다.

  • 통째로 갈아 엎는다? NoNo..😣😣
  • 리뷰어에 대한 예의, 페어에 대한 예의가 아닙니다.

신뢰할 수 있는 글을 참고합시다.

  • velog, 개인 블로그는 정답이 아니예요. (물론 나 또한 정답이 아니다!)
  • 2차 저작물은 스스로 검증하고 사용하세요!

HTML/CSS

태그 100% 사용해봐요.

MDN 문서를 보는 습관을 들이면 좋겠다고 생각이 드는 대목이었어요.

  • 태그마다 유용한 속성이 즈엉말 많아요🔍🔍
<input type="number" min="1000" max="10000" />

Node List에 대한 이해

  • NodeList는 Array는 아니지만 ForEach 정도는 사용할 수 있어요.
  • 약간 유사 Array느낌이죠?

💪Javascript

빌트인(Built-in) 객체의 prototype 확장

빌트인 객체 : Array, Set, ... 기본적으로 주어진 객체들이예요~

// 기존 메서드 대체 (굳이 map을 대신할 함수를 만든다라...;;;)
Array.prototype.map = function () {
	return [];
}

// 새로운 메서드 추가
Array.prototype.deepCopy = function () {
	return JSON.parse(JSON.stringify(this));
};
  • prototype 으로 새로운 함수를 만든다는 시도는 좋아요. 직접 해보면서 어떤 문제가 발생할지에 대해 생각해봐요.
  • 하지만 (위의 map을 대신하는 함수를 만드는 것처럼) 기존 spec을 무시하는 일은 삼가하는게 좋을 것 같아요.
  • 참고로 class 없이 prototype을 사용하면 클래스처럼 만들 수 있어요. (Object로 하는 방식, prototype을 이용하는 방식, class를 이용하는 방식)

this 제대로 알아봅시다!

  • 일반 함수와 화살표 함수의 차이가 뭔지에 대해 알아야할 것 같아요.
    (공원이 퀴즈 낸거 거의 못 맞춤ㅠㅠ)

  • 함수가 실행될 때 this가 어떤 걸로 결정되는지 알아야함을 느꼈어요.


Babel

⚙️바벨은 ES6가 지원하지 않는 곳에서 코드가 돌아갈 수 있도록 변경해주는 툴입니다.

  • babeljs.io에서 코드가 어떤 식으로 바뀌는지 알 수 있어요.

DOM selecting을 반복하지 말자!

💰 DOM Selecting도 아주 비싼 작업이예요.

  • 불필요하게 새로 셀렉팅하는 작업이 생기지 않도록 합시다!

한 크루가 이런 방식도 생각을 했네요. (하지만 동적으로 생성되고 사라지는 DOM 요소에 대해서는 정상 동작을 할지 모르겠네요.)

const $ = (selector) => $[selector] = $[selector] || document.querySelector(selector);

💪사용성을 챙기는 디테일

프론트 개발자 하고 싶다며... 왜 신경을 안쓰니?

많은 FE들이 E에만 집중하고 F는 등한시하는 경우가 있습니다.

예를 들면 이런 거 할 수 있잖아요.

  • 클릭이 가능한 요소에 대하여 cursor: pointer
  • 로또 6개의 번호를 입력할 때 2글자 입력하면 바로 다음 칸으로 넘어가기

😢 충분히 할 수 있으면서 챙기지 않는 것에 부끄러움을 느껴야 할 것 같아요. 사용성에 대한 고미을 해봅시다.


사용자의 실수 방지하기

deactivateForm() { 
    $('#money-input').setAttribute('disabled', true);
    $('#purchase-button').setAttribute('disabled', true);
}
  • 이런 식으로 입력을 받고 나면 입력 Form 자체를 disabled처리하는 것도 한 가지 예시가 되겠죠?

사용자에게 친절해지기 (에러 메세지)

    try {
        // some code
    } catch (error) {
        alert(error.message); 
    }

👭 사용자와 개발자가 보는 에러 메세지가 같게 하기 보다는 별도로 작성해요!


일관성

💩 똥을 만들어도 일관성있게 만들면 유지 보수가 훨씬 쉽다고 했죠? 지난 피드백에서도 배웠어요.


언제까지 약속만 할 것인가

아직 와닿지 않는 피드백이예요. 필요할 때 다시 돌아올게요. 하지만 이 피드백을 이해하시는 분들이 있을 수도 있은이 남기긴 하겠습니다.
`

  • 쓸데 없는 메서드를 만들어서 class extends를 하는 행위는 별로예요.
  • 추상 클래스 만들었으면 인스턴스를 스스로 만들 수 없어요.
    • 생성자 함수, 라이프 사이클... 내 맘대로 안된다?
  • 추상 클래스가 뭔지부터 알아봅시다.

네이밍 네이밍 네이밍

  • 아무리 강조해도 지나치지 않죠? 아래를 조심하세요.
Data
Info
Manager
Model

☝️ 솔직히 너무 쓰고 싶은 네이밍들이죠? 하지만 너무 모호하다는 사실!

const lottoData = new LottoData();
const model = new Model();
  • 코드를 타고 들어가지 않아도 무슨 말인지 알 수 있나요??

불친절한 인자 넘기기

emit(this.showLottoToggle, '@lottoToggle', '');
  • 인자에 대한 고민도 해봅시다.
    저는 인자가 많아질 경우 객체로 인자를 묶어 넘기는 방식에 눈을 떴어요. (꼬재의 꿀같은 코드 감사합니다.)

부정 조건문보다는 긍정 조건문

😇긍정이 사람이 읽기가 더 편해요.

여기서 포코의 피드백 추가!

❓엄청 헷갈리죠❓

!isNaN(number) // 숫자형이 아닌게 아니다
!isEmptyXXX(number) // 빈 것이 아니다

if (...) {
 거짓일때 실행 // 안헷갈리나요?
} else {
 참일때 실행 // 저는 헷갈립니다
}

!isMoneyPositive or isNotMoneyPositive 보다는 isMoneyNegative

👉 early return을 제외하고는 사람의 의식대로(긍정 우선) 코드를 작성해보면 어떨까 싶어요.


상수도 관심사가 있을 수도

  • 상수도 그 특성과 의미에 따라 분류할 수 있어요.

YAGNI(You aren't gonna need it)

한 마디로 오버하지마!

  • 구조화, 영역 분리 목표를 열심히 하는 것은 좋지만, 진짜로 필요한지에 대해서 생각해봐야해요.
  • 내가 앞서 나간 것은 아닌가? 🏃‍♂️🏃‍♂️
  • 불필요한 폴더 구조, 깊이
  • 불필요한 최적화, 추상화

자율적 + 협력적 객체

private, class 객체 지향의 여러 복잡한 원칙들을 알기 이전에 왜 이런 개념들이 나왔을까 생각해보셨나요?

🎯우리의 목표는 객체 지향이 아니라 유지보수하기 쉬운 코드예요.
1. 파악하고 예측이 쉽다.
2. 기능 추가/수정이 쉽다.

협력 공동체의 일원으로 우리는 협력적이고 자율적이어야 해요. 그리고 객체👣도 마찬가지예요.

  1. 객체👣는 '협력적'이어야 한다.외부의 도움을 무시한 채 모든 것을 스스로 처리하려고 하는 전지전능한 객체는 내부적인 복잡도에 의해 자멸하고 만다.
  1. 객체는 '자율적'이어야 한다. 객체 공동체에 속한 객체들은 공동의 목표를 달성하기 위해 협력에 참여하지만, 스스로의 결정과 판단에 따라 행동하는 자율적인 존재다.

객체의 자율성은 객체의 내부와 외부를 명확하게 구분하는 것으로부터 나온다. 객체의 사적인 부분은 객체 스스로 관리하고 외부에서 간섭받지 않도록 차단하며, 객체의 외부에서는 객체가 스스로 허락한 수단을 통해서만 객체에 접근해야 한다.

객체는 다른 객체가 '무엇(what)'을 수행하는지는 알 수 있지만 '어떻게(how)' 수행하는지에 대해서는 알 수 없다.

[출처] -<객체지향의 사실과 오해> 중에서


💪Test

E2E와 Unit 테스트를 구분하기

app.test.js에서 한 번에 테스트하기보단, 각 테스트 대상마다 테스트 파일을 따로 만들어볼까요?

import LottoGenerator from '../model/lottoGenerator.js'; 
import LottoNumber from '../model/lottoNumber.js';

✍️ 또, 하나의 테스트를 위해 이렇게 여러 import가 필요한 경우 통합 테스트 ,E2E테스트는 아닌지 확인해봐야해요.


단위 테스트가 실패하는 이유는 가능하면 구체적인 1가지

✍️웬만하면 expect를 하나만 하는 것을 권장해요.
예를 들어 자연수만 받아야하는데 입력이 비정상적인 에러인 경우
- 다양한 에러가 있을 수 있어요. (빈칸이라든지, 문자열이라든지, 실수라든지, 음수라든지..)
- 이걸 위해 하나의 테스트에 여러 개의 expect가 존재하면 좋을까 고민이 필요해요.


테스트 코드 내에 구현 코드 두지 않기

TDD → Test Driven 입니다.
📝 테스트 코드 내에서 로직을 따로 짜는 건
- 실제 구현 코드에 대해서는 테스트가 되지 않는다.
- 그렇다면 리팩토링을 마음놓고 할 수 있는 안전장치로서의 역할을 해주지 못한다.


Github Actions 사용해보기

좋은 기능들이 정말 많아요.

profile
함께 웃어야 행복한 개발자 장호영입니다😃

0개의 댓글