메소드가 인수 이름 (유형 아님)만으로 구별하기에 충분합니까?


36

메소드가 인수 이름 (유형 아님)만으로 구별하기에 충분합니까, 아니면 더 명확하게 이름을 지정하는 것이 더 낫습니까?

예를 들어 T Find<T>(int id)T FindById<T>(int id).

ById인수 이름을 유지 하는 것보다 더 명시 적으로 이름을 지정 해야하는 이유가 있습니까?

내가 생각할 수있는 한 가지 이유는 메소드의 서명이 동일하지만 의미가 다른 경우입니다.

FindByFirstName(string name)FindByLastName(string name)


4
따라서 과부하를 찾을 때 포함 T Find<T>(string name)시키거나 (int size)불가피한 문제를 어떻게 해결할 계획입니까?
UKMonkey

3
@UKMonkey 어떤 피할 수없는 문제?
Konrad

3
첫 번째 경우 : 여러 항목의 이름이 같은 경우 함수 서명을 변경해야합니다. 이는 사람들이 돌아 오는 것과 혼동 될 수 있음을 의미합니다. 후자의 경우 인수는 동일하므로 불법 과부하입니다. "byX"로 함수의 이름을 지정하거나 인수에 대한 오브젝트를 작성하여 동일한 인수로 과부하에 해당하는 항목을 가질 수 있습니다. 상황에 따라 잘 작동합니다.
UKMonkey

2
@UKMonkey 당신이 원한다면 몇 가지 코드 예제로 답변을 게시 할 수 있습니다
Konrad

3
ID는 아마도 ID단순한 객체가 아닌 불투명 한 객체 여야 합니다 int. 그렇게하면 코드의 일부에서 int 또는 그 반대로 id를 사용하지 않는 컴파일 타임 검사를받을 수 있습니다. 그리고 그와 함께 당신은 할 수 있습니다 find(int value)find(ID id).
Bakuriu

답변:


68

더 명확하게 이름을 지정해야 할 이유가 있습니다.

그것은 주로 방법이 될 아니에요 정의 자체 설명해야하지만, 방법의 사용 . 반면 findById(string id)find(string id)자명 모두 사이에 큰 차이가 존재 findById("BOB")하고 find("BOB"). 전자의 경우 임의의 리터럴이 실제로 ID라는 것을 알고 있습니다. 후자의 경우 확실하지 않습니다. 실제로 이름이나 다른 이름 일 수 있습니다.


9
당신이 변수 또는 속성 이름이 기준점이다가 다른 경우의 99 %를 제외하고 : findById(id)find(id). 어느 쪽이든 갈 수 있습니다.
Greg Burghardt

16
@GregBurghardt : 특정 값은 반드시 메소드와 호출자에 대해 같은 방식으로 명명되지는 않습니다. 예를 들어, double Divide(int numerator, int denominator)메소드에 사용되는 것을 고려 하십시오 double murdersPerCapita = Divide(murderCount, citizenCount). 그렇지 않은 경우가 많거나 이름이 잘못된 경우가
많으므로

1
@Flater : 질문에 코드 (일종의 영구 저장 장치에서 물건 찾기)를 사용하면이 메소드를 "murderedCitizenId"또는 "citizenId"로 호출 할 수 있다고 생각합니다 ... 인수 또는 변수 이름이 실제로는 생각하지 않습니다. 여기서 모호합니다. 그리고 솔직히 나는 어느 쪽이든 갈 수 있습니다. 실제로 매우 의견이 많은 질문입니다.
Greg Burghardt

4
@GregBurghardt : 단일 예제에서 전역 규칙을 추출 할 수 없습니다. OP의 질문은 일반적으로 주어진 예에 국한되지 않습니다. 예, 같은 이름을 사용하는 것이 의미가있는 경우도 있지만 그렇지 않은 경우도 있습니다. 따라서이 답변 에서는 사용 사례의 하위 집합에 필요 하지 않더라도 일관성유지 하는 것이 가장 좋습니다 .
Flater

1
이름 정의 매개 변수 는 혼동이 이미 존재 한 후에 혼동 해결합니다 . 메소드 정의를 살펴볼 필요가 있기 때문에 명시 적으로 이름이 지정된 메소드 는 이름이 메소드 호출에 존재 하여 혼동 을 완전히 피합니다 . 또한 이름과 인수 유형이 같지만 인수 이름이 다른 두 개의 메소드를 가질 수 없으므로 특정 경우 명시적인 이름이 필요합니다.
Darkhogg

36

FindById ()의 장점 .

  1. 미래 교정 : 당신이 시작하면 Find(int), 나중에 다른 방법 (추가 할 필요가 FindByName(string), FindByLegacyId(int), FindByCustomerId(int), FindByOrderId(int), 등), 나 같은 사람들이 찾고있는 사람이 나이를 지출하는 경향이있다 FindById(int). 별로 문제 만약 당신이 할 수있는 변경됩니다 Find(int)FindById(int)그것이 필요하게되면 - 미래의 교정은 이러한 관한 경우 의.

  2. 더 쉽게 읽을 수 있습니다. Find호출이 record = Find(customerId);Yet 인 FindById경우 읽기가 약간 더 쉬운 경우 완벽하게 괜찮 습니다 record = FindById(AFunction());.

  3. 일관성 . 어디에서나 FindByX(int)/ FindByY(int)패턴을 일관되게 적용 할 수 있지만 Find(int X)/ Find(int Y)는 충돌하기 때문에 불가능합니다.

Find ()의 장점

  • 키스. Find간단하고 간단하며, operator[]이와 관련하여 가장 기대되는 2 개의 함수 이름 중 하나입니다. (일부 인기있는 대안이되고 get, lookup또는 fetch상황에 따라).
  • 일반적으로 함수의 기능을 정확하게 설명하는 잘 알려진 단일 단어 인 함수 이름이 있으면이를 사용하십시오. 여러 단어로 된 이름이 더 길더라도 함수의 기능을 설명하는 데 약간 더 좋습니다. 예 : Length vs NumberOfElements . 트레이드 오프가 있으며 라인을 그릴 위치는 진행중인 토론의 대상입니다.
  • 중복성을 피하는 것이 일반적으로 좋습니다. 를 살펴보면 FindById(int id)중복을로 변경하여 쉽게 중복성을 제거 할 수 Find(int id)있지만 트레이드 오프가 있습니다.

또는 강력한 형식의 ID를 사용하여 두 가지 장점을 모두 얻을 수 있습니다 .

CustomerRecord Find(Id<Customer> id) 
// Or, depending on local coding standards
CustomerRecord Find(CustomerId id) 

구현 Id<>: C #에서 ID 값을 강력하게 입력

위의 링크뿐만 아니라 여기에 의견 Id<Customer>은 내가 다루고 싶은 여러 가지 우려를 제기했습니다 .

  • 우려 1 : 제네릭의 남용입니다. CustomerId그리고 OrderID다른 유형 (있다 customerId1 = customerId2;=> 좋은, customerId1 = orderId1;=> 나쁜), 그러나 우리는 하나이를 구현 사본을 붙여 넣거나 메타 프로그래밍으로 할 수 있도록 구현은 거의 동일하다. 제네릭을 노출하거나 숨기는 것에 대한 논의에는 가치가 있지만 메타 프로그래밍은 제네릭을위한 것입니다.
  • 우려 2 : 간단한 실수를 멈추지 않습니다 ./ 문제를 찾아내는 해결책입니다. 강력한 형식의 ID를 사용하여 제거 된 주요 문제는에 대한 호출에서 잘못된 인수 순서입니다 DoSomething(int customerId, int orderId, int productId). 강력한 유형의 ID는 OP가 요청한 항목을 포함하여 다른 문제도 방지합니다.
  • 우려 3 : 실제로 코드를 가릴뿐입니다. 에 ID가 있는지 알기가 어렵습니다 int aVariable. 에 ID가 있음을 쉽게 알 Id<Customer> aVariable수 있으며 고객 ID임을 알 수 있습니다.
  • 우려 4 :이 ID는 강력한 유형이 아니며 랩퍼 일뿐입니다. String그냥 래퍼 byte[]입니다. 랩핑 또는 캡슐화는 강력한 입력과 충돌하지 않습니다.
  • 우려 5 : 과도하게 설계되었습니다. 내가 추가하는 것이 좋습니다 않지만 여기에 최소한의 버전입니다 operator==그리고 operator!=당신은에만 의존하지 않으려는 경우뿐만 아니라 Equals:

.

public struct Id<T>: {
    private readonly int _value ;
    public Id(int value) { _value = value; }
    public static explicit operator int(Id<T> id) { return id._value; }
}

10

이것에 대해 생각하는 또 다른 방법은 언어의 유형 안전을 사용하는 것입니다.

다음과 같은 메소드를 구현할 수 있습니다.

Find(FirstName name);

여기서 FirstName은 이름을 포함하는 문자열을 감싸는 간단한 객체이며 메서드가 수행하는 작업이나 호출되는 인수에 대해 혼동 될 수 없습니다.


4
OP 질문에 대한 답변이 무엇인지 잘 모르겠습니다. 인수 유형에 따라 "찾기"와 같은 이름을 사용하도록 권장합니까? 또는 인수에 대해 명시적인 유형이있는 경우에만 이러한 이름을 사용하고 다른 곳에는 "FindById"와 같은보다 명확한 이름을 사용하도록 권장합니까? 또는 "찾기"와 같은 이름을보다 실현 가능하게하기 위해 명시 적 유형을 도입하는 것이 좋습니다.
Doc Brown

2
@DocBrown 나는 후자를 생각하고 그것을 좋아한다. 실제로 피터의 대답 인 iiuc와 비슷합니다. 내가 이해 한 이론적 근거는 두 가지이다 : (1) 함수가 무엇을 하는가는 인수 유형에서 분명하다; (2) string name = "Smith"; findById(name);설명이 아닌 일반 유형을 사용하면 가능합니다. 와 같은 실수를 할 수 없습니다 .
피터-복원 모니카

5
일반적으로 컴파일 타임 유형 안전의 팬이지만 래퍼 유형에주의하십시오. 유형 안전성을 위해 래퍼 클래스를 도입하면 초과 작업을 수행하면 API가 심각하게 복잡해질 수 있습니다. 예를 들어, winapi가 가지고있는 "아티스트는 이전에 int"로 알려진 전체 문제 장기적으로 나는 대부분의 사람들이 끝없는 DWORD LPCSTR등 복제본을보고 "int / string / etc"라고 생각 한다고 말하면서 실제로 코드를 설계하는 것보다 도구를 준비하는 데 더 많은 시간을 소비합니다. .
jrh

1
@jrh 맞습니다. "명 목적"유형을 도입하기위한 리트머스 테스트 (이름 만 다름)는 일반적인 함수 / 방법이 사용 사례에서 의미가없는 경우입니다. 예를 들어 ints는 종종 합산, 곱하기 등 ID에 무의미합니다. 와 ID구별됩니다 int. 이것은 (예를 들어, 우리가있는 경우에 우리는 가치를 부여 할 수있는 아래로 축소하여 API를 단순화 할 수 있습니다 ID, 그것은 것에만 작업을 find하지 예 age또는 highscore). 반대로, 우리가 자신을 많이 변환하거나 find여러 유형에 대해 동일한 함수 / 메서드 (예
:)를 작성한다면,

1

FindByID와 같은 명시 적 선언에 투표 할 것입니다 .... 소프트웨어는 변경을 위해 구축되어야합니다. 열리고 닫혀 있어야합니다 (SOLID). 따라서 클래스는 FindByName과 같은 유사한 find 메소드를 추가하기 위해 열려 있습니다.

그러나 FindByID가 닫히고 구현이 단위 테스트되었습니다.

나는 술어를 가진 메소드를 제안하지 않을 것이며, 그것들은 일반적인 수준에서 좋습니다. 필드 (ByID)를 기준으로 다른 방법론을 완료 한 경우 어떻게해야합니까?


0

다음과 같은 술어를 사용하도록 제안한 사람이 아무도 없습니다.

User Find(Predicate<User> predicate)

이 접근 방식을 사용하면 API의 표면을 줄일 수있을뿐만 아니라 API를 사용하는 사용자에게 더 많은 제어 권한을 부여 할 수 있습니다.

충분하지 않으면 언제든지 필요에 따라 확장 할 수 있습니다.


1
문제는 지수와 같은 것을 이용할 수 없기 때문에 효율성이 떨어진다는 것입니다.
Solomon Ucko
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.