2014-04-28 4 views
0

현재 프로젝트에서 좋은 아키텍처를 얻으려고 애 쓰고 있습니다. 소프트웨어 엔지니어링 (DI, 단위 테스트 등)의 모범 사례를 사용하려고하는 심각한 n 계층 응용 프로그램을 설계하는 것은 제 주먹으로 생각합니다. 내 프로젝트는 Onion 아키텍처를 사용하고 있습니다. 그것은 내 비즈니스 개체를 잡고 :DAL 개체를 Core 개체로 변환하는 클래스 도우미가있는 것이 바람직하지 않습니다.

나는 4 층

  1. 핵심 계층 있습니다. 여기에는 비즈니스 엔티티를 대표하는 클래스가 있습니다. 이러한 객체 중 일부는 서비스 인터페이스에 대한 참조를가집니다.

  2. DAL (데이터 액세스) 계층 : POCO 개체를 정의하고 코어 계층에 정의 된 저장소 인터페이스를 구현합니다. 이 레이어에서는 DAL의 POCO 개체와 Core의 Business Object를 변환하는 역할을하는 큰 유틸리티 클래스를 설계하는 것이 좋습니다.

  3. 서비스 레이어 : 코어에 정의 된 서비스 인터페이스를 구현합니다. 이 계층의 역할은 DAL에 정의 된 저장소에 대한 액세스를 제공하는 것입니다. 나는이 레이어가 쓸모 없다고 일차적으로 믿었 기 때문에 내 코어 레이어에 저장소 인터페이스 정의를 직접 사용했습니다. 그러나 매우 긴 instanciation 코드를 쓰는 데 몇 주를 보냈다 - 생성자가 5-6 개의 IRepository 매개 변수를 사용하는 것을 보았을 때 - 나는 Service Layer의 포인트를 얻었다.

  4. 프리젠 테이션 레이어. 아무것도 말할 필요가 없지만,이 레이어에 의존성 삽입을 구성한다는 점만 제외하면 (Ninject를 사용하고 있습니다).

나는 내 코드가 잘못되었다는 것을 많은 시간을 보았 기 때문에 아키텍처를 변경하고 적어도 3 번 이상 코드를 다시 작성했습니다. (긴 매개 변수 목록을 가진 긴 생성자와 같은 것들). 다행히도 비트 당 비트 (bit per bit) 나는 여러 가지 코딩 패턴을 한 점에서 찾아 냈습니다. 난 그냥 내 DI와 순환 의존성 건너 한 내 DAL2Core 도우미 좋은 생각이 있었다면 내가 심각하게 궁금하네요 그러나

... 내가 같은 코드를 작성할 수 있습니다이 도우미로

감사 :

 DAL.Point p = DAL2Core.PointConverter(point); // point is a Core Object 
     context.Points.Add(p); 
     context.SaveChanges(); 

약간의 코드 중복을 줄입니다. 그런 다음 DAL에 정의 된 내 저장소 각각 자신의 DAL2Core 회원이 :

private IDAL2CoreHelper DAL2Core; 

을 그리고 저장소 생성자에서 주입.

DAL2Core 클래스 자체는 다소 복잡합니다 ... 우선, 모든 저장소와 모든 프로세서 (서비스 계층)에 대한 속성이 있습니다. 프로세서가있는 이유는 내 핵심 객체가 프로세서 종속성을 주입해야하기 때문입니다.

[Inject] 
    private Core.IUserRepository UserRepository{ get; set; } 
    [Inject] 
    private Core.IPointsRepository PointsRepository { get; set; } 


... 

    [Inject] 
    private Core.IUserProcessor UserProcessor{ get; set; } 
    [Inject] 
    private Core.IPointsProcessor CoursProcessor { get; set; } 

합니다 (DAL2Core 도우미 때문에, 저장소에 필요한 생성자 주입 순환 의존성을 야기) : 난 그냥 설명하기 위해 아래에있는 내 DAL2Core 유틸리티 클래스에 참조 된 저장소 및 프로세서의 일부를 넣었습니다

public Core.User UserConverter(DAL.User u) 
    { 
     Core.User user = new Core.User(UserProcessor); 
     user.FirstName= u.FirstName; 
     user.Name= u.Name; 
     user.ID = u.ID; 
     user.Phone= u.Phone; 
     user.Email= u.Email; 
     user.Birthday= u.Birthday; 
     user.Photo = u.Photo; 
     return user; 
    } 

이 클래스는 600 백 개 라인과 같다 :

그리고는이 클래스는 다음과 같은 간단한 방법을 많이 가지고있다. DAL2Core Convertion 코드는 한 곳에서만 호출되기 때문에 많은 코드를 저장하지 않으므로이 코드를 리포지토리에 두는 것이 좋습니다. 그리고 가장 큰 문제는 -이 헬퍼를 리포지토리 클래스에서 분리하기로 결정한 이후 Ninject가주기적인 예외를 throw합니다.

내가 시도한 디자인에 대해 어떻게 생각합니까? 좋은/일반적인 관행입니까? 그리고 어떻게 코드 냄새없이이 DAL2Core 변환을 현명하고 효율적으로 수행 할 수 있습니까? 이 아키텍처 문제를 해결하는 데 정말로 기대하고 있습니다. 지난 3 주간 배관 및 아키텍처 문제를 다루었으며 실제로 프로젝트를 발전시키지 않았습니다. 나는 매우 늦어지고있다. 그러나 나는 정말 고품질의 코드를 만들고 싶다. 나는 많은 것들이있는, 공장의 많은 것들과 같은, 나에게 잔인한 것처럼 보이는 건축 솔루션을 피하고 싶다. 그러나 나는 언젠가는 나로부터의 이해가 부족하다는 느낌을 받는다.

미리 도움 주셔서 감사합니다.

답변

3

당신이 찾고있는 것은 AutoMapper, Value injector 또는 이와 비슷한 것입니다.

기본적으로 레이어 간의 데이터 모델을 분리하여 연결을 줄이고 테스트 가능성을 높이는 것이 좋습니다. 제네릭 매퍼를 사용하면 코드 중복을 줄일 수 있습니다.

희망이 도움이됩니다.

+0

+1 AutoMapper는 내가 제안한 것입니다. – Mike

+0

또 다른 요점은 AutoMapper 또는 일부 기능을 사용하면 맵핑이 자체적으로 레이어/애스펙트에 강제로 적용된다는 것입니다. 테스트에 도움이 될 수 있습니다. 프로덕션에서 우리는 빌더 (조수와 같은 인스턴스가 아닌 인스턴스)와 AutoMapper의 조합을 사용하며 추가 된 신뢰를 위해 객체 매핑에 대한 객체에 대한 어설 션을 제공 할 수 있습니다. – brumScouse

+0

그것이 내가 필요로하는 것처럼 고마워! 나는 많은 재산으로 이름을 바꾸지 않아도되기를 바랍니다. 그러나 어쨌든 그것은 그것이가는 길인 것처럼 보인다. – reddy