2011-01-03 28 views
7

Trong cuốn sách coders at work, tác giả hỏi "Làm thế nào để bạn sử dụng bất biến trong mã của bạn". Xin giải thích ý nghĩa của câu hỏi này.Các xác nhận bất biến có phù hợp với lập trình C# không?

tôi thấy bất biến lớp on wiki, nhưng ví dụ là trong Java và tôi không đủ trong Java có tay nghề cao để liên hệ ví dụ này để C#. .NET 4.0 giới thiệu sự bất biến, hiệp phương sai, và contravariance và được giải thích rõ ràng here. Tính bất biến quá rộng. Các tác giả sử dụng từ này dường như có liên quan đến kiểm tra đơn vị. Đối với những người đọc cuốn sách, tác giả có ý nghĩa gì? Chúng ta đang nói về việc đưa ra một giả định và chỉ đơn giản là kiểm tra tính hợp lệ sau khi thử nghiệm đơn vị?

Trả lời

10

Từ bất biến không có nghĩa là nhiều thứ không thay đổi trong một số điều kiện nhất định. Có rất nhiều loại bất biến khác nhau. Ví dụ trong vật lý, tốc độ ánh sáng là bất biến theo biến đổi lorentz, tức là nó không thay đổi nếu bạn chuyển sang khung tham chiếu. Trong lập trình có nhiều loại bất biến nữa. Có những bất biến đẳng cấp không thay đổi trong suốt vòng đời của một đối tượng, những bất biến phương pháp mà không thay đổi trong suốt vòng đời của một hàm, ...

Một bất biến đẳng cấp là cái gì đó luôn luôn (ít nhất là ở công khai quan sát được) lần) đúng trong một thể hiện của lớp đó.

Điều này hoàn toàn không liên quan đến co-/contra-variance. Co-/Contra-variance mô tả các kiểu có thể được thay thế cho các kiểu khác với các tham số (kiểu) chung hoặc các kiểu trả về khác nhau. Trong khi bạn có thể gọi một cái gì đó bất biến bởi vì nó không hỗ trợ Co-/Contra-variance, đây là một loại bất biến hoàn toàn khác với một lớp hoặc phương thức bất biến.

Ví dụ một số loại bộ sưu tập có thể có những bất biến sau:

  • dữ liệu!= Null
  • Kích> = 0
  • Công suất> = 0
  • Kích < = Công suất

Với lớp này:

class MyCollection<T> 
{ 
    private T[] data; 
    private int size; 

    public MyCollection() 
    { 
    data=new T[4]; 
    } 

    public int Size{get{return size;}} 
    public int Capacity{get{return data.Length;}} 

    [ContractInvariantMethod] 
    protected void ClassInvariant() 
    { 
    Contract.Invariant(data != null); 
    Contract.Invariant(Size >= 0); 
    Contract.Invariant(Capacity >= 0); 
    Contract.Invariant(Size < Capacity); 
    } 
} 

Hầu hết các lớp có một số bất biến, nhưng không phải tất cả mọi người thực thi chúng. .net 4 thêm một cách tốt đẹp để tài liệu và khẳng định chúng bằng cách sử dụng các hợp đồng mã.

+1

Buồn cười bạn nói .NET invariance không liên quan đến các loại bất biến khác. Tôi không đồng ý, nhưng có lẽ đó là nơi tôi sai. Có lẽ loại bất biến không liên quan đến sự bất biến đẳng cấp và việc sử dụng thử nghiệm đơn vị, hoặc chỉ liên quan đến mức thô sơ. Nếu chúng ta định nghĩa "bất biến" đơn giản là "không thay đổi". Câu hỏi đặt ra là "Làm thế nào để bạn kiểm tra những thứ không thay đổi". Hoặc, là câu hỏi "Làm thế nào để bạn kiểm tra một loạt các giá trị hợp lệ"? –

+0

@ P.Brian Có nhiều loại bất biến. Và loại phương sai là hoàn toàn không liên quan đến bất biến class. Tôi đã thêm một đoạn giới thiệu. – CodesInChaos

+0

@ P.Brian Để xem làm thế nào để thực thi một bất biến lớp trong .net 4 xem "Lee" của câu trả lời. Nếu bạn làm điều đó (và chọn cài đặt trình biên dịch chính xác), mã của bạn sẽ được viết lại để nó kiểm tra bất biến ở phần cuối của bất kỳ phương thức công khai nào. – CodesInChaos

2

Trong trường hợp này, bất biến có nghĩa là các điều kiện áp dụng cho các tham số và vẫn đúng trong suốt thời gian của hàm/phương thức.

Từ wikipedia:

Trong khoa học máy tính, một vị được gọi là bất biến để một chuỗi các hoạt động với điều kiện: nếu vị là đúng trước khi bắt đầu chuỗi, sau đó nó là đúng ở phần cuối của trình tự.

Trong .NET, các bất biến có thể được kiểm tra/thi hành sử dụng Code Contracts.

+0

Tôi không nghĩ rằng bạn cần phải đọc cuốn sách để hiểu câu hỏi của tôi, nhưng cách tác giả hỏi câu hỏi là "vấn đề thực tế" hoặc "cách bạn sử dụng những thứ này" như thể mọi người làm điều đó. Tôi đã không bao giờ cố ý sử dụng bất biến cho bất kỳ mục đích nào, và trong .NET có vẻ như chúng ta cần một thuộc tính tường để thậm chí xem xét chúng. Vì vậy, được sử dụng phổ biến của bất biến một điều của quá khứ hoặc giới hạn để lắp ráp/C/C + +? –

+0

@ P.Brian.Mackey - Tôi chưa bao giờ sử dụng chúng, tuy nhiên, nó xuất hiện rằng những người đến từ một nền CS cố gắng sử dụng chúng nó một nỗ lực để có được "chính xác" tốt hơn. Tôi đoán anh ta giả định mọi người đều biết về bất biến và cách sử dụng chúng - hãy xem xét những người được nêu trong cuốn sách :) – Oded

1

Ý nghĩa trong ngữ cảnh này không liên quan đến co và contra phương sai cho generics được giới thiệu trong C# 4, mà đúng theo ý nghĩa như bài viết wikipedia bạn liên kết tới. Trong C#, điều này có thể là xác nhận gỡ lỗi (ví dụ: Debug.Assert(condition)) cũng như thư viện hợp đồng mã. Có ví dụ như ContractInvariantMethodAttribute mà có thể được áp dụng cho một phương pháp trong một lớp mà khẳng định bất biến lớp:

[ContractInvariantMethod] 
protected void ClassInvariant() 
{ 
    Contract.Invariant(someCondition); 
} 
2

Đó dụ trong Wiki đang triển khai bất biến với JML, mà là một rất cụ thể, kỳ lạ và có lẽ cũng công nghệ nghiên cứu mặc dù, nhưng nó không phải là chủ đạo cần thiết. Ngoài ra, nó không chỉ nói về những bất biến mà chỉ nói về việc khẳng định một kẻ đột biến đã làm những gì được mong đợi, đó không phải là những gì tôi nghĩ đến khi tôi nghĩ về bất biến. Tôi đã không đọc Coders tại nơi làm việc nhưng tôi nghi ngờ bất cứ ai trong Coders tại nơi làm việc đã sử dụng JML.

Dù sao, tôi luôn nghĩ rằng bất biến là một cách tuyệt vời để "sụp đổ sớm" và giữ cho mã của bạn không cố gắng làm những điều hợp lý khi thực tế trạng thái chương trình ở trạng thái không hợp lý (không có kế hoạch).

Một ví dụ điển hình về bất biến trong mã C# có thể là không bao giờ đưa đối tượng vào N-Hibernate để lưu trừ khi đối tượng đó vượt qua các biến thể của nó, trong đó phải có nhiều đối tượng để ngăn không cho dữ liệu không nhạy cảm vào cơ sở dữ liệu. Chúng ta hãy xem nếu tôi có thể nghĩ ra bất kỳ ví dụ khác ...

  • Giả sử bạn có một lớp người dùng mà là luôn phải có một tài sản địa chỉ email chính, sau đó là một bất biến để kiểm tra trước khi tiết kiệm có thể là để thực hiện , hãy đảm bảo rằng trường địa chỉ email không trống. Nếu không, logic ứng dụng khác xuống đường giả định địa chỉ email tồn tại cho tất cả người dùng có thể gây rối khi cố gắng để gửi cho người dùng một email sau.

  • Giả sử thêm rằng một đối tượng tài "có nhiều" đối tượng Email, và giả sử rằng nó không thực hiện bất kỳ ý nghĩa đối với Email để tồn tại mà không một người dùng sở hữu, sau đó một bất biến trên lớp Email có thể đảm bảo rằng tham chiếu của Email là người dùng của nó luôn không phải là null, nếu không, bạn có đối tượng email mồ côi mà có thể dẫn đến ngoại lệ con trỏ null khi bạn cố gắng tham khảo chủ sở hữu của email.

  • Giả sử bạn đang viết GUI mà được cho là trình bày trạng thái của đối tượng Amazon S3 theo dạng WPF thông thường . Một bất biến trên mẫu có thể là để đảm bảo rằng biểu mẫu được ràng buộc đúng với đối tượng trước khi thực hiện bất kỳ trình xử lý sự kiện nào trên biểu mẫu đó.

  • Giả sử bạn đang viết StackOverflow. Một bất biến ở đây có thể là để đảm bảo rằng mức độ danh tiếng của người dùng không bao giờ là tiêu cực, thậm chí nếu người dùng đang sử dụng hình phạt danh tiếng. Danh tiếng phủ định có thể phá vỡ các đồ thị đẹp đó mang lại trải nghiệm như một hàm thời gian (trừ khi các đồ thị đó được chuẩn bị để biểu đồ các đường bên dưới trục 0, mà chúng rất có thể là ...).

Khi kiểm tra các bất biến, bạn có thể thực hiện việc này ở cuối bất kỳ phương pháp nào làm thay đổi trạng thái dữ liệu. Ở cấp độ lập trình phòng thủ tích cực và hoang tưởng nhất, bạn có thể kiểm tra một bất biến trước và sau tất cả các phương pháp.

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