함수 내에서 내부 스코프 블록 사용이 잘못된 스타일입니까?


10

다음과 같은 위험이있는 경우가 있습니다.

  • 재사용하지 않는 변수 재사용 (예 1 참조)

  • 또는 다른 변수 대신 변수를 사용하여 의미 적으로 닫습니다 (예 2 참조).

예 1 :

var data = this.InitializeData();
if (this.IsConsistent(data, this.state))
{
    this.ETL.Process(data); // Alters original data in a way it couldn't be used any longer.
}

// ...

foreach (var flow in data.Flows)
{
    // This shouldn't happen: given that ETL possibly altered the contents of `data`, it is
    // not longer reliable to use `data.Flows`.
}

예 2 :

var userSettingsFile = SettingsFiles.LoadForUser();
var appSettingsFile = SettingsFiles.LoadForApp();

if (someCondition)
{
    userSettingsFile.Destroy();
}

userSettingsFile.ParseAndApply(); // There is a mistake here: `userSettingsFile` was maybe
                                  // destroyed. It's `appSettingsFile` which should have
                                  // been used instead.

범위를 도입하면이 위험을 완화 할 수 있습니다.

예 1 :

// There is no `foreach`, `if` or anything like this before `{`.

{
    var data = this.InitializeData();
    if (this.IsConsistent(data, this.state))
    {
        this.ETL.Process(data);
    }
}

// ...

// A few lines later, we can't use `data.Flows`, because it doesn't exist in this scope.

예 2 :

{
    var userSettingsFile = SettingsFiles.LoadForUser();

    if (someCondition)
    {
        userSettingsFile.Destroy();
    }
}

{
    var appSettingsFile = SettingsFiles.LoadForApp();

    // `userSettingsFile` is out of scope. There is no risk to use it instead of
    // `appSettingsFile`.
}

잘못 보입니까? 그런 구문을 피하겠습니까? 초보자가 이해하기 어렵습니까?


7
각각의 독립적 인 "스코프 블록"이 대신 고유 한 방법 또는 함수 여야한다고 주장 할 수 있습니까?
Dan Pichelman 2016

"보통"제대로 구현되지 않았지만 "디자인"문제는 아닙니다. 때로는 의도적으로 피할 수없는 경우도 있습니다 (예 : 예외 / 자원 범위 지정).
JustinC

답변:


35

함수가 너무 길어서 원하지 않는 부작용이나 변수의 불법 재사용을 더 이상 인식 할 수 없다면, 더 작은 함수로 분할하여 내부 범위를 무의미하게 만들어야합니다.

개인적인 경험으로 이것을 뒷받침하기 위해 : 몇 년 전 ~ 150K 줄의 코드로 C ++ 레거시 프로젝트를 상속했으며 정확히이 기술을 사용하는 몇 가지 방법이 포함되었습니다. 그리고 그 모든 방법이 너무 길다는 것을 추측하십시오. 우리가 그 코드의 대부분을 리팩토링 할 때, 메소드는 점점 작아지고 더 이상 남아있는 "내부 범위"메소드가 더 이상 없다고 확신합니다. 그들은 단순히 필요하지 않습니다.


4
그러나 왜 나쁜가요? 많은 명명 된 함수를 갖는 것도 혼란 스럽습니다.
Kris Van Bael

1
+1 정확히, 범위가 필요한 경우 함수로 추출 할 수 있는 특정 작업 을 수행하고 있을 수 있습니다. 크리스, 그것은 많은 함수를 생성하는 것이 아닙니다.이 경우가 발생했을 때 (한 블록의 범위가 다른 블록의 범위와 충돌 할 수있는 경우) 일반적으로 함수가 사용되어야합니다. 나는 이것을 다른 언어 (즉, 평범한 오래된 함수 대신 IIFE를 사용하는 JavaScript)에서도 항상 본다.
Benjamin Gruenbaum 2016 년

10
@KrisVanBael : "많은 명명 된 함수를 갖는 것도 혼란 스러워요"-설명적인 이름을 사용하는 경우에는 정반대입니다. 너무 큰 함수를 생성하는 것이 코드를 유지 관리하기 어려워지고 확장하기가 더 어려워지는 가장 큰 이유입니다.
Doc Brown

2
함수의 이름이 명확하게 문제가되는 기능이 너무 많으면 원래 함수 본문과 상당한 독립성을 가질 수 있으므로 일부 함수는 새로운 유형으로 롤업 될 수 있습니다. 일부는 너무 밀접하게 관련되어 제거 될 수 있습니다. 갑자기 그렇게 많은 기능이 없습니다.
JustinC

3
아직 확신하지 못했습니다. 종종 긴 기능은 실제로 좋지 않습니다. 그러나 스코프에 대한 모든 요구에 별도의 기능이 필요하다는 것은 나에게 너무 흑백입니다.
Kris Van Bael

3

초보자 (및 프로그래머)는 다음을 생각하기가 훨씬 쉽습니다.

  • 관련이없는 변수를 사용하지 않는 것

생각보다 :

  • 관련이없는 변수를 사용하지 못하게하는 코드 구조 추가

또한 독자의 관점에서 볼 때 이러한 블록은 명백한 역할이 없습니다. 블록을 제거해도 실행에 영향을 미치지 않습니다. 독자는 코더가 달성하고자하는 것을 추측하려고 머리를 긁을 수 있습니다.


2

범위를 사용하는 것은 기술적으로 옳습니다. 그러나 코드를 더 읽기 쉽게하려면 다른 방법으로 해당 부분을 추출하고 그 의미를 전체 이름으로 지정해야합니다. 이런 식으로 변수 범위를 지정하고 작업 이름을 지정할 수도 있습니다.


0

변수 재사용이 코드 냄새가 아닌 것보다 더 자주 동의합니다. 아마도 이러한 코드는 더 작고 독립적 인 블록으로 리팩토링되어야합니다.

C #에서 팝업되는 경향이있는 OTOH라는 특정 시나리오가 있습니다. 스위치 케이스 구문을 사용할 때입니다. 상황은 다음과 같이 매우 잘 설명되어 있습니다. 중괄호가 있거나없는 C # 스위치 문… 차이점은 무엇입니까?

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