Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[Refactoring] 3-2. 코드에서 나는 악취 (중복 코드, 긴 함수, 긴 매개변수, 전역 데이터, 가변 데이터, switch 문, 반복문, default value) 본문

Refactoring (리펙토링)

[Refactoring] 3-2. 코드에서 나는 악취 (중복 코드, 긴 함수, 긴 매개변수, 전역 데이터, 가변 데이터, switch 문, 반복문, default value)

jake-kim 2023. 1. 15. 11:34

중복 코드

  • 똑같은 코드 구조가 여러곳에서 반복되는 주는 단점
    • 코드가 중복되면 각각을 볼 때마다 서로 차이점은 없는지 주의 깊게 살펴야하는 부담이 존재
  • 한 클래스에 딸린 두 개의 메소드가 똑같은 표현식 사용? -> 함수 추출하기를 사용 (6절에서 계속)
  • 코드가 비슷한데 완전히 같지 않다면? -> 문장 슬라이드 (8절에서 계속)

긴 함수

  • 오랜 기간 잘 활용되는 프로그램들은 짧은 함수로 구성
  • 짧은 함수로 작성한다는 의미?
    • 코드는 끝없이 위임하는 방식으로 작성되기 때문에 코드를 이해하고, 공유하고, 선택하기 쉬우려면 함수의 이름이 짧은 구성이 많을때 재 역할을 수행
    • 예전 언어는 서브루틴을 호출하는 비용이 컸기 때문에 함수 호출을 없애는 방향이었지만 지금은 별 차이가 없으므로 함수를 적극 이용
    • 장황한 네이밍보다는 짧은 함수인 네이밍을 사용할 것
  • 함수를 어떻게 사용하는지?
    • 훨씬 적극적으로 함수를 쪼개기
    • 주석을 달아야 할 만한 부분은 무조건 함수로 만들 것
    • 함수 이름은 동작 방식이 아닌 의도가 나타나게, 무엇을 하는지 네이밍할 것

긴 매개변수 목록

  • 암적 존재인 전역 데이터가 늘어나는 것을 방지하기 위해 함수에 필요한 것들은 전역변수를 사용하지 않고 모조리 매개변수로 넘기는게 정석이지만, 긴 매개변수를 지양할 것
  • 매개변수 목록이 길어지게 되면 그 자체로 이해하기 어려운 함수가 될 수 있기 때문
  • 매개변수가 길어지게 되면 객체를 따로 정의하여 넘길 것

전역 데이터

  • 전역 데이터는 코드베이스 어디에서든 건드릴 수 있고 값을 누가 바꿨는지 찾아낼 메커니즘이 없는 문제가 존재
  • 버그가 존재할 때 그 원인이 되는 코드를 찾기가 힘듦
  • 대표적인 전역 데이터는 singleton 패턴
  • 이런 것을 방지하기 위해 대표적인 리팩토링은 변수 캡슐화하기(6장) - 전역 데이터를 함수로 감싸서 데이터를 수정하는 부분을 쉽게 찾을 수 있고 접근을 통제하는 방법
  • 전역 데이터를 클래스나 모듈에 집어넣고 그 안에서만 사용할 수 있도록 접근 범위를 최소로 정하는 해결 방법도 존재

가변 데이터

  • 가변 데이터의 문제: 데이터를 변경 > 예상치 못한 결과나 버그가 존재
    • 코드의 다른 곳에서는 다른 값을 기대한다는 사실을 인식하지 못한 채 수정해버리면 프로그램이 오작동되며 원인 파악이 힘듦
  • swift에서 collection 타입이 value type인 이유도 이런 가변 데이터를 최소화하기 위함
    • 함수형 프로그래밍의 불변성 특징 - 데이터를 변경하려면 반드시 원래 데이터는 그대로 둔 채 변경하려는 값에 해당 복사본을 만들어서 반환한다는 개념을 사용

switch 문

  • 중복된 switch문이 생기게 될 때, case가 하나 추가될 때마다 다른 switch문들도 모두 찾아서 함께 수정해야하는 번거로움이 존재

반복문

  • for문 내부가 길어지게 되면 한눈에 코드를 파악하기 어려운 장황한 코드가 발생
  • for문 대신 map, filter와 같은 함수형 프로그래밍 파이프 연산을 사용하여 코드에서 각 원소들이 어떻게 처리되는지 쉽게 파악할 수 있도록 구현

default value

  • 매개변수에 default value를 설정할 수 있지만, 인스턴스를 가져올 때는 주어진 초기화 프로퍼티만 보고 코딩을 할 것이므로 이런 오측을 방지하기 위하여 default value 지양

메시지 체인

  • 다른 객체를 요청하는 작업이 연쇄적으로 이어지는 코드
    • 클라이언트(모듈을 사용하는 쪽 코드) 가 한 객체를 통해 다른 객체를 얻은 뒤 방금 얻은 객체에 또 다른 객체를 요청하는 방식
    • 함수 A에서 getSomething() 호출하며, getSomething()함수에서 또 다시 다른 getElement() 호출하는 형태
    • 클라이언트가 객체 네비게이션 구조에 종속됐음을 의미 (= 네비게이션 중간 단계를 수정하면  클라이언트 코드도 수정이 되는 안좋은 코드)

주석

  • 적당한 주석은 코드를 이해하기 매우 좋아져서 좋은점이 있지만 장황한 주석은 지양
    • 주석을 남겨야 한다면 -> 그부분 함수로 뺄것(주석 대신의 역할)
    • 시스템 동작하기 위한 선행조건? -> assert() 사용

코드 악취 판단법?

  • 장황한 코드 -> 고민하기
  • 클라이언트 코드 입장에서 한 번에 이해하기 어려운 코드인지? -> 사용하는 클라이언트 코드 입장에서 이해하기 쉬운 구조로 짜기
  • 주석을 많이 남겨야하는 코드인것 같은지? -> 함수로 빼기

* 참고

- Refactoring (Marting Flowler)

 

Comments