2009-03-27 34 views
5

Nếu tôi có ba thực thể, Project, ProjectRole và Person, trong đó một Person có thể là thành viên của các Project khác nhau và nằm trong các Role khác nhau (chẳng hạn như "Project Lead", hoặc "Project Member"). một mối quan hệ?Làm cách nào để bạn mô hình hóa vai trò/mối quan hệ với Domain Driven Design?

Trong cơ sở dữ liệu, tôi hiện có các trình tạo tab sau: Project, Person, ProjectRole Project_Person với PersonId & ProjectId là PK và ProjectRoleId như một mối quan hệ FK.

Tôi thực sự thua lỗ ở đây vì tất cả các mô hình miền tôi đưa ra dường như phá vỡ một số quy tắc "DDD". Có bất kỳ 'tiêu chuẩn' nào cho vấn đề này không?

Tôi đã xem xét Mô hình đối tượng được sắp xếp hợp lý và có ví dụ về dự án và ProjectMember trông như thế nào, nhưng AddProjectMember() trong Project sẽ gọi ProjectMember.AddProject(). Vì vậy, dự án có một danh sách các ProjectMembers, và mỗi ProjectMember trong trở lại có một tham chiếu đến dự án. Có vẻ hơi phức tạp với tôi.

cập nhật

Sau khi đọc thêm về chủ đề này, tôi sẽ thử như sau: Có vai trò riêng biệt, hoặc tốt hơn, mối quan hệ mô hình, mà là của một vai trò loại nhất định trong tên miền của tôi. Ví dụ, ProjectMember là một vai trò riêng biệt cho chúng ta biết điều gì đó về mối quan hệ mà một người chơi trong một dự án. Nó chứa một ProjectMembershipType cho chúng ta biết thêm về Role mà nó sẽ chơi. Tôi biết chắc chắn rằng mọi người sẽ phải đóng vai trò bên trong một dự án, vì vậy tôi sẽ mô hình mối quan hệ đó.

ProjectMembershipTypes có thể được tạo và sửa đổi. Đây có thể là "Nhà lãnh đạo dự án", "Nhà phát triển", "Cố vấn bên ngoài" hoặc một điều gì đó khác.

Một người có thể có nhiều vai trò bên trong một dự án và những vai trò này có thể bắt đầu và kết thúc vào một ngày nhất định. Các mối quan hệ như vậy được mô hình hóa bởi lớp ProjectMember.

public class ProjectMember : IRole 
{ 
    public virtual int ProjectMemberId { get; set; } 
    public virtual ProjectMembershipType ProjectMembershipType { get; set; } 

    public virtual Person Person { get; set; } 
    public virtual Project Project { get; set; } 
    public virtual DateTime From { get; set; } 
    public virtual DateTime Thru { get; set; } 
    // etc... 
} 

ProjectMembershipType: ie. "Project Manager", "Developer", "Adviser"

public class ProjectMembershipType : IRoleType 
{ 
    public virtual int ProjectMembershipTypeId { get; set; } 
    public virtual string Name { get; set; } 
    public virtual string Description { get; set; } 

    // etc... 
} 

Trả lời

1

Bạn đang lập mô hình mối quan hệ nhiều-nhiều: một dự án có thể có nhiều người làm việc trên đó và một người có thể làm việc trên nhiều dự án.

Bạn đang lập mô hình quan hệ dưới dạng vai trò dự án, ngoài việc phân phát dưới dạng liên kết hai hướng từ Person < -> Project, cũng ghi lại RoleType và bắt đầu/kết thúc của Người đó điền vào RoleType đó . (Chú ý cách tiếng Anh hoạt động "đó" là viết tắt của cơ sở dữ liệu FK hoặc, trong mã, con trỏ/tham chiếu?)

Vì những FK đó, chúng ta có thể trong cơ sở dữ liệu theo đồ thị từ Person, thông qua Project Role, để dự án:

select a.person_id, b.project_role_id, c.project_id 
from person a join project_role b on (a.id = b.person_id) 
join project c on (b.project_id = c.id) 
where a.person_id = ? 

Hoặc chúng ta có thể làm theo nó theo một hướng khác, từ dự án:

select a.person_id, b.project_role_id, c.project_id 
from person a join project_role b on (a.id = b.person_id) 
join project c on (b.project_id = c.id) 
where c.project_id = ? 

Lý tưởng nhất, chúng tôi muốn để có thể làm điều tương tự trong mã C#. Vì vậy, có, chúng tôi muốn một người để có một danh sách, và dự án để có một danh sách, và một tham chiếu ProjectRole cho một người và một dự án.

Vâng, Project::addPerson(Person&) thực sự nên Project::addProjectRole(ProjectRole&), trừ khi chúng tôi quyết định rằng Project::addPerson(Person&) là một phương pháp tiện lợi của hình thức:

void Project::addPerson(Person& p) { 
    this.addProjectRole(new ProjectRole(p, &this, RoleType::UNASSIGNED) ; 
} 

Một ProjectRole không có một danh sách, nó có-một tham chiếu đến một Person và một tham chiếu đến một dự án. Nó cũng có, như các giá trị, ngày bắt đầu, ngày kết thúc và kiểu vai trò (mà là một enum hoặc một cá thể lớp bắt chước một giá trị enum - nghĩa là chỉ có một đối tượng cho mỗi loại enum và không trạng thái, bất biến và không có tính chất, và do đó có thể chia sẻ giữa nhiều ProjectRoles).

Bây giờ điều này không có nghĩa là truy xuất một người từ cơ sở dữ liệu sẽ làm cho toàn bộ cơ sở dữ liệu được thống nhất trong biểu đồ đối tượng trong mã; những proxy lười chỉ lấy về sử dụng có thể cứu chúng ta khỏi điều đó. Sau đó, nếu chúng ta hiện chỉ quan tâm đến Người, và không phải Vai trò của Người (và Dự án, chúng ta có thể lấy Người. (NHibernate, ví dụ, tôi nghĩ điều này nhiều hơn hoặc ít liên tục hơn.)

Về cơ bản , Tôi nghĩ rằng:

1) Đây là cách tiêu chuẩn để thể hiện quan hệ nhiều-nhiều; 2) Tiêu chuẩn cho mối quan hệ có dữ liệu bổ sung (khi nào, loại nào) và; 3) bạn đã có khá nhiều ý tưởng đúng, và chỉ cần được tận tâm trong việc nhận được phản hồi ở đây.

0

Bạn không nhầm lẫn "Mô tả" về vai trò của một người trong dự án? Thêm khái niệm "RoleDescription" (một 'vai trò lớp' để nói), và "RoleInstance" đối tượng đề cập đến những người thực sự trong các dự án có thể giúp đỡ.

+0

Tôi không biết, điều đó là có thể, tôi không chắc chắn ý bạn là gì – kitsune

+0

Tôi sợ tôi hẹn hò từ thời đại cơ sở dữ liệu quan hệ nhưng ăn quá nhiều OOD ... Tôi đang đề cập đến 'Giải pháp thứ hai' Câu trả lời của Jamie. – xtofl

0

Điều bạn có là mối quan hệ nhiều - nhiều, với dữ liệu bổ sung, vai trò. Chúng tôi có một cấu trúc tương tự, ngoại trừ trường hợp của chúng tôi, một người có thể có nhiều vai trò trong một dự án, vì vậy tôi đã phải vật lộn với cùng một câu hỏi. Một giải pháp là tạo ra một lớp ProjectPerson mở rộng Person và thêm vai trò tài sản:

public class ProjectPerson : Person 
{ 
    public string Role { get; set; } 
} 

lớp dự án của bạn bây giờ có một bộ sưu tập các ProjectPerson nhưng lớp người có một tập hợp các dự án bởi vì nó không có ý nghĩa với mở rộng lớp Project để thêm role. Bạn sẽ phải thực hiện một số công việc bổ sung (tra cứu Person trong bộ sưu tập ProjectPerson) để tìm vai trò trên một Project từ góc nhìn của Person.

Giải pháp thứ hai là cách tiêu chuẩn để xử lý mối quan hệ nhiều-nhiều với dữ liệu bổ sung. Tạo một lớp ProjectRole và mô hình hóa nó như là một mặt của hai mối quan hệ một-nhiều từ Project và Person. Tức là cả Project và Person đều có một bộ sưu tập ProjectRole.

Điều quan trọng là phải xem xét chiến lược truy cập dữ liệu của bạn sẽ hỗ trợ tốt như thế nào trong việc chọn giải pháp. Bạn muốn tránh các tình huống khi tải bộ sưu tập yêu cầu một hoặc nhiều chuyến đi đến cơ sở dữ liệu cho từng đối tượng trong bộ sưu tập.

+0

Tôi khuyên bạn nên chống lại lớp 'ProjectPerson', vì sớm hay muộn bạn sẽ kết thúc với một 'BillablePerson', 'InternshipPerson' và 'TerriblePerson', tất cả đều đề cập đến cùng một người 'thực'. I'ld gắn bó với quan hệ có một thay vì giải pháp thừa kế. – xtofl

+0

Tôi không hiểu đối số của bạn: giải pháp đề xuất sẽ tạo ra các phần mở rộng bổ sung của Người như thế nào? ProjectPerson chỉ là một Person trong một vai trò trong bối cảnh của một Project. Trong thuật ngữ cơ sở dữ liệu, nó được truy xuất bằng cách nối bảng người đó với bảng liên kết nhiều-nhiều. –

3

Đây là cách tôi sẽ xử lý nó:

class Person 
{ 
    string Name { get; set; } 
    IList<Role> Roles { get; private set; } 
} 

class Role 
{ 
    string Name { get; set; } 
    string Description { get; set; } 
    IList<Person> Members { get; private set; } 
} 

class Project 
{ 
    string Name { get; set; } 
    string Description { get; set; } 
    IList<ProjectMember> Members { get; private set; } 
} 

class ProjectMember 
{ 
    Project Project { get; private set; } 
    Person Person { get; set; } 
    Role Role { get; set; } 
} 

Các ProjectMember lớp mang lại cho họ tất cả cùng nhau. Mô hình này cung cấp cho bạn sự linh hoạt để chỉ định cùng một Người cho các Dự án khác nhau với các Vai trò khác nhau (ví dụ: ông có thể là Nhà phát triển trên ProjectA và Người thử nghiệm trên ProjectB).

Vui lòng không tạo các lớp học đặc biệt cho vai trò - bài học đó đã được học.

Tôi đã tạo một sample app để chứng minh điều này (nó bao gồm các mối quan hệ quá):

  1. Run "bin \ debug \ RolesRelationshipsSample.exe"
  2. Nhấp đúp vào biểu tượng thư viện để tạo ra các đơn vị
  3. Kéo/thả chúng để chỉ định các mối quan hệ thích hợp

Vui lòng chơi với mã. Hi vọng bạn tìm được thứ hữu dụng.

+0

Cảm ơn! Tôi đã đi vào một hướng tương tự như của bạn, xin vui lòng kiểm tra câu hỏi cập nhật của tôi. – kitsune

+0

@Vijay Patel Tại sao không tạo ra các lớp học đặc biệt? Điều gì sẽ xảy ra nếu mỗi vai trò có thể thực hiện các hành động khác nhau trong dự án? – richard

+0

@Richard: Từ ví dụ của tôi, phân loại phụ từ "Vai trò" không phải là vấn đề. Tôi nghĩ rằng tôi đã ám chỉ đến kịch bản từ Jamie Ide bên dưới http://stackoverflow.com/a/689618/80369 –

0

Dường như có hai thực thể chính - Thành viên dự án và dự án. Thành viên dự án có các thuộc tính 'Vai trò thành viên' và 'Tên thành viên'. Một trong các thuộc tính này có thể thuộc về một miền, nghĩa là một tập hợp các giá trị có thể được duy trì trong các bảng tra cứu để thuận tiện và sử dụng để tìm kiếm. Người ta cho rằng ai đó yêu cầu thông tin về tất cả các thành viên của dự án thực hiện một vai trò/công việc cụ thể.

Lưu ý. Các bảng tra cứu có thể có các mục được thêm vào nhưng thông thường sẽ không có giá trị của một mục được thay đổi. Khi một giá trị được chọn từ bảng tra cứu thì nó được coi là một cố định vĩnh viễn của bảng sở hữu - trong trường hợp này là bảng Thành viên dự án.

Tôi không mong đợi sẽ nhìn thấy thực thể hoặc bảng 'Người' trong bất kỳ doanh nghiệp nào khác ngoài sự tiện lợi như bảng tra cứu như trong trường hợp trên. Bộ phận nhân sự sẽ giữ một danh sách các nhân viên có thông tin cụ thể được yêu cầu bởi biên chế vv nhưng không có gì cơ bản abut Những người mà doanh nghiệp sẽ cần phải biết. NB Xác định quy trình nghiệp vụ để xác định thực thể - đừng tạo ra nó.

Các vấn đề liên quan