긴 방법은 항상 나쁜가요? [닫은]


64

그래서 이전에 둘러 보았을 때 긴 방법이 나쁜 습관이라는 의견을 발견했습니다.

나는 긴 방법이 나쁘다는 것을 항상 동의하지 않습니다 (그리고 다른 사람들의 의견을 원합니다).

예를 들어 객체를 뷰로 보내기 전에 약간의 처리를 수행하는 장고 뷰가 있습니다. 긴 메서드는 350 줄의 코드입니다. 매개 변수를 처리하도록 쿼리를 정렬 / 필터링 한 다음 비트 단위로 쿼리가 반환 한 객체에 대해 약간의 처리를 수행하도록 코드를 작성했습니다.

따라서 처리는 주로 조건부 집계이므로 데이터베이스에서 쉽게 수행 할 수없는 복잡한 규칙이 있으므로 주 루프 외부에서 선언 된 변수가 루프 중에 변경됩니다.

variable_1 = 0
variable_2 = 0
for object in queryset :
     if object.condition_condition_a and variable_2 > 0 :
     variable 1+= 1
     .....
     ...    
     . 
      more conditions to alter the variables

return queryset, and context 

따라서 이론에 따르면 모든 코드를 더 작은 방법으로 분리해야하므로 뷰 방법을 최대 한 페이지 길이로 유지할 수 있습니다.

그러나 과거에 다양한 코드베이스에서 작업 한 결과, 때로는 가장 바깥 쪽의 메서드를 유지하면서 한 방법에서 다음 방법으로 끊임없이 뛰어 넘어야 할 때 코드를 읽기 어렵게 만듭니다.

형식이 긴 긴 메소드를 사용하면 내부 메소드에 숨겨져 있지 않기 때문에 논리를 더 쉽게 볼 수 있습니다.

코드를 더 작은 메소드로 분해 할 수는 있지만 종종 두세 가지에 사용되는 내부 루프가 있으므로 더 복잡한 코드 또는 한 가지가 아닌 두 가지 또는 세 가지 (또는 각 작업마다 내부 루프를 반복 할 수는 있지만 성능이 저하 될 수 있습니다).

긴 방법이 항상 나쁘지는 않은 경우가 있습니까? 한 곳에서만 사용되는 방법을 쓰는 경우가 항상 있습니까?

업데이트 : 1 년 전에이 질문을 한 것 같습니다.

그래서 (혼합) 응답 후 코드를 리팩터링하여 메소드로 나눕니다. 데이터베이스에서 복잡한 관련 개체 집합을 검색하는 Django 앱이므로 테스트 인수가 나오지 않습니다 (테스트 사례에 대한 관련 개체를 만드는 데 거의 1 년이 걸렸을 것입니다. "이것은 어제 완료되었습니다"유형이 있습니다. 누군가가 불평하기 전에 작업 환경). 코드의 해당 부분에서 버그를 수정하는 것이 이제는 쉽지만 크게는 아닙니다.

전에 :

#comment 1 
bit of (uncomplicated) code 1a  
bit of code 2a

#comment 2 
bit of code 2a
bit of code 2b
bit of code 2c

#comment 3
bit of code 3

지금:

method_call_1
method_call_2
method_call_3

def method_1 
    bit of (uncomplicated) code 1a  
    bit of code 2a

def method_2 
    bit of code 2a
    bit of code 2b
    bit of code 2c

def method_3
    bit of code 3

156
모든 절대 값은 나쁘다. 항상.
Joachim Sauer

30
(이 식물 또는 유사한 형태) 자주 인수를 "당신이 그 (것)들을 재사용 할 수있는 경우 추출 방법"나는를 볼 수 있지만, 나는 그것을 사지 않는다 :이 방법은 하나 이상의 일을하고 있다면, 당신이 해야 읽기 쉽도록 그것에서 방법을 추출 / 이러한 새로운 메소드가 코드의 한 지점에서만 호출 되더라도 유지 보수성 이 향상 됩니다.
Joachim Sauer

4
@ gnat : 와우, 빌드 단계에서 어떤 종류의 수동 인라인 (예 : 전처리기를 통해)이 더 나은 해결책이 아니겠습니까?
Joachim Sauer

11
내가 아는 최고의 프로그래머 중 하나는 실제로 측정을 원한다면 지역 변수의 수가 실제 길이보다 낫습니다. 그는 용기가 수백 줄 길이의 한 방법 인 복잡한 경로 최적화 프로그램을 개발하고 있었지만 유지되는 상태 (지역 변수)의 양은 매우 적었습니다.
Chuu

2
긴 방법이 항상 나쁜 것은 아닙니다. 그러나 그들은 당신이 항상보고 스스로에게 "이것이 나쁜가요?"
Carson63000

답변:


80

아니요, 긴 방법이 항상 나쁜 것은 아닙니다.

Code Complete 책 에서 긴 방법이 더 빠르고 작성하기 쉬우 며 유지 관리 문제를 일으키지 않는 것으로 측정됩니다.

실제로, 가장 중요한 것은 DRY를 유지하고 우려의 분리를 존중하는 것입니다. 때로는 계산 시간이 길지만 실제로 문제가되지는 않습니다.

그러나 개인적 경험으로 볼 때, 대부분의 긴 방법은 관심의 분리가 부족한 경향이 있습니다. 실제로, 긴 메소드는 코드에서 무언가 잘못되었음을 감지하는 쉬운 방법이며 코드 검토를 수행 할 때 특별한주의가 필요합니다.

편집 : 의견이 작성되면 답변에 흥미로운 점이 추가됩니다. 실제로 함수의 복잡성 메트릭 (NPATH, 순환 복잡성 또는 더 나은 CRAP)도 확인합니다.

실제로 긴 함수에서는 이러한 메트릭을 확인하지 말고 모든 기능에서 자동 도구 (예 : Java의 checkstyle 등)로 경고를 포함하는 것이 좋습니다.


41
+1 : "아니오, 긴 방법은 항상 나쁘지는 않지만" 거의 항상 나쁩니다.
Binary Worrier

67
긴 방법의 몸은 고전이다 코드 냄새 그 자체에 문제가 아니지만, 거기에 있다는 표시입니다 : 아마 이 문제.
Joachim Sauer

6
+1이지만 여전히 긴 방법 의 순환 복잡성 을 확인하는 것이 좋습니다 . 값이 높으면 단위 테스트가 불가능한 방법을 나타냅니다 (길이 방법에는 제어 흐름 논리가 거의 없음).
Daniel B

11
의견을 최소화하기 위해 메소드 이름을 사용합니다. 때로는 "getSelectedNodeWithChildren"과 같은 것들로 이어지지 만 동료가 계속 코드를 읽을 수 있다고 말합니다. 나는 또한 약어를 피하려고 노력하지만, 쓰기는 좋지만 읽기는 쉽지 않습니다.
K ..

4
@ da_b0uncer 그것은 또한 내가 따르는 정책입니다. 코드를 작성하는 것보다 코드를 읽는 것이 어렵 기 때문에 코드를 더 읽기 쉽게 만들려면 더 많은 노력을 기울여야합니다.
deadalnix

55

여기에 초점의 대부분은 항상 단어 주위에있는 것 같습니다 . 그렇습니다. 절대가 나쁘고 소프트웨어 공학은 과학만큼이나 예술적입니다. 그러나 모든 것이 ...하지만 여러분이 제시 한 예에서는 그 방법이 나뉘면 더 좋을 것입니다. 쪽으로. 다음은 일반적으로 메소드 분할을 정당화하기 위해 사용하는 인수입니다.

가독성 : 다른 사람들에 대해서는 잘 모르겠지만 350 줄의 코드를 빨리 읽을 수는 없습니다. 그렇습니다. 내 자신의 코드이고 그것에 대해 많은 가정을 할 수 있다면 매우 빨리 훑어 볼 수는 있지만 요점은 아닙니다. 다른 방법에 대한 10 번의 호출 (각각 설명이 포함 된 이름)로 구성된 경우 해당 방법을 쉽게 읽을 수있는 방법을 고려하십시오. 이를 위해 코드에 레이어링을 도입했으며 고급 방법은 진행 상황에 대해 독자에게 짧고 달콤한 개요를 제공합니다.

편집-다른 시각으로 생각하면 다음과 같이 생각하십시오. 새로운 팀원에게이 방법을 어떻게 설명 하시겠습니까? 확실히 그것은 당신이 "음, 그것은 A, B, 그리고 때로는 C 등을하는 것으로 시작합니다"라는 선을 따라 요약 할 수있는 어떤 구조를 가지고 있습니다. 다른 메소드를 호출하는 짧은 "개요"메소드가 있으면이 구조가 분명해집니다. 350 줄의 코드를 찾아서 도움이되지 않는 것은 매우 드 rare니다. 인간의 두뇌는 100 개의 항목을 다루는 것이 아닙니다.

재사용 성 : 긴 방법은 응집력이 낮은 경향이 있습니다. 종종 하나 이상의 작업을 수행합니다. 낮은 응집력은 재사용의 적입니다. 여러 작업을 하나의 방법으로 결합하면 이전보다 적은 수의 장소에서 재사용 될 수 있습니다.

테스트 가능성과 응집력 : 위의 의견에서 순환 복잡성 을 언급 했습니다. 방법이 얼마나 복잡한 지에 대한 꽤 좋은 척도입니다. 입력에 따라 코드를 통한 고유 경로 수의 하한을 나타냅니다 (편집 : MichaelT의 설명에 따라 수정 됨). 또한 분석법을 적절하게 테스트하려면 사이클로 메틱 복잡도 수보다 많은 테스트 사례가 있어야합니다. 불행히도, 실제로 서로 의존하지 않는 코드 조각을 모을 때, 이러한 종속성 부족을 확신 할 수있는 방법이 없으며 복잡성이 함께 증가하는 경향이 있습니다. 이 측정 값을 수행하려는 여러 가지 수의 표시로 생각할 수 있습니다. 너무 높으면 나눠서 정복해야 할 때입니다.

리팩토링 및 구조 : 긴 메소드는 종종 코드에서 일부 구조가 부족하다는 신호입니다. 종종 개발자는 해당 방법의 여러 부분 사이에 공통점이 무엇인지, 그리고 그 사이에 선이 그려지는 위치를 파악할 수 없었습니다. 긴 방법이 문제라는 것을 인식하고 더 작은 방법으로 나누는 것은 실제로 전체에 대해 더 나은 구조를 식별하기위한 더 긴 길의 첫 단계입니다. 아마도 하나 또는 두 개의 클래스를 작성해야합니다. 결국 더 복잡해질 필요는 없습니다!

또한이 경우 긴 방법을 사용하는 변명은 "... 주 루프 외부에서 선언 된 일부 변수는 루프 중에 변경됩니다"라고 생각합니다. 나는 파이썬 전문가는 아니지만이 문제가 참조로 전달되는 형태로 사소하게 수정 될 수 있다고 확신합니다.


13
항상 질문의 일부를 불신하고 육류에 초점을 둔 +1 : 긴 방법이 나쁜지 아닌지. OP는 자신의 시나리오가 최우선 사례 인 것처럼 정당성을 찾고 있다고 생각하지만 일반적으로 사람들이 일반적이지 않은 시나리오에 필요한 나쁜 관행을 설명한다고 들었을 때 좋은 사례를 사용하기 위해 열심히 노력하지 않았기 때문입니다. 흔하지 않은 시나리오는 매우 드물지만 긴 방법은 슬프게도 매우 일반적입니다.
Jimmy Hoffa

2
위의 목록을 보면 알 수 있습니다. 메서드에서 코드로 이동하지 않고 메서드를 더 길게 작성하고 주석을 많이 포함하고 형식을 지정함으로써 과거 경험에서 말한 가독성이 향상됩니다. 코드의 일부가 재사용 될 것으로 기대하지 않습니다. 코드 재사용은 대부분 상속을 통해 이루어집니다.
wobbily_col

1
@wobbily_col BTW, 더 짧은 방법을 사용한다는 이론적 근거를 통해 잘 작성된 텍스트를 찾고 있다면 Clean Code 의 처음 몇 장을 읽으십시오 . 이는 설명을 잘 수행합니다.
Daniel B

5
@wobbily_col 당신은 많은 방법으로 코드를 이해하기 위해 너무 많이 뛰어 다니는 것이 혼란 스럽다고 말하는데, 여기서 누락 된 점은 명명의 중요성에 있다고 생각합니다. 방법이 아니라 이름이있는 경우, 당신이 그것을 호출하는 방법은이 일을 부르는 방법의 기본 지식없이 완전하게 이해할 수 있어야 무엇을하고 있는지 알아 그것을보고 할 필요가 없습니다, 예를 들어 당신은 이제까지 사용한 someVar.toString()및 느낌 toString의 코드를보고 그것이 무엇을하고 있는지 알아야합니까? 좋은 메소드 이름으로 인해 바로 읽었습니다.
Jimmy Hoffa

4
참고로, n 개의 매개 변수가 필요한 메소드를 갖는 것은 코드 냄새이며 메소드가 둘 이상의 작업을 수행 할 수 있음을 나타냅니다. 명명하기 어려운 방법을 사용하는 것도 마찬가지입니다. 그리고 모든 매개 변수가 실제로 필요한 경우 일반적으로 더 큰 개념의 일부이며 자체 클래스로 묶을 수 있어야합니다. 물론, 우리는이 규칙을 사용하지 않는 것이 더 나은 예를 생각해 낼 수 있습니다. 제 요점은 그러한 방법을 보면 그것을 통해 조사하면 어떤 방식 으로든 나쁘다는 것입니다.
KL

28

긴 방법은 항상 좋지 않지만 때로는 다른 방법보다 낫습니다.


5
설명이 없으면 다른 사람이 반대 의견을 게시 할 경우이 답변이 쓸모 없게 될 수 있습니다. 예를 들어 누군가가 "긴 방법은 결코 나쁘지 않지만 때로는 대안보다 나쁘다"고 주장하는 경우. ,이 답변이 독자가 두 가지 반대 의견을 선택하는 데 어떻게 도움이됩니까? 더 나은 형태로 편집 하는 것을 고려하십시오
gnat

9

긴 방법은 코드 냄새 입니다. 일반적으로 문제가 있음을 나타내지 만 어렵지 않은 규칙은 아닙니다. 일반적으로, 정당화되는 경우에는 많은 주와 상당히 복잡한 비즈니스 규칙이 있습니다 (발견 한 바와 같이).

다른 질문에 관해서는 한 번만 호출하더라도 논리 청크를 별도의 메소드로 분리하는 것이 도움이됩니다. 높은 수준의 논리를 쉽게 볼 수 있으며 예외 처리를 좀 더 깔끔하게 만들 수 있습니다. 처리 상태를 나타 내기 위해 20 개의 매개 변수를 전달할 필요가없는 한!


7

긴 방법이 항상 나쁘지는 않습니다. 일반적으로 문제가있을 수 있다는 신호입니다.

내가 작업하고있는 시스템에는 10,000 줄 이상의 길이가있는 십여 가지 방법이 있습니다. 하나는 현재 54,830 줄입니다. 그리고 괜찮습니다.

이 엄청나게 긴 함수는 매우 간단하고 자동 생성됩니다. 이 54,830 줄 길이의 몬스터에는 1962 년 1 월 1 일부터 2012 년 1 월 10 일 (마지막 릴리스)까지의 일극 운동 데이터가 포함되어 있습니다. 또한 사용자가 자동 ​​생성 된 파일을 업데이트 할 수있는 절차도 릴리스합니다. 이 소스 파일에는 http://data.iers.org/products/214/14443/orig/eopc04_08_IAU2000.62-now 의 극좌표 모션 데이터가 포함되어 있으며 C ++로 자동 변환됩니다.

보안 설치에서는 해당 웹 사이트를 즉석에서 읽을 수 없습니다. 외부 세계와는 관련이 없습니다. 웹 사이트를 로컬 복사본으로 다운로드하고 C ++로 파싱하는 것도 옵션이 아닙니다. 구문 분석이 느리며 이는 빨라야합니다. 다운로드, C ++로 자동 번역 및 컴파일 : 이제 빠른 것이 있습니다. (최적화 컴파일하지 마십시오. 최적화 컴파일러가 5 만 라인의 매우 간단한 직선 코드를 컴파일하는 데 걸리는 시간이 놀랍습니다. 컴퓨터에서 파일 하나를 최적화하는 데 30 분 이상 걸리며 최적화는 전혀 아무 것도 달성하지 못합니다. 최적화 할 것은 없으며 간단한 직선 코드이며, 하나의 할당 문이 뒤 따릅니다.)


6
"다른 하나의 할당 문"... "데이터 파일"이라고 부릅니다. 왜 코드입니까?
Joachim Sauer

3
@JoachimSauer-Monte Carlo 설정에서 런타임에 큰 데이터 파일을 구문 분석하는 것은 좋지 않습니다. 아주 나쁜 생각입니다.
David Hammen

4
@DavidHammen : 그런 다음 링커 / 로더를 강요하는 것처럼 초기화 시간에 수행하십시오. 또는 데이터 파일을 C 코드 대신 헤더 파일에 C 구조로 작성하십시오. 최소한 로더는 데이터 블록으로로드됩니다.
Javier

3
@Javier : 초기화 할 때라도 최소한 Monte Carlo 설정에서는 매우 나쁜 생각 일 수 있습니다. 초기화하는 데 몇 분이 걸리지 만 실행하는 데 몇 초 밖에 걸리지 않는 시뮬레이션은 하룻밤 동안 수만 번의 실행을 거칠 수 있습니다. 주요 초기화 시간 작업을 컴파일하여 시간 작업을 컴파일하면 해당 문제가 해결됩니다. 우리는 컴파일 된 데이터 구조 접근법을 포함하여 여러 가지 기술을 시도했습니다. 작동하지 않거나 경우에 따라 작업하기가 매우 어려울 수 있습니다 (예 : 거대한 중력 모델). 직선 코드 접근 방식은 자동 생성 및 검증이 쉽습니다. 그것은 못생긴 코드입니다.
David Hammen

7
재미있는 이야기 +1. 생성 된 코드는 물론 소스 코드가 아니므로 규칙을 '파괴'하지 않는다고 주장 할 수 있습니다. 하나는 그 자체가 좋은 짧은 방법을 가지고 코드 생성기 가정
JK합니다.

7

긴 방법을 깨는 좋은 방법과 나쁜 방법이 있다고 가정 해 봅시다. "머리에 가장 바깥쪽에있는 방법을 유지"한다는 것은 가장 최적의 방법으로 분석하지 않거나 하위 방법의 이름이 잘못되었다는 표시입니다. 이론적으로 긴 방법이 더 좋은 경우가 있습니다. 실제로는 매우 드 rare니다. 더 짧은 메소드를 읽을 수있게 만드는 방법을 알 수 없다면 누군가에게 코드를 검토하도록하고 메소드 단축에 대한 아이디어를 구체적으로 요청하십시오.

예상 성능 저하를 유발하는 다중 루프의 경우 측정 없이는이를 알 수있는 방법이 없습니다. 여러 개의 작은 루프는 필요한 모든 것이 캐시에 머무를 수 있음을 의미하는 경우 훨씬 빠릅니다. 성능 저하가 있더라도 일반적으로 가독성을 높이기 위해 무시할 만합니다.

긴 메서드는 읽기가 어렵지만 쓰기 가 더 쉽다고 말할 것입니다 . 그래서 아무도 좋아하지 않아도 확산됩니다. 체크인하기 전에 처음부터 리팩터링하는 계획에는 아무런 문제가 없습니다.


1
"체크인하기 전에 처음부터 리팩토링을 계획하는 데 아무런 문제가 없습니다." +1입니다. 오늘날 대부분의 IDE에는 리팩토링 도구가있어이를 매우 쉽게 할 수 있습니다. 그러나 존재하지 않는 함수에 물건을 위임하고 나중에 메서드를 작성하고 채우는 역 방법이 있지만 시도한만큼 그렇게 코딩 할 수 없었습니다.
Tjaart

"머리에 가장 바깥쪽에있는 방법을 유지해야한다"는 +1은 가장 최적의 방법으로 해체하지 않는다는 표시입니다.
Michael Shaw

4

긴 메서드는 계산 및 공간 효율적일 수 있으며 논리를보다 쉽게보고 디버깅하기가 더 쉽습니다. 그러나이 규칙은 한 명의 프로그래머 만 해당 코드를 만질 때만 실제로 적용됩니다. 코드가 원자 적이 지 않으면 확장하기가 어려울 것입니다. 본질적으로 다음 사람은 처음부터 시작해야하며 디버깅 및 테스트는 알려진 좋은 코드를 사용하지 않으므로 영원히 걸릴 것입니다.


34
최소한 두 명의 프로그래머가 있습니다 : "당신"과 "지금부터 3 주 후".
Joachim Sauer

3

우리가 기능 분해 라고 부르는 것은 가능하면 더 긴 방법을 더 작은 방법으로 나누는 것을 의미합니다. 분석법에 정렬 / 필터링이 포함되어 있다고 언급했듯이 이러한 작업에 대해 별도의 분석법 또는 기능이 더 좋습니다.

정확하게, 당신의 방법은 perforimng 1 작업에만 집중해야합니다.

그리고 어떤 이유로 다른 메소드를 호출 해야하는 경우 이미 작성중인 방법으로 수행하십시오. 또한 가독성을 위해 주석을 추가 할 수 있습니다. 일반적으로 프로그래머는 메소드 설명에 여러 줄 주석 (C, C ++, C # 및 Java에서 / ** /)을 사용하고 한 줄 주석 (C, C ++, C # 및 Java에서 //)을 사용합니다. 더 나은 코드 가독성 (예 : JavaDoc )을 위한 유용한 문서 도구도 있습니다 . .Net 개발자 인 경우 XML 기반 주석을 조사 할 수도 있습니다 .

루프는 프로그램 성능에 영향을 미치며 올바르게 사용하지 않으면 응용 프로그램 오버 헤드가 발생할 수 있습니다. 아이디어는 가능한 한 중첩 루프를 사용하도록 알고리즘을 설계하는 것입니다.


"함수는 한 번만 수행해야합니다."라고도합니다.
lorddev

3

긴 함수를 작성해도 괜찮습니다. 그러나 실제로 필요한지 여부에 따라 상황에 따라 다릅니다. 예를 들어, 최고의 알고리즘 중 일부는 조각 일 때 가장 잘 표현됩니다. 반면에 객체 지향 프로그램에서 많은 루틴이 접근 자 루틴이 될 것입니다. 테이블 구동 방식을 통해 조건을 최적화 할 수있는 경우 긴 스위치 케이스가있는 긴 처리 루틴 중 일부 o.

Code Complete 2에는 루틴의 길이에 대한 훌륭한 짧은 토론이 있습니다.

이론적으로 최상의 497 최대 길이는 종종 66 ~ 132 줄의 1 ~ 2 페이지의 프로그램 목록으로 설명됩니다. 현대 프로그램은 몇 개의 더 긴 루틴과 혼합 된 매우 짧은 루틴의 볼륨을 갖는 경향이 있습니다.

수십 년의 증거에 따르면 그러한 길이의 루틴은 짧은 루틴보다 더 오류가 발생하지 않습니다. 중첩 깊이, 변수 수 및 기타 복잡성 관련 고려 사항과 같은 문제로 길이를 지정하는 대신 루틴 길이를 535로 지정할 수 있습니다.

약 200 줄보다 긴 루틴을 작성하려면주의하십시오. 비용 절감, 오류율 감소 또는 200 줄보다 큰 크기로 구별되는 더 큰 루틴을 사용한 연구는 없으며 200 줄의 코드를 통과 할 때 이해의 상한에 도달해야합니다. 536 제한 그 자체.


2

거의 항상 틀렸다는 또 다른 투표. 그러나 정답 인 두 가지 기본 사례를 찾습니다.

1) 기본적으로 다른 많은 메소드를 호출하고 실제 작동하지 않는 메소드. 달성하기 위해 50 단계를 거치는 프로세스가 있고 50 개의 호출이있는 메소드를 얻습니다. 그것을 해체하려고 시도하면 일반적으로 얻을 것이 없습니다.

2) 발송자. OOP 디자인은 대부분의 이러한 방법을 제거했지만 들어오는 데이터 소스는 본질적으로 데이터이므로 OOP 원칙을 따를 수 없습니다. 데이터를 처리하는 코드에 일종의 디스패처 루틴이있는 것은 드문 일이 아닙니다.

또한 자동 생성 된 물건을 다룰 때 질문을 고려해서는 안된다고 말하고 싶습니다. 자동 생성 된 코드의 기능을 이해하려는 사람은 아무도 없습니다. 사람이 이해하기 쉬운 지 여부는 중요하지 않습니다.


1
50 단계 프로세스는 여러 버킷으로 요약 될 수 있습니다. 1-9 단계는 매개 변수 확인이므로 매개 변수 확인이라는 새 메소드를 작성하십시오. (이것이 불가능한 몇 가지 예가 있다고 확신합니다. 하나를 보는 데 관심이 있습니다).
sixtyfootersdude

@sixtyfootersdude : 물론입니다. 나는 그것이 불가능하다고 말하지 않았으며, 그것을 깨뜨려 서 얻는 것이 없다고 말했다. 50 단계가 아니었지만 게임 세계 만들기와 같은 것이 었습니다. # 1은 빈 세계를, # 2는 지형을 만든 다음 그 후 여러 단계를 거쳐 여러 방식으로 마사지했습니다.
Loren Pechtel

& sixtyfootersdude : 한번도 보지 못한 코드를 알고 개선하는 방법이 놀랍습니다.
gnasher729

2

나는 당신이 주신 예를 다루고 싶었습니다.

예를 들어 객체를 뷰로 보내기 전에 약간의 처리를 수행하는 장고 뷰가 있습니다. 긴 메서드는 350 줄의 코드입니다. 매개 변수를 처리 할 수 ​​있도록 코드를 작성했습니다. 쿼리 세트 정렬 / 필터링 후 비트 단위로 쿼리가 반환 한 객체를 약간 처리합니다.

우리 회사의 가장 큰 프로젝트는 Django를 기반으로 구축되었으며 긴 뷰 기능도 있습니다 (많은 350 줄 이상). 나는 우리가 그렇게 오래 될 필요는 없으며 그들이 우리를 해칠 것이라고 주장합니다.

이러한 뷰 함수는 모델, 도우미 클래스 또는 도우미 함수로 추출해야하는 느슨하게 관련된 많은 작업을 수행합니다. 또한 여러 가지 일을하기 위해 뷰를 재사용하게되는데,이를보다 일관된 뷰로 나누어야합니다.

나는 당신의 견해가 비슷한 특징을 가지고 있다고 생각합니다. 제 경우에는 문제가 발생한다는 것을 알고 변경을 위해 노력하고 있습니다. 문제가 발생한다는 데 동의하지 않으면 문제를 해결할 필요가 없습니다.


2

누군가 이미 이것을 언급했는지 모르겠지만 긴 방법이 나쁜 이유 중 하나는 일반적으로 여러 수준의 추상화가 포함되기 때문입니다. 루프 변수와 모든 종류의 일이 발생합니다. 가상의 기능을 고려하십시오.

function nextSlide() {
  var content = getNextSlideContent();
  hideCurrentSlide();
  var newSlide = createSlide(content);
  setNextSlide(newSlide);
  showNextSlide();
}

해당 기능에서 모든 애니메이션, 계산, 데이터 액세스 등을 수행했다면 혼란 스러웠을 것입니다. nextSlide () 함수는 일관된 추상화 계층 (슬라이드 상태 시스템)을 유지하고 다른 계층은 무시합니다. 이것은 코드를 읽을 수있게합니다.

그들이하는 일을보기 위해 더 작은 방법을 계속 사용해야한다면, 기능을 나누는 운동은 실패한 것입니다. 읽고있는 코드가 자식 메서드에서 명백한 일을하지 않는다고해서 자식 메서드가 잘못되었다는 것을 의미하지는 않습니다.

내가 방법을 만들 때 나는 보통 일종의 나누기 및 정복 전략으로 작은 방법으로 나눕니다. 같은 방법

   if (hasMoreRecords()) { ... }

확실히 더 읽기 쉽다

if (file.isOpen() && i < recordLimit && currentRecord != null) { ... } 

권리?

나는 절대 진술이 나쁘다는 것에 동의하고 또한 일반적으로 긴 방법이 나쁘다는 것에 동의합니다.


1

실화. 나는 한 번 이천 라인 이상의 방법을 만났다. 이 방법에는 해당 지역에서 수행 한 작업을 설명하는 지역이 있습니다. 지역을 읽은 후 지역 이름에 따라 자동 추출 방법을 사용하기로 결정했습니다. 내가 완료했을 때, 그 방법은 각각 약 50 줄의 40 개의 메소드 호출에 불과했으며 모두 동일하게 작동했습니다.

너무 큰 것은 주관적입니다. 때로는 현재 방법보다 더 이상 분석법을 분석 할 수없는 경우가 있습니다. 책을 쓰는 것과 같습니다. 대부분의 사람들은 긴 단락은 보통 분할되어야한다는 데 동의합니다. 그러나 때로는 하나의 아이디어가 있고 나누는 것이 그 단락의 길이에 의해 야기되는 것보다 더 많은 혼란을 야기합니다.


0

방법의 요점은 코드 역류를 줄이는 데 도움이됩니다. 메소드에는 담당하는 특정 기능이 있어야합니다. 여러 곳에서 코드를 다시 해싱하면 소프트웨어 사양을 변경하도록 설계된 사양에서 코드가 예기치 않은 결과가 발생할 위험이 있습니다.

350 줄을 갖는 방법은 수행하는 많은 작업이 특수한 작업을 수행하기 위해 많은 양의 코드가 필요하지 않은 다른 곳에서 복제되는 것을 제안합니다.


코드를 줄이는 데 도움이되는 것은 무엇 입니까?
Avner Shahar-Kashtan

@ AvnerShahar-Kashtan, 그는 아마도 "중복"을 의미 할 것입니다 :-)
Péter Török

0

실제로 나쁜 습관을 가진 긴 방법은 아닙니다.

샘플을 리팩토링하는 실제 행위는 다음과 같습니다.

varaible_1 = 0
variable_2 = 0
for object in queryset :
     if object.condition_condition_a and variable_2 > 0 :
     variable 1+= 1
     .....
     ...    
     . 
      more conditions to alter the variables

return queryset, and context 

Status status = new Status();
status.variable1 = 0;
status.variable2 = 0;
for object in queryset :
     if object.condition_condition_a and status.variable2 > 0 :
     status.variable1 += 1
     .....
     ...    
     . 
      more conditions to alter the variables (status)

return queryset, and context 

그리고

class Status {
    variable1 = 0;
    variable2 = 0;

    void update(object) {
        if object.condition_condition_a and variable2 > 0 {
            variable1 += 1
        }
    }
};

Status status = new Status();
for object in queryset :
     status.update(object);
     .....
     ...    
     . 
      more conditions to alter the variables (status)

return queryset, and context 

당신은 이제 훨씬 더 짧은 방법뿐만 아니라 훨씬 더 유용하고 이해하기 쉬운 방법으로 가고 있습니다.


0

나는 방법이 매우 길다는 사실을 확인해야하지만 즉시 반 패턴은 아닙니다. 거대한 방법에서 찾아야 할 가장 큰 것은 많은 중첩입니다. 당신이 가지고 있다면

foreach(var x in y)
{
    //do ALL the things
    //....
}

루프 본문이 극도로 현지화되지 않았으므로 (즉, 4 개 미만의 매개 변수를 보낼 수 있음) 다음과 같이 변환하는 것이 좋습니다.

foreach(var x in y)
{
    DoAllTheThings(x);
}
...
void DoAllTheThings(object x)
{
    //do ALL the things
    //....
}

결과적으로 함수 길이를 크게 줄일 수 있습니다. 또한 함수에서 중복 코드를 찾아서 별도의 함수로 이동하십시오.

마지막으로 일부 방법은 길고 복잡하며 수행 할 수있는 작업이 없습니다. 일부 문제는 쉽게 코딩 할 수없는 솔루션이 필요합니다. 예를 들어, 매우 복잡한 문법을 ​​파싱하면 실제로 길지 않은 방법을 만들 수 있습니다.


0

진실은, 그것은 달려 있습니다. 언급했듯이 코드가 우려를 분리하지 않고 한 방법으로 모든 것을 시도하면 문제가됩니다. 코드를 여러 모듈로 분리하면 코드를 쉽게 읽을 수있을뿐만 아니라 여러 프로그래머가 코드를 작성할 수 있습니다. 소스 파일 당 하나의 모듈 (클래스)을 고수하는 것이 좋습니다.

둘째, 기능 / 프로 시저와 관련하여 :

void setDataValueAndCheckForRange(Data *data) {/*code*/} 

"데이터"의 범위 만 확인하는 경우 좋은 방법입니다. 동일한 범위가 여러 기능에 적용되는 경우 BAD 방법입니다 (잘못된 코드의 예).

void setDataValueAndCheckForRange(Data *data){ /*code */}
void addDataValuesAndCheckForRange(Data *result, Data *d1, Data *d2){ /*code*/}
void subDataValuesAndCheckForRange(Data *result, Data *d1, Data *d2){ /*code*/}
void mulDataValuesAndCheckForRange(Data *result, Data *d1, Data *d2){ /*code*/}

이것은 다음과 같이 리팩토링되어야합니다.

bool isWithinRange(Data *d){ /*code*/ }
void setDataValue(Data *d) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 
void addDataValue(Data *d, Data *d1, Data *d2) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 
void subDataValue(Data *d, Data *d1, Data *d2) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 
void mulDataValue(Data *d, Data *d1, Data *d2) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 

코드를 가능한 많이 재사용하십시오. 그리고 그것은 당신의 프로그램의 각 기능이 단순 할 필요가있을 때 가능합니다.

견적 : 마운틴은 작은 알갱이로 구성되어 있습니다. 바다는 작은 방울의 물로 구성되어 있습니다 .. (-Sivananda)


0

긴 방법은 문장, 부작용 및 변경 가능성을 선호하는 명령형 언어에서 "나쁜"경향이 있습니다. 이러한 기능은 복잡성과 버그가 증가하기 때문입니다.

표현, 순도 및 불변성을 선호하는 함수형 프로그래밍 언어에서는 걱정할 이유가 적습니다.

기능적 및 명령형 언어에서 재사용 가능한 코드 덩어리를 공통 최상위 루틴으로 분해하는 것이 가장 좋지만 중첩 함수 등으로 어휘 범위를 지원하는 기능적 언어에서는 실제로 하위 루틴을 상위에서 숨기는 것이 더 나은 캡슐화입니다 다른 최상위 함수로 분리하는 것보다


그러나 기능적 언어에서는 긴 방법이 훨씬 덜 일반적입니다.
itsbruce
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.