값으로 전달 된 매개 변수의 값을 수정하지 않는 이유가 있습니까?


9

함수 본문에서 값별 매개 변수의 값을 수정하거나 반대하는 객관적이고 지원 가능한 소프트웨어 엔지니어링 인수가 있습니까?

우리 팀에서 반복되는 스 패트 (주로 좋은 재미)는 값으로 전달 된 매개 변수를 수정 해야하는지 여부입니다. 팀 구성원 중 일부는 매개 변수를 절대로 지정해서는 안된다는 점을 잘 알고 있으므로 원래 함수에 전달 된 값을 항상 조사 할 수 있습니다. 나는 매개 변수가 메서드 호출 구문으로 초기화 된 로컬 변수에 불과하다는 것에 동의하지 않습니다. 값별 매개 변수의 원래 값이 중요한 경우이 값을 명시 적으로 저장하도록 로컬 변수를 선언 할 수 있습니다. 나는 우리 둘 다 우리의 입장을 매우 잘지지한다고 확신하지 못한다.

이것이 해결 불가능한 종교적 갈등인가, 어느 방향 으로든 객관적인 소프트웨어 엔지니어링 이유가 있는가?

참고 : 원칙의 문제는 특정 언어의 구현 세부 사항에 관계없이 남아 있습니다. 예를 들어, 인수 목록이 항상 동적 인 JavaScript에서 매개 변수는 arguments오브젝트 에서 로컬 변수 초기화를위한 구문 설탕으로 간주 될 수 있습니다 . 그럼에도 불구하고, 매개 변수 선언 식별자는 여전히 호출자로부터 수신자에게 정보의 전달을 캡처하기 때문에 "특별한"것으로 취급 할 수있다.


여전히 언어마다 다릅니다. "내가 가장 좋아하는 언어의 관점에서 그렇다"는 말은 잘못된 주장의 한 형태이기 때문에 언어에 구애받지 않는다고 주장한다. 언어마다 다른 두 번째 이유는 모든 언어에 대해 보편적 인 답변이없는 질문은 각 언어의 문화와 규범에 따라 달라지기 때문입니다. 이 경우 언어 별 규범이 다르면이 질문에 대한 답변이 달라집니다.
rwong

팀원들이 당신을 가르치려고하는 원칙은 "하나의 변수, 하나의 목적"입니다. 불행히도, 당신은 어느 쪽의 결정도 확실한 증거를 찾지 못할 것입니다. 가치있는 것을 위해, 나는 다른 목적을 위해 매개 변수를 선택한 것을 기억하지 않으며, 그것을 고려한 것을 기억하지 않습니다. 그것이 좋은 생각일지도 모른다는 생각이 들지 않았으며, 나는 여전히 그렇게 생각하지 않습니다.
Robert Harvey

나는 이것이 이전에 요청되었을 것이라고 생각했지만, 내가 찾을 수있는 유일한 속임수는 이 오래된 SO 질문 입니다.
Doc Brown

3
함수형 언어 디자이너가 "let"할당이 오류가 적은 것으로 간주하는 것처럼 언어가 인수 돌연변이를 금지하는 것은 오류가 적은 것으로 간주됩니다. 연구를 통해이 가정을 입증 한 사람은 아무도 없습니다.
Frank Hileman

답변:


15

매개 변수는 메소드 호출 구문으로 초기화 된 로컬 변수에 불과하다는 것에 동의하지 않습니다.

세 번째 위치를 채택합니다. 매개 변수는 로컬 변수와 같습니다. 기본적으로 둘 다 불변으로 처리해야합니다. 따라서 변수는 한 번 할당 된 다음 변경하지 않고 읽을 수만 있습니다. 루프의 경우 for each (x in ...), 변수는 각 반복의 컨텍스트 내에서 변경할 수 없습니다. 그 이유는 다음과 같습니다.

  1. 코드를 "제 머리에 실행"하기 쉽게 만들어줍니다.
  2. 변수에 대해 더 설명적인 이름을 허용합니다.

할당되고 변경되지 않는 많은 변수가있는 메소드에 직면하여 각 변수의 현재 값을 기억하려고하는 대신 코드를 읽는 데 집중할 수 있습니다.

동일한 방법으로, 이번에는 변수가 적지 만 값이 항상 변경되므로 이제 변수의 현재 상태를 기억하고 코드가 수행하는 작업을 수행해야합니다.

내 경험상, 전자는 나의 가난한 뇌에서 훨씬 더 쉽다. 나보다 다른 영리한 사람들은이 문제가 없을 수도 있지만 도움이됩니다.

다른 점은 다음과 같습니다.

double Foo(double r)
{
    r = r * r;
    r = Math.Pi * r;
    return r;
}

double Foo(int r)
{
    var rSquared = r * r;
    var area = Math.Pi * rSquared;
    return area;
} 

예를 들어, 제 생각에는 변수 이름으로 인해 두 번째 예에서 무슨 일이 벌어지고 있는지 훨씬 더 명확 r합니다. 첫 번째 예 보다 훨씬 더 많은 정보를 독자에게 전달 합니다.


"로컬 변수 .... 기본적으로 불변으로 취급되어야합니다." - 뭐?
whatsisname

1
for불변 변수로 루프 를 실행하는 것은 매우 어렵습니다 . 함수에서 변수를 캡슐화하는 것만으로는 충분하지 않습니까? 단순한 함수에서 변수를 따르는 데 문제가 있으면 함수가 너무 길 수 있습니다.
Robert Harvey

@RobertHarvey for (const auto thing : things)는 for 루프이며, 도입 한 변수는 (로컬로) 변경할 수 없습니다. for i, thing in enumerate(things):또한 현지인을 변경하지 않습니다
Caleth

3
이것은 일반적으로 IMHO의 아주 좋은 정신 모델입니다. 그러나 내가 추가하고 싶은 한 가지 : 종종 하나 이상의 단계에서 변수를 초기화하고 나중에 변경할 수없는 것으로 취급하는 것이 허용됩니다. 이것은 여기에 제시된 일반적인 전략에 위배되는 것이 아니라 항상 문자 그대로 따르는 것에 대한 반대입니다.
Doc Brown

3
와우,이 의견을 읽으면, 여기있는 많은 사람들이 기능적 패러다임을 연구 한 적이 없다는 것을 알 수 있습니다.
Joshua Jones

4

이것이 해결 불가능한 종교적 갈등인가, 어느 방향 으로든 객관적인 소프트웨어 엔지니어링 이유가 있는가?

그것은 내가 (잘 쓰여진) C ++에 대해 정말로 좋아하는 것 중 하나입니다. const string& x1상수 참조, string x2사본 및 const string x3상수 사본입니다. 내가 알고있는 함수에 무슨 일이 일어날 지. 그렇지 않은 경우 불변으로 만들 이유가 없으므로 변경 x2 됩니다 .

따라서 언어를 사용할 수 있는 경우 매개 변수로 수행 할 작업을 선언하십시오. 그것은 관련된 모든 사람들에게 최선의 선택이되어야합니다.

당신의 언어가 이것을 허용하지 않는다면,은 총알 해결책이 없을 것입니다. 둘 다 가능합니다. 유일한 지침은 최소한의 놀라움의 원칙입니다. 한 가지 접근 방식을 취해 코드베이스 전체에 적용하고 혼합하지 마십시오.


또 다른 좋은 일이 있다는 것입니다 int f(const T x)int f(T x)기능 바디 만 다릅니다.
중복 제거기

3
const int xx를 명확하게하는 것과 같은 매개 변수가있는 C ++ 함수 는 내부에서 변경되지 않습니다. 나에게 매우 이상한 스타일처럼 보인다.
Doc Brown

@DocBrown 나는 두 가지 스타일 중 어느 것도 판단하지 않고 매개 변수를 변경해서는 안된다고 생각하는 사람이 컴파일러가 그것을 보장 할 수 있고 매개 변수를 변경한다고 생각하는 사람도 그렇게 할 수 있다고 말하고 있습니다. 두 가지 의도는 언어 자체를 통해 명확하게 전달 될 수 있으며, 언어를 보장 할 수없는 언어와 임의의 지침에 의존해야하고 모든 사람이이를 읽고 준수하기를 원하는 언어에 비해 큰 이점입니다.
nvoigt

@nvoigt : 누군가가 ( "값별") 함수 매개 변수를 수정하는 것을 선호한다면, 그 const매개 변수 목록이 방해를 받으면 단순히 매개 변수 목록에서 제거합니다 . 그래서 나는 이것이 질문에 대답하지 않는다고 생각합니다.
Doc Brown

@DocBrown 그러면 더 이상 const가 아닙니다. 중요하지 않은지 여부는 중요하지 않습니다. 중요한 것은 언어 에 의심의 여지없이 개발자 에게 전달 하는 방법이 포함되어 있다는 것입니다 . 내 대답은 명확하게 의사 소통하는 한 중요하지 않습니다 .C ++로 쉽게 만들 수 있습니다. 다른 사람들은 그렇지 않을 수 있으며 규칙이 필요합니다.
nvoigt

1

그렇습니다. 이것은 하나님이 프로그램을 읽지 않는 것을 제외하고는 "종교적 갈등"입니다. 따라서 개인적 판단의 문제가되는 가독성 갈등으로 다운 그레이드됩니다. 그리고 나는 그것을 확실히하고 두 가지 방법으로 그것을 보았습니다. 예를 들어

무효 전파 (OBJECT * object, double t0, double dt) {
  이중 t = t0; / * 값을 변경하지 않도록 t0의 로컬 사본 * /
  while (무엇이든) {
    timestep_the_object (...);
    t + = dt; }
  반환; }

따라서 여기서는 인수 이름 t0 때문에 값을 변경하지 않기로 선택했을 것입니다. 그러나 대신 인수 이름을 tNow 또는 이와 유사한 것으로 변경했다고 가정하십시오 . 그런 다음 로컬 사본을 잊어 버렸을 것입니다 .tNow + = dt; 마지막 진술.

그러나 반대로 프로그램을 작성한 고객이 경험이 거의없는 일부 새로운 프로그래머를 고용하려고한다고 알고 있다고 가정 해 봅시다. 그런 다음 가치에 의한 기준 대 기준과 혼동하는 것에 대해 걱정할 것입니다. 그러나 그들의 마음은 모든 비즈니스 논리를 소화하려고 애 쓰고 100 % 바쁩니다. 그래서 이런 종류의 경우 나는 항상 읽을 수 있는지 여부에 관계없이 변경 될 인수의 로컬 사본을 선언합니다.

이런 종류의 질문에 대한 답은 경험과 함께 나타나며 정식 종교적 대답은 거의 없습니다. 단 하나 뿐인 답변이 있다고 생각하는 사람은 아마도 더 많은 경험이 필요합니다.

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