2010-06-21 6 views
1

사면 여기에 길이 ... 희망 나는 내가 처음으로 생산 MVC 작업의 과정에있어 ... 바다에적절한 장소 - 비즈니스 로직이나 데이터 액세스

를 가지 않았다 DDD 원칙에 충실하려고 노력하고 있습니다. 응용 프로그램의 보안 요구 사항을 처리하는 방법과 관련된 몇 가지 질문에 답을 얻었으므로 SO 커뮤니티에서 최상의 실천 제안을 제공 할 수 있는지 알 수있을 것이라고 생각했습니다.

도메인 정보는

단순화 된 설명을 사용하려면이 응용 프로그램은 AffiliateCompanies, UsersCustomers이있을 것이다.

  • AffiliateCompanies은 계층 구조이므로 하나의 제휴사가 가입하고 다른 제휴사의 활동과 연결될 수 있습니다. 루트는 제품/서비스를 제공하는 주요 회사입니다.
  • Users은 모두 계열사에 속합니다.
  • Customers은 제품/서비스가 판매되는 조직입니다. 제휴사는 고객에게 배정되어 계층 적으로 관련이없는 2 명의 계열사가 고객을 분할하는 것이 가능합니다.

보안 정보

권리는 배열의 ACL 유형에 따라 결정됩니다 응용 프로그램에서 특정 작업을 수행 할 수 있습니다. 각 User 개체는 수행 할 수있는 작업과 해당 사용 권한의 범위 (개체, 계열사의 개체 또는 전체 계층 구조의 개체)를 결정하는 SystemAccessRules 컬렉션의 속성을가집니다. 사용자는 역할에 속할 수도 있습니다. 역할 자체에는 동일한 컬렉션 SystemAccessRules이 있습니다.

결과적으로 사용자가 로그인하여 "고객"목록을 보려는 경우 해당 목록은 개별적으로 할당 된 고객, 해당 계열 조직의 고객 또는 고객으로 구성 될 수 있습니다 자신의 조직 또는 자녀 계열 조직의 누구에게나 할당됩니다.

데이터베이스 고려 옆

DDD, 어떤 점에서 스토리지 전략은 활동하기 시작한다. 이 간단한 시나리오에서는, 테이블은 객체 사이의 관계를 지원하기 위해 몇 가지 지원 테이블 (A 역할 테이블 포함) 위의 객체에 정렬 :

  • AffiliateCustomers -이 테이블은 다 대다 수 있습니다 각 엔티티의 PK를 자체적으로이 테이블의 복합 PK 인 FK 쌍으로 저장하여 계열사와 고객 간의 관계를 정의합니다.
  • ACL -이 테이블에는 보안 정보, 특히 항목 (사용자 또는 역할), 문제의 조치 (예 : "CreateCustomer"), 권한 (허용 또는 거부) 및 범위 자신의 물건, 조직 또는 네트워크).

질문 ...마지막으로

나는 저장소와 서비스의 조합을 사용하고 있습니다. 나는 비즈니스 로직을 서비스와 저장소 또는 데이터베이스에서 유지하려고 노력하고 있지만 보안 설계로 인해 "고객"목록에 대한 간단한 요청이 특히 데이터 세트가 커짐에 따라 엄청난 부담이 될 수 있습니다. 가능하면 Linq를 사용하려고했지만이 아키텍처는 적합하지 않은 것 같습니다. 내가 그것을보고, 여기 내 선택이다 :

  1. 는 서비스 메소드의 인수로 요청을 승인 (또는 문맥하여 결정) 및 서비스 방법은 Linq를 저장소에 여러 쿼리를 통해 목록을 채울 수 있습니다. 이렇게하려면 고객 목록을 가져온 다음 각 고객을 통해 ACL 데이터를 가져 오기 위해 다른 쿼리를 실행 한 다음 해당 데이터를 사용하여 사용 권한을 기반으로 첫 번째 목록을 필터링해야합니다. 계층 구조 문제는 가능하다면 약간의 멋진 Linq 풋워크 (예 : this)가 필요합니다. 계층 구조 문제가 작동하도록 만들 수있다하더라도
    , 인수로 요청을 수락 ... 잘

  2. 을 수행하지만, (그것을하고 필요한 권한을 통과하지 않습니다이 솔루션처럼 보인다 예를 들어 "고객보기")를 저장소에 연결하여 데이터의 계층 적 성격을 설명 할 수있는 CTE 쿼리에서 여러 EXISTS 절을 사용하는 저장 프로 시저를 통해 데이터베이스에서 적절한 데이터를 검색하고 역할 및 사용자 보안.
    이것은 데이터베이스에 상당한 양의 논리를 푸시합니다. 이는 매우 DDD가 안 좋고 일반적으로 좋지 않은 것처럼 보입니다.

나는 두 번째 옵션쪽으로 더 기울고 있어요,하지만 나는 그것을 한 적이 방법은 그 때문에 나의 과거 프로젝트에있을 수있다. 나는 전반적인 디자인이 올바른지 잘 모르겠다. (과거에는 비트 플래그를 사용하여 권한 선언을했기 때문에 비트 연산자를 사용하여 DB 쿼리를 수행하는 것이 훨씬 쉬웠다.)

비슷한 상황에 처한 사람이 있습니까? 그렇다면 내가 추구하는 솔루션의 성능과 유지 관리 가능성에 대해 의견을 말할 수 있습니까? 나는 고집 센 프로그래밍 원리를 고수하고 싶지만 단순함과 상식을 희생하지는 않습니다.

+0

답변 만이 아니라 KISS 및 YAGNI 원칙을 기억하십시오. 저장소 코드/서비스 인터페이스를 중심으로 응용 프로그램 코드를 설계하여 내부 내용을 항상 1에서 2로 변경할 수 있습니다. 그런 다음 가능한 가장 간단하고 쉬운 구현을 수행하십시오. 예 : 2 당신이 익숙한 것이면. 놓친 것이 나중에 깨질 수 있기 때문에 너무 많이 디자인에 집어 넣지 마십시오. 그냥 충분히 추상화하고 리팩터링을 점진적으로 유지하십시오. – queen3

+0

예, 저는 지금 현실이 아닌 예상 요구 사항에 대한 과도한 엔지니어링에 대한 열망에 저항하고 있습니다. 동시에 나는 구석에 페인트 칠하고 싶지 않다.나는 목록의 각 AffiliateCompany 객체에있는 IEnumerable 속성의 내용을 들여다 봄으로써 보안을 평가하는 것이 얼마나 안 좋은지 몇 가지 테스트를해야 할 것이라고 생각한다. 결국 그게 그 평가를 데이터베이스에 두는 것에 대한 나의 질문을 이끌어내는 것입니다 ... 나는 DB가 더 빨라질 것이고, 나는 얼마나 더 빨리 빠지는 지 알 것입니다. –

답변

0

specification pattern을 사용하여 비즈니스 규칙을 데이터 액세스 계층으로 전달하는 것을 고려 했습니까?

서비스는 저장소로 전달되는 사양 트리를 구성합니다. 저장소는 사양을 Expression<Func<Customer, bool>>으로 변환하여 IQueryable<Customer>.Where(...)으로 전달합니다. 저장소가 컬렉션을 구체화하면 (예 : ToList()을 호출하면 비즈니스 규칙이 SQL로 변환되고 데이터베이스 서버에서 실행됩니다.

지난 번 확인한 경우 LINQ to SQL은 CTE를 지원하지 않으므로보기를 사용하여 계층 구조를 병합해야 할 수 있습니다.

+0

그 패턴을 보면 코드가 읽기 쉽다는 것을 좋아합니다. 지금은 확장 메서드 Has (enum)를 사용하여 지정된 보안 열거 형이 사용자 역할의 일부인지 테스트하지만 그다지 좋지 않습니다. 나는 # 2로 가면서 DB에 사용자와 역할 정보를 보내고 결과를 필터링하도록했습니다. 그것은 잘 작동하고 성능은 좋지만 DB 변경 사항을 추적하기가 더 어려워 유지 관리가 약간 어려움이 입증됩니다. 테이블 변경은 뷰, 함수, sprocs 등에 대한 변경을 의미합니다. –

관련 문제