관심사의 분리

hazel's·2022년 5월 11일
0

react

목록 보기
7/13
post-thumbnail

확장성, 유지보수보다는 현재는 기능구현에 중점을 두고 있었다. 로그인기능 자체를 구현하는 것, 여러 기능을 구현하는데 익숙해졌지만, 좋은 개발자란 무작정 구현하는 것이아니라 기능구현을 좀더 확장성있고 편리하게 유지보수 할수 있는 기능구현을 하는 것이다.

로직부분, 기능부분, 뷰부분을 나눠서 동일한 관심사의 코드가 모일수 있도록 하는것

관심사의 분리

정의

  • 코드를 아무리 아름답게 작성하더라도 다양한 이유로 (기획의 변화, 디자인 변경, 요청 사항 추가, 로직 변경) 개발 기간 동안 적어도 한번은 처음과는 다른 조건과, 상황에 대응하도록 수정해야 할 필요성이 생길 것이다.

그럴때마다 지금까지 만들었던 모든 컴포넌트와 UI를 다시 갈아엎는 것 보다 나은 해결책이 있다.

🔐 한번에 한가지 걱정만 하게 단위를 잘게 나누는것이다. 그렇게 되면 전체 기능을 파악하기 위해 읽어야 하는 코드의 단위가 줄어들게 되고, 코드에 대한 파악이 빨라지면서 문제를 효과적으로 해결할 수 있다.

해당 사항이 있는 일부분만 변경시키기 때문에 변화에 대한 내구성을 갖추게 된다. 컴퓨터 공학에서는 이렇게 ' 한번에 한가지만 걱정해도 괜찮도록' 각각의 관심사에 따라 코드를 분리하는 기법을 관심사의 분리라고 부른다.

관심사의 분리가 적절히 구현된 코드

  • loose Coupling : 낮은 결합도, 각각의 코드가 서로 얽혀있지않고 독립적으로 잘 분리되어 있음.
  • High Cohesive : 높은 응집도, 유사한 내용끼리 비슷한 위치에 잘 모여 있음

예를 들어 맥도날드의 직원들은 각자 역할에 따라 위치해있고, 정해진 작업만을 반복합니다. 카운터에서 주문을 받고 계산을 해주는 캐셔는 주문을 받아 결제 및 잔돈을 계산해주고, 받은 주문을 주방에 넣습니다.

주방은 어떤가요? 캐셔에게서 주문을 받아 빵과 패티를 굽고, 양상추 위에 소스를 뿌리고 각각을 조립해 햄버거를 만듭니다. 그리고 포장지에 햄버거를 담아 카운터에 건넵니다.

각자가 맡은 일을 하는 구조라고 할 수 있다. 캐셔가 토마토가 몇개 들어가 있는 햄버거를 만드는 일을 신경 쓸 필요가 없다. 토마토 몇개 들어가 있는 건 캐셔의 관심사가 아니기때문이다.

🎉 관심사 분리의 장점

  • 코드가 더욱 명료해짐 : 자신이 어떤 일을 하고, 어떤 목적을 가지고 설계된 코드인지 보다 잘 드러나게 됨.
  • 코드 재사용성이 올라감 : 여러 역할이 엉켜있는 코드보다, 역할 별로 잘 분리되어 있는 코드를 재사용하기 쉬움.
  • 유지 보수가 용이함 : 변경 사항이 발생했을때 해당 관심사에 연관된 코드만 수정하면 됨.
  • 테스트 코드가 작성하기 쉬워짐 : 얽혀있는 로직보다 분리되어 있는 로직에 대한 테스트가 보다 더 간단함.
  1. 예시1
const loginForm = document.getElementsByClassName('loginForm')[0];
const loginBtn = document.getElementById('loginBtn');

function handleInput() {
  const idValue = document.getElementById('id').value;
  const pwValue = document.getElementById('pw').value;

  const isIdValid = idValue.length > 1;
  const isPasswordValid = pwValue.length > 1;
  const isLoginInputValid = isIdValid && isPasswordValid;
//버튼 속성들을 바꿔주는 구현
  loginBtn.disabled = !isLoginInputValid
  loginBtn.style.opacity = isLoginInputValid ? 1 : 0.3;
  loginBtn.style.cursor = isLoginInputValid ? 'pointer' : 'default';
}
//이벤트 리스너
const init = () => {
  loginForm.addEventListener('input', handleInput);
};

init();
  1. 예시2
const loginForm = document.getElementsByClassName('loginForm')[0];
const loginBtn = document.getElementById('loginBtn');
//함수 생성 - 명확하게 나눠져 있으므로 이안에서 수정
function validateForm() {
  const idValue = document.getElementById('id').value;
  const pwValue = document.getElementById('pw').value;

  const isIdValid = idValue.length > 1;
  const isPasswordValid = pwValue.length > 1;

  return isIdValid && isPasswordValid;
}

function handleButtonActive(isButtonActive) {
  loginBtn.disabled = !isButtonActive
  loginBtn.style.opacity = isButtonActive ? 1 : 0.3;
  loginBtn.style.cursor = isButtonActive ? 'pointer' : 'default';
}

function handleLoginInput() {
  const isFormValid = validateForm();
  handleButtonActive(isFormValid);
}

const init = () => {
  loginForm.addEventListener('input', handleLoginInput);
};

init();
  1. 예시3
function $(selector) {
  return document.querySelector(selector)
}

const loginForm = $('.loginForm');
const loginBtn = $('#loginBtn');

const validator = {
  id: (id) => id.length > 1,
  password: (password) => password.length > 1,
}

function validateForm(form, validator) {  
  for (const key in form) {
    const value = form[key]
    const isValid = validator[key](value)
    
    if (!isValid) return false
  }
  
  return true
}

function handleButtonActive(button, isFormValid) {
  button.disabled = isFormValid ? false : true;
  button.style.opacity = isFormValid ? 1 : 0.3;
  button.style.cursor = isFormValid ? 'pointer' : 'default';  
}

function handleInput() {
  const isFormValid = validateForm({
    id: $('.id').value,
    password: $('.pw').value
  }, validator)
  
  handleButtonActive(loginBtn, isFormValid)
}

function init() {
  loginForm.addEventListener('input', handleInput);
};

init();

profile
좋아하는 것을 하나하나 채워가면 행복해질꺼야

0개의 댓글