Khi thiết kế một lớp nên nhất quán trong hành vi được ưa chuộng hơn so với thực hành lập trình phổ biến? Để đưa ra một ví dụ cụ thể:
Một quy ước chung là: Nếu một lớp sở hữu một đối tượng (ví dụ như nó đã tạo ra nó), nó có trách nhiệm làm sạch nó sau khi hoàn thành. Một ví dụ cụ thể sẽ có trong .NET rằng nếu lớp của bạn sở hữu một IDisposable
đối tượng thì nó sẽ loại bỏ nó vào cuối vòng đời của nó. Và nếu bạn không sở hữu nó thì đừng chạm vào nó.
Bây giờ nếu chúng ta nhìn vào StreamWriter
lớp trong .NET thì chúng ta có thể tìm thấy trong tài liệu rằng nó đóng luồng bên dưới khi nó được đóng / xử lý. Điều này là cần thiết trong trường hợp StreamWriter
được khởi tạo bằng cách chuyển vào một tên tệp khi người viết tạo ra luồng tệp bên dưới và do đó cần phải đóng nó. Tuy nhiên, người ta cũng có thể vượt qua trong một luồng bên ngoài mà nhà văn cũng đóng.
Điều này đã gây khó chịu cho tôi rất nhiều lần (vâng tôi biết bạn có thể tạo một trình bao bọc không đóng nhưng đó không phải là vấn đề) nhưng rõ ràng Microsoft đã đưa ra quyết định rằng sẽ luôn nhất quán khi đóng luồng bất kể nó đến từ đâu.
Khi tôi gặp một mẫu như vậy trong một trong các lớp của mình, tôi thường tạo một ownsFooBar
cờ được đặt thành false trong trường hợp FooBar
được đưa vào qua hàm tạo và ngược lại. Bằng cách này, trách nhiệm làm sạch nó được chuyển cho người gọi khi anh ta vượt qua ví dụ một cách rõ ràng.
Bây giờ tôi đang tự hỏi liệu có thể nhất quán nên được ưu tiên hơn thực tiễn tốt nhất (hoặc có thể thực hành tốt nhất của tôi không tốt)? Bất kỳ đối số cho / chống lại nó?
Chỉnh sửa để làm rõ
Với "tính nhất quán" Ý tôi là: Hành vi nhất quán của lớp luôn nắm quyền sở hữu (và đóng luồng) so với "thực tiễn tốt nhất" để chỉ sở hữu một đối tượng nếu bạn tạo ra nó hoặc chuyển giao quyền sở hữu một cách rõ ràng.
Đối với một ví dụ nơi nó đang mê hoặc:
Giả sử bạn có hai lớp nhất định (từ thư viện của bên thứ 3) chấp nhận luồng để thực hiện điều gì đó với nó, như tạo và xử lý một số dữ liệu:
public class DataProcessor
{
public Result ProcessData(Stream input)
{
using (var reader = new StreamReader(input))
{
...
}
}
}
public class DataSource
{
public void GetData(Stream output)
{
using (var writer = new StreamWriter(output))
{
....
}
}
}
Bây giờ tôi muốn sử dụng nó như thế này:
Result ProcessSomething(DataSource source)
{
var processor = new DataProcessor();
...
var ms = new MemoryStream();
source.GetData(ms);
return processor.ProcessData(ms);
}
Điều này sẽ thất bại với một ngoại lệ Cannot access a closed stream
trong bộ xử lý dữ liệu. Đó là một chút được xây dựng nhưng nên minh họa điểm. Có nhiều cách khác nhau để khắc phục nhưng tuy nhiên tôi cảm thấy rằng tôi làm việc xung quanh một cái gì đó tôi không cần phải làm.