Mỗi lần tôi cần phải cung cấp thêm thông tin về một ngoại lệ Tôi ngạc nhiên mà cách thực sự là đúng cách để làm điều này.
Vì lợi ích của câu hỏi này, tôi đã viết một ví dụ. Giả sử có một lớp nơi chúng tôi muốn cập nhật Abbreviation
tài sản. Từ quan điểm RẮN, nó có thể không hoàn hảo nhưng ngay cả khi chúng ta đã truyền phương thức worker qua DI với một số dịch vụ thì tình huống tương tự sẽ xảy ra - một ngoại lệ xảy ra không có bối cảnh nào. Quay lại ví dụ ...
class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Abbreviation { get; set; }
}
Sau đó, có một số trường hợp của lớp và một vòng lặp trong đó phương thức worker được gọi. Nó có thể ném StringTooShortException
.
var persons =
{
new Person { Id = 1, Name = "Fo" },
new Person { Id = 2, Name = "Barbaz" },
}
public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
foreach (var person in persons)
{
try
{
person.Abbreviation = GenerateAbbreviation(person.Name);
}
catch(Exception ex)
{
// ?
}
}
// throw AggregateException...
}
public IEnumerable<string> GenerateAbbreviation(string value)
{
if (value.Length < 5)
{
throw new StringTooShortException(value);
}
// generate abbreviation
}
Câu hỏi là: làm thế nào để thêm Person
hoặc của nó Id
(hoặc bất cứ điều gì khác)?
Tôi biết ba kỹ thuật sau:
1 - Sử dụng Data
tài sản
Ưu điểm:
- dễ dàng thiết lập thông tin bổ sung
- không yêu cầu tạo ra nhiều ngoại lệ hơn
- không yêu cầu thêm
try/catch
Nhược điểm:
- không thể dễ dàng tích hợp vào
Message
- loggers bỏ qua lĩnh vực này và sẽ không bỏ nó
- yêu cầu khóa và đúc giá trị becasue là
object
- không bất biến
Thí dụ:
public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
foreach (var person in persons)
{
try
{
person.Abbreviation = GenerateAbbreviation(person.Name);
}
catch(Exception ex)
{
ex.Data["PersonId"] = person.Id;
// collect ex
}
}
// throw AggregateException...
}
2 - Sử dụng thuộc tính tùy chỉnh
Ưu điểm:
- tương tự như
Data
tài sản nhưng đánh máy mạnh - dễ dàng tích hợp vào
Message
Nhược điểm:
- yêu cầu ngoại lệ tùy chỉnh
- logger sẽ bỏ qua chúng
- không bất biến
Thí dụ:
public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
foreach (var person in persons)
{
try
{
person.Abbreviation = GenerateAbbreviation(person.Name);
}
catch(Exception ex)
{
// not suitable for this exception because
// it doesn't have anything in common with the Person
}
}
// throw AggregateException...
}
3 - Bao bọc ngoại lệ với một ngoại lệ khác
Ưu điểm:
Message
có thể được định dạng theo một cách có thể dự đoán- loggers sẽ bỏ các ngoại lệ bên trong
- bất biến
Nhược điểm:
- yêu cầu bổ sung
try/catch
- bao gồm làm tổ
- tăng độ sâu của các ngoại lệ
Thí dụ:
public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
foreach (var person in persons)
{
try
{
try
{
person.Abbreviation = GenerateAbbreviation(person.Name);
}
catch(Exception ex)
{
throw new InvalidPersonDataException(person.Id, ex);
}
}
catch(Exception ex)
{
// collect ex
}
}
// throw AggregateException...
}
- Có bất kỳ mô hình khác?
- Có mô hình tốt hơn?
- Bạn có thể đề xuất thực hành tốt nhất cho bất kỳ / tất cả trong số họ?