속성에 부작용이 있어야 함 몇 가지 다른 방식으로 사용되는 속성을 보았습니다.

C #의 속성은 상태 변경을 알리는 것 외에 부작용이 있어야합니까?

몇 가지 다른 방식으로 사용되는 속성을 보았습니다. 처음 액세스 할 때 값을로드하는 속성에서 다른 페이지로 리디렉션하는 등의 부작용이 큰 속성에 액세스합니다.



답변

속성 세터 는 거의 모든 경우에 부작용이 있기 때문에 읽기 전용 속성 또는 적어도 속성 getter 에 대해 이야기한다고 가정합니다 . 그렇지 않으면별로 유용하지 않습니다.

일반적으로 좋은 디자인 은 최소한의 놀람 원칙을 따릅니다 . 발신자가 기대하지 않는 일, 특히 미래의 결과 가 바뀔 수있는 일을하지 마십시오 .

일반적으로 속성 게터에는 부작용이 없어야합니다.

그러나 “부작용”의 의미에 대해주의합시다 .

부작용은 , 기술적 인 모든 상태 변경. 공개적으로 접근 가능한 상태 일 수도 있고 … 완전히 비공개 일 수도 있습니다.

지연 / 지연 로더는 거의 독점적으로 개인 상태의 한 예입니다. 해당 자원을 해제하는 것은 호출자의 책임이 아닌 한, 지연된 초기화를 사용하여 일반적으로 놀라움과 복잡성을 입니다. 호출자는 일반적으로 내부 구조 의 초기화 를 명시 적으로 신호 할 필요가 없습니다 . 따라서 게으른 초기화는 위의 원칙을 위반 하지 않습니다 .

다른 예는 동기화 된 속성입니다. 메소드가 스레드로부터 안전하기 위해서는 종종 중요한 섹션이나 뮤텍스에 의해 보호되어야합니다. 크리티컬 섹션을 입력하거나 뮤텍스를 획득하는 단계 부작용; 일반적으로 전역 상태 인 상태를 수정합니다 . 그러나,이 부작용이 필요한 더 방지하기 위해 놀라운 종류 – 수정되는 데이터의 놀람을 다른 스레드 (또는 악화, 부분적으로 변형).

따라서 제한 사항을 다음과 같이 조금 풀었 습니다 . 속성 읽기에는 시맨틱변경하는 눈에 띄는 부작용이나 부작용 이 없어야합니다 .

발신자가 부작용에 영향을 미치 거나 부작용을 인식 할 수있는 방법이 없다면 해당 부작용으로 인한 피해는 없습니다. 특정 부작용의 존재를 검증하기 위해 테스트를 작성하는 것이 불가능한 경우, 개인 구현 세부 사항으로 레이블을 지정할 정도로 현지화되어 있으므로 외부 세계에 대한 정당한 우려가 없습니다.

그러나 조심하십시오. 엄지 손가락의 규칙으로, 당신은 해야 종종 개인 구현 세부 예기치 않게 누출 공개 될 수 있습니다 것으로 생각 무엇 때문에, 부작용을 피하려고합니다.


답변

질문으로 질문에 대답하겠습니다. 폼의 너비 속성을 수정하면 어떻게됩니까?

내 머리 꼭대기에서 이렇게하면 :

  • 백업 필드의 값을 변경하십시오.
  • 이벤트를 시작하십시오.
  • 양식의 크기를 변경하고 변경 사항을 창 관리자에게보고 한 후 다시 그리기를 요청하십시오.
  • 폼의 크기를 조정할 때 크기 나 위치를 변경해야하는 컨트롤이 변경 될 수 있도록 변경 폼에 컨트롤을 알립니다.
  • 이벤트가 발생하도록 변경된 모든 컨트롤을 발생시키고 창 관리자에게 다시 그려야한다고 알립니다.
  • 아마 다른 것들도.

(면책 조항 : 저는 .NET 개발자가 아닌 델파이 개발자입니다. C #에서는 100 % 정확하지 않을 수도 있지만 특히 델파이를 기반으로 한 원래 .NET 프레임 워크의 양을 고려하면 꽤 가깝습니다.)

이러한 “부작용”은 모두 폼의 너비 속성을 변경하면 발생합니다. 어떻게 든 부적절하거나 부정확 한 것으로 보입니까?


답변

Microsoft 디자인 규칙 , 특히 다음 중 하나를 살펴보십시오 .

CA1024 : 적절한 경우 속성 사용

… 이러한 조건 중 하나가 존재하는 경우 방법이 속성이 될 수 있습니다.

  • 인수를 취하지 않고 객체의 상태 정보를 반환합니다.
  • 단일 인수를 허용하여 객체 상태의 일부를 설정합니다.

속성은 마치 필드 인 것처럼 동작해야합니다. 메소드가 실패 할 경우, 특성으로 변경해서는 안됩니다. 다음과 같은 상황에서는 방법보다 속성이 좋습니다.

  • 이 방법은 시간이 많이 걸리는 작업을 수행합니다. 이 방법은 필드의 값을 설정하거나 얻는 데 필요한 시간보다 느리게 느립니다.
  • 이 방법은 변환을 수행합니다. 필드에 액세스하면 저장된 데이터의 변환 된 버전이 반환되지 않습니다.
  • Get 메소드는 관찰 가능한 부작용이 있습니다. 필드 값을 검색해도 부작용이 발생하지 않습니다.
  • 실행 순서가 중요합니다. 필드 값을 설정한다고해서 다른 작업이 발생하는 것은 아닙니다.
  • 메소드를 연속해서 두 번 호출하면 다른 결과가 생성됩니다.
  • 이 메소드는 정적이지만 호출자가 변경할 수있는 오브젝트를 리턴합니다. 필드 값을 검색하면 호출자가 필드에 저장된 데이터를 변경할 수 없습니다.
  • 이 메소드는 배열을 반환합니다 …

답변

나는 속성에 부작용이 없어야한다고 생각합니다. 그러나이 규칙에는 한 가지 예외가 있습니다 : 지연 로딩. 속성에 무언가를 게으르게로드하려면 클라이언트가 게으른로드가 진행되고 있음을 알 수 없으며 일반적으로 신경 쓰지 않기 때문에 좋습니다.

편집 : 아, 한 가지 더- “PropertyXYZ가 변경되었습니다!” (예 : INotifyPropertyChanged)-세터에서 괜찮습니다.


답변

앞에서 언급 한 게으른 로딩 외에도 로깅 기능도 있습니다. 이것들은 드물지만 의문의 여지가 없습니다.


답변

프로그래밍에는 절대적인 것이 거의 없습니다. 질문에 답하기 위해서는 바람직한 객체 속성을 살펴보고 이것이 우리의 경우에 적용되는지 확인해야합니다.

  1. 우리는 수업을 쉽게 테스트 할 수 있기를 원합니다.
  2. 클래스가 동시성을 지원하기를 원합니다
  3. 우리는 제 3 자에게 수업을 쉽게 추론하기를 원합니다.

만약 우리가이 질문들 중 일부에 대답한다면, 속성과 그 부작용에 대해 매우 신중하게 생각하는 것이 좋습니다. 부작용을 말할 때 값을 업데이트하는 것이 그 자체로 부작용이기 때문에 보조 부작용을 의미한다고 가정 합니다.

일반적으로 부작용이 많을수록 수업을 테스트하기가 더 어려워집니다. 2 차 부작용이 많을수록 동시 처리가 더 어려워 질 수 있지만 어쨌든 중요한 디자인 사고가 필요한 어려운 문제입니다.

큰 문제는 아마도 클래스를 “블랙 박스”로 취급하는 사람들을위한 것일 것입니다. 속성을 읽었 기 때문에 일부 상태가 변경되었거나 다른 변경 ( 계단식 업데이트).

일반적으로 아니오, 우리는 속성을 가능한 한 쉽게 추론하고 간단하게 만들고 싶습니다. 디자인 결정에 암시되어 있습니다. 그렇지 않으면 방법 일 것입니다. 좋은 프로그래머는 항상 규칙을 어길 수 있지만 정말 좋은 이유가 있는지 확인하십시오. 🙂


답변