Refactoring V1

Shaun·2022년 4월 24일
1

Refactoring

목록 보기
1/6
post-thumbnail

맨날 같은 형식으로만,맨날 반복되는 코드 ,같은 기능이지만 다른 성능....

좀더 효율적으로, 좀더 좋은 코드에 대한 욕심이 많다.

자바라는 언어를 쓰지만 자바의 특성을 살리면서 코드를 작성하지 못한것 같아 저번시간에는 자바에 대해 다시한번 공부했다.
-> 객체지향

이제는 조금 더 나아가 리팩토링에 대해 알아보려한다.

이 글은 '인프런 자바 리팩토링 -백기선 ' 강의를 듣고 정리한 글입니다

리팩토링을 는 이유부터 알아보자!

  • 소프트웨어는 계속변하기때문에

  • 시간이 갈수록 구조 변경으로 인한 수정등이 많아진다. 그럴수록 더 복잡하고 어려운 코드들을 효과적으로 수정 처리 하기 위함!

지금부터 코드의 안좋은점, 안좋은느낌, 은 '냄새' 로 표현을 합니다.

함수이름

  • 좋은코드의 기본은 '좋은 함수 이름'
  • 좋은 함수 이름이란 그 함수가 어떠한 역활을 하는지 짐작할수 있는 이름

사용할 수 있는 리팩토링기술

1. 함수 선언 변경하기

  • 좋은 이름을 찾는 방법은 함수에 주석을 작성한 다음 주석을 토대로 함수 이름을 작성해본다.

2. 변수 이름 바꾸기

  • 더 많이 사용되는 변수일수록 그 이름이 더 중요하
  • 여러 함수에 걸쳐 쓰이는 필드 이름에는 더 많이 고민하고 이름을 짓는다.

3. 필드 이름 바꾸기

  • Record 자료 구조의 필드 이름은 프로그램 전반에 걸쳐 참조될 수 있기 때문에 매우 중요하다.
  • Record: 특정 데이터와 관련있는 필드를 묶어놓은 자료구조 (Kotlin 의 Data Class 와 매우 흡사)

중복코드

중복코드의 단점

  • 비슷한지, 동일한지 자세히 봐야한다
  • 코드를 변경하면 다른곳도 동일학게 변경해야함

사용할 수 있는 리팩토링기술

  • 동일한 코드를 여러 메소드에서 사용하는경우 => 함수 추출하기
  • 코드가 비슷하게 생겼지만 완전히 같지는 않는 경우 => 코드 분리하기
  • 여러 하위 클래스에 동일한 코드가 있다면 => 메소드 올리기

중복코드/함수 추출하기

  • "의도""구현" 을 분리하기
  • 코드를 한줄한줄 읽으면서 의미파악을 해야 이해한다? => 그 코드는 "구현" 에 가깝다
  • 코드를 보자마자 어느정도 의미파악이 바로 가능하다? =? 그 코드는 "의도" 에 가깝다.
  • 이렇게 하면 서로 좀더 독립적이며 기능 수정이 필요한 부분만 수정하면된다 전체코드가아닌

  • 코드에서 중복되는 내용들을 메서드로 추출해 정리 해봤다(함수 추출)
  • 코드들이 서로 좀더 독립적이며 수정시 기존 실행되는 부분은 그대로 두며 실질적인 부분만 수정하면 된다.

중복코드 / 코드 정리

  • 관련있는 코드끼리 묶여있어야 코드를 좀더 쉽게 이해할수있다.

  • 함수에서 사용할 변수를 상단에 미리 선언하기보다는, 해당 변수를 사용하는 코드 바로 위에 선언하자.

  • 관련 있는 코드끼리 묶은뒤 -> 함수추출하기

중복코드 / 메서드 올리기

  • 중복코드는 당장은 잘 동작하지만 미래에 버그를 만들어 낼 빌미를 제공한다. 수정시에도 다 수정 해야됌.

  • 여러 하위 클래스에 동일한 코드가 있다면, 이 방법을 적용 해보자

  • 상속시 하위클래스에서 중복되는 코드들을 위로 올려주는 방법




  • 중복된코드를 상속 부모-자식 클래스 개념으로 나눈다.

  • 한쪽만 고쳐도(부모) 양쪽(자식) 에게 영향을 줄수 있다.

  • 완전똑같지 않고, 약간 다른경우 (위의 예시의 경우 파라미터) 에는 메서드 추출로 한번 감싸준다

긴 함수

  • 함수에 "좋은 이름" 을 사용 했다면 해당 함수의 코드를 보지 않고도 이해할수 있어야한다

  • 어떤 코드에 "주석" 을 남기고 싶다면, 주석 대신에 함수를 만들고 함수의 이름으로 "의도" 를 표현해보자

  • 함수가 길어도 ‘의도’ 가 가 잘들어나있으면 괜찮고 함수가 한줄이여도 이해하기 어려운 ‘구현’ 에 가까우면 좋지 못한 코드이다.

사용할 수 있는 리팩토링기술

1.함수로 분리 하면서 전달해야할 매개변수가 많아지면

  • 임시 변수를 질의 함수로 바꾸기
  • 매개변수 객체 만들기
  • 객체 통쨰로 넘기기
  1. 함수 추출하기

  2. 조건문이 너무길다 => 조건문 분해하기

  3. 여러 switch => 조건문을 다형성으로 바꾸기

  4. 반복문 안에서 여러 작업을 하고 있어서 하나의 메소드로 추출하기 어렵다면 => 반복문 쪼개기

긴함수/임시 변수를 질의 함수로 바꾸기(매개변수 줄이기)

  • 변수를 사용하면 반복해서 동일한 계신식도 피하며 "좋은 이름" 을 사용해 메서드 의미를 표현할수도 있다.

  • 메서드로 추출해서 메서드에서 사용하는 매개변수 줄이기

  • 한 눈에 보기에도 이해하기 힘든 코드이다. 일단 메서드 추출을 해주자

  • 함수추출 기능을 사용해 메서드를 추출해준다. 그래도 매개변수가 너무많다. 매개변수 rate를 뺴보자 -> rate가 만들어지는 부분도 메서드추출해준다

  • Rate 를 메서드에게 전달하는게 아닌 ‘빼낸 메서드 안에서 호출해서 사용’ 하면 매개변수를 줄이면서 동작이 가능하도록 할수있다.

  • 임시변수(함수추출)를 쿼리로 뺴냈을때 파라미터를 줄일수 있다.

  • 메서드추출-> 메서드에 넣기(그안에서 추출한 메서드는 동작을 하니 매개변수로 안보내줘도됌)

긴함수/매개변수 객체 만들기(매개변수 줄이기2)

  • 매개변수 객체 만들기다.
  • 매개변수를 줄일때 같은 성향의 매개변수가 같이 자주사용되면 객체로 묶어서 사용해주자

긴함수/객체 통째로 넘기기(매개변수 줄이기3)

  • 2번 방법과 매우 흡사하지만 2번은 아예 그 파라미터들이 파생되어오는 레코드나 클래스드들이 없을떄 만들면서 바로 preserveWholeObject에 바로 적용되지만 3번은 이미 그파라미터들이 파생되어오는 레코드나 클래스들이 있을경우

  • 파라미터로 객체를 넘겨준뒤 이 함수가 이객체에 의존하는게 맞는지 , 그 이후로는 메서드의 위치 를 생각해줘야한다.

  • 매개변수로 username과 map 형식 homework 를 받는 레코드 객체가 있다하자

  • 저렇게 따로따로 받는게 아니라 아예 한꺼번에 그 데이터 를 다 가지고 있는 객체를 통쨰로 보낸다.

메서드 위치

  • 이 메서드의 기능을 수행하기위해서 필요한것들은 다 Participant라는 클래스 안에 다 있다. 다만 우리가 필요한건 totalNumberOfEvents

  • 그러면 totalNumberOfEvents 매개변수로 받으면 굳이 이건 여기에 위치하지 않아도 되지 않을까? 필요한건 저것뿐이니 저것만주면 동작을 정상적으로 하니까

  • 원래 studyBoard클래스에 있던 getRate()라는 함수를 매개변수에 객체를 보내는대신에 그 자료타입에 해당되는 클래스로 위치를 옮겨줬다.

  • 객체를 매개변수로 통쨰로 보내주지않고 필요한 매개변수만 가볍게 받도록 수정한 결과이다

= 필요한 요소가 적으면 굳이 객체를 통쨰로까지 받아오면서 그자리에 있을필요없다. 필요한 요소가 많은쪽으로 자리를 옮기며 나머지 요소를 매개변수로 받자

함수를 명령으로 바꾸기

  • 함수를 독립적인 객체인, Command 로 만들어 사용할 수 있다.(= 확장성 있는 함수를 따로 클래스로 분리하는 방법)

  • 커맨드 패턴 적용시 장점은 더 복잡한 기능을 구현하는데 필요한 여러 메서드, 로직을 추가 할수있다.

  • 커맨드 패턴의 단점으로는 그만큼 클래스가 늘어나 전체적으로 복잡해진다.

  • 대부분 경우 "함수"를 사용하지만 커맨드 말고 다른 방법이 없는 경우에 사용

  • 일단 미래에 확장성이 있을만한 메서드를 함수 추출하기로 따로 분리해준다.

  • command로 뽑기 -> 추출한 부분을 따로 클래스를 만들어 넣어준뒤 이 메서드에 필요한 연관된 메서드들도 같이 옮겨준다

  • 이렇게 만들어주면 이전보다 좀더 독립적인 command 가 생성된다.


  • 기존부분을 따로 뺴서 만들어준 클래스로 바꿔준다. 똑같이 동작하지만 분리를 함으로써 나중에 분리시킨 메서드에 좀더 복잡한 내용이나 확장 수정등이 더 쉬워진다.

  • 하지만 그만큼 클래스를 추가해야 함으로 전체적으로 복잡성은 올라간다.

조건문 분해하기(if-else)

  • 한눈에 보기에 내용파악이 힘들다

  • 함수 추출 기능을사용해 함수이름으로 그 의미를 표현해주자

  • 세세한 내용은 직접 코드들을 봐야하지만 대략적으로 어떻게 돌아가는지 파악이 가능해졌다.

  • 하지만 여기서 더간단하게 삼항 연산자로 만들어주면?

  • 이렇게 한줄로 표현가능.

  • if -else 문 = 삼항연산자 생각해보자

반복문 쪼개기(for)

  • 보통 반복문 하나에 여러 기능 넣는게 성능도 좋고 그러지만 될수있으면 나누자 왜냐하면 나중에 오류나 수정시 전자는 전체코드를 수정하기때문(코드가 다 반복문 안에 있으니)

  • 변경/수정 하기 쉬운 flexible한 코드가 좋은코드다. 그렇지 못한 코드는 개발비용과 효율성에 영향을 주기때문

  • 각각 기능을 나누면 그만큼 독립적이라 서로에게 영향을 주지않는다.

  • 이렇게 안쪽에서 작업을 한가지 더하는 반복문이 있다.


  • 일단 두가지 기능을 하나하나로 나눈다. 그뒤로 메서드 추출로 각각 추출해준다 ( 기능을 나눠준뒤에 각각 메서드추출)

  • 메서드의 매개변수를 줄이고싶다면(매개변수는 그 메서드가 필요로하는것들) 매개변수와 메서드를 같이 묶어서 메서드 추출. => 필요로 하는것을 아예 안으로 내장 시켜버리기

  • 공통으로 많이사용하면 클래스 필드로 올려버린다.

조건문을 다형성으로 바꾸기(switch-case)

  • switch-case 구문은 case에 따라 실행코드가 달라진다

  • 상속 부모-자식 관계 클래스들을 만들어준다.

  • 자바의 다형성 으로 인해 자식마다 각각 다르게 동작하는 메서드를 오버라이딩 한다.

부모클래스 일부

  • 우리가 원하는 것을 ( 하위클래스들중에) 골라 쓰면 됀다. 그 자식클래스에서 오버라이딩한 메서드가 실행됀다.
profile
호주쉐프에서 개발자까지..

0개의 댓글