반환 값과 반환 문 계산을 한 줄로 나누시겠습니까?


26

동료와 의견을 나누고 return두 줄로 반환 값을 계산 하는 진술 에 대해 토론했습니다 .

예를 들어

private string GetFormattedValue()
{
    var formattedString = format != null ? string.Format(format, value) : value.ToString();
    return formattedString;
}

대신에

private string GetFormattedValue()
{
    return format != null ? string.Format(format, value) : value.ToString();
}

코드 측면에서는 첫 번째 변형에서 실제로 가치를 보지 못합니다. 나를 위해, 후자는 특히 짧은 방법에 대해 더 명확합니다. 그의 주장은 이전의 변형이 디버그하기 쉽다는 것이 었습니다. VisualStudio는 중단 점으로 인해 실행이 중지 될 때 명령문을 매우 상세하게 검사 할 수 있기 때문에 아주 작은 장점입니다.

내 질문은, 코드를 덜 명확하게 작성하는 것이 여전히 유효하다면, 디버깅을 더 쉽게 만드는 것입니까? 분할 계산 및 명령문이 있는 변형에 대한 추가 인수 return 있습니까?


18
VS에서는 작동하지 않지만 복잡한 표현식에서 조건부 중단 점을 설정할 수 없다고 가정하거나 (입력하기가 복잡 할 수 있음) 편의상 편의를 위해 할당하고 별도의 명령문으로 되돌릴 수 있습니다. 컴파일러는 어쨌든 동일한 코드를 만들었을 것입니다.
tofro

1
이것은 아마도 언어에 따라 다를 수 있습니다. 특히 변수가 포인터 동작 대신 객체 동작을 갖는 언어에서 특히 그렇습니다. @Paul K의 설명은 포인터 동작이있는 언어, 객체에 단순한 값 동작이있는 언어 및 성숙하고 고품질 인 컴파일러가있는 언어에 해당됩니다.
MSalters

4
"VisualStudio를 사용하면 중단 점으로 인해 실행이 중지 될 때 명령문을 매우 상세하게 검사 할 수 있습니다." 함수가 둘 이상의 멤버가있는 구조체를 반환하면 어떻게 반환 값을 얻습니까? (그리고 그 기능에 대한 지원은 기껏해야 반점입니다. 반환 값을 전혀 얻지 못하는 조합이 많이 있습니다).
Voo

2
누군가가 오늘 사용하고있는 디버거에서 "문에 대한 매우 상세한 검사"를하는 방법은 어떤 디버거에서 쉽게 디버깅 할 수 있도록 코드를 작성하는 나쁜 옵션이됩니까?
Ian

16
전체 기능 몸체를 다음과 같이 줄여서 더욱 귀찮게합니다.private string GetFormattedValue() => string.Format(format ?? "{0}", value);
Graham

답변:


46

변수를 설명하는 것은 잘 알려진 리팩토링 으로 복잡한 표현을 더 읽기 쉽게 만드는 데 도움이 될 수 있습니다. 그러나 표시된 경우

  • 추가 변수는 주변 메소드 이름에서 명확하지 않은 것을 "설명"하지 않습니다
  • 문장이 더 길어 지므로 (약간) 읽기가 어렵다

또한 최신 버전의 Visual Studio 디버거는 불필요한 변수를 도입하지 않고도 대부분의 경우 함수의 반환 값을 표시 할 수 있습니다 (그러나주의해야합니다. 몇 가지주의 사항 있습니다.

따라서이 특정 경우, 나는 당신에게 동의하지만 설명 변수가 실제로 코드 품질을 향상시킬 수있는 다른 경우가 있습니다.


내가 거기 확실히 것을 너무 동의 있다 가, 의심의 여지 유용하는 경우.
Paul Kertscher

2
나는 보통 result변수의 이름 으로 사용 합니다. 훨씬 더 길고 쉬운 디버깅
edc65

26
@ edc65 : 일반적인 이름은 result 종종 코드에 노이즈를 추가하고 가독성을 거의 높이 지 않습니다. 정확히 내 대답의 요점입니다. 이것은 디버깅에 도움이되는 맥락에서 정당화 될 수 있지만 별도의 변수가 필요없는 디버거를 사용할 때는 피할 것입니다.
Doc Brown

6
@JonHanna 방법 도구 나에 따르면 오래. 이름 result은 이것이 함수의 결과 값이라는 정보를 전달하므로 함수가 리턴되기 전에이를 확인할 수 있습니다.
edc65

1
@ edc65하지만 유용하게 보입니다. 이제 코드를 읽을 때 즉시 코드를 인식하지 못합니다. 따라서 코드가 읽기 어려워졌습니다.
Jon Hanna

38

사실은 다음과 같습니다.

a) 컴파일러가 변수를 멀리 최적화하므로 최종 코드에는 영향을 미치지 않습니다.

b) 분리하면 디버깅 기능이 향상됩니다.

나는 개인적으로 시간의 99 %를 분리하는 것이 좋은 습관이라는 결론에 도달했습니다.

이 방법으로 수행하는 데 중요한 단점은 없습니다. 부풀어 오른 코드는 읽을 수 없거나 디버그하기 어려운 코드와 비교하여 사소한 문제이기 때문에 코드를 부풀린다는 주장은 잘못되었습니다. 또한이 방법만으로는 혼란스러운 코드를 만들 수 없으며 이는 전적으로 개발자에게 달려 있습니다.


9
이것은 정답입니다. 이를 통해 중단 점을 설정하고 디버깅 할 때 값을 쉽게 볼 수 있으며 내가 아는 단점이 없습니다.
Matthew James Briggs

점 b의 경우 Visual Studio Code에서 반환에 중단 점을 넣은 다음 GetFormattedValue () 식을 추가하면 중단 점에 도달했을 때 결과가 표시되므로 추가 줄이 필요하지 않습니다. 그러나 디버거에 추가 표현식을 추가 할 필요가 없으므로 추가 행이있는 로컬을 쉽게 볼 수 있습니다. 정말 개인적인 취향의 문제입니다.
Jon Raynor

3
리턴 값은 @JonRaynor이며, 함수의 닫는 괄호에 중단 점을 두십시오. 리턴 값이 여러 개인 함수에서도 리턴 값을 포착합니다.
Baldrickk

16

종종 일부 결과의 이름을 지정하기 위해 변수를 도입하면 코드를보다 자체 문서화 할 때 매우 유용합니다. 이 경우 변수 이름이 메소드 이름과 매우 유사하기 때문에 이는 요인이 아닙니다.

한 줄 방법에는 고유 한 값이 없습니다. 변경 사항이 더 많은 행을 도입하지만 코드를 더 명확하게 만들면 좋은 변경입니다.

그러나 일반적으로 이러한 결정은 개인 취향에 따라 크게 달라집니다. 예를 들어 조건부 연산자를 불필요하게 사용하고 있기 때문에 두 솔루션이 혼동됩니다. if 문을 선호했을 것입니다. 그러나 팀에서는 다른 협약에 동의했을 수도 있습니다. 그런 다음 컨벤션에서 제안하는대로하십시오. 이와 같은 경우에 규칙이 침묵하는 경우 장기적으로 중요하지 않은 매우 작은 변경 사항입니다. 이 패턴이 반복적으로 발생하면 팀이 이러한 사례를 처리하려는 방식으로 토론을 시작할 수 있습니다. 그러나 그것은“좋은 코드”와“아마도 조금 더 나은 코드”로 헤어를 나누고 있습니다.


1
"조건 연산자를 불필요하게 사용하고 있기 때문에 두 솔루션이 혼동되는 것을 발견했습니다." — 실제 사례는 아니며 단지 무언가를 빨리 만들어야했습니다. 분명히 이것은 최선의 예가 아닐 수도 있습니다.
Paul Kertscher

4
본질적으로 이것이 "레이더 아래"차이라고 말하면 +1입니다 (다른 것들은 같음).
TripeHound

3
@ Mindwin은 삼항 연산자를 사용할 때 일반적으로 여러 줄로 나누므로 실제 사례와 허위 사례를 명확하게 알 수 있습니다.
Arturo Torres Sánchez

2
@ ArturoTorresSánchez 나도 그렇게하지만, 대신의 ?:I를 사용 if() {하고 } else {- - - - - - - - \\ :)
Mindwin

3
@Mindwin, 그러나 나는 (개체 이니셜 라이저와 같은) 표현의 중간에있을 때 그렇게 할 수 없습니다
Arturo Torres Sánchez

2

질문에 대한 답변 :

내 질문은, 코드를 덜 명확하게 작성하는 것이 여전히 유효하다면, 단순히 디버깅을 더 쉽게 만드는 것입니까?

예. 사실, 당신의 이전 문장의 일부가 될 날 (악의)에 보이는 작은 근시안적 "(아래 굵은 참조) 이전 변종 디버깅 쉽다는 것을이었다 무엇이든지 그의 주장 - 아주 작은 장점입니다 으로 VisualStudio 때문에, 중단 점으로 인해 실행이 중지 될 때 명령문을 매우 상세하게 검사 할 수 있습니다. "

일부 추정에 따르면 프로그래머 시간의 50 %가 디버깅에 소비되기 때문에 (쉽게 디버깅 할 수 있음) "거의 장점 " 은 아닙니다 ( 가역 디버깅 소프트웨어 ).

split 계산 및 return 문이있는 변형에 대한 추가 인수가 있습니까?

예. 일부 개발자는 분할 계산을보다 쉽게 ​​읽을 수 있다고 주장합니다. 물론 이것은 디버깅에 도움이되지만 누군가 코드에서 수행하거나 적용 할 수있는 비즈니스 규칙을 해독하려는 경우에도 도움이됩니다.

참고 : 비즈니스 규칙은 자주 변경 될 수 있으므로 데이터베이스에서 더 잘 제공 될 수 있습니다. 그럼에도 불구하고이 분야의 명확한 코딩은 여전히 ​​가장 중요합니다. ( 비즈니스 규칙 엔진을 작성하는 방법 )


1

더 나아가겠다.

private string GetFormattedValue()
{
    if (format != null) {
        formattedString = string.Format(format, value);
    } else {
        formattedString = value.ToString()
    }
    return formattedString;
}

왜?

더 복잡한 논리에 삼항 연산자를 사용하면 읽을 수 없으므로 더 복잡한 명령문에는 위와 같은 스타일을 사용합니다. 이 스타일을 항상 사용하면 코드가 일관되고 사람이 파싱하기 쉽습니다. 또한 이러한 종류의 일관성을 도입하고 코드 보푸라기 및 기타 테스트를 사용하면 goto fail형식 오류를 피할 수 있습니다.

또 다른 장점은 테스트 적용을 잊어 버린 경우 코드 적용 범위 보고서가 format널이 아님 을 알려 줍니다. 삼항 연산자의 경우에는 그렇지 않습니다.


내가 선호하는 대안-당신이 "가능한 한 빨리 군중을 얻는다"고 방법에서 여러 번의 반품에 반대하지 않는 경우 :

private string GetFormattedValue()
{
    if (format != null) {
        return string.Format(format, value);
    }

    return value.ToString();
}

따라서 마지막 반품을보고 기본값이 무엇인지 확인할 수 있습니다.

일관성을 유지하는 것이 중요합니다. 모든 방법이 하나 이상의 규칙을 따르도록하십시오.


1
첫 번째 예제는 value.ToString()형식이 null이 아닌 경우 불필요하게 호출 되기 때문에 나쁜 습관으로 보입니다 . 일반적으로 사소한 계산이 포함될 수 있으며 형식 문자열을 포함하는 버전보다 시간이 오래 걸릴 수 있습니다. 예를 들어 valuePI를 소수점 이하 100 만 자리까지 저장하는 형식과 처음 몇 자리 만 요청하는 형식 문자열을 고려하십시오.
Steve

1
private string GetFormattedValue() => string.Format(format ?? "{0}", value); 동일 하지 않은지, 디버거에 의존하는 대신 단위 테스트를 사용하여 정확성을 확인하십시오.
Berin Loritsch

1
삼항 명확하지 않을 수도 있지만 null 종결자는 명확 하게 만들 수 있습니다 . 적어도이 경우에.
Berin Loritsch

1
친애하는 일기, 오늘 나는 잘 알려진 (약 40 년 동안 존재하는) 패러다임, 관용구 및 연산자를 사용하여 명확하고 간결한 코드를 작성하는 것이 인용, 큰 따옴표는 영리한 큰 따옴표이며 인용 부호가 아니라 지나치게 자세한 코드를 작성하는 것을 읽었습니다. 대신 할 수 가능성이없이 단지 사전 프로그래밍 배경으로 다섯 살짜리에 비밀 보이는 것을 피하기 위해 시도하는 동안 상기 운영자, 숙어 및 패러다임을 사용하여 건조되지는 -이다 선명도 대신. 지옥, 난 진짜 나이가 들었어야했는데, 내 사랑하는 일기 ... 나는 기회가 생겼을 때 바둑을 배웠어야 했어.
vaxquis

1
"더 복잡한 논리에 삼항 연산자를 사용하는 것은 읽을 수 없습니다."실제로는 (논리가 지나치게 복잡하다는 것을 알았지 만) 이것은 OP의 코드에는 해당되지 않으며 삼항 연산자에 대한 특정 사항도 아닙니다. 내가 자신있게 말할 수있는 유일한 것은 선이 너무 길다는 것입니다. gist.github.com/milleniumbug/cf9b62cac32a07899378feef6c06c776 는 내가 그것을 다시 포맷하는 방법입니다.
milleniumbug

1

나는 그러한 기술이 디버그의 필요성에 의해 정당화 될 수 있다고 생각하지 않습니다. 나는이 접근법을 수천 번 직접 경험했으며 때때로이 작업을 계속하고 있지만 Martin Fowler가 디버깅에 대해 말한 것을 항상 명심하십시오 .

또한 사람들은 디버깅에 소비하는 시간을 과소 평가합니다. 그들은 긴 버그를 추적하는 데 얼마나 많은 시간을 소비 할 수 있는지 과소 평가합니다. 테스트를 통해 버그를 추가하면 바로 알 수 있습니다. 크롤링하고 숨길 수 있기 전에 즉시 버그를 수정할 수 있습니다. 디버깅보다 좌절하거나 시간을 낭비하는 것은 거의 없습니다. 우리가 처음에 버그를 만들지 않았다면 훨씬 더 빨리 지옥이 아닐까요?


마틴 파울러는 똑똑한 사람이며 나는 그의 (그리고 당신의) 견해를 읽는 것을 즐겼습니다. 나는 테스트가 필요하고 그 노력에 더 많은 시간을 소비해야한다고 굳게 믿고 있지만, 우리 모두가 잘못된 인간이라는 사실은 모든 테스트가 모든 버그 를 근절하지는 않는다는 것을 시사합니다 . 따라서 디버깅은 항상 프로그램 개발 및 지원 프로세스의 일부입니다.
tale852150

1

삼항 연산자와 같은 문제에 대한 문제에 사람들이 걸려 있다고 생각합니다. 그렇습니다. 많은 사람들이 싫어하기 때문에 어쨌든 기르는 것이 좋습니다.

질문의 초점과 관련하여 반환 된 문을 변수로 참조하도록 옮기십시오 ...

이 질문은 내가 동의하지 않는 두 가지 가정을합니다.

  1. 두 번째 변형이 더 명확하거나 읽기 쉽습니다 (반대가 사실이라고 말합니다).

  2. 누구나 Visual Studio를 사용합니다. Visual Studio를 여러 번 사용했으며 잘 사용할 수 있지만 일반적으로 다른 것을 사용하고 있습니다. 특정 IDE를 강요하는 개발 환경은 회의적입니다.

명명 된 변수로 무언가를 나누는 것은 거의 읽기가 어렵지 않으며 거의 ​​항상 반대입니다. 자기 문서 감독이 분명히 나쁜 경우와 같이 누군가가 문제를 일으킬 수있는 구체적인 방식var thisVariableIsTheFormattedResultAndWillBeTheReturnValue = ... 은 별개의 문제입니다. var formattedText = ...괜찮습니다.

특정 경우, 그리고 아마도 1- 라이너에 대해 이야기하고 있기 때문에 많은 경우에 변수는 함수 이름이 이미 알려주지 않았다고 말하지 않습니다. 따라서 변수가 많이 추가되지 않습니다. 디버깅 인수는 여전히 유지 할 수 있지만이 특정 경우 디버깅 할 때 초점이 될만한 것을 보지 못하고 누군가가 디버깅을 위해 해당 형식이 필요한 경우 나중에 쉽게 쉽게 변경할 수 있습니다.

일반적으로 일반 규칙을 요청한 경우 (예 : 일반화 된 형식의 예) 변형 1 (2 라이너)을 선호하는 모든 사항이 정확합니다. 이것들은 좋은 지침입니다. 그러나 지침은 유연해야합니다. 예를 들어, 현재 작업중 인 프로젝트는 한 줄에 최대 80 자이므로 많은 줄을 나눕니다.하지만 일반적으로 81-85 자의 줄을 찾아서 가독성을 나누거나 줄이기가 어려울 수 있습니다. 한계.

가치를 추가 할 가능성이 없기 때문에 주어진 특정 예에 대해 2 줄을 사용하지 않을 것입니다. 이 경우 점이 다른 방법으로 할만 큼 강하지 않기 때문에 변형 2 (1 라이너)를 사용합니다.

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