재산에서 예외를 던지는 것은 나쁜 형태입니까?


15

나는 항상 속성들 (즉, 그들의 집합 / get 오퍼레이션)이 빠르거나 즉각적이고 고장이 없어야한다는 생각을 해왔다. 속성을 가져 오거나 설정하려고 시도하거나 잡을 필요가 없습니다.

그러나 일부 객체의 속성에 역할 기반 보안을 적용하는 몇 가지 방법을 찾고 있습니다. 예를 들어 Employee.Salary 속성입니다. 내가 그 사람을 통해 실행 한 솔루션 중 일부는 시도 (특히 하나는 AOP의 예는 여기에 접근이 올바른 권한이없는 경우 예외를 throw 포함) - 그러나 이것은 내가 했어 개인 규칙에 반하는 지금은 오랫동안

그래서 묻습니다. 틀렸습니까? 상황이 바뀌 었습니까? 속성이 예외를 던질 수 있어야한다는 것이 인정 되었습니까?


1
StackOverflow의에 같은 질문은 더 많은 관심과 그래서 더 나은 답변을 얻었다.
로마 Starkov

답변:


14

속성 값을 설정하면 유효하지 않은 값에 예외를 던지는 것이 좋습니다.

속성 값을 얻는 것은 (거의) 예외를 던져서는 안됩니다

역할 기반 액세스의 경우 서로 다른 / 주황색 인터페이스 또는 파사드를 사용하십시오. 사람들이 가질 수없는 것을 보지 못하게하십시오!


5

나는 그것이 주로 나쁜 형태라고 생각하지만 때로는 예외를 사용하는 것이 좋습니다. 좋은 예는 추상 속성 Stream.Length 입니다. 지침에 따라 게터의 부작용을 피하고 세터의 부작용을 제한하는 데 더 관심이 있습니다.


4

속성 설정자 또는 getter에서 예외를 던질 필요가 있다고 생각하면 디자인에 결함이 있다고 주장합니다.

속성은 단지 값인 것을 나타내는 추상화입니다 . 예외가 발생할 수도 있다는 두려움없이 가치를 설정할 수 있어야합니다. *

속성을 설정하면 부작용이 발생하는 경우 실제로 메서드로 구현해야합니다. 그리고 부작용이 발생하지 않으면 예외가 발생하지 않습니다.

다른 답변에서 이미 언급 한 예는 Stream.Position속성입니다. 이로 인해 부작용이 발생하고 예외가 발생할 수 있습니다. 그러나이 속성 설정 기는 기본적으로 Stream.Seek대신 호출 할 수 있는 래퍼 입니다.

개인적으로, 나는 그 입장이 쓰기 가능한 재산이 아니어야한다고 믿습니다.

속성 설정 기에서 예외를 발생시키려는 유혹을받을 수있는 또 다른 예는 데이터 유효성 검사에 있습니다.

public class User {
    public string Email {
        get { return _email; }
        set { 
            if (!IsValidEmail(value)) throw InvalidEmailException(value);
            _email = value;
        }
    }

그러나이 문제에 대한 더 나은 해결책이 있습니다. 유효한 이메일 주소를 나타내는 유형을 소개하십시오.

public class Email {
    public Email(string value) {
        if (!IsValidEmail(value)) throw new InvalidEmailException(value);
        ...
    }
    ...
}

public class User {
    public Email Email { get; set; }
}

Email클래스는 유효한 이메일 주소가 아닌 값을 보유 할 수 없도록하고, 클래스는 저장 이메일에 대한 필요성을 검증하는 의무에서 해방됩니다.

또한 전자 메일 주소가 무엇인지, 어떻게 유효성을 검사하는지에 대한 지식이 더 높은 응집력 (좋은 소프트웨어 설계의 지표)으로 이어집니다 Email.

* ObjectDisposedException은 현재 생각할 수있는 유일한 유효한 예외입니다.


2

귀하의 질문은 .NET에만 해당되는 것으로 알고 있지만 C #은 Java와 일부 기록을 공유하므로 관심이 있으실 것으로 생각합니다. 나는 하지 뭔가가 자바에서 수행되기 때문에,이 C #으로 수행되어야 함을 의미있는 방법으로. 특히 C #에서 속성에 대한 언어 수준 지원이 크게 개선 된 방식에서 두 가지가 매우 다르다는 것을 알고 있습니다. 나는 단지 상황과 관점을주고 있습니다.

로부터 자바 빈즈 사양 :

제한된 특성 때때로 특성 변경이 발생하면 다른 Bean이 변경을 유효성 검증하고 부적합한 경우이를 거부 할 수 있습니다. 이러한 종류의 검사를 수행하는 속성을 제한된 속성이라고합니다. Java Beans에서는 PropertyVetoException을 지원하기 위해 제한된 특성 설정 메소드가 필요합니다. 업데이트를 시도한 제한된 속성의 사용자에게이 문서가 거부 될 수 있습니다. 따라서 간단한 제약 속성은 다음과 같습니다.

PropertyType getFoo();
void setFoo(PropertyType value) throws PropertyVetoException;

이 모든 것을 소금 한 알과 함께 가져 가십시오. JavaBeans 사양은 구식이며 C # 속성은 (IMO) Java의 "이름 지정 규칙"기반 속성에 비해 크게 개선되었습니다. 나는 단지 약간의 맥락을 제시하려고 노력하고 있습니다.


좋은 지적이지만 setter 메서드와 ac # 속성 setter의 차이점은 다른 경우가 될만큼 중요합니다. 마찬가지로, Java의 확인 된 예외는 호출 코드가 예외가 발생할 수 있음을 인식하도록 강제하므로 이로 인해 누군가를 놀라게 할 가능성이 줄어 듭니다.
Steven Evers

2

속성의 요점은 Uniform Access Principle입니다 . 즉, 저장 또는 계산에 의해 구현 되든 동일한 인터페이스를 통해 값에 액세스 할 수 있어야합니다. 속성이 프로그래머의 제어를 넘어서는 오류 조건을 나타내는 예외, 즉 잡히고 처리해야하는 종류의 예외를 발생시키는 경우, 클라이언트가 계산을 통해 값을 얻었음을 알게됩니다.

반면에, 어설 션이나 어설 션과 같은 예외를 사용하는 데 문제가 발생하지 않습니다.이 예외는 잡히고 처리되지 않고 프로그래머에게 API의 잘못된 사용을 알리기위한 것입니다. 이 경우 API 사용자 관점의 정답은 예외를 처리하지 않습니다 (따라서 값이 계산 또는 저장을 통해 획득되는지 여부를 암시 적으로 고려함). 개체가 유효하지 않은 상태가 아니거나 어설 션이 실행되지 않도록 코드를 수정하도록 코드를 수정해야합니다.


“고객이 계산을 통해 값을 얻는다는 것을 고객에게 강요하는 방법”을 알 수 없습니다. 확실히 스토리지에 액세스하면 예외가 발생할 수 있습니다. 실제로, 둘 사이의 차이점을 어떻게 정의 할 것입니까?
Timwi

필자는 필드 (스토리지)에서 값을 검색하고 적절한 유형의 변수 (예 : 캐스팅없이)에 변수를 배치하는 등 무해한 것을 수행하는 것만으로도 예외를 던질 수 없다는 점이 구별된다고 생각합니다. 이 경우 이후에 값으로 무언가를 한 경우에만 예외가 발생할 수 있습니다. 속성 게터에 예외가 발생하면이 경우 단순히 값을 검색하여 변수에 배치하는 작업으로 인해 예외가 발생할 수 있습니다.
윌리 박사의 견습생

1

AFAIK,이 지침은 주로 설계 시 속성이 사용될 수있는 사고 과정에서 비롯됩니다 . (예 : TextBox의 Text 속성) 디자이너가 액세스하려고 할 때 속성에서 예외가 발생하면 VS는 좋은 하루를 보내지 않을 것입니다. 디자이너를 사용하려고 할 때 많은 오류가 발생하고 UI 디자이너에게는 렌더링되지 않습니다. 예외 시나리오에서 볼 수있는 것은 "xxx Exception"이고 VS IIRC를 방해하지는 않지만 디버그 시간에도 적용됩니다.

POCO의 경우 실제로 아무런 해를 끼치지는 않지만 여전히 직접 수행하지는 않습니다. 사람들이 속성에 더 자주 액세스하기를 원하므로 일반적으로 저렴한 비용이어야합니다. 속성은 메소드 작업을 수행해서는 안되며 정보를 가져 오거나 설정하고 일반적인 규칙으로 수행해야합니다.


0

컨텍스트에 따라 많이 달라 지지만 일반적으로 예외를 포함한 모든 종류의 분리 가능한 논리를 속성에 넣지 마십시오. 예를 들어, 디자인 타임에 예상하지 못한 오류가 발생하는 속성을 반복하기 위해 리플렉션을 사용하여 사용자 (또는 사용중인 일부 라이브러리)가 수행 할 수있는 많은 것들이 있습니다.

나는 일반적으로 당신이 절대적으로, 분명히, 결과에 대해 너무 걱정하지 않고 무언가를 차단하고 싶을 때가있을 수 있지만 일반적으로 말합니다. 보안 고전적인 경우가 될 것 같습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.