설정 전용 속성을 사용하지 않는 것이 좋은 이유는 무엇입니까?


9

오늘 직장에서 동료 중 한 명이 내 코드를 검토하고 set-only 속성을 제거하고 대신 메서드를 사용하도록 제안했습니다.

우리 둘 다 다른 일로 바빴 기 때문에 그는 Property Design"프레임 워크 디자인 지침"책 의 섹션 을 보라고 말했습니다 . 이 책에서 작가는 다음과 같이 피했다.

게터보다 접근성이 더 넓은 세터가있는 속성

그리고 왜 set-only 속성을 갖는 것이 권장되지 않는지 궁금합니다. 누군가 나를 명확히 할 수 있습니까?


6
집합 전용 속성이 적절하다고 생각되는 상황을 설명 할 수 있습니까? 답변이 좀 더 관련성이 있습니다.
JohnFx

1
의미 적으로 의미있는 예를 생각하려고합니다. 마음에 떠오르는 것은 수업 의 Password재산입니다 User. 설정할 수는 있지만 얻을 수는 없습니다. 그런 다음 읽기 전용 HashedPassword속성 을 가질 수 있습니다. 집합을 호출하면 해시가 수행되고 HashedPassword속성이 변경 됩니다. 당신이 그렇게한다면 소리 치지 않을 것입니다.
Scott Whitlock

답변:


15

나는 그것이 기대와 관련이 있다고 생각합니다. 집합 전용 속성은 일반적이지 않으며 속성은 일반적으로 많은 처리없이 값을 저장하기 위해 "덤"집합에 사용됩니다. setter에서 많은 작업을 수행하는 경우 메소드를 사용하는 것이 좋습니다. 사람들은 메소드를 실행하는 데 오랜 시간이 걸리고 잠재적으로 부작용이있을 것으로 예상합니다. 속성에서 유사한 종류의 동작을 구현하면 예상을 위반하는 코드가 생성 될 수 있습니다.

다음은 Microsoft 속성 사용 지침의 관련 섹션입니다 .

속성 대 방법

클래스 라이브러리 디자이너는 종종 클래스 멤버를 속성 또는 메서드로 구현할지 결정해야합니다. 일반적으로 메소드는 조치를 나타내고 특성은 데이터를 나타냅니다. 다음 지침을 사용하여 이러한 옵션 중에서 선택하십시오.

  • 멤버가 논리 데이터 멤버 인 경우 특성을 사용하십시오. 다음 멤버 선언 Name에서 클래스의 논리적 멤버이므로 속성입니다.
public string Name
{
    get 
    {
        return name;
    }
    set 
    {
        name = value;
    }
}

다음과 같은 경우 방법을 사용하십시오.

  • 작업은과 같은 변환 Object.ToString입니다.
  • 작업 캐시는 사용자에게 결과 캐싱을 고려해야한다는 의사 소통을하기에 충분히 비쌉니다.
  • 접근자를 사용하여 속성 값을 얻는 것은 get관찰 가능한 부작용이 있습니다.
  • 멤버를 두 번 연속으로 호출하면 다른 결과가 생성됩니다.
  • 실행 순서가 중요합니다. 유형의 속성은 어떤 순서로든 설정하고 검색 할 수 있어야합니다.
  • 멤버는 정적이지만 변경할 수있는 값을 반환합니다.
  • 멤버가 배열을 반환합니다. 배열을 반환하는 속성은 매우 잘못 될 수 있습니다. 일반적으로 사용자가 내부 상태를 변경할 수 없도록 내부 배열의 사본을 반환해야합니다. 이는 사용자가 자신이 색인화 된 속성이라고 쉽게 가정 할 수 있다는 사실과 함께 비효율적 인 코드로 이어집니다. 다음 코드 예제에서 Methods 속성을 호출 할 때마다 배열의 복사본이 만들어집니다. 결과적으로 배열의 2 ^ n + 1 사본이 다음 루프에서 작성됩니다.
Type type = // Get a type.
for (int i = 0; i < type.Methods.Length; i++)
{
   if (type.Methods[i].Name.Equals ("text"))
   {
      // Perform some operation.
   }
}

[... 더 길게 예시 ...]

읽기 전용 및 쓰기 전용 속성

사용자가 속성의 논리 데이터 멤버를 변경할 수없는 경우 읽기 전용 속성을 사용해야합니다. 쓰기 전용 속성을 사용하지 마십시오.


그렇습니다-최저 놀람의 원리는 여기에서 작동합니다.
Paul Butcher

6

대부분의 경우 단순히 의미가 없기 때문입니다. 설정할 수는 있지만 읽을 수없는 속성은 무엇입니까?

OO가 실제 세계를 더 잘 표현하기 위해 설정된 속성 만 사용하면 모델링이 제대로 수행되지 않을 수 있습니다.

편집 : 참조 : /programming/4564928/are-set-only-properties-bad-practice 기본적으로 직관적이지 않으며 set only 속성은 기본적으로 다른 이름의 방법이므로 사용해야합니다. 방법.


1
이전에는 설정 전용 속성을 사용했습니다. 개체의 개인 필드에 기록하여 동작을 구성합니다. 외부 코드가 현재 값을 알 필요는 없지만 변경해야 할 때 유용합니다. 물론 드문 일이지만, 나는 그것이 일어나는 것을 보았습니다.
메이슨 휠러

@Mason-나는 절대로 절대 사용 해서는 안된다고 말하지않았지만 본질적으로 규칙보다는 예외가되어야합니다.
Jon Hopkins

@MasonWheeler는 그렇지 Foo Foo { private get; set; }않습니까? 나는 그
글만

6

글쎄, 당신이 무언가에 속성을 설정할 수는 있지만 결코 얻지 못한다면, 당신이 설정 한 값을 다른 것이 바꾸거나 덮어 쓸 것인지 결코 알 수 없을 것입니다. 설정 한 값에 의존하고 원하는 시간이 될 때까지 값을 유지할 수없는 경우 문제가 될 수 있습니다.

set-only 속성 대신 메서드를 사용하면 사용자에게 다소 혼란이 줄어 듭니다. 이름 방법의 보통 표시 세트 - 또는 GET- 하지만, 속성 이름은 일반적으로 그 무언가가 있습니다 표시하지 않는 경우에만 설정하고 있지 받은 수. 속성이 "ReadOnlyBackgroundColour"와 같은 것이면 다른 코더와 혼동하지는 않지만 이상하게 보일 것입니다.


동의하지만이 경우 setter 방법이 어떻게 달라 집니까?
트래비스 기독교

1
@Travis Christian : OP가 세터는 있지만 게터가없는 상황에서 작동하는 것 같습니다. 그래서 그들은 무언가를 설정할 수 있지만 나중에 변경되는지 알 수 없습니다.
FrustratedWithFormsDesigner

@Frustrated 그러나 그들은 또한 방법으로 무언가가 다시 바뀌 었는지 결코 알지 못했습니다.
Adam Lear

@Anna Lear ♦ : 게터가 있다면 코드에서 설정 한 값이 갑자기 의심 스러울 수있는 지점이 있다면 사용하기 전에 최소한 값을 테스트 할 수 있습니다.
FrustratedWithFormsDesigner

3
@Frustrated 동의합니다. 문제는 set-only 속성을 사용하는 것과 vs 같은 방법을 사용하는 것에 관한 것입니다.
Adam Lear

-1

이것은 매우 오래된 주제이지만이 후기 단계에서 내 견해로 뛰어 들었으며 쓰기 전용 속성에 대한 사례를 만들려고 할 때 의견을 남기고 싶습니다 ...

ActiveReport여러 사용자 선택 후 인스턴스화되고 포스트 백에서 실행되는 웹 사이트의 일부인 클래스 세트가 있습니다.

VB 코드는 다음과 같습니다.

  Public Class SomeReport
    Private greader As New GenericReporting.CommonReader("AStoredProcedure", 
                                      {New SqlParameter("budget_id", 0)})

    Public WriteOnly Property BudgetID As Integer
      Set(value As Integer)
        greader.Parameters("budget_id").Value = value
      End Set
    End Property

    Public Sub New(Optional budget_id As Integer = 0)
      ' This call is required by the designer.
      InitializeComponent()

      ' Add any initialization after the InitializeComponent() call.
      BudgetID = budget_id
    End Sub
  End Class

이 보고서는 일반 내장을 사용 CommonReader하고 저장 프로 시저 및 기본 배열을 사용하며 SqlParameter, 각각은 보고서 디자인에 따라 인스턴스화시 매개 변수로 전달되거나 인스턴스화 후 사용자가 설정할 수있는 관련 WriteOnly 속성이 있습니다. 보고서 Run메소드를 호출합니다 .

  '''''''''''''''''''''''
  ' Parameter taken from a user selected row of a GridView
  '
  Dim SomeBudgetID As Integer = gvBudgets.SelectedDataKey.Values(budget_id)

  '''''''''''''''''''''''      
  ' On Instantiation
  '
  Dim R as ActiveReport = New SomeReport(SomeBudgetID)
  R.Run()

  '''''''''''''''''''''''      
  ' Or On Instantiation using "With" syntax
  '
  Dim R as ActiveReport = New SomeReport() With {.BudgetID = SomeBudgetID}
  R.Run()

  '''''''''''''''''''''''
  ' Or After
  '
  Dim R as ActiveReport = New SomeReport()
  R.BudgetID = SomeBudgetID
  R.Run()

보시다시피,이 경우 쓰기 전용 속성이

  1. SqlParameters는 일반적인 종류이므로 더 강력한 유형 검사가 가능합니다.
  2. 보고서 작성에 대한 유연성이 향상되어 모든 매개 변수가 사용 가능해 지거나 나중에 추가되면 보고서를 즉시 인스턴스화 할 수 있습니다.
  3. 속성은 인스턴스화시 "With"구문을 지원합니다
  4. 매개 변수가 사용자에게 알려지고 보고서에 의해 변경되지 않으므로 "getter"가 실제로 필요한가?
  5. 이후 SqlParameter의이 클래스와 원시하지 값은, 쓰기 전용 속성을 설정 매개 변수에 대한 간단한 인터페이스를 허용

이것이 저의 생각입니다.

대신 메소드로 변환 할 수 있습니까? 확실하지만 인터페이스는 ... 더 좋지 않은 것 같습니다.

  R2.BudgetID = SomeBudgetID

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