리 팩터가 더 높은 LOC로 끝나는 것이 합리적입니까? [닫은]


25

더 논리적 인 코드보다 더 자세한 코드가 더 간결한 코드보다 더 깨끗한 경우가 있습니까?



18
물론 그렇습니다. 중복을 제거하더라도 새로운 추출 함수를 정의하는 코드는 자체 공간을 차지합니다. 새로운 함수를 작성하는 데는 네 줄이 필요하고 두 줄만 저장할 수 있지만 여전히 가치있는 일입니다.
Kilian Foth

5
"더 간결한 코드"? 줄 수가 적을수록 "더 나은"코드를 의미한다는 잘못된 생각이 싫습니다. 그렇지 않습니다. 실제로는 대개 반대입니다. 이 점은 온다 - 그리고 그것은 정말 빨리 도달 할 것 - 점점 더 적게 공간에 의미를 밀어 넣는 경우 코드를 만드는 어려워 이해하기. 실제로, 많은 수상자들이 타협 할 수없는 코드를 작성하기 위해 인간 이해의 한계에 의존 하는 전체 경쟁-국제 난독 화 C 코드 경연 대회가 있습니다.
Andrew Henle

1
질문 제목과 질문 자체가 다른 질문을합니다. 예를 들어 if 문은 논리적으로 동일하지만 단 한 줄의 삼항 식으로 변경할 수 있습니다.
Captain Man

1
-1 *** 더 많은 장황한 코드 (더 많은 논리 문에서와 같이) *** 자세한 내용과 논리 문의 수는 서로 관련이 없습니다. 정의를 바꾸는 것은 나쁜 형태입니다.
Pieter B

답변:


71

그에 대한 답을 찾기 위해 나에게 일어난 실제 사례를 살펴 보겠습니다. C #에서 유지 관리하는 라이브러리에는 다음 코드가 있습니다.

TResult IConsFuncMatcher<T, TResult>.Result() =>
    TryCons(_enumerator) is var simpleMatchData && !simpleMatchData.head.HasValue
        ? _emptyValue.supplied
            ? _emptyValue.value
            : throw new NoMatchException("No empty clause supplied");
        : _recursiveConsTests.Any() 
            ? CalculateRecursiveResult() 
            : CalculateSimpleResult(simpleMatchData);

이를 동료들과 논의하면서 만장일치의 평결은 중첩 된 삼항식이 "영리한"사용과 함께 is var간결하지만 읽기 어려운 코드라는 결과였다.

그래서 나는 그것을 다음과 같이 리팩토링했다.

TResult IConsFuncMatcher<T, TResult>.Result()
{
    var simpleMatchData = TryCons(_enumerator);

    if (!simpleMatchData.head.HasValue)
    {
        return _emptyValue.supplied
            ? _emptyValue.value
            : throw new NoMatchException("No empty clause supplied");
    }

    return _recursiveConsTests.Any() 
        ? CalculateRecursiveResult() 
        : CalculateSimpleResult(simpleMatchData);
}

원래 버전에는 암시 적으로 하나의 복합 표현식 만 포함되었습니다 return. 새 버전에는 이제 명시 적 변수 선언, if명령문 및 두 개의 explicit이 포함 returns됩니다. 더 많은 문장과 더 많은 코드 줄이 포함되어 있습니다. 그러나 내가 상담 한 모든 사람들은 "깨끗한 코드"의 핵심 측면 인 읽기 쉽고 추론하기가 쉽다고 생각했습니다.

따라서 귀하의 질문에 대한 답변은 강조되는 "예"이며 간결한 코드보다 더 자세한 정보가 더 명확 할 수 있으므로 유효한 리팩토링입니다.


34
요즘, 개발자의 두뇌는 디스크, CPU, RAM 또는 네트워크 대역폭보다 부족한 리소스입니다. 다른 것들도 중요하며 특정 응용 프로그램에서는 제한 요소가 될 수 있지만 대부분의 경우 개발자가 코드를 먼저 이해 한 다음 그 밖의 것을 이해하는 능력을 최적화하려고합니다 .
anaximander

2
@anaximander, 동의합니다. 다른 사람들이 먼저 읽고 두 번째로 읽을 수 있도록 코드를 작성하십시오. 그렇기 때문에 다른 사람이 내 코드를 개발하는 유일한 사람이라하더라도 다른 사람이 내 코드를 검토하도록하는 것이 유용한 이유입니다.
David Arno

4
그것을 검토하고 있다면, 반품 명세서의 순서를 반대로 바꾸고 !조건에서 제거하는 것이 좋습니다 . 또한 두 번째 수익을에 제안하는 것이 좋습니다 else. 그러나 그것이 서있는 것처럼, 그것은 큰 개선입니다.
Martin Bonner는 Monica

2
@DavidArno 나는 그 논리를 보았고, if (!foo.HasValue)코드의 관용구라면 훨씬 더 강력합니다. 그러나 이것은 실제로 출구 초기 if가 아닙니다 . "이것 또는 저것에 의존하십시오."
Martin Bonner는 Monica

2
@fabric 부울 값의 비교는 위험합니다. 나는 그것을 최대한 많이 피한다.
Martin Bonner는 Monica

30

1. LOC와 코드 품질 간의 상관 관계가 없습니다.

리팩토링의 목표는 코드의 품질을 향상시키는 것입니다.

LOC는 코드의 품질과 관련이있는 매우 기본적인 측정 항목입니다. 예를 들어, 수천 개의 LOC가있는 방법은 품질 문제가있을 수 있습니다. 그러나 LOC가 유일한 메트릭 이 아니며 많은 경우 품질과의 상관 관계가 부족합니다. 예를 들어, 4 LOC 방법이 6 LOC 방법보다 더 읽기 쉽고 유지 보수가 필요한 것은 아닙니다.

2. 일부 리팩토링 기술은 LOC 추가로 구성됩니다.

당신이 먹는 경우 리팩토링 기법의 목록을 쉽게 intentionnally으로 구성 사람 자리 수 있습니다 추가 LOCS을. 예 :

두 가지 모두 매우 유용한 리팩토링 기술이며 LOC에 미치는 영향은 사용 여부를 고려할 때 전혀 관련이 없습니다.

LOC를 사용하지 마십시오.

LOC는 위험한 측정 항목입니다. 측정하기가 매우 쉽고 올바르게 해석하기가 매우 어렵습니다.

코드 품질 측정 기술에 익숙해 질 때까지 먼저 LOC 측정을 피하십시오. 대부분의 경우 관련성이 없으며 코드의 품질이 저하되는 경우가 있습니다.


LOT (텍스트 라인)을 더 추가하여 답을 리팩토링하고 품질을 개선했습니다. : p
grinch

12

소스 코드의 바이트 수 또는 LoC 수를 최소화 한 최종 결과를 보려면 Stack Exchange Code Golf 사이트에 제출 한 내용을 살펴보십시오 .

이러한 방식으로 소스 코드가 줄어든다면 곧 유지 관리 할 수없는 혼란이 생길 ​​것입니다. 그러한 코드를 작성한 사람이 당시에 완전히 이해했다고해도 6 개월 후에 다시 돌아 오면 얼마나 효율적일까요? 이러한 최소 코드가 실제로 더 빨리 실행된다는 증거는 없습니다.

팀의 모든 구성원이 코드를보고 바로 수행하는 방식을 이해할 수 있도록 코드를 작성해야합니다.


어쩌면 중복 일 수도 있지만 철자하는 것이 좋습니다. 당신은 당신이 항상 더 많은 명 LoC와 끝까지 읽을 수 있도록 코드 golfed 리팩토링 경우
JollyJoker

1

그렇습니다. 리팩토링은 더 많은 코드 줄을 만들 수 있습니다.

가장 일반적인 경우 IMO는 일반적이지 않은 코드를 사용하여보다 일반적이고 유연하게 만드는 경우 입니다. 코드를 일반화하면 코드 줄이 크게 증가하기도합니다 (때로는 두 개 이상).

새로 일반 코드를 내부 소프트웨어 구성 요소 대신 다른 라이브러리에서 라이브러리로 사용하려면 일반적으로 단위 테스트 코드와 코드 내 문서 마크 업을 추가하여 코드 줄을 다시 늘립니다.

예를 들어 다음은 모든 소프트웨어 개발자에게 발생하는 매우 일반적인 시나리오입니다.

  • 귀하의 제품에는 긴급한 우선 순위가 높은 새로운 기능이나 버그 수정 또는 2 주간의 개선이 필요합니다 (또는 프로젝트 규모 / 회사 규모 등을 위해 긴급한 것으로 간주되는 기간)
  • 열심히 일하고 XYZ를 정시에 제공하면 효과가 있습니다. 축하합니다! 잘 했어!
  • XYZ를 개발하는 동안 기존 코드 디자인 / 구현은 실제로 XYZ를 지원하지 않았지만 XYZ를 코드베이스에 심을 수있었습니다.
  • 문제는 심이 추악하고 코드 냄새가 심하다는 것입니다. 왜냐하면 까다로운 / 영리한 / 못생긴 / 나쁜 연습-그러나 Kinda-works 일을했기 때문입니다.
  • 나중에 시간을 찾으면 많은 클래스를 변경하거나 새로운 클래스의 계층을 추가 할 수있는 코드를 리팩터링하고 새로운 솔루션은 "올바른"것이며 더 이상 나쁜 코드 냄새가 없습니다 ... "올바른 방법"은 이제 더 많은 코드 줄을 차지합니다.

내 머리 꼭대기에서 나에게 오는 몇 가지 구체적인 예 :

  • 커맨드 라인 인터페이스 의 경우 5000 줄의 if / else-if 코드가 있거나 콜백을 사용할 수 있습니다 ... 각 콜백은 훨씬 작고 읽기 / 테스트 / 확인 / 디버그 / 등을 쉽게 읽을 수 있지만 못생긴 5000 줄의 if / else-if 코드를 더 작게 코딩
  • N 처리 방법을 지원하는 코드 처리를 위해 가장 추악한 if / else 문을 다시 사용할 수 있습니다 ...
    • 또는 더 좋거나 더 나은 콜백으로 전환 할 수 있지만 콜백에는 더 많은 코드 줄이 필요합니다 (여전히 컴파일 시간이 걸립니다)
    • 또는 더 추상화하고 런타임에 변경할 수있는 플러그인을 수행 할 수 있습니다. 플러그인은 새 플러그인마다 기본 제품을 다시 컴파일하거나 기존 플러그인을 수정할 필요가 없기 때문에 좋습니다. 다른 사용자가 제품을 확장 할 수 있도록 API를 게시 할 수 있습니다. 그러나 플러그인 접근 방식은 더 많은 코드 줄을 사용합니다.
  • GUI의 경우 훌륭한 새 위젯을 만듭니다.
    • 귀하 또는 동료는 새 위젯이 XYZ 및 ABC에 적합하지만 지금은 위젯이 XYZ에서만 작동하도록 긴밀하게 통합되어 있다고 말합니다.
    • 위젯을 리팩터링하여 둘 다 작동하지만 이제 총 코드 줄이 증가합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.