TypeScript의 인터페이스 및 클래스 코딩 지침에 대해 혼란 스러움


81

TypeScript 코딩 지침을 읽었습니다.

그리고 나는이 진술이 다소 혼란 스럽다는 것을 발견했습니다.

인터페이스 이름의 접두사로 "I"를 사용하지 마십시오.

"I"접두사 없이는 이런 말이별로 의미가 없습니다.

class Engine implements IEngine

나는 명백한 것을 놓치고 있습니까?

내가 이해하지 못한 또 다른 점은 다음과 같습니다.

클래스

일관성을 위해 코어 컴파일러 파이프 라인에서 클래스를 사용하지 마십시오. 대신 함수 클로저를 사용하십시오.

수업을 전혀 사용하지 말아야한다는 내용입니까?

누군가 나를 위해 그것을 정리할 수 있기를 바랍니다 :)


13
명확히하기 위해 이것은 프로젝트 구현 방법에 대한 스타일 가이드 라인이 아니라 TypeScript의 코드 스타일에 대한 문서입니다. I접두사를 사용하는 것이 귀하와 귀하의 팀에게 의미가 있다면 그것을 사용하십시오. 그렇지 않다면 아마도 자바 스타일의 SomeThing(인터페이스) SomeThingImpl(구현)을 사용하십시오.
Brocco 2015-08-07

2
코딩 가이드 라인의 장점 은 가이드 라인 이므로 구현 여부를 선택할 수 있다는 것입니다. 개인적 I으로 인터페이스를 나타내는 데 사용 합니다. 그 이유는 제가 익숙하고 팀원들에게 의미가 있기 때문입니다.
Jon Preece

예, 그들은 단지 지침 일뿐입니다. 그러나 대부분의 경우 지침 뒤에는 좋은 이유가 있습니다. 그래서 당신이 익숙한 것을 고수하는 것은 당신을 프로그래머로 발전시키는 것이 아닙니다. :)
Snæbjørn

3
우리 팀이 TS를 사용하기 시작했을 때 인터페이스에 I- 접두사도 사용했습니다. C # 영향이라고 생각합니다. 그런 다음 I- 접두사를 사용하지 않는 것에 대한 TypeScript 팀의 지침을 읽었습니다. 그것을 깨닫는 데 몇 주가 걸렸습니다. 나는 그들이 왜 그런 규칙을 가지고 있는지에 대한 정보를 열심히 찾고 있었다. 잠시 후 깨달았습니다. 인터페이스에 대한 I- 접두사는 결함입니다 (적어도 TypeScript에서는), 이점을 제공하는 것보다 더 많은 문제를 유발합니다.
Stanislav Berkov 2017

VSCode에서를 입력 let engine = new E...하면 Classes 만 자동 제안됩니다. 인터페이스는 그렇지 않습니다. 그것을 깨닫지 못했습니다. 이것이 제가 'I'접두사를
붙인

답변:


165

팀 / 회사가 프레임 워크 / 컴파일러 / 도구 세트를 제공 할 때 그들은 이미 경험과 모범 사례를 가지고 있습니다. 그들은 그것을 지침으로 공유합니다. 지침은 권장 사항 입니다. 마음에 들지 않으면 무시할 수 있습니다. 컴파일러는 여전히 코드 를 컴파일 합니다 . 비록 때 로마에 ...

이것이 TypeScript 팀이 I접두사 인터페이스를 권장하지 않는 이유 입니다.

이유 # 1 헝가리 표기법 의 시대 가 지났습니다.

I-prefix-for-interface 서포터의 주요 주장은 접두사가 유형이 인터페이스인지 여부를 즉시 파악하는 데 유용하다는 것입니다. 접두사가 즉시 그루 킹 (피킹)에 도움이된다는 진술은 헝가리 표기법에 호소합니다 . I인터페이스 이름, C클래스, A추상 클래스, s문자열 변수, cconst 변수, i정수 변수의 접두사 . 나는 그러한 이름 장식이 식별자 위로 마우스를 가져 가거나 핫키를 통해 유형 정의로 이동하지 않고도 유형 정보를 제공 할 수 있다는 데 동의합니다. 이 작은 이점은 헝가리 표기법의 단점과 아래에 언급 된 다른 이유 보다 큽니다 . 헝가리어 표기법은 현대 프레임 워크에서 사용되지 않습니다. C #에는I이전 이유 (COM)로 인한 인터페이스의 접두사 (그리고 이것은 C #의 유일한 접두사)입니다. 돌이켜 보면 .NET 설계자 (Brad Abrams) 중 한 명이 prefix를 사용하지 않는I 것이 더 나았을 것이라고 생각합니다 . TypeScript는 COM 레거시가 없으므로 I인터페이스에 대한 접두사 규칙 이 없습니다 .

이유 # 2- I접두사가 캡슐화 원칙을 위반 함

블랙 박스가 있다고 가정 해 봅시다. 해당 상자와 상호 작용할 수있는 유형 참조를 얻을 수 있습니다. 인터페이스인지 클래스인지 신경 쓰지 마십시오. 인터페이스 부분 만 사용하면됩니다. 그것이 무엇인지 (인터페이스, 특정 구현 또는 추상 클래스) 알기를 요구하는 것은 캡슐화의 위반입니다.

예 : 코드에서 API Design Myth : Interface as Contract 를 수정해야한다고 가정 해 보겠습니다 (예 : 인터페이스 삭제 ICarCar대신 기본 클래스 사용). 그런 다음 모든 소비자에서 이러한 교체를 수행해야합니다. I-prefix는 블랙 박스 구현 세부 사항에 대한 소비자의 암시 적 종속성을 유발합니다.

이유 # 3 잘못된 이름 지정으로부터 보호

개발자는 이름에 대해 제대로 생각하기가 게으 릅니다. 이름 지정은 컴퓨터 과학에서 두 가지 어려운 것 중 하나입니다 . 개발자가 인터페이스를 추출해야 할 때 I클래스 이름에 문자 를 추가하기 만하면 인터페이스 이름을 얻을 수 있습니다. I인터페이스에 대한 접두사를 허용하지 않으면 개발자가 인터페이스에 적합한 이름을 선택하도록 두뇌에 부담을줍니다. 선택한 이름은 접두사뿐만 아니라 의도의 차이를 강조해야합니다.

추상화 사례 : 인터페이스 및 관련 클래스를 정의 해서는 안됩니다 . 추상화이며 계약에 사용되어야합니다. 구현에는 설명적이고 고유 한 이름이 있어야합니다 (예 : .ICarCarCarSportsCar, SuvCar, HollowCar

좋은 예 : WpfeServerAutosuggestManager implements AutosuggestManager, FileBasedAutosuggestManager implements AutosuggestManager.

나쁜 예 : AutosuggestManager implements IAutosuggestManager .

이유 # 4 적절하게 선택된 이름은 API Design Myth : Interface as Contract 에 대해 예방 접종을합니다 .

실습에서 나는 Car implements ICar이름 지정 체계 가있는 별도의 인터페이스에서 클래스의 인터페이스 부분을 생각없이 복제 한 많은 사람들을 만났습니다 . 클래스의 인터페이스 부분을 별도의 인터페이스 유형으로 복제한다고해서 마술처럼 추상화로 변환되지는 않습니다. 여전히 구체적인 구현을 얻을 수 있지만 인터페이스 부분이 중복됩니다. 추상화가 좋지 않은 경우 인터페이스 부분을 복제해도 어쨌든 개선되지 않습니다. 추상화를 추출하는 것은 어려운 작업입니다.

참고 : TS에서는 모의 클래스 나 오버로딩 기능을위한 별도의 인터페이스가 필요하지 않습니다. 클래스의 공용 멤버를 설명하는 별도의 인터페이스를 만드는 대신 TypeScript 유틸리티 유형을 사용할 수 있습니다 . Eg Required<T>는 유형의 모든 공용 멤버로 구성된 유형을 구성합니다 T.

export class SecurityPrincipalStub implements Required<SecurityPrincipal> {
  public isFeatureEnabled(entitlement: Entitlement): boolean {
      return true;
  }
  public isWidgetEnabled(kind: string): boolean {
      return true;
  }

  public areAdminToolsEnabled(): boolean {
      return true;
  }
}

일부 공용 멤버를 제외한 유형을 생성하려면 생략 및 제외 조합을 사용할 수 있습니다 .


3
인터페이스 이름보다 구체적인 클래스 이름을 지정하는 데 대한 귀하의 요점이 마음에 들지만 I접두사는 유형에 구현이 있는지 여부를 즉시 파악하는 데 도움이된다고 생각합니다 . 인터페이스 사용의 주요 이점은 외부 코드의 구현 세부 사항을 특정 구현에 연결하지 않는 것입니다.
cchamberlain

1
@demisx가 어색하다고 느끼면하지 말아야합니다. 질문에 답하십시오. 정말 필요합니까? 그들이 어떤 의미를 가지고 있습니까, 아니면 올바른 엔지니어링을 수행한다는 잘못된 감각으로 사용합니까?
Stanislav Berkov 2018

2
당신의 포인트는 이론적으로 좋은 소리를하지만, 현실은 "I"접두사가 종종 대신에 충분히 큰 팀에서 "IMPL"접미사에 대한 거래입니다
jameslk

3
@jameslk 내가없이 일을 명명 알고 IImpl하드입니다 ( "두 개의 하드 컴퓨터 과학 가지가 있습니다 : 캐시 무효화 및 명명 것들"- 필 Karlton)하지만 행할 수는.
Stanislav Berkov

5
I 제거는 일반적으로 DefaultFooService 또는 FoodServiceImpl과 같은 구현에 접두사 또는 접미사를 추가하여 대체된다는 데 동의합니다. 접두사를 사용하면 계약과 구현 / 추상간에 겹치는 이름 지정 문제가 발생하지 않습니다. 또한 반복의 요점은 유효하지만 인터페이스의 요점은 계약이 있고 구현을 다른 것으로 대체 할 수 있다는 것입니다. 일반적으로 이것은 단위 테스트에서 절대적으로 중요합니다. 추상화 및 불변성 등의 이점은 말할 것도 없습니다.
chris

45

참조하는 링크에 대한 설명 :

이것은 프로젝트 구현 방법에 대한 스타일 가이드 라인이 아니라 TypeScript의 코드 스타일에 대한 문서입니다.

I접두사를 사용하는 것이 당신과 당신의 팀에게 의미가 있다면 그것을 사용하십시오 (I do).

그렇지 않다면 아마도 자바 스타일의 SomeThing(인터페이스) SomeThingImpl(구현)을 사용하십시오.


19
설명을 위해. Typescript 핸드북은 여전히 In general, do not prefix interfaces with I (e.g. IColor). Because the concept of an interface in TypeScript is much more broad than in C# or Java, the IFoo naming convention is not broadly useful.다음과 같이 말합니다. 엄격하지는 않지만 강력한 권장 사항처럼 보입니다.
Guria

3
동의하다. TypeScript 자체뿐만 아니라 모든 TypeScript 기반 프로젝트에 대한 Microsoft의 코드 지침처럼 들립니다. 이 지침은 매우 혼란스럽고 여전히 모든 인터페이스 앞에 "I"가 붙습니다.
demisx

3
유지하는 것이 합리적이라고 생각하는 시나리오가 있습니다 I. React 프로젝트에는 Card인터페이스와 Card. 소품에는 배열이 필요 Card하지만 구성 요소가 아닌 유형이 필요합니다. 이름을 지정 ICard하거나 CardComponent...
BrunoLM

3
SomeThingImpl implements SomeThing만큼 좋습니다 SomeThing implements ISomeThing. 경우 SomeThing추상화입니다 다음이어야한다 이름 Concrete[Some]Thing implements SomeThing.
Stanislav Berkov 2017

@Guria가 말했듯이 TypeScript 핸드북에 모든 것이 나와 있다고 생각합니다. 예제에주의를 기울이면 잘 사용하는 방법을 알게 될 것입니다.
giovannipds

0

나는 찾을 @ stanislav-berkov을 '영업의 질문에 꽤 좋은 대답이야. 나는 2 센트 만 공유 할 것이며, 결국에는 당신의 팀 / 부서 / 회사 / 무엇이든간에 공통의 이해를 얻고 준수 할 자체 규칙 / 지침을 설정하는 것입니다.

가능하고 바람직 할 때마다 표준 및 / 또는 규칙을 고수하는 것은 좋은 관행이며 이해하기 쉽게 유지합니다. 다른 한편으로는 우리가 코드를 작성하는 방법을 여전히 자유롭게 선택할 수 있다고 생각합니다.

감정적 인 측면, 코드 작성 방식 또는 코딩 스타일에 대해 조금 생각하면 우리의 성격과 어떤 경우에는 우리의 기분까지도 반영됩니다. 이것은 우리가 규칙을 따르는 코딩 기계뿐만 아니라 인간을 유지하는 것입니다. 코딩은 단순한 산업화 된 과정이 아니라 공예가 될 수 있다고 생각합니다.


-1

인터페이스가되는 유형은 구현 세부 사항입니다. 구현 세부 사항은 API : s에서 숨겨져 야합니다. 그것이 당신이 피해야하는 이유 I입니다.

당신은 모두를 피해야 prefix 하고 suffix . 둘 다 잘못되었습니다.

  • ICar
  • CarInterface

해야 할 일은 API에서 예쁜 이름을 표시하고 구현에 숨겨진 구현 세부 정보를 갖는 것입니다. 그것이 내가 제안하는 이유입니다.

  • Car -API에 노출되는 인터페이스입니다.
  • CarImpl -소비자에게 숨겨진 해당 API의 구현.

현재 저는 SpringBoot 배경에서 확립 된이 구조도 활용합니다. 그래서 이것은 TS에서 적절한 것으로 간주됩니까? TS 커뮤니티에는 명확한 답변없이 무엇이 적절한 지에 대한 많은 의견이있는 것으로 보입니다.
Impurity

2
Impl접미사를 사용하면 IBob 아저씨로 접두사를 구타하는 모든 것을 알고있는 것을 대체하는 부작용이 있습니다 .
Szczepan Hołyszewski
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.