“인터페이스 프로그래밍”이해


29

"구현 대신 인터페이스 프로그래밍"이라는 용어를 많이 접하게되었으며 그 의미를 이해하고 있다고 생각합니다. 그러나 그것이 이점과 가능한 구현인지 이해하고 싶습니다.

"인터페이스 프로그래밍"이란 가능한 경우 구체적인 구현을 참조하는 대신보다 추상적 인 수준의 클래스 (인터페이스, 추상 클래스 또는 때로는 일종의 수퍼 클래스)를 참조해야 함을 의미합니다.

Java의 일반적인 예는 다음을 사용하는 것입니다.

List myList = new ArrayList();대신에 ArrayList myList = new ArrayList();.

이것에 관한 두 가지 질문이 있습니다.

  1. 이 접근 방식의 주요 이점을 이해하고 싶습니다. 이점은 대부분 유연성이라고 생각합니다. 구체적인 구현이 아닌보다 높은 수준의 참조로 객체를 선언하면 개발주기와 코드 전체에서 더 많은 유연성과 유지 관리가 가능합니다. 이 올바른지? 유연성이 주요 이점입니까?

  2. '인터페이스 프로그래밍'방법이 더 있습니까? 또는 "구체적인 구현이 아닌 인터페이스로 변수를 선언"하는 것이이 개념의 유일한 구현입니까?

자바 구조 인터페이스에 대해 이야기하지 . 나는 OO 원칙 "구현이 아닌 인터페이스에 프로그래밍"에 대해 이야기하고있다. 이 원칙 에서 세계 "인터페이스"는 클래스의 "슈퍼 타입"( 인터페이스, 추상 클래스 또는 더 구체적인 하위 클래스보다 더 추상적이고 덜 구체적인 단순 슈퍼 클래스)을 나타냅니다.




답변:


44

"인터페이스 프로그래밍"이란 가능한 경우 구체적인 구현을 참조하는 대신보다 추상적 인 수준의 클래스 (인터페이스, 추상 클래스 또는 때로는 일종의 수퍼 클래스)를 참조해야 함을 의미합니다.

이것은 정확하지 않습니다 . 또는 적어도 완전히 정확하지는 않습니다.

더 중요한 점은 프로그램 설계 관점에서 비롯됩니다. 여기에 당신의 디자인을 집중 수단 "인터페이스에 프로그래밍" 무엇을 하지, 코드가하고 어떻게 그것을 않습니다. 이는 디자인을 정확하고 유연하게 만드는 중요한 차이점입니다.

주요 아이디어는 도메인이 소프트웨어보다 훨씬 느리게 변경된다는 것입니다. 식료품 목록을 추적 할 소프트웨어가 있다고 가정 해보십시오. 80 년대에이 소프트웨어는 명령 행 및 플로피 디스크의 일부 플랫 파일에 대해 작동합니다. 그런 다음 UI를 얻습니다. 그런 다음 목록을 데이터베이스에 넣을 수 있습니다. 나중에 클라우드 나 휴대 전화 또는 페이스 북 통합으로 옮길 수 있습니다.

구현 (플로피 디스크 및 명령 줄)을 중심으로 코드를 설계 한 경우 변경 준비가되지 않은 것입니다. 인터페이스를 중심으로 코드를 디자인 한 경우 (식료품 목록 조작) 구현은 자유롭게 변경할 수 있습니다.


답변 해주셔서 감사합니다. 당신이 쓴 것에 의해 판단하면 "인터페이스로 프로그래밍하는"의 의미와 그 이점이 무엇인지 이해합니다. 그러나 나는 한 가지 질문이 있습니다-이 개념의 가장 일반적인 예는 다음과 같습니다 객체 타입 (Aka, List myList = new ArrayList()대신에 ArrayList myList = new ArrayList(). (질문은 다음 코멘트에 있음)
Aviv Cohn

내 질문은 : "인터페이스 프로그래밍"원칙이 발생하는 실제 코드의 장소에 대해 더 많은 예제를 제공해 줄 수 있습니까? 마지막 주석에서 설명한 일반적인 예를 제외하고?
Aviv Cohn

6
아니요 . List/ ArrayList내가 전혀 말하는 것이 아닙니다. 그것은 더 제공처럼 Employee객체가 아니라 당신이 직원 기록을 저장하는 데 사용할 연결된 테이블의 세트를. 또는 노래를 반복 할 수있는 인터페이스를 제공하고 이러한 노래가 섞이거나 CD 또는 인터넷에서 스트리밍되는 경우 신경 쓰지 않습니다. 그들은 단지 일련의 노래 일뿐입니다.
Telastyn

"구현이 아닌 인터페이스로 프로그래밍하는 것"이 ​​추상화 OO 원칙을 표현하는 원칙이라고 말 하시겠습니까?
Aviv Cohn

1
@ AvivCohn SpringFramework를 좋은 예로 제안합니다. Spring의 모든 기능은 인터페이스와 Springs의 주요 동작을 직접 구현하여 기능을 계속해서 향상 시키거나 사용자 정의 할 수 있습니다. 인터페이스 프로그래밍은 통합 프레임 워크 를 설계하는 최고의 전략이기도합니다 . 다시 스프링은 스프링 통합으로 작동합니다. 디자인 타임에 인터페이스로 프로그래밍은 우리가 UML로 할 것입니다. 아니면 내가 할 것입니다. 그것이 하는 방식 에서 스스로를 추상화하고 해야 할 일 에 집중하십시오 .
Laiv

18

"인터페이스 프로그래밍"에 대한 나의 이해는 질문이나 다른 답변이 제안하는 것과 다릅니다. 그것은 내 이해가 정확하거나 다른 답변의 것들이 좋은 아이디어가 아니라고 말했을 때, 그들이 그 용어를 들었을 때 내가 생각하는 것이 아니라는 것입니다.

인터페이스 프로그래밍은 인터페이스에서 보장하는 것만 사용하는 프로그래밍 인터페이스 (클래스 라이브러리, 함수 집합, 네트워크 프로토콜 등)가 표시 될 때를 의미합니다. 기본 구현에 대한 지식이있을 수 있지만 (작성했을 수도 있음) 해당 지식을 사용해서는 안됩니다.

예를 들어 API가 내부에 대한 "핸들링"인 불투명 한 값을 제공한다고 가정 해보십시오. 여러분은이 핸들이 실제로 포인터라는 것을 알고 있으며이를 참조 해제하고 일부 값에 액세스 할 수 있으므로 원하는 작업을 쉽게 수행 할 수 있습니다. 그러나 인터페이스는 해당 옵션을 제공하지 않습니다. 특정 구현에 대한 지식입니다.

이것의 문제점은 코드와 구현 사이에 인터페이스가 강력하게 연결되어 인터페이스가 방지해야한다는 것입니다. 정치에 따라 구현을 더 이상 변경할 수 없음을 의미 할 수 있습니다. 이는 코드를 손상 시키거나 코드가 매우 취약하여 기본 구현의 모든 업그레이드 또는 변경시 계속 중단됩니다.

이것의 큰 예는 Windows 용으로 작성된 프로그램입니다. WinAPI는 인터페이스이지만 많은 사람들이 Windows 95와 같은 특정 구현으로 인해 작동하는 트릭을 사용했습니다. 이러한 트릭으로 인해 프로그램 속도가 빨라지거나 필요한 것보다 적은 코드로 작업을 수행 할 수있었습니다. 그러나 이러한 트릭은 API가 다르게 구현 되었기 때문에 Windows 2000에서 프로그램이 충돌한다는 것을 의미했습니다. 프로그램이 충분히 중요하다면 Microsoft는 실제로 프로그램을 계속 작동시키기 위해 구현에 해킹을 추가 할 수 있지만 그 비용은 Windows 코드의 복잡성 (모든 문제가 있음)이 증가합니다. 또한 와인 사용자에게는 WinAPI를 구현하려고하기 때문에 인생을 더욱 힘들게 만듭니다. 그러나이 작업을 수행하는 방법에 대한 문서 만 참조 할 수 있습니다.


그것은 좋은 지적이며, 특정 상황에서 이것을 많이 들었습니다.
Telastyn

너의 의도를 알 겠어. 그래서 당신이 말하는 것을 일반적인 프로그래밍에 적용 할 수 있는지 봅시다 : 추상 클래스 B의 기능을 사용하는 클래스 (클래스 A)가 있다고 가정 해 봅시다. 클래스 C와 D는 클래스 B를 상속합니다. 수업이 있다고합니다. 클래스 A가 클래스 C 또는 D를 직접 사용하는 경우이를 '구현 프로그래밍'이라고하며 이는 매우 유연한 솔루션이 아닙니다. 그러나 클래스 A가 클래스 B에 대한 참조를 사용하는 경우 나중에 C 구현 또는 D 구현으로 설정할 수 있으면 더 유연하고 유지 관리 할 수 ​​있습니다. 이 올바른지?
Aviv Cohn

이것이 맞다면 내 질문은- '구체적 클래스 참조보다는 인터페이스 참조 사용'일반적인 예 이외의 '인터페이스 프로그래밍'에 대한 더 구체적인 예가 있습니까?
Aviv Cohn

2
@AvivCohn이 답변에 약간 늦었지만 구체적인 예는 월드 와이드 웹입니다. 브라우저 전쟁 (IE 4 시대) 동안 웹 사이트는 사양에 따라 작성된 것이 아니라 일부 브라우저 (Netscape 또는 IE)의 단점에 대해 작성되었습니다. 이것은 기본적으로 인터페이스 대신 구현으로 프로그래밍되었습니다.
Sebastian Redl

9

나는 나에게 공식적으로 가르쳐지지 않았기 때문에 나의 개인적인 경험에 대해서만 이야기 할 수 있습니다.

첫 번째 요점이 맞습니다. 유연성이 향상되면 호출하지 않아야하는 구체적인 클래스의 구현 세부 사항을 실수로 호출 할 수 없기 때문에 발생합니다.

예를 들어, ILogger현재 구체적인 LogToEmailLogger클래스 로 구현 된 인터페이스를 고려하십시오 . 이 LogToEmailLogger클래스는 모든 ILogger메소드와 속성을 공개 하지만 구현 별 속성도 가지고 sysAdminEmail있습니다.

응용 프로그램에서 로거를 사용할 때 코드를 사용하여 로거를 설정하지 않아도 sysAdminEmail됩니다. 이 속성은 로거 설정 중에 설정해야하며 세계에서 숨겨져 야합니다.

구체적인 구현에 대해 코딩하는 경우 로거를 사용할 때 실수로 구현 특성을 설정할 수 있습니다. 이제 응용 프로그램 코드가 로거와 밀접하게 연결되어 있으므로 다른 로거로 전환하려면 먼저 코드를 원래 코드에서 분리해야합니다.

이런 의미에서 인터페이스 코딩 은 커플 링을 느슨하게 합니다.

두 번째 요점과 관련하여 인터페이스에 코딩하는 또 다른 이유는 코드의 복잡성을 줄이는 것입니다.

예를 들어, 나는 다음과 같은 인터페이스와 게임을 상상 I2DRenderable, I3DRenderable, IUpdateable. 단일 게임 구성 요소가 2D 및 3D 렌더링 가능 콘텐츠를 모두 갖는 것은 드문 일이 아닙니다. 다른 구성 요소는 2D만이 고 다른 구성 요소는 3D 일 수 있습니다.

하나의 모듈에서 2D 렌더링을 수행하는 경우 I2DRenderables 컬렉션을 유지하는 것이 좋습니다 . 컬렉션의 객체가 다른 모듈 I3DRenderable인지 또는 IUpdateble다른 모듈이 객체의 이러한 측면을 처리 할 책임이 있는지는 중요하지 않습니다 .

렌더링 가능한 객체를 목록으로 저장하면 I2DRenderable렌더링 클래스의 복잡성이 낮아집니다. 3D 렌더링 및 업데이트 논리는 그다지 중요하지 않으므로 하위 오브젝트의 이러한 측면은 무시할 수 있으며 무시해야합니다.

이러한 의미에서 인터페이스에 대한 코딩은 우려 사항격리 하여 복잡성을 낮게 유지합니다 .


4

여기서 사용되는 단어 인터페이스에는 두 가지 용도가있을 수 있습니다. 질문에서 주로 언급하는 인터페이스Java 인터페이스 입니다. 그것은 구체적으로 자바 개념이며,보다 일반적으로 프로그래밍 언어 인터페이스입니다.

인터페이스에 프로그래밍하는 것이 더 넓은 개념이라고 말하고 싶습니다. 많은 웹 사이트에서 사용할 수있는 현재 널리 사용되는 REST API는 더 높은 수준의 인터페이스에 대한 광범위한 프로그래밍 개념의 또 다른 예입니다. 코드의 내부 작업과 외부 세계 (인터넷 사용자, 다른 프로그램, 같은 프로그램의 다른 부분) 사이에 계층을 만들어 외부 세계를 변경하지 않는 한 코드 내부의 모든 것을 변경할 수 있습니다. 인터페이스 또는 정의하려는 계약에 의해 정의되는 위치입니다.

그러면 인터페이스에 의존하는 다른 모든 것을 말할 필요없이 내부 코드를 리팩토링 할 수있는 유연성이 제공됩니다.

또한 코드가 더 안정적이어야 함을 의미합니다. 인터페이스를 고수함으로써 다른 사람들의 코드를 깨뜨리지 않아야합니다. 실제로 인터페이스를 변경해야 할 경우 새 버전의 인터페이스에 주요 변경 사항이 있음을 알리는 API의 새 주요 버전 (1.abc ~ 2.xyz)을 릴리스 할 수 있습니다.

@Doval 이이 답변에 대한 의견에서 지적한 것처럼 오류의 지역 성도 있습니다. 이것들은 모두 캡슐화로 귀결된다고 생각합니다. 객체 지향 디자인의 객체에 사용하는 것처럼이 개념은 더 높은 수준에서도 유용합니다.


1
일반적으로 간과되는 이점은 오류의 지역성입니다. Map이 필요하고 바이너리 트리를 사용하여 구현한다고 가정 해보십시오. 이것이 작동하려면 키에 순서가 있어야하고 현재 노드의 키보다 "보다 작은"키가 왼쪽 하위 트리에 있고 "보다 큰"키는 켜져있는 불변을 유지해야합니다. 오른쪽 하위 트리 인터페이스 뒤에 맵 구현을 숨길 때 맵 조회가 잘못되면 버그 맵 모듈에 있어야 함 을 알 수 있습니다. 노출되면 버그가 프로그램의 어느 곳에 나 있을 수 있습니다 . 나에게 이것은 주요 이점이다.
Doval

4

실제 세계 비유가 도움이 될 수 있습니다.

인터페이스의 주 전원 플러그.
예; TV, 라디오, 진공 청소기, 세탁기 등의 전원 코드 끝에있는 3 핀으로

메인 플러그가있는 (즉, "메인 플러그가 있습니다"인터페이스를 구현하는) 모든 어플라이언스는 정확히 같은 방식 으로 처리 될 수 있습니다 . 그것들은 모두 벽면 콘센트에 꽂을 수 있으며 그 소켓에서 전원을 끌 수 있습니다.

무엇 각각의 장비가 수행하는 것은 완전히 다른 것입니다. 당신은 TV로 카펫을 멀리 청소하지 않을 것이며 대부분의 사람들은 엔터테인먼트를 위해 세탁기를 보지 않습니다. 그러나 이러한 모든 기기는 벽면 콘센트에 꽂을 수있는 일반적인 동작을 공유합니다.

그것이 바로 인터페이스가 당신을 얻는 것입니다.
통합 에 의해 수행 될 수있는 행동 많은 상속의 합병증 필요없이 객체의 다른 클래스.


1

"인터페이스 프로그래밍"이라는 용어는 많은 해석에 개방적입니다. 소프트웨어 개발의 인터페이스는 매우 일반적인 단어입니다. 다음은 몇 년 동안 내가 훈련 한 주니어 개발자들에게이 개념을 설명하는 방법입니다.

소프트웨어 아키텍처에는 광범위한 자연 경계가 있습니다. 일반적인 예는 다음과 같습니다.

  • 클라이언트와 서버 프로세스 사이의 네트워크 경계
  • 응용 프로그램과 타사 라이브러리 간의 API 경계
  • 프로그램 내에서 서로 다른 비즈니스 도메인 사이의 내부 코드 경계

중요한 것은 이러한 자연적 경계가 존재할 때 경계가 식별되고 그 경계가 어떻게 행동하는지에 대한 계약이 명시되어 있다는 것입니다. "다른 쪽"의 작동 여부가 아니라 상호 작용이 사양과 일치하는지 여부에 따라 소프트웨어를 테스트합니다.

이것의 결과는 다음과 같습니다.

  • 사양을 구현하는 한 외부 부품 교환 가능
  • 올바른 행동을 확인하기위한 단위 테스트의 자연스러운 포인트
  • 통합 테스트가 중요해졌습니다. 사양이 모호 했습니까?
  • 개발자는 특정 작업을 수행 할 때 더 작은 관심사

이것의 대부분이 클래스 및 인터페이스와 관련 될 수 있지만, 데이터 모델, 네트워크 프로토콜 및보다 일반적인 방식으로 여러 개발자와의 작업과 관련이 있다는 것을 인식하는 것이 중요합니다.

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