리팩토링이란 무엇이며 코드 만 수정하는 것은 무엇입니까?


81

리팩토링은 "기능이 변경되지 않도록 프로그램의 구조를 변경하는 것"이라는 것을 알고 있습니다. 나는 대학에서 마지막 해 프로젝트에서 함께 일하고있는 몇몇 사람들과 이야기를 나누었고 그들이 리팩토링에 대해 훨씬 더 광범위한 (더 나은 단어를 원하기 위해)보기를 가지고 있다는 사실에 놀랐습니다 .

리팩토링을 메서드 추출 및 클래스 이름 바꾸기와 같은 것으로 간주합니다. 또한 (자바와 같은 데이터 구조를 변경하는 등의 작업을 제안 LinkedListArrayList,) (병합 일종의 대신 거품 정렬을 사용하여) 알고리즘을 변경, 심지어 리팩토링 같은 코드의 큰 덩어리를 재 작성.

나는 그들이 틀렸다고 확신했지만, 그들이 제안한 것이 프로그램의 행동을 바꾸지 않고 프로그램을 바꾸었기 때문에 (아마도 더 좋게 만들었 기 때문에) 이유를 설명 할 수 없었습니다. 내가 옳고 더 중요한 이유는 무엇입니까?

답변:


77

Martin Fowler의 "Refactoring : Improving the Design of Existing Code" 는 아마도 참고 자료 일 것입니다.

리팩토링은 기존 코드베이스의 디자인을 개선하기위한 제어 된 기술입니다. 그 본질은 일련의 작은 행동 보존 변환을 적용하는 것입니다. 각각은 "너무 작아서 할 가치가 없습니다". 그러나 이러한 각 변환의 누적 효과는 상당히 중요합니다. 작은 단계로 수행함으로써 오류 발생 위험을 줄일 수 있습니다. 또한 구조 조정을 수행하는 동안 시스템이 손상되는 것을 방지 할 수 있습니다. 따라서 장기간에 걸쳐 시스템을 점진적으로 리팩토링 할 수 있습니다.

리팩토링은 단위 테스트와 함께 진행됩니다. 리팩토링하기 전에 테스트를 작성하면 리팩토링에 대한 신뢰 수준 (테스트 범위에 비례)이 있습니다.

좋은 참조 : 리팩토링에 대한 정보


16
Fowler의 인용문은 물론 관련이 있습니다. 예, 단위 테스트와 함께 진행됩니다 ... 그러나 이것은 실제로 질문에 대한 답을 제공합니까? 누가 옳은가, OP 또는 그의 동료, 그리고 그 이유는 무엇입니까?
Jonik

36

Fowler는 동작에 영향을 미치는 코드 변경과 그렇지 않은 변경 사이에 명확한 선을 그립니다. 그는 그렇지 않은 것을 "리팩토링"이라고 부릅니다. 이것은 이다 우리가 리팩토링 및 코드 수정 활동을 비 리팩토링에 우리의 일을 나누면 때문에, 우리는 다른, 목표에 적합한 기술을 적용 할 수 있습니다 (파울러는 "다른 모자를 쓰고"이라고 부른다), 중요한 차이.

리팩토링 또는 동작 보존 코드 수정을 수행하는 경우 :

  • 모든 단위 테스트는 수정 전후에 통과해야합니다.
  • 테스트를 수정하거나 새 테스트를 작성할 필요가 없습니다.
  • 완료되면 더 깨끗한 코드를 기대합니다.
  • 우리는 새로운 행동을 기대하지 않습니다

행동을 바꾸는 코드를 수정한다면 :

  • 우리는 새로운 행동을 기대합니다
  • 우리는 새로운 테스트를 작성해야합니다
  • 완료되면 더 더러운 코드를 얻을 수 있습니다 (그런 다음 리팩토링해야합니다).

이 구별을 놓치면 주어진 코드 수정 작업에 대한 우리의 기대는 혼란스럽고 복잡합니다. 그것이 단어와 그 의미가 중요한 이유입니다.


3
+1, 정확히. 특히 당신이 제공하는 근거; 혼란스러운 기대. 내 자신의 대답을 쓸 때, 나는 :) 내가 깔끔하게로 적어 실패하더라도,이 점을 염두에 있었다
Jonik

18

내 견해를 제공하려면 :

코드를 발견 된 것보다 더 나은 상태로 만드는 작은 점진적 변경

확실히 예 : 기능과 직접 관련이없는 "외형"변경 (예 : 변경 요청으로 청구되지 않음).

확실히 아니오 : 큰 청크를 다시 쓰는 것은 "작고, 점진적인"부분을 분명히 위반합니다. 리팩토링은 종종 재 작성 의 반대로 사용됩니다. 다시하는 대신 기존을 개선하세요.

분명한 가능성 : 데이터 구조와 알고리즘을 대체하는 것은 다소 경계적인 경우입니다. IMO에서 결정적인 차이점은 작은 단계입니다. 전달 준비를하고 다른 케이스를 처리 할 준비를합니다.


예 : 벡터 사용으로 인해 속도가 느려지는 Report Randomizer 모듈이 있다고 가정 해보십시오. 벡터 삽입이 병목이라는 것을 프로파일 링했지만, 안타깝게도 모듈은 여러 위치에서 연속 메모리에 의존하므로 목록을 사용할 때 상황이 조용히 중단됩니다.

재 작성은 모듈을 처음부터 더 좋고 빠른 건물로 버리고 이전 건물에서 일부 조각을 선택하는 것을 의미합니다. 또는 새 코어를 작성한 다음 기존 대화 상자에 맞추십시오.

리팩토링은 포인터 산술을 제거하기 위해 작은 조치를 취하여 전환되도록하는 것을 의미합니다. 포인터 산술을 래핑하고 직접 포인터 조작을 해당 함수에 대한 호출로 대체하는 유틸리티 함수를 만든 다음 컴파일러가 포인터 산술이 여전히 사용되는 위치에 대해 불평하도록 반복자 전환 한 다음으로 전환 list한 다음 궁극 기능.


이면에있는 아이디어는 코드 자체가 악화된다는 것입니다. 버그를 수정하고 기능을 추가 할 때 작은 단계로 품질이 저하됩니다. 변수의 의미가 미묘하게 변경되고, 함수가 격리를 깨뜨리는 추가 매개 변수를 가져오고, 루프가 약간 복잡해집니다.이 중 어느 것도 실제 버그가 아닙니다. 루프를 복잡하게 만드는 줄 수를 알려주지 않지만 가독성과 유지 관리에 문제가 있습니다.

마찬가지로 변수 이름을 변경하거나 함수를 추출하는 것은 자체적으로 눈에 띄는 개선이 아닙니다. 그러나 모두 함께, 그들은 느린 침식에 맞서 싸 웁니다.

매일 사람이 땅에 떨어지는 자갈의 벽처럼. 그리고 매일 한 통행인이 그것을 집어 다시 넣습니다.


12

Martin Fowler의 정의를 염두에두고

리팩토링은 기존 코드 본문을 재구성하여 외부 동작을 변경하지 않고 내부 구조를 변경하는 훈련 된 기술입니다.

... 당신이 분명히 옳다고 생각합니다.

또한 데이터 구조 변경 (예 : Java LinkedList에서 ArrayList로), 알고리즘 변경 (버블 정렬 대신 병합 정렬 사용), 리팩토링으로 큰 코드 청크를 다시 작성하는 것과 같은 것을 제안했습니다.

알고리즘을 훨씬 빠른 것으로 변경하는 것은 외부 동작이 변경되기 때문에 리팩토링이 아닙니다! (그런 다음 효과가 눈에 띄지 않으면 결국 리팩토링이라고 부를 수 있으며 조기 최적화도 가능합니다. :-)

이것은 내 애완 동물입니다. 사람들이 용어를 엉성하게 사용하는 것은 성가신 일 입니다. 기본적으로 어떤 종류의 변경이나 수정을 위해 우연히 리팩토링 을 사용하는 사람들을 만났습니다 . 예, 그것은 유행하고 멋진 유행어와 모든 것이지만 변경 , 재 작성 또는 성능 향상 과 같은 평범한 오래된 용어에는 문제가 없습니다 . 적절한 경우이를 사용하고 소프트웨어의 내부 구조를 진정으로 개선하는 경우를 위해 리팩토링 을 예약 해야합니다. 특히 개발 팀 내에서 작업 을 정확하게 논의하기 위한 공통 언어를 갖는 것이 중요합니다.


3
나는 확실히 빠른 코드를 만드는 것은 외부 행동의 변화 ... 자격 것이 아니에요
GalacticCowboy

2
네, 당신의 요점은 당신이 그것을 보는 각도에 달려 있다고 생각합니다. :) 어쨌든, IMO는 프로그래밍 할 때 매 순간 어떤 "모자"를 입고 있는지, 즉 정확히 달성하려는 것이 무엇인지에주의를 기울여야합니다. 즉, 기능을 추가 / 수정할 때, 리팩토링 할 때, 최적화 (성능 향상) 할 때 의식적으로 분리해야합니다. IIRC, Fowler는 리팩토링에 대한 그의 결정적인 책에서도 이에 대해 이야기합니다.
Jonik

1
외부 변경 부분의 경우, 동작이 중요하다면 외부 동작을 변경하지 않고 [...]라고 말할 수 있습니다. 성능이 어느 쪽이든 (빠르거나 느리게) 중요한 경우 "리팩토링"단계의 일부로 성능에 영향을 줄 수있는 변경을 수행하지 마십시오.
Loki

11

코드 조각에 대한 인터페이스가 변경되면 리팩토링 이상의 것으로 생각합니다.

리팩토링의 일반적인 경우는 다음과 같습니다.

  • "오, 내 모든 단위 테스트가 실행되지만 내 코드를 더 깨끗하게 만들 수 있다고 생각합니다."
  • 코드를 더 읽기 쉽고 명확하고 효율적으로 변경
  • 단위 테스트를 다시 실행하고 (테스트를 변경하지 않고) 여전히 작동하는지 확인합니다.

즉, 리팩토링이라는 용어는 논의중인 인터페이스와 관련이 있습니다. 즉, 한 인터페이스 뒤에서 코드를 리팩토링하고 하위 수준에서 다른 코드를 더 광범위하게 변경할 수 있습니다 (이 차이점이 여기에서 동료와 혼동을 일으키는 원인이 될 수 있습니까?).


7

나는 당신이 옳다고 생각하지만, 단어의 의미를 놓고 논쟁하는 것은 특별히 흥미 롭거나 생산적이지 않습니다.


6
나는 보통 이것에 동의하지만, 우리가 작성한 문서를 검토 할 때 토론이 나왔고, 같은 단어를 사용할 때 같은 것에 대해 이야기 할 때 좋은 것 같아요.
David Johnstone

4

http://en.wikipedia.org/wiki/Code_refactoring

코드 리팩토링은 소프트웨어의 내부 비 기능적 속성 (예 : 코드 가독성 향상, 코드 구조 단순화, 코드 변경)을 개선하기 위해 외부 기능 동작이나 기존 기능을 수정하지 않고 컴퓨터 프로그램의 내부 구조를 변경하는 프로세스입니다. 주어진 프로그래밍 패러다임을 고수하고, 유지 보수성을 개선하고, 성능을 개선하거나, 확장 성을 개선합니다.

리팩토링 코드에는 기존 코드를 깨는 것이 포함된다는 데 동의합니다. 버그가 발생하지 않도록 유닛 테스트가 있는지 확인하면 나머지 코드가 컴파일됩니다. Resharper for C #과 같은 리팩토링 도구를 사용하면이 작업이 매우 쉬워집니다!

  • 코드를 더 이해하기 쉽게 만들기
  • 코드를 정리하고 더 깔끔하게 만들기
  • 코드 제거! 중복되고 사용되지 않는 코드 및 주석은 삭제해야합니다.
  • 성능 향상
  • 좀 더 일반적인 것을 만듭니다. 가능한 가장 간단한 것부터 시작한 다음, 테스트 / 분리 또는 일반화를 쉽게 만들어 다형성을 통해 다양한 방식으로 작동 할 수 있도록 리팩토링합니다.
  • 코드를 건조하게 유지-반복하지 마십시오. 따라서 리팩토링 세션에는 반복되는 코드를 가져와 단일 구성 요소 / 클래스 / 모듈로 리팩토링하는 작업이 포함될 수 있습니다.

3

나는 동의하지 :

소프트웨어 엔지니어링에서 "리팩토링"소스 코드는 전체 결과를 변경하지 않고 개선하는 것을 의미합니다. [...]

리팩토링의 하위 집합에 사용되는보다 정확한 용어를 이미 알고 있으며, 이는 매우 일반적인 용어입니다.


1

누구도 '리팩토링'이라는 용어에 대한 너무 강력한 정의의 혜택을받을 수 없다고 생각합니다. 당신이 그것을 인식하는 방법과 동료들 사이의 경계는 모호하며 많은 사실에 따라 그들의 또는 당신의 견해에 더 가까울 수 있습니다. 동적이므로 정의 해 봅시다. 먼저 리팩토링하려는 시스템 또는 하위 시스템의 경계를 정의하십시오.

메서드 인 경우 이름, 입력 인수, 반환 된 값의 유형 및 가능한 던지는 문을 고정합니다. 외부에서 보는 방식을 변경하지 않고 메서드 내부의 모든 변경 사항을 적용합니다.

클래스를 리팩터링하고 공용 API를 수정하고 변수 이름 바꾸기를 사용하는 경우 추출 메서드 및 기타 사용 가능한 모든 기술이 클래스를 더 읽기 쉽고 성능이 향상되도록 변경합니다.

리팩토링하는 코드의 일부가 패키지 또는 모듈 인 경우 클래스 이름 변경, 삭제, 인터페이스 도입, 코드를 수퍼 / 하위 클래스로 푸시 / 풀링 할 수있는 내부 리팩토링을 수행합니다.


0

리팩토링 = 기능적 요구 사항을 변경하지 않고 유지하면서 비 기능적 요구 사항을 개선합니다.

비 기능적 요구 사항 = 모듈성, 테스트 가능성, 유지 보수성, 가독성, 관심사 분리, liskov 원칙 등 ...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.