🏄CHALLENGE/클린코드 북클럽

클린코드 챌린지 DAY16-17/18-19 :: 10장. 클래스, 복습, 실전미션

Joyleedev 2024. 9. 9. 22:38

 

과제 :  TIL 작성하기

 

오늘 TIL 3줄 요약

  • 코드의 행과 코드 블록을 올바르게 작성했을지라도, 깨끗한 클래스를 사용하여 더 차원 높은 단계까지 신경써야 한다.
  • 클래스는 하나의 책임만을 맡아 작고, 변경하기 쉬워야 한다.
  • 그리하여 우리는 유연성과 재사용성이 높아지는 클래스로 깔끔한 코드를 구현할 수 있어야 한다. 

TIL (Today I Learned) 날짜

2024. 09. 09

 

오늘 읽은 범위

10장. 클래스

 

책에서 기억하고 싶은 내용을 써보세요.

- 클래스의 체계는 가장 먼저 변수 목록 > 적적 공개 상수 > 정적 비공개 상수 > 비공개 인스턴수 > 공개 함수 > 비공개 함수 순으로 내려간다. (172p)

-  클래스는 작아야 한다 (172p)

  • 단일 책임 원칙(Single Responsibility Principle) : 클래스나 모듈을 변경할 이유가 하나뿐이어야 한다는 원칙이다.
  • 각 클래스 메서드는 클래스 인스턴스 변수를 하나 이상 사용해야 한다. 일반적으로 메서드가 변수를 더 많이 사용 할 수록 메서드와 클래스는 응집도가 더 높다. 모든 인스턴스 변수를 메서드마다 사용하는 클래스는 응집도가 가장 높다. 응집도가 높다는 말은 클래스에 속한 메서드와 변수가 서로 의존하며 논리적인 단위로 묶인다는 의미이기 때문이다.

- 클래스는 변경하기 쉬워야 한다. (185p)

  • 깨끗한 시스템은 클래스를 체계적으로 정리해 변경에 수반하는 위험을 낮춘다.
  • OCP(Open-Closed Principle) : 클래스는 확장에 개방적이고 수정에 폐쇄적이어야 한다는 원칙
  • 이상적인 시스템이라면 새 기능을 추가할 때 시스템을 확장할 뿐 기존 코드를 변경하지 않는다.
  • DIP 원칙 (Dependecny Inversion Principle) : 추상 클래스를 사용하여 시스템의 결합도를 낮춰 유연성과 재사용성을 높이고 시스템 요소를 잘 격리시켜 각 요소를 이해하기 쉬워지게 해야 한다.

오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요

프론트엔드에서 사용하는 클래스와는 다소 다른 내용의 백엔드에서 사용하는 클래스가 완전히 이해하는 데에는 조금 한계가 있었다. 하지만 프론트엔드에서 사용하는 클래스와도 분명 일맥상통하는 내용들이 보였다. 예를 들어 하나의 클래스에는 하나의 책임만이 따라야 한다. 이 책임을 나는 '역할'로 보았다. 이전 단계로 랜딩되는 버튼이라면, btn_prev나 link_prev와 같은 클래스를 부여하여 이전으로 이동하는 책임만을 따른다는 것을 명시해야 하지 btn_link나 btn_move 와 같이 다소 모호한 역할을 부여해서는 클래스를 사용해서는 안된다고 생각하였다.

확장에 개방적이고 수정에 폐쇄적이어야 한다는 원칙 또한 프론트엔드 클래스에도 적용시킬 수 있을 것 같다. 클래스가 파생 클래스를 생성할 수 있어야 한다는 것인데, 복잡한 디자인 요소나 기능적인 부분이 많이 쓰이는 요소라면 특히 이 부분은 신경써서 클래스를 작명해야 한다고 생각한다.

클래스 작명은 프로그래밍의 기초 중에 기초이며, 동시에 가장 중요한 부분을 차지한다고 생각한다. 어떻게 작명하냐에 따라 프로그래밍을 하는 데에 있어 전체적인 작업 시간과 작업의 질을 결정한다. 따라서 모호하지 않게, 변경에 취약하지 않게 잘 지어 코드의 유연성과 재사용성을 높여야겠다는 생각이 들었다.

 

 

궁금한 내용이 있거나, 잘 이해되지 않는 내용이 있다면 적어보세요.

프론트엔드에서는 css의 공통 레이아웃을 잡기 위해 다소 포괄적인 클래스로 네이밍하기도 하는데, 이런 부분은 SRP에 어긋나도 될까? ㅎㅎ

 

오늘 읽은 다른사람의 TIL

https://bamidev.notion.site/DAY-12-6332c8ef91d743159092098cee7c1917

 

 

DAY16-17 과제 : 실전 미션 - 배운 내용 적용하여 리팩토링 하기!

1️⃣

// 본인이 가장 잘하는 언어로(JS, Python 등등) 더러운 코드를 깨끗한 코드로 리팩토링하는 예시를 만들어보세요. 현재 파일은 JS 로 되어있지만. 자유롭게 다른 언어로 변경해주세요. 

// 원칙 1. 
//의미있는 이름을 지어라

// Before 😣
function updateOptions() {
  $('select option').each(function() {
    var text = $(this).text().trim();
    text = text.replace(/:/g, '').trim();

    if (text.includes('[품절]')) {
      text = text.replace(/\+\d+[,\d]*원/, '').trim();
      text = text.replace(/\[품절\]/, '(품절)').trim();
    } else {
      text = text.replace(/\+\d+[,\d]*원/, function(match) {
        return match.replace(/^\+/, '');
      }).trim();
    }

    text = text.replace(/(\d{1,3}(?:,\d{3})*)원/, function(match) {
      return '(' + match + ')';
    }).trim();

    $(this).text(text);
  });
}


// 무엇을 고치려고 하는지, 고치려는 문제가 무엇인지 알려주세요.
//var text = $(this).text().trim(); 에서 text라는 변수 이름이 너무 포괄적이다 ㅋㅋ ㅠㅠ
//왜 이렇게 지었을까 정말.. 이 책을 읽기 전에는 이게 그냥 음..텍스트니까~ 아몰랑 ~ 하고 지었다면
//이 책을 읽은 이상 이걸 보고 도저히 그냥 지나칠 수가 없게 되었다..
//text라고 하면 귀에걸면 귀걸이, 코에걸면 코걸이가 될 수 있기 때문에 
//독자의 입장에선 굉장히 혼란스러운 이름이 될 수 있다...


// After 😎
function updateOptions() {
  $('select option').each(function() {
    var selectOptionText = $(this).text().trim();
    selectOptionText = selectOptionText.replace(/:/g, '').trim();

    if (selectOptionText.includes('[품절]')) {
      selectOptionText = selectOptionText.replace(/\+\d+[,\d]*원/, '').trim();
      selectOptionText = selectOptionText.replace(/\[품절\]/, '(품절)').trim();
    } else {
      selectOptionText = selectOptionText.replace(/\+\d+[,\d]*원/, function(match) {
        return match.replace(/^\+/, '');
      }).trim();
    }

    selectOptionText = selectOptionText.replace(/(\d{1,3}(?:,\d{3})*)원/, function(match) {
      return '(' + match + ')';
    }).trim();

    $(this).text(selectOptionText);
  });
}



// 어떻게 고쳤는지, 사례에서 무엇을 배워야 하는지 설명해주세요.
//변수명을 'selectOptionText' 으로 고쳐주었다.
//그리하여 select의 option태그의 text를 변수명으로 받는다 ~ 라는 것을 누가봐도 알 수 있게끔
//수정해주었다. 앞으로 text나 value, img와 같은 이름은 피하고 앞에 정확히 설명해줄 수 있는 단서를 더 제공해가며
//의미있는 이름을 지어주어야 겠다 !!

 

2️⃣

// 본인이 가장 잘하는 언어로(JS, Python 등등) 더러운 코드를 깨끗한 코드로 리팩토링하는 예시를 만들어보세요. 현재 파일은 JS 로 되어있지만. 자유롭게 다른 언어로 변경해주세요.

// 원칙 2. 
//함수나 변수로 표현할 수 있다면 주석을 달지 마라.

// Before 😣
//옵션값 가격 판매가에 삽입
var firstOptionText = $('select option').text();
var matches = firstOptionText.match(/\+(\d{1,3}(?:,\d{3})*)원/);
if (matches) {
  var firstOptionPrice = matches[1];
  console.log(firstOptionPrice);
}
$('.firstOptPrice').text(firstOptionPrice);


// 무엇을 고치려고 하는지, 고치려는 문제가 무엇인지 알려주세요.
//우선 여기서도..matches라는 너무 불분명한 변수명이 있는데 이건 뒤로하고 ^^
//해당 코드는 select의 option에 가장 첫번째에 있는 옵션가를 판매가 영역에 노출시키는 코드이다.
//그래서 주석으로 옵션값 가격 판매가에 삽입 이라고 달아주었는데, 
//이걸 함수 안에 넣어준다면 함수명으로 표현하면 되지 굳이 주석을 달아주지 않아도 될 것 같았다.


// After 😎
function setFirstOptionPriceToSalePrice() {
  var firstOptionText = $('select option').text();
  var matches = firstOptionText.match(/\+(\d{1,3}(?:,\d{3})*)원/);

  if (matches) {
    var firstOptionPrice = matches[1];
    console.log(firstOptionPrice);
    $('.firstOptPrice').text(firstOptionPrice);
  }
}
setFirstOptionPriceToSalePrice();


// 어떻게 고쳤는지, 사례에서 무엇을 배워야 하는지 설명해주세요
//첫번째 옵션가를 판매가에 넣는다는 의미를 가진 setFirstOptionPriceToSalePrice 로 함수명을 설정하여
//주석을 삭제해도 해당 코드가 무슨 역할을 하고있는지 알 수 있게 해주었다.
//코드가 2-3줄 더 추가되고 적당한 이름을 짓느라 시간이 좀 더 걸렸지만, 보기에 훨씬 깔끔해진 것 같다!

 

3️⃣

// 본인이 가장 잘하는 언어로(JS, Python 등등) 더러운 코드를 깨끗한 코드로 리팩토링하는 예시를 만들어보세요. 현재 파일은 JS 로 되어있지만. 자유롭게 다른 언어로 변경해주세요.

// 원칙 3. 
//서술적인 이름을 사용하라.

// Before 😣
function checkAndReset() {
  const {
    x,
    y
  } = getTransform();
  const scale = myPanzoom.getScale();

  if (x > translateXThreshold || x < translateXNegativeThreshold || y > translateYThreshold || y < translateYNegativeThreshold) {
    myPanzoom.pan(0, 0);
    myPanzoom.zoom(0, { animate: false });
  }
}

// 무엇을 고치려고 하는지, 고치려는 문제가 무엇인지 알려주세요.
//해당 코드는 panzoom.js라는 라이브러리를 함께 사용하여 마우스 드래그가 일정 범위 이상으로 넘어갈 시
//다시 원위치시키는 코드이다. 함수명을 checkAndReset로 지었는데,
//이것은 독자가 보기에 해당 함수가 정확히 어떤 걸 체크하고 리셋하는지를 정확히 알 수 없는 다소 불친절한
//함수명이기 때문에 좀 더 구체적이고 서술적인 이름이 필요할 것 같았다.


// After 😎
function checkPanBoundsAndReset() {
  const {
    x,
    y
  } = getTransform();
  const scale = myPanzoom.getScale();

  if (x > translateXThreshold || x < translateXNegativeThreshold || y > translateYThreshold || y < translateYNegativeThreshold) {
    myPanzoom.pan(0, 0);
    myPanzoom.zoom(0, { animate: false });
  }
}


// 어떻게 고쳤는지, 사례에서 무엇을 배워야 하는지 설명해주세요.
//함수명을 checkPanBoundsAndReset으로 지어서 독자가 보기에 해당 함수는 pan bound를 체크하여
//리셋시키는 역할을 한다는 것을 알 수 있게 해주었다.
//결국 원칙 1과 원칙 2로 귀결되는것 같기도 한데, 책으로 읽었을때보다 실무에 적용시켜보니
//한눈에 함수가 어떤 일을 하는지 알 수 있게 해주어
//유지보수나 재사용성에 좀 더 용이할것 같다는게 뭔지 매우 와닿았다.
//솔직히 이름이 생각이 안나면 챗GPT를 이용하여 이름을 짓는것도 결코 창피한 일이 아닌 것 같다.
//이상한 이름을 짓거나 애매하게 코딩하여 나중에 이슈가 발생하는 것 보단 훨~ 씬 나은듯!

클린코드 챌린지 DAY11 :: 9장. 단위 테스트