2015-01-06 16 views
6

Cập nhật:Reposted on Programmers Stack Exchange do bị giữ nguyên như chủ yếu dựa trên ý kiến.Ưu điểm & nhược điểm của việc sử dụng cấu trúc để thực thi xác thực loại được tích hợp

Các đối tượng miền thường có các thuộc tính có thể được biểu diễn bằng loại được tích hợp nhưng có giá trị hợp lệ là tập con của các giá trị có thể được biểu thị bằng loại đó.

Trong những trường hợp này, giá trị có thể được lưu trữ bằng cách sử dụng loại được tích hợp nhưng cần đảm bảo giá trị luôn được xác thực tại điểm nhập, nếu không chúng tôi có thể kết thúc với giá trị không hợp lệ.

Một cách để giải quyết điều này là lưu trữ giá trị dưới dạng tùy chỉnh struct có một trường sao lưu đơn private readonly của kiểu được cài sẵn và có hàm tạo xác thực giá trị được cung cấp. Sau đó, chúng tôi luôn có thể chắc chắn chỉ sử dụng các giá trị được xác thực bằng cách sử dụng loại struct này.

Chúng tôi cũng có thể cung cấp toán tử truyền từ và cho loại được tích hợp sẵn để các giá trị có thể nhập và thoát liền mạch làm loại cơ bản.

Ví dụ như một tình huống mà chúng ta cần đại diện cho tên của đối tượng miền và các giá trị hợp lệ là bất kỳ chuỗi nào có độ dài từ 1 đến 255 ký tự. Chúng ta có thể đại diện này bằng cách sử dụng cấu trúc sau:

public struct ValidatedName : IEquatable<ValidatedName> 
{ 
    private readonly string _value; 

    private ValidatedName(string name) 
    { 
     _value = name; 
    } 

    public static bool IsValid(string name) 
    { 
     return !String.IsNullOrEmpty(name) && name.Length <= 255; 
    } 

    public bool Equals(ValidatedName other) 
    { 
     return _value == other._value; 
    } 

    public override bool Equals(object obj) 
    { 
     if (obj is ValidatedName) 
     { 
      return Equals((ValidatedName)obj); 
     } 
     return false; 
    } 

    public static implicit operator string(ValidatedName x) 
    { 
     return x.ToString(); 
    } 

    public static explicit operator ValidatedName(string x) 
    { 
     if (IsValid(x)) 
     { 
      return new ValidatedName(x); 
     } 
     throw new InvalidCastException(); 
    } 

    public static bool operator ==(ValidatedName x, ValidatedName y) 
    { 
     return x.Equals(y); 
    } 

    public static bool operator !=(ValidatedName x, ValidatedName y) 
    { 
     return !x.Equals(y); 
    } 

    public override int GetHashCode() 
    { 
     return _value.GetHashCode(); 
    } 

    public override string ToString() 
    { 
     return _value; 
    } 
} 

Ví dụ cho thấy to- string cast như implicit như thế này không bao giờ có thể thất bại nhưng từ- string cast như explicit vì điều này sẽ ném cho các giá trị không hợp lệ, nhưng tất nhiên cả hai có thể là implicit hoặc explicit. Lưu ý rằng người ta chỉ có thể khởi tạo cấu trúc này theo cách của một dàn diễn viên từ string, nhưng người ta có thể kiểm tra xem liệu một diễn viên như vậy sẽ thất bại trước bằng phương pháp IsValidstatic hay không. Điều này có vẻ là một mô hình tốt để thực thi xác nhận các giá trị tên miền có thể được biểu diễn bằng các loại đơn giản, nhưng tôi không thấy nó được sử dụng thường xuyên hoặc được đề xuất và tôi quan tâm đến lý do tại sao.

Vì vậy, câu hỏi của tôi là: bạn thấy điều gì là lợi thế và bất lợi của việc sử dụng mẫu này và tại sao?

Nếu bạn cảm thấy rằng đây là một mẫu xấu, tôi muốn hiểu tại sao và những gì bạn cảm thấy là lựa chọn tốt nhất.

+0

Đối với tôi trình xác thực là logic miền có thể truy cập thông qua nhà máy hoặc lớp tĩnh trong một không gian tên rất cụ thể. tức là: 'MyApp.Validators' và trình xác thực lớp cụ thể trong không gian tên đó như' ClientValidator' chứa tất cả xác nhận hợp lệ. Tôi thực sự không thấy việc sử dụng cấu trúc ở đây – Franck

+0

Hãy đến với các bạn, Ứng cử viên để chuyển sang các lập trình viên có thể trao đổi, chắc chắn không chỉ đơn thuần là ý kiến ​​mặc dù –

+1

Tôi sẽ cung cấp câu trả lời của tôi, nhưng với 1 phiếu bầu gần nhất để được Q & A đóng lại. .... –

Trả lời

0

Cách của bạn là một chút mã công bằng, bạn phải thêm kiểm tra bình đẳng và truyền khi ý định của bạn là xác thực.

bạn đang ở đâu tại nếu bạn cần validatedname2 mà không thể được null hoặc khoảng trắng và có từ 8 & 16 ký tự không có dấu chấm câu và sau đó ValdatedNameType3 ...

Mine sẽ sử dụng thuộc tính, ví dụ allow_blank và chiều dài tối đa hoặc thậm chí là một regex

+0

Đó là một ý tưởng hay. Anh ta có thể thêm thuộc tính vào mọi thuộc tính và sau đó tạo ra một phương thức lấy bất kỳ lớp nào và sử dụng sự phản chiếu để lấy tất cả các thuộc tính của trình duyệt tính hợp lệ và áp dụng chúng cho từng thuộc tính một. Rất chung chung và có thể mở rộng. – Franck

+0

Tôi đồng ý rằng trong trường hợp có nhiều loại như vậy, điều này có thể trở thành một số ít để tạo ra tất cả, nhưng đối với nhiều loại, điều này có thể đạt được bằng cách sử dụng mẫu vì chỉ có rất nhiều loại xác thực có thể cần thiết cho các giá trị có thể được biểu diễn bằng các loại được tích hợp sẵn. – gmoody1979

+0

Các vấn đề mà tôi thấy bằng cách sử dụng thuộc tính: trước hết nếu loại giá trị tên miền được sử dụng ở nhiều vị trí, cần phải thêm các thuộc tính đó vào mọi cách sử dụng, điều này có thể lộn xộn và dễ dàng không đồng bộ. Thứ hai và có lẽ quan trọng hơn, điều này đòi hỏi bạn phải ở trong một tình huống mà bạn đang sử dụng xác nhận dựa trên thuộc tính. Tôi cho rằng điều này có lẽ là do câu hỏi cơ bản hơn về việc xác nhận các đối tượng miền sẽ được xử lý ở đâu. Nhưng tôi nhận ra đó là một câu hỏi cơ bản hơn, rộng hơn và chủ quan hơn. – gmoody1979

0

Cách của bạn khá nặng và chuyên sâu. Tôi thường xác định các thực thể tên miền như:

public class Institution 
{ 
    private Institution() { } 

    public Institution(int organizationId, string name) 
    { 
     OrganizationId = organizationId;    
     Name = name; 
     ReplicationKey = Guid.NewGuid(); 

     new InstitutionValidator().ValidateAndThrow(this); 
    } 

    public int Id { get; private set; } 
    public string Name { get; private set; }   
    public virtual ICollection<Department> Departments { get; private set; } 

    ... other properties  

    public Department AddDepartment(string name) 
    { 
     var department = new Department(Id, name); 
     if (Departments == null) Departments = new List<Department>(); 
     Departments.Add(department);    
     return department; 
    } 

    ... other domain operations 
} 

Trong hàm tạo của đối tượng, xác thực được kích hoạt bằng FluentValidation.Để đảm bảo bạn không thể tạo một thực thể có trạng thái không hợp lệ. Lưu ý rằng các thuộc tính đều là chỉ đọc - bạn chỉ có thể đặt chúng thông qua hàm tạo hoặc các hoạt động miền chuyên dụng.

Xác nhận của tổ chức này là một lớp riêng biệt:

public class InstitutionValidator : AbstractValidator<Institution> 
{ 
    public InstitutionValidator() 
    { 
     RuleFor(institution => institution.Name).NotNull().Length(1, 100).WithLocalizedName(() => Prim.Mgp.Infrastructure.Resources.GlobalResources.InstitutionName);  
     RuleFor(institution => institution.OrganizationId).GreaterThan(0); 
     RuleFor(institution => institution.ReplicationKey).NotNull().NotEqual(Guid.Empty); 
    } 
} 

Những xác nhận cũng có thể dễ dàng tái sử dụng, và bạn viết mã ít soạn sẵn.

+0

Đây là loại hình có vẻ phổ biến hơn nhiều. Nhưng điều này không bị ảnh hưởng bởi việc xác nhận, ví dụ, Tên của tổ chức, có liên quan đến việc sử dụng tên như một tài sản của một tổ chức? Điều gì sẽ xảy ra nếu chúng ta muốn sử dụng một tên Instemem bị loại bỏ khỏi bối cảnh của một đối tượng Institution? – gmoody1979

+0

Trong trường hợp đó, bạn có thể tạo một InstitutionNameValidator tổng quát hơn, được sử dụng trong các thực thể khác nhau. Vì các trình duyệt tính hợp lệ này có thể sử dụng lại được, bạn có thể làm bất cứ điều gì bạn muốn ... –

+0

Có thể là mẫu tương đương trực tiếp hơn, mặc dù bạn vẫn phải đảm bảo rằng bạn theo dõi thời điểm giá trị đã được xác thực và khi chúng không có, và bạn có khả năng sẽ xác nhận cùng một điều liên tục hoặc tệ hơn không ở tất cả. Ngoài ra còn có các chi phí của việc tạo ra một đối tượng Validator bất cứ khi nào bạn muốn xác nhận, hoặc ít nhất có một tay, có thể hoặc có thể không phải là một vấn đề tùy thuộc vào kịch bản. – gmoody1979

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