책을 보며 느낀것 이지만 이번 챕터는 WCF 만 제한된 내용은 아닙니다.
아키텍처가 되자. 라는 얘기가 생각나네요.


개요

인터페이스(또는 클래스)를 서비스 지향적인 계약으로 노출

è  언어의 인터페이스 등의 기능을 이용해 프로그래밍: WCF 서비스와 계약으로 제공

 

1.     Operation 오버로딩

 

Interface ICalculator

{

   Int Add(int arg1, int arg2);

   Double Add(double arg1, double arg2);

}

 

C++이나 C# 등의 프로그래밍 언어는 이름은 같지만 파라미터의 타입이나 수가 다른 메서드의 오버로딩을 지원하고 있다. 중요한 건 Operation 오버로딩은 개념상 WSDL 기반의 동작에서는 동작할 수 없다는 것이다. 따라서 다음과 같은 계약은 컴파일이 가능하지만 서비스 호스트 로드 시 Invalid operationException 예외를 발생시킨다.

 

하지만 수동으로 Operation 오버로딩을 가능하게 설정할 수 있다. 그 방법은 OperationContract 애트리뷰트의 Name 속성을 이용하여 Operation의 가칭을 지어 주는 것이다.

 

[ServiceContract]

Interface ICalculator

{

   [OperationContract(Name = “AddInt”)]

   Int Add(int arg1, int args2);

  

   [OperationContract(Name = “AddDouble”)]

   Double Add(double arg1, double arg2);

}

 

클라이언트에서도 참조한 계약의 Name 프로퍼티를 이용하여 참조된 Opetion과 동일한 이름의 가칭(별칭)을 주어 메서드를 오버로딩 할 수 있다.

 

[ServiceContract]

Public interface ICalculator

{

   [OperationContract(Name = “AddInt”)]

   Int Add(int arg1, int arg2);

 

   [OperationContract(Name = “AddDouble”)]

   Double Add(double arg1, double arg2);

}

 

Public partial class CalculatorClient : ClientBase<ICalculator>, ICalculator

{

   Public int Add(int arg1, int arg2)

   {

      Return Cahnnel.Add(arg1, arg2);

   }

 

   Public double Add(double arg1, double arg2)

   {

      Return Channel.Add(arg1, arg2);

   }

}

 

이렇게 하여 클라이언트는 Operation 오버로딩을 통하여 읽기 쉽고 자연스러운 프로그래밍 모델로 구현할 수 있다.

 

CalculatorClient proxy = new CalculatorClient();

 

Int result1 = proxy.Add(1, 2);

Double result2 = proxy.Add(1.0, 2.0);

 

Proxy.Close();

 

2.     계약의 상속

 

서비스 계약의 인터페이스는 각각 파생할 수 있고, 계약의 계층으로 정의하여 이용할 수 있지만, ServiceContract 애트리뷰트는 상속이 불가능하다. 따라서 인터페이스의 모든 계층은 명백한 ServiceContract 애트리뷰트를 가지고 있어야 한다.

 

호스트는 최종적으로 상속받은 인터페이스로 하나의 엔드 포인트를 노출시킬 수 있다.

 

<service name = “MyCalculator”>

   <endpoint

      Address = http://localhost:8001/MyCalculator/

      Binding = “basicHttpBinding”

      Contract = “IScientificCalculator”

   />

</service>

 

인터페이스를 상속하여 정의된 서비스 엔드 포인트의 메타 데이터를 클라이언트가 참조하게 되면 클라이언트의 계약은 상속 계층을 유지하지 않고, 하나의 계약 안에 포함되어 구성한다. , 그 계약은 기존의 인터페이스들에서 가졌던 모든 Operation이 하나의 계약으로 조합된다. 또한 참조된 계약의 모든 메서드는 하나의 프록시를 통해 구현된다.

 

추가사항: 클라이언트에서 상속의 재구성

 

3.     서비스 계약의 설계 및 팩토링

 

서비스 계약에 대한 디자인을 어떻게 할 것인가?

어느 계약에 어느 동작들을 포함시킬 것인가?

서비스 계약에는 얼마나 많은 동작들을 가지는 것이 좋은가?

è  서비스 지향적 분석 및 설계

 

WCF 에서 만의 내용이 아닌 객체지향 프로그램으로 생각하자. 서비스 계약을 분해할 때 언제나 재사용적인 관점들을 생각해야 한다.

 

간단한 예를 통해 생각해보자.

강아지 서비스 모델을 만들고 싶다고 가정해보자. 이 서비스의 요구 사항을 살펴보면 강아지는 짖을 수 있거나 물어 오기 놀이를 할 수 있다. 또한 가출병원의 등록 번호를 가지고 있고 백신 접종도 할 수 있을 것이다. , IDog 서비스 계약을 정의할 수 있고 PoodleService, GermanShepherdService와 같은 서비스의 종류도 정의할 수 있을 것이다.

 

[ServiceContract]

Interface IDog

{

   [OperationContract]

   Void Fetch();

 

   [OperationContract]

   Void Bark();

 

   [OperationContract]

   Long GetVetClinicNumber();

 

   [OperationContract]

   Void Vaccinate();

}

 

Class PoodleService : IDog

{ … }

 

Class GermanShepherdService : IDog

{ … }

 

하지만 IDog 서비스 계약의 구성은 요소화가 잘 되었다고 보기 어렵다. Fetch() Bark() 같은 경우는 논리적으로 관련이 있지만 GetVetClinicNumber() Vaccinate()는 논리성이 조금 떨어진다. Fetch() Bark()는 개가 가지고 있는 특성의 한 요소지만 GetVetClinicNumber() Vaccinate()는 다른 동물들도 가지고 있는 요소이기 때문이다.

 

[ServiceContract]

Interface IPet

{

   [OperationContract]

   Logn GetVetClinicNumber();

 

   [OperationContract]

   Void Vaccinate();

}

 

[ServiceContract]

Interface IDog

{

   [OperationContract]

   Void Fetch();

 

   [OperationContract]

   Void Bark();

}

 

더 나은 요소화적인 서비스를 위해 IPet 인터페이스를 생성해서 GetVetClinicNumber() vaccinate() 동작을 분리 시켰다. 이렇게 강아지과의 동물을 구별해 놓으면 서비스 계약의 재사용성이 가능하기 때문이다.

 

이러한 유형에서 각각의 독립된 계약으로 정의하지 않고 계약들의 상속으로 서비스를 요소화 할 수 있다.

 

팩토링

서비스 계약은 하나의 동작을 갖는 것이 가능하지만 이것은 피해야 할 것이다. 서비스 계약은 어떤 개체의 특징 중 하나인데 만약 한 가지 동작으로 표현 가능하다면 그 특징은 꽤 단조로운 편이라고 할 수 있다. 이 한 동작에 대해 다음을 생각해 보자. 너무 많은 파라미터를 사용하고 있지는 않은지? 너무 조잡하여 여러 개의 동작으로 나누는 것이 좋지 않은지? 기존에 존재하는 다른 서비스 계약에 포함시켜야 하지 않은지?

 

동작들을 요소화한 후에 각각의 동작들이 너무 세분화 되어 있지는 않은지를 살펴봐야 한다. 만약 12개 이상의 동작을 가지고 있다면 서비스 계약의 상속이나 서비스 계약의 분리로 요소화할 수 있는 방법을 정확하게 찾아 적용해야 할 것이다. 또한 코딩 표준을 정해 경우에 상관없이 넘지 말아야 할 상한선을 정하는 것이 좋다.

(최적 멤버 수는 3~5, 서비스 계약 안의 동작들은 6~9개의 동작이 적당)

 

추가사항: 계약 쿼리


Posted by glycerine
,