함수에서 파라미터를 주문하는 가장 좋은 방법은 무엇입니까?


52

때때로 (드물게), 적절한 양의 매개 변수를 취하는 함수를 만드는 것이 가장 좋은 경로 인 것 같습니다. 그러나 내가 할 때 종종 매개 변수의 순서를 임의로 선택하는 것처럼 느낍니다. 나는 가장 중요한 매개 변수를 먼저 사용하여 "중요도 순서"로 이동합니다.

더 좋은 방법이 있습니까? 선명도를 높이는 매개 변수를 정렬하는 "모범 사례"방법이 있습니까?


5
명명 된 매개 변수로 인해 문제가 줄어 듭니다. 파이썬은 그것을 극단적으로 가져갑니다. 좋은 예는 C #에 MessageBox.Show있습니다. 이것도 살펴보십시오.
Job

8
Haskell에서 부분 함수 적용의 유용성은 일반적으로 자연스러운 인수 순서를 제안합니다.
tdammers

적절한 양의 매개 변수를 어떻게 생각하십니까?
Chris

나는 2를 생각하고 있었다. 비록 순서는 두 매개 변수에 모두 동일하게 적용된다고 생각한다.
케이시 패튼

3
@tdammers 이것은 카레를 직접 지원하는 모든 언어에 해당합니다
jk.

답변:


55

일반적으로 사용하십시오 .

실제 테스트 인 함수 테스트를 작성하십시오.
뭔가 당신이 실제로 원하는 그 기능을 수행합니다 .

그리고 어떤 순서로 그것들을 내려 놓았는지보십시오.

비슷한 기능을하는 기능을 이미 가지고 있거나 알고 있지 않는 한.
이 경우 : 적어도 첫 번째 주장에 대해서는 이미 수행 한 내용을 준수 하십시오.

예를 들어 모두 문서 / 객체 / 파일 포인터 / 값 시리즈 / 좌표 를 첫 번째 인수로 사용합니까? 신을 위해서 그러한 주장에 따르십시오 .

동료미래의 자기 자신을 혼동 하지 마십시오 .


12
"혼란을 피하십시오 ... 미래의 자아"는 일반적으로 좋은 철학처럼 들립니다.
Jeanne Pindar 3

28

나는 항상 같은 우선 순위를 갖지는 않지만 일반적으로 이러한 규칙을 따릅니다. 나는 그것이 자동 사고 과정 이라고 생각하고 공개 API 디자인을 제외하고는 그것을 너무 많이 생각하지 않습니다 .

선택 유입 경로

  1. 의미론
  2. 중요성 / 관련성
  3. 사용 빈도
  4. I / O 문제

1. 시맨틱 스 우선

특히 OOP 에서 작업 또는 메시지 에 대한 의미 상 의미에 따라 매개 변수를 선택 하십시오. 잘 명명 된 매개 변수를 가진 잘 명명 된 메소드의 서명은 다음과 같아야합니다.

  • 자연스럽게 전화를 걸고
  • 의도와 행동 측면에서 자기 설명 적이어야합니다.

(이러한 이유로, 원시 형식 대신 사용자 정의 유형 또는 별명을 사용하면 서명의 표현성이 향상 될 수 있습니다.)

2. 그런 다음 중요성

가장 "중요한"매개 변수가 먼저 나온다 (또는 다음으로 ...)

3. 그런 다음 주파수

특히 명명 된 매개 변수는 없지만 위치 매개 변수의 기본값을 가질 수있는 언어에서 빈도도 중요합니다. 즉, 매개 변수의 순서가 다양하지 않으며 N 번째 매개 변수의 기본값을 강제로 적용하려는 경우 분명히 N + 1 매개 변수를 설정할 수 없습니다 (언어에 자리 표시 자 매개 변수 개념이있는 경우 제외) ).

좋은 소식은 일반적으로 빈도가 중요도와 관련되어 있으므로 이전 시점과 밀접한 관련이 있다는 것입니다. 그리고 적절한 의미를 갖도록 API를 작성하는 것은 아마도 당신에게 달려 있습니다.

4. I / O를 잊지 말자

메소드 / 함수가 일부 입력을 가져 와서 출력을 생성하고 후자가 "반환"(반환 문을 통해) 또는 "thrown"(예외 시스템 사용)하지 않는 경우 통과 옵션이 남습니다. 다른 매개 변수 (또는 입력 매개 변수)를 사용하여 호출자에게 값을 다시 보냅니다. 이는 시맨틱과 관련이 있으며 대부분의 경우 첫 번째 매개 변수가 출력을 정의하고 마지막 매개 변수가 출력을 수신하는 것이 좋습니다.

또한 매개 변수를 줄이고 의미를 최대화하는 다른 방법은 기능적인 방법을 사용하거나 빌더 패턴 을 정의하는 것이므로 입력을 명확하게 쌓고 출력을 정의하고 필요할 때 검색 할 수 있습니다.

(글로벌 변수를 언급하지 않는 이유는 무엇입니까? 왜 사용합니까?)


고려해야 할 사항

  • 사용성

    ZJR의 조언 을 따르면 위의 대부분이 자연스럽게 표시됩니다 . 사용하십시오!

  • 리팩토링 고려

    매개 변수 순서가 걱정된다면 위의 문제와 API가 잘못 설계되었다는 사실 에서이 문제가 발생할 수 있습니다. 매개 변수가 너무 많으면 구성 요소 화 / 모듈화 및 리팩토링 될 수 있습니다 .

  • 성능 고려

    일부 언어의 구현은 매개 변수를 사용할 때 런타임 메모리 관리에 매우 중요한 영향을 미칩니다. 따라서 많은 언어의 스타일 북이 매개 변수 목록을 간단하고 짧게 유지하는 것이 좋습니다 이유 입니다. 예를 들어 최대 4 개의 매개 변수에서 나는 당신이 이유를 알아내는 연습으로 남겨 둡니다.

  • Clean Code 의 권장 사항에 대한 Bevan의 답변 과 언급 은 확실히 관련이 있습니다!


18

나는 매개 변수 순서에 대한 걱정이 잘못된 것에 대해 걱정한다는 것을 정중하게 제출합니다.

밥 아저씨의 " 깨끗한 코드 "( Clean Code)에서 그는이 방법이 두 개 이상의 주장을 가져서는 안된다는 주장을 설득력있게 주장한다. 이 경우 주문은 명백하거나 중요하지 않습니다.

그러나 불완전하게, 나는 Uncle Bob의 조언을 따르려고 노력하고 있습니다-그리고 그것은 코드를 향상시키고 있습니다.

드문 경우지만 메소드에 더 많은 정보 가 필요한 것 같으면 매개 변수 객체를 도입 하는 것이 좋습니다. 일반적으로 이것이 알고리즘의 핵심 인 새로운 개념 (객체)을 발견하는 첫 번째 단계라는 것을 알았습니다.


나는 당신에게 확실히 동의합니다! 첫 번째 진술은 이것이 나에게 전형적인 것이 아니라는 점을 목표로했습니다. 그러나 실제로 매개 변수를 전달해야하고 전체 프로그램을 리팩터링하는 것이 가치가 없다면 주문에 대해 궁금합니다.
케이시 패튼

3
기침 PHP 기침 . 죄송합니다. 매개 변수의 순서에 대해 걱정하지 않아도됩니다.
Craige

그런 다음 많은 인수를 취하는 매개 변수 객체에 대한 생성자가 없습니까?
detly

아니요-매개 변수 객체는 더 읽기 쉬운 방식으로 여러 명령문에 대해 "빌드"될 수 있기 때문입니다.
Bevan

2
@Bevan : 이것은 매우 논쟁의 여지가 있습니다. 이런 식으로 오브젝트를 빌드하면 더 이상 변경할 수 없습니다. 그러나 가능할 때마다 객체를 불변으로 유지하는 것이 유지 관리 성을 높이는 또 다른 좋은 방법입니다.
tdammers

10

IN 매개 변수를 먼저, OUT 매개 변수를 두 번째로 넣으려고합니다. 자연 createPoint(double x, double y)순서도 createPoint(double y, double x)있습니다. 예를 들어 .


5
예를 들어 에서처럼 항상 하나의 OUT 인수와 가변 개수의 인수가있는 경우 반대가 더 좋습니다 addAllTo(target, something1, something2).
maaartinus

동일한 규칙을 따르지만 가능한 경우 OUT 매개 변수와 대부분의 프로그래머도 피하려고합니다. 따라서이 권장 사항이 실제로 OP를 도와주는 기능의 수는 다소 작아야합니다.
Doc Brown

7
@DocBrown 당신은 정말 좋은 프로그래머를 피하려고 시도해서는 안되며, 주변에있는 것이 유용 할 수 있습니다.
RyanfaeScotland

@RyanfaeScotland : 젠장, 게시하기 전에 내 의견을 두 번 읽어야합니다 (또는 5 분 이내에 변경 가능) ;-)
Doc Brown

6

이 특정 주제와 관련하여 문서화 된 "모범 사례"를 본 적이 없지만 제 개인 표준은 사용중인 방법에 나타나는 순서대로 또는 방법이 데이터 계층으로 전달 데이터베이스 스키마 또는 데이터 계층 메소드에 나타나는 순서대로 나열합니다.

또한 메소드의 여러 과부하가있는 경우 일반적인 방법은 각 메소드 오버로드에 대해 각기 다른 메소드가 끝에 추가되는 모든 (또는 대부분의) 메소드에 공통적 인 매개 변수로 시작하여 매개 변수를 나열하는 것입니다. :

void func1(string param) { }
void func2(string param, int param2) { }
void func3(string param, string param3) { }
void func3(string param, int param2, string param3) { }


3

나는 종종 const매개 변수를 먼저 (즉, 값으로 전달하는 매개 변수) 배치 한 다음 참조로 전달하는 C / C ++ 규칙을 따릅니다 . 이것은 함수를 호출하는 올바른 방법 일 필요는 없지만 각 컴파일러가 매개 변수를 처리하는 방법에 관심이 있다면 규칙에 대한 다음 링크 및 / 또는 매개 변수가 스택으로 푸시되는 순서를 살펴보십시오.

http://msdn.microsoft.com/en-us/library/zthk2dkh%28v=vs.80%29.aspx

http://en.wikipedia.org/wiki/Calling_convention


관심있는 다른 링크는 msdn.microsoft.com/en-us/library/984x0h58%28v=vs.71%29.aspx 재귀 함수에 대해서는 다음 링크를 참조하십시오. Publications.gbdirect.co.uk/c_book/chapter4/… 잊어 버린 것은 아니지만 새 사용자이므로 링크가 두 개 이상인 댓글을 게시 할 수 없습니다.
Bill

1

나는 보통 "저렴한 모양이 아닌 것"매개 변수 순서로 진행합니다. 메소드 / 함수 정의로 이동해야하는 횟수가 적을수록 좋습니다. 그리고 작은 툴팁이 뜨면 (VS) 그렇게하는 것이 더 쉬운 방법을 설명하는 매개 변수의 이름을 지정하는 것이 좋습니다.

매개 변수의 선과 선이있는 경우 다른 디자인을 고려할 수 있습니다. 물러서서 더 많은 기능 / 방법으로 나누는 방법을 살펴보십시오. 단지 아이디어이지만 함수에 12 개의 매개 변수가 있으면 거의 항상 매개 변수 문제가 아니라 디자인 문제입니다.


2
"cyprtic": 포인트를 만드는 좋은 방법.
Bevan

2
@Bevan, 전에 오타가 없었어요?

1
나는 항상 기록하는 cyprtic 이 너무 좋았 기 때문에 오타 가 있었는데 그것이 의도적 이라고 생각했습니다 . 실수로 변경 한 경우에도 다시 변경하십시오.
Bevan

1
@Bevan, 하하 괜찮아 당신이 무슨 말을하는지 봅니다. 좋은 지적! 다시 변경됨 =)

1

때때로 (드물게), 적절한 양의 매개 변수를 취하는 함수를 만드는 것이 가장 좋은 경로 인 것 같습니다.

이 방법 에서 SRP 를 위반한다는 몇 가지 매개 변수를 사용하는 것이 종종 명확한 지표 입니다. 많은 매개 변수가 필요한 방법은 한 가지 작업 수행 할 가능성이 없습니다 . 예외는 수학 함수 또는 구성 방법 일 수 있으며, 실제로 여러 매개 변수 가 필요합니다. 악마가 성수를 피하기 때문에 여러 매개 변수를 피할 것입니다. 메서드 내에서 더 많은 매개 변수를 사용할수록 메서드가 너무 복잡 할 가능성이 높아집니다. 복잡성이 클수록 유지 관리가 어렵고 바람직하지 않습니다.

그러나 내가 할 때 종종 매개 변수의 순서를 임의로 선택하는 것처럼 느낍니다. 나는 가장 중요한 매개 변수를 먼저 사용하여 "중요도 순서"로 이동합니다.

priniple에서는 무작위 로 선택 하고 있습니다. 물론 매개 변수 A 가 매개 변수 B 보다 관련 이 있다고 생각할 수 있습니다 . 그러나 B 가 가장 관련성이 높은 매개 변수 라고 생각하는 API 사용자에게는 해당되지 않을 수 있습니다 . 따라서 순서를 고르는 데주의를 기울여도 다른 사람들에게는 무작위로 보일 수 있습니다.

더 좋은 방법이 있습니까? 선명도를 높이는 매개 변수를 정렬하는 "모범 사례"방법이 있습니까?

몇 가지 방법이 있습니다.

a) 사소한 경우 : 두 개 이상의 매개 변수를 사용하지 마십시오.

b) 지정한 언어를 선택하지 않았을 때 매개 변수 이름이 지정된 언어를 선택했을 가능성이 있습니다 . 이것은 훌륭한 구문 설탕 으로 매개 변수 순서의 중요성을 완화시킬 수 있습니다.fn(name:"John Doe", age:36)

모든 언어가 그러한 멋을 허용하는 것은 아닙니다. 그럼 무엇?

c) Dictionary / Hashmap / Associative Array 를 매개 변수로 사용할 수 있습니다 . 예를 들어 Javascript는 다음을 허용합니다 fn({"name":"John Doe", age:36}). (b)에서 멀지 않은 거리.

d) 물론 Java 와 같이 정적으로 유형이 지정된 언어로 작업하는 경우 . Hashmap을 사용할 수 있지만 HashMap<String, Object>매개 변수의 유형이 다르고 캐스팅해야 할 때 형식 정보 가 느슨합니다 (예 : 작업 시).

다음 논리적 단계는 Object적절한 속성이나 구조체 와 같은 더 가벼운 무언가 (예 : C # 또는 C / C ++) 와 함께 (Java를 사용 하는 경우) 전달하는 것 입니다.

경험 법칙 :

1) 가장 좋은 경우-분석법에 매개 변수 가 전혀 필요 하지 않습니다.

2) 좋은 경우-방법에는 하나의 매개 변수가 필요합니다

3) 허용 가능한 경우-분석법에 두 개의 매개 변수가 필요합니다

4) 다른 모든 사례는 리팩토링되어야한다


0

대부분의 플랫폼에서 작동하는 불완전한 사람 버전의 명명 된 매개 변수-종종 매개 변수로 복잡한 객체가 더 좋습니다. 그리고 부팅 동작으로 매개 변수의 문을 엽니 다.

하지 말아야 할 대부분의 예를 들어, PHP의 표준 라이브러리 문서를 읽으려고 할 수 있습니다.


0

필자는 일반적으로 특정 느낌에 따라 "느낌"(으로 표시 될 수 있음 ORDER BY required DESC, SOME_MAGIC_FEELING(importancy,frequency)) 에 따라 중요도 및 사용 빈도를 결합하여 측정하는 것보다 먼저 필요한 것을 먼저 주문합니다 .

그러나 다른 사람들이 지적 했듯이이 문제를 일으키는 근본적인 문제는 너무 많은 매개 변수 (IMHO,> 3이 너무 많음)를 사용하는 것이며 이것이 해결해야 할 실제 문제라고 생각합니다. Rebecca Murphey의 블로그에 흥미로운 게시물 이 있습니다 .

나는 당신이 1-3 개의 주장만을 가질 때, 정확한 순서는 분명하고 당신은 옳은 것을 "느끼고"있다고 ​​생각합니다.


0

@Wyatt Barnetts의 답변과 비슷하지만 메소드에 대한 몇 가지 매개 변수 또는 매우 명시 적 매개 변수 이상인 대신 객체를 전달하는 것이 좋습니다. 이는 일반적으로 업데이트 / 유지 관리가 쉽고 읽기쉬우 며 주문에 대한 걱정이 없습니다 . 또한 메소드에 너무 많은 매개 변수는 코드 냄새 이며 이를 수정하기 위해 따를 수 있는 공통 리팩토링 패턴 이 있습니다.

명시 적 예 :

public int add(int left, int right)
{
  return left + right;
}

이것은 꽤 명확하게 정의 된 예이고 덧셈은 교환 적이므로 (순서는 중요하지 않음) 그냥 따라 가십시오.

그러나 더 복잡한 것을 추가하면 :

public SomeComplexReturnValue Calculate(int i, float f, string s, object o)
{
  // do work here
}

될 것입니다 :

public class SomeComplexInputForCalculation
{
  public int i; 
  public float f;
  public string s; 
  public object o;
}

public SomeComplexReturnValue Calculate(SomeComplexInputForCalculation input)
{
  // do work here
}

도움이 되었기를 바랍니다...


0

카레가 가장 유익하다고 생각하는 방식으로 주문하십시오. 예를 들어, 함수 매개 변수가 먼저 있습니다.


0

"중요한 것"이 전부를 의미하는 것은 아닙니다. 몇 가지 규칙이 있습니다.

호출 객체 (보통 이름이 sender)를 전달하면 먼저 진행됩니다.

목록에는 약간의 유창함 이 있어야 합니다. 즉, 읽을 때 논증이 무엇인지 알아야합니다. 예:

CopyFolder (문자열 경로, 부울 재귀);

재귀를 먼저 넣으면 아직 컨텍스트가 없기 때문에 혼란 스러울 것입니다. 이미 폴더 (2), 폴더 (2)를 복사하는 것이라면 인수 재귀가 의미가 있습니다.

또한 IntelliSense와 유사한 기능이 제대로 작동합니다. 사용자는 인수를 채울 때 배우고 방법과 그 기능을 이해합니다. 마찬가지로 과부하는 동일한 부품에 대해 동일한 순서를 유지해야합니다.

그러면이 점에서 "동일한"인수가 여전히있을 수 있으며 순서가 인수의 유형에 따라달라고 할 수도 있습니다. 단지 몇 줄의 문자열을 연속으로 가지고 있고 나서 몇 개의 부울을 더 좋아 보이기 때문입니다. 어떤 수준에서 이것은 기술이 아닌 예술이 될 것입니다.

단일 인수로 끝나기 위해 모든 인수를 객체로 래핑해야한다는 진술은별로 신경 쓰지 않습니다. 그것은 단지 자신을 속이는 것입니다 (이 방법을 덜 복잡하게 만들지는 않지만 여전히 모든 인수가 있으므로 숨겨 두었습니다). 메소드에서 메소드로 몇 번 전달하면 리팩토링이 훨씬 쉬워 지지만 디자인 측면에서 차이를 만드는 척하는 것은 여전히 ​​편리합니다. 그것은 당신이 무언가를 나타내는 의미있는 객체로 끝나는 것과는 다릅니다. 그것은 메소드 선언의 목록과 다르지 않은 많은 인수 일뿐입니다. 밥 삼촌을 행복하게 만들지는 않을 것입니다.

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