클래스 및 인터페이스 파일을 가장 잘 구성하는 방법은 무엇입니까?


17

OK .. 모든 토론 후에 내가 다루고있는 구체적인 예를 더 잘 반영하기 위해 질문을 약간 변경하고 있습니다.


나는이 개 수업을 ModelOne하고 ModelTwo이 클래스는 기능의 유사한 유형을 수행하지만 서로 관련이없는. 그러나 나는 제 3 유형이 CommonFunc모두 구현되어 일부 공공 기능을 포함 ModelOne하고 ModelTwo및 당 밖으로 고려되었습니다 DRY. 두 모델은 클래스 내에서 인스턴스화됩니다 ModelMain(자체는 상위 레벨 등에서 인스턴스화되지만이 레벨에서 중단됩니다).

사용중인 IoC 컨테이너는 Microsoft Unity 입니다. 나는 전문가 인 척하지 않지만, 컨테이너에 인터페이스와 클래스의 튜플을 등록하고 구체적인 클래스를 원할 때 특정 인터페이스와 일치하는 객체에 대해 IoC 컨테이너에 요청한다는 것입니다. 이것은 Unity에서 인스턴스화하려는 모든 객체에 대해 일치하는 인터페이스가 있어야 함을 의미합니다. 각 클래스는 서로 다른 (겹치지 않는) 기능을 수행하기 때문에 인터페이스와 클래스 1 사이에 1 : 1 비율이 있음을 의미합니다 . 그러나 내가 쓰는 모든 수업에 대해 인터페이스를 노예로 쓰고 있다는 의미는 아닙니다.

따라서 코드 현명한 나는 2 :

public interface ICommonFunc 
{ 
}

public interface IModelOne 
{ 
   ICommonFunc Common { get; } 
   .. 
}

public interface IModelTwo
{ 
   ICommonFunc Common { get; } 
   .. 
}

public interface IModelMain 
{ 
  IModelOne One { get; } 
  IModelTwo Two { get; } 
  ..
}

public class CommonFunc : ICommonFunc { .. }

public class ModelOne : IModelOne { .. }

public class ModelTwo : IModelTwo { .. }

public class ModelMain : IModelMain { .. }

문제는 솔루션을 구성하는 방법에 관한 것입니다. 수업과 인터페이스를 함께 유지해야합니까? 아니면 클래스와 인터페이스를 함께 유지해야합니까? EG :

옵션 1- 클래스 이름으로 구성

MySolution
  |
  |-MyProject
  |   |
      |-Models
      |   |
          |-Common
          |   |
          |   |-CommonFunc.cs
          |   |-ICommonFunc.cs
          |
          |-Main
          |   |
          |   |-IModelMain.cs
          |   |-ModelMain.cs
          |
          |-One
          |   |
          |   |-IModelOne.cs
          |   |-ModelOne.cs
          |
          |-Two
              |
              |-IModelTwo.cs
              |-ModelTwo.cs
              |

옵션 2- 기능별로 구성 (주로)

MySolution
  |
  |-MyProject
  |   |
      |-Models
      |   |
          |-Common
          |   |
          |   |-CommonFunc.cs
          |   |-ICommonFunc.cs
          |
          |-IModelMain.cs
          |-IModelOne.cs
          |-IModelTwo.cs
          |-ModelMain.cs
          |-ModelOne.cs
          |-ModelTwo.cs
          |

옵션 3- 인터페이스 및 구현 분리

MySolution
  |
  |-MyProject
      |
      |-Interfaces
      |   |
      |   |-Models
      |   |   |
      |       |-Common
      |       |   |-ICommonFunc.cs
      |       |
      |       |-IModelMain.cs
      |       |-IModelOne.cs
      |       |-IModelTwo.cs
      |
      |-Classes
          | 
          |-Models
          |   |
              |-Common
              |   |-CommonFunc.cs
              |
              |-ModelMain.cs
              |-ModelOne.cs
              |-ModelTwo.cs
              |

옵션 4- 기능 예제 추가

MySolution
  |
  |-MyProject
  |   |
      |-Models
      |   |
          |-Components
          |   |
          |   |-Common
          |   |   |
          |   |   |-CommonFunc.cs
          |   |   |-ICommonFunc.cs
          |   |   
          |   |-IModelOne.cs
          |   |-IModelTwo.cs
          |   |-ModelOne.cs
          |   |-ModelTwo.cs
          |
          |-IModelMain.cs
          |-ModelMain.cs
          |

경로의 클래스 이름으로 인해 옵션 1을 싫어합니다. 그러나 IoC 선택 / 사용으로 인해 1 : 1 비율로 경향 이 있습니다. 논쟁의 여지가있을 수 있습니다)이 파일 사이의 관계를 보는 장점이있다.

옵션 2는 저에게 호소력이 있지만 지금은 ModelMain 모델과 하위 모델 .

옵션 3은 인터페이스 정의를 구현에서 분리하는 데 사용되지만 이제 경로 이름에 이러한 인공 휴식이 있습니다.

옵션 4. 옵션 2를 사용하여 구성 요소를 상위 모델과 분리하기 위해 조정했습니다.

다른 것을 선호 할만한 이유가 있습니까? 아니면 내가 놓친 다른 잠재적 인 레이아웃?


1. Frank는 1 : 1 비율로 C ++ 일의 .h 및 .cpp 파일로 돌아가는 것을 언급했습니다. 나는 그가 어디에서 왔는지 안다. Unity에 대한 나의 이해가 나를이 코너에 넣는 것 같지만, 당신이 또한 욕설을 따르는 경우 어떻게 그것을 벗어날 수 있는지조차 확실하지 않습니다. 그러나 그것은 Program to an interface 다른 날 토론입니다.

2. 각 객체 생성자의 세부 사항을 생략했습니다. 이것은 IoC 컨테이너가 필요에 따라 개체를 주입하는 곳입니다.


1
어. 인터페이스 / 클래스 비율이 1 : 1 인 것으로 보입니다. 어떤 IoC 컨테이너를 사용하고 있습니까? Ninject는 1 : 1 비율이 필요없는 메커니즘을 제공합니다.
RubberDuck

1
@RubberDuck FWIW Unity를 사용하고 있습니다. 나는 그것의 전문가로 주장하지 않습니다,하지만 내 클래스가 아니라 하나의 책임을 설계하는 경우, 내가 어떻게 할 수 없습니다 거의 1로 끝날 : 1의 비율로?
피터 M

IBase가 필요합니까 아니면 기본이 추상적 일 수 있습니까? 이미 IBase를 구현할 때 IDerivedOne이있는 이유는 무엇입니까? 파생 된 것이 아니라 IBase에 의존해야합니다. Unity에 대해서는 잘 모르지만 다른 IoC 컨테이너를 사용하면 "문맥 구분"주입을 수행 할 수 있습니다. 기본적으로을 Client1필요로하는 경우을 IBase제공합니다 Derived1. 가 Client2필요할 때 IBaseIoC는을 제공합니다 Derived2.
RubberDuck

1
베이스가 추상적이라면 그럴만 한 이유가 없습니다 interface. 은 interface정말 모든 가상 구성원과 단지 추상 클래스입니다.
RubberDuck

1
RubberDuck이 맞습니다. 불필요한 인터페이스는 단순히 성가시다.
Frank Hileman

답변:


4

인터페이스는 기본적으로 기본 클래스와 유사하므로 기본 클래스에 사용하는 것과 동일한 논리를 사용하십시오. 인터페이스를 구현하는 클래스는 인터페이스와 밀접한 관련이 있습니다.

"Base Classes"라는 디렉토리를 선호한다고 생각합니다. 대부분의 개발자는이를 원하지 않으며 "인터페이스"라는 디렉토리도 있습니다. c #에서 디렉토리는 기본적으로 네임 스페이스이므로 혼동 될 수 있습니다.

가장 좋은 방법은 별도의 라이브러리에 라이브러리를 배치하고 비슷한 방식으로 네임 스페이스 / 디렉토리를 구성해야하는 경우 클래스 / 인터페이스를 분리하는 방법에 대해 생각하는 것입니다. .net 프레임 워크 디자인 지침에는 유용한 네임 스페이스 제안 이 있습니다.


제공 한 링크에 익숙하지만 파일 구성과 관련이 있는지 잘 모르겠습니다. VS는 초기 네임 스페이스의 경로 이름을 기본값으로 사용하지만 이것이 임의의 선택이라는 것을 알고 있습니다. 또한 코드 '샘플'과 레이아웃 가능성을 업데이트했습니다.
Peter M

@PeterM 어떤 IDE를 사용하고 있는지 잘 모르겠지만 Visual Studio는 디렉토리 이름을 사용하여 클래스를 추가 할 때 네임 스페이스 선언을 자동으로 생성합니다. 이는 디렉토리 이름과 네임 스페이스 이름간에 차이가있을 수 있지만 그렇게하는 것이 더 어렵다는 것을 의미합니다. 그래서 대부분의 사람들은 그렇게하지 않습니다.
Frank Hileman

VS를 사용하고 있습니다. 그리고 그래 나는 고통을 안다. Visual Source Safe 파일 레이아웃의 추억을 되살립니다.
피터 M

1
@PeterM 1 : 1 인터페이스 대 클래스 비율과 관련하여. 일부 도구에는 이것이 필요합니다. 나는 이것을 도구의 결함이라고 생각한다.
Frank Hileman

1

복잡한 프로젝트에서 더 많은 폴더 / 네임 스페이스를 사용하여 두 번째 접근 방식을 취합니다. 그것은 구체적인 구현에서 인터페이스를 분리한다는 것을 의미합니다.

다른 프로젝트에서 인터페이스 정의를 알아야 할 수도 있지만, 특히 IoC 컨테이너를 사용할 때이를 구현하는 구체적인 클래스를 알 필요는 없습니다. 따라서 다른 프로젝트는 구현 프로젝트가 아닌 인터페이스 프로젝트 만 참조하면됩니다. 이를 통해 참조를 낮게 유지하고 순환 참조 문제를 방지 할 수 있습니다.


코드 예제를 수정하고 더 많은 옵션을 추가했습니다
Peter M

1

디자인 질문과 마찬가지로 항상 가장 먼저 할 일은 사용자를 결정하는 것입니다. 그들은 당신의 조직을 어떻게 사용할 것입니까?

그들은 당신의 수업을 사용할 코더입니까? 그런 다음 코드에서 인터페이스를 분리하는 것이 가장 좋습니다.

그들은 당신의 코드 관리자입니까? 그런 다음 인터페이스와 클래스를 함께 유지하는 것이 가장 좋습니다.

앉아서 사용 사례를 작성하십시오. 그러면 최고의 조직이 당신 앞에 나타날 수 있습니다.


-2

인터페이스를 별도의 라이브러리에 저장하는 것이 좋습니다. 첫째, 이런 종류의 디자인은 의존성을 증가시킵니다. 이러한 인터페이스를 다른 프로그래밍 언어로 구현할 수 있습니다.

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