Tôi thường thấy mình cần phải thực hiện một lớp học là một bảng liệt kê / bộ sưu tập một cái gì đó. Xem xét cho chủ đề này ví dụ giả định trong IniFileContent
đó là một bảng liệt kê / bộ sưu tập các dòng.
Lý do lớp này phải tồn tại trong cơ sở mã của tôi là vì tôi muốn tránh logic kinh doanh được lan truyền khắp nơi (= đóng gói where
) và tôi muốn thực hiện theo cách có thể hướng đối tượng nhất.
Thông thường tôi sẽ thực hiện nó như sau:
public sealed class IniFileContent : IEnumerable<string>
{
private readonly string _filepath;
public IniFileContent(string filepath) => _filepath = filepath;
public IEnumerator<string> GetEnumerator()
{
return File.ReadLines(_filepath)
.Where(l => !l.StartsWith(";"))
.GetEnumerator();
}
public IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
Tôi chọn thực hiện IEnumerable<string>
vì nó làm cho việc sử dụng của nó thuận tiện:
foreach(var line in new IniFileContent(...))
{
//...
}
Tuy nhiên tôi đang tự hỏi nếu làm như vậy "bóng tối" ý định lớp học? Khi nhìn vào IniFileContent
giao diện, người ta chỉ thấy Enumerator<string> GetEnumerator()
. Tôi nghĩ nó không rõ ràng về dịch vụ mà lớp đang thực sự cung cấp.
Hãy xem xét sau đó thực hiện thứ hai này:
public sealed class IniFileContent2
{
private readonly string _filepath;
public IniFileContent2(string filepath) => _filepath = filepath;
public IEnumerable<string> Lines()
{
return File.ReadLines(_filepath)
.Where(l => !l.StartsWith(";"));
}
}
Mà được sử dụng ít thuận tiện hơn (nhân tiện, nhìn thấy new X().Y()
cảm giác như có gì đó không ổn với thiết kế lớp):
foreach(var line in new IniFileContent2(...).Lines())
{
//...
}
Nhưng với một giao diện rõ ràng IEnumerable<string> Lines()
làm rõ ràng những gì lớp này thực sự có thể làm.
Việc thực hiện nào bạn sẽ thúc đẩy và tại sao? Ngụ ý, nó có phải là một thực tiễn tốt để thực hiện IEnumerable để đại diện cho một liệt kê của một cái gì đó?
Tôi không tìm kiếm câu trả lời về cách:
- đơn vị kiểm tra mã này
- tạo một hàm tĩnh thay vì một lớp
- làm cho mã này dễ bị tiến hóa logic kinh doanh trong tương lai
- tối ưu hóa hiệu suất
ruột thừa
Đây là loại mã thực sự sống trong cơ sở mã của tôi, thực hiệnIEnumerable
public class DueInvoices : IEnumerable<DueInvoice>
{
private readonly IEnumerable<InvoiceDto> _invoices;
private readonly IEnumerable<ReminderLevel> _reminderLevels;
public DueInvoices(IEnumerable<InvoiceDto> invoices, IEnumerable<ReminderLevel> reminderLevels)
{
_invoices = invoices;
_reminderLevels = reminderLevels;
}
public IEnumerator<DueInvoice> GetEnumerator() => _invoices.Where(invoice => invoice.DueDate < DateTime.Today && !invoice.Paid)
.Select(invoice => new DueInvoice(invoice, _reminderLevels))
.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
new
cho trường hợp sử dụng này, khó kiểm tra đơn vị, mơ hồ khi tôi / O ngoại lệ có thể xảy ra, vv Tôi xin lỗi, tôi không cố tỏ ra thô lỗ. Tôi nghĩ rằng tôi đã quá quen với những lợi ích của việc tiêm phụ thuộc .
IniFileContent
.