예외에 대한 추가 정보를 제공해야 할 때마다 실제로 어떤 방법이 올바른 방법 인지 궁금 합니다.
이 질문을 위해 예를 썼습니다. Abbreviation
속성 을 업데이트하려는 클래스가 있다고 가정 해 봅시다 . SOLID 관점에서 보면 완벽하지는 않지만 일부 서비스를 통해 DI를 통해 작업자 메서드 를 전달하더라도 동일한 상황이 발생합니다. 예외가 발생하면 컨텍스트가 없습니다. 예제로 돌아 가기 ...
class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Abbreviation { get; set; }
}
그런 다음 클래스의 인스턴스와 작업자 메서드가 호출되는 루프가 있습니다. 던질 수 있습니다 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
}
질문은 : Person
또는 그 Id
(또는 다른 것) 를 추가하는 방법은 무엇입니까?
다음 세 가지 기술을 알고 있습니다.
1- Data
속성 사용
장점 :
- 추가 정보를 쉽게 설정
- 더 많은 예외를 만들 필요가 없습니다
- 추가가 필요하지 않습니다
try/catch
단점 :
- 에 쉽게 통합 될 수 없습니다
Message
- 로거는이 필드를 무시하고 덤프하지 않습니다.
- 키와 캐스팅이 필요하기 때문에 값이
object
- 불변의
예:
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-사용자 정의 특성 사용
장점 :
Data
속성 과 유사 하지만 강력한 유형- 에 쉽게 통합
Message
단점 :
- 맞춤 예외가 필요합니다
- 로거는 그들을 무시합니다
- 불변의
예:
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-예외를 다른 예외로 랩
장점 :
Message
예측 가능한 방식으로 형식화 가능- 로거는 내부 예외를 덤프합니다
- 불변의
단점 :
- 추가가 필요합니다
try/catch
- 중첩 증가
- 집행의 깊이를 증가
예:
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...
}
- 다른 패턴이 있습니까?
- 더 나은 패턴이 있습니까?
- 일부 / 모두 모범 사례를 제안 할 수 있습니까?