C #에서 인터페이스를 사용하지 않는 방법

응용 프로그램을 디자인 할 때 종종 인터페이스와 추상 클래스를 사용해야합니다. 이 문서에서는 "인터페이스 남용"의 몇 가지 일반적인 예와이를 방지하기 위해 사용할 수있는 전략에 대해 설명합니다. 또한 "구현이 아닌 인터페이스에 프로그래밍"이라는 신조가 의미하는 바에 대해서도 설명합니다.

인터페이스 란 무엇입니까?

먼저 인터페이스와 프로그래밍에 인터페이스가 필요한 이유를 이해하겠습니다. 인터페이스는 엄격하게 계약입니다. 구현이 없습니다. 인터페이스에는 멤버 선언 만 포함됩니다. 메서드 선언은 가질 수 있지만 정의는 가질 수 없습니다. 인터페이스에서 선언 된 멤버는 인터페이스를 확장하거나 구현하는 유형 (클래스 및 구조체)에서 구현되어야합니다. 인터페이스는 필드를 포함 할 수 없습니다. 인터페이스는 데이터 멤버를 가질 수 없기 때문에 직렬화 할 수 없습니다. 내가 말했듯이 인터페이스는 정의가 아닌 선언 만 가질 수 있습니다.  

인터페이스 변경 방지 

인터페이스를 확장하는 클래스 또는 구조체는 모든 멤버를 구현해야합니다. 구현이 변경 되더라도 코드는 계속 작동합니다. 그러나 계약, 즉 인터페이스가 변경되면 인터페이스를 확장하는 모든 유형의 구현을 변경해야합니다. 즉, 인터페이스를 변경하면 인터페이스를 확장하는 모든 유형에 영향을줍니다. 인터페이스를 확장하는 유형은 계약을 준수해야합니다. 따라서 인터페이스를 거의 변경할 필요가 없을 때만 사용하십시오. 또한 일반적으로 기존 인터페이스를 변경하는 것보다 새 인터페이스를 만드는 것이 좋습니다. 

구현이 아닌 인터페이스에 프로그래밍

"구현이 아닌 인터페이스에 프로그램"이라는 말을 가끔 들어 보셨을 것입니다. 코드에서 인터페이스를 사용하고 있었지만 여전히 구현을 프로그래밍하고있었습니다. 이제 두 접근 방식의 차이점을 살펴 보겠습니다.

인터페이스로 프로그래밍 할 때 구체적인 구현 대신 가장 일반적인 추상화 (인터페이스 또는 추상 클래스)를 사용합니다. 인터페이스는 균일 성을 보장하므로 인터페이스 프로그래밍은 유사한 객체를 균일 한 방식으로 처리 할 수 ​​있음을 의미합니다. 그렇게하면 구현에서 분리됩니다. 즉, 구현이 다를 수 있습니다. 이것은 또한 디자인에 유연성을 추가합니다.

다음 코드 스 니펫은 인터페이스에 대한 프로그래밍을 보여줍니다. 몇 가지 메서드의 선언이 포함 된 IRepository라는 인터페이스를 고려하십시오. ProductRepository 및 CustomerRepository 클래스는 아래와 같이 IRepository 인터페이스를 확장하고 IRepository 인터페이스에 선언 된 메서드를 구현합니다.

공용 인터페이스 IRepository

    {

        // 일부 코드

    }

    공용 클래스 ProductRepository : IRepository

    {

        // 일부 코드

    }

    공용 클래스 CustomerRepository : IRepository

    {

        // 일부 코드

    }

다음 코드를 사용하여 ProductRepository의 인스턴스를 만들 수 있습니다.

IRepository 저장소 = new ProductRepository ();

아이디어는 여기에서 IRepository 인터페이스를 구현하는 모든 클래스를 사용할 수 있다는 것입니다. 따라서 다음 문도 유효합니다.

IRepository 저장소 = new CustomerRepository ();

구현으로 프로그래밍하면이 균일 성이 손실됩니다. 대신 코드에서 동작을 제어하기위한 "if..else"또는 "switch..case"문과 같은 일부 구문이 있습니다.

인터페이스의 남용 방지

모든 클래스를 인터페이스와 연결하는 것은 좋은 방법이 아닙니다. 이러한 방식으로 인터페이스를 과도하게 사용하면 불필요한 복잡성이 발생하고 코드 중복이 발생하며 YAGNI를 위반하며 코드베이스의 가독성 및 유지 관리 가능성이 감소합니다. 인터페이스는 동일한 동작을 가진 개체를 그룹화하는 데 사용됩니다. 개체의 동작이 동일하지 않으면이 그룹화가 필요하지 않습니다. 인터페이스를 여러 번 구현하지 않을 때 인터페이스를 사용하는 것이 인터페이스 남용의 예입니다.

클래스의 공용 멤버와 일치하는 클래스에 대한 인터페이스를 만드는 것은 매우 일반적입니다. 이렇게하면 값을 전혀 추가하지 않고 실제 추상화를 추가하지 않고 클래스의 인터페이스를 복제 할뿐입니다.

이제 인터페이스가 어떻게 과도하게 사용되는지에 대한 예를 살펴 보겠습니다. IProduct라는 다음 인터페이스를 고려하십시오.

공용 인터페이스 IProduct

    {

        int Id {get; 세트; }

        string ProductName {get; 세트; }

        double Price {get; 세트; }

        int Quantity {get; 세트; }

    }

Product 클래스는 아래와 같이 IProduct 인터페이스를 확장합니다.

공개 클래스 제품 : IProduct

    {

        public int Id {get; 세트; }

        public string ProductName {get; 세트; }

        public double Price {get; 세트; }

        public int Quantity {get; 세트; }

    }

인터페이스와 구현이 동일하므로 IProduct 인터페이스가 필요하지 않습니다. 중복 코드는 필요하지 않습니다.

다른 예를 살펴 보겠습니다. 다음 코드 조각은 Save 및 Update라는 두 가지 메서드 선언이있는 IProductManager라는 인터페이스를 보여줍니다.

 공용 인터페이스 IProductManager

    {

        void Save (IProduct 제품);

        무효 업데이트 (IProduct 제품);

    }

IProductManager 인터페이스에는 ProductManager 클래스의 공용 메서드 선언이 포함되어 있습니다. ProductManager 클래스는 다음과 같습니다.

 공용 클래스 ProductManager : IProductManager

    {

        public void Save (IProduct 제품)

        {

           // 여기에 구현 작성

        }

        공개 무효 업데이트 (IProduct 제품)

        {

            // 여기에 구현 작성

        }

    }

IProduct 및 IProductManager 인터페이스는 인터페이스 남용의 예입니다. 이 두 인터페이스는 모두 단일 구현을 가지며 값을 전혀 추가하지 않습니다.

인터페이스를 사용하면 코드에서 불필요한 커플 링을 제거하고 코드를 쉽게 테스트 할 수 있습니다. 그러나 인터페이스의 과도한 사용은 피해야합니다. 둘 이상의 구현이있을 때만 인터페이스를 사용하십시오. 수행 할 역할이 많거나 여러 책임이있는 클래스가있는 경우에도 인터페이스를 사용할 수 있습니다. 이 경우 클래스는 각 역할에 대해 하나씩 여러 인터페이스를 구현할 수 있습니다.