속성의 요점은 무엇입니까?


11

다음은 속성과 내 반론에 대한 몇 가지 주장입니다.

getter 및 setter 메소드를 작성하는 것보다 사용하기 쉬움

Getter와 Setter 메소드 쌍은 코드 ​​냄새입니다. 이것을 쉽게 작성하는 것은 Scantron 양식을 사용하고 모든 'C'를 채워 수학 시험에 쉽게 실패하지 못하게하는 것과 같습니다. 지속성을 위해 상태 만 포함 된 객체는 getter / setter를 사용하지 않아야하며 지속시 불변의 객체를 생성해야합니다.

대상 소비자에게 중요한 것은 대상이 아닌 대상이하는 방식입니다. 그것의 행동은 그것이하는 일입니다. 그것의 상태는 그것을하는 방법입니다. 객체 상태에 관심이있는 경우 (영구를 제외하고 OO를 위반하더라도) 단순히 OOP를 수행하지 않고 그 이점을 잃어 버리는 것입니다.

소비자에게 대략적인 성능 표시를 제공합니다.

이것은 주어진 재산에 대해 미래에 변할 수있는 것입니다. 릴리스 1.0에서 PropertyX에 액세스하면 단순히 필드가 반환됩니다. 릴리스 1.5에서 필드가 널인 경우 PropertyX는 널 오브젝트 패턴을 사용하여 새 널 오브젝트를 작성합니다. 릴리스 2.0에서는 필드가 PropertyX의 getter 메소드에 의해 추가 검증되고 있습니다.

재산이 점점 복잡 해짐에 따라 재산 사용에 대한 성과 표시는 점점 더 진실 해 보이지 않습니다.

그들은 공공 장소보다 낫다

사실입니다. 그러나 방법도 마찬가지입니다.

그것들은 방법과 객체의 근본적으로 다른 측면을 나타내며, 객체의 모든 소비자는 이것에 관심을 가져야합니다.

위의 내용이 모두 사실입니까?

입력하기가 더 쉬워요

물론 타이핑 myObject.Length은 타이핑 보다 쉽지만 myObject.Length()약간의 구문 설탕으로 해결할 수는 없습니까?


속성 대신 메서드를 사용하는 이유는 무엇입니까?

  • 성능이 보장되지 않습니다. 메소드가 더 복잡 해지더라도 API는 진실성을 유지합니다. 소비자는 성능 문제가 발생하고 API에 의존하지 않는 경우 코드를 프로파일 링해야합니다.

  • 소비자가 생각하는 것은 적습니다. 이 속성에 세터가 있습니까? 방법은 확실하지 않습니다.

  • 소비자는 적절한 OOP 사고 방식을 생각하고 있습니다. API 소비자로서 객체의 동작과 상호 작용하는 데 관심이 있습니다. API에서 속성을 볼 때 상태와 매우 비슷합니다. 실제로 속성이 너무 많으면 속성도 아니어야하므로 실제로 API에있는 속성은 소비자에게 표시되는 상태입니다.

  • API 프로그래머는 리턴 값이있는 메소드에 대해 더 깊이 생각하고 가능한 경우 이러한 메소드에서 오브젝트의 상태를 수정하지 않습니다. 가능하면 쿼리에서 명령을 분리해야합니다.


왜 메서드 대신 속성을 사용합니까? MSDN의 대부분의 요점 은 코드 냄새 자체이며 속성이나 메서드에 속하지 않습니다.

(이러한 생각은 CQS에 대해 생각한 후에 나에게왔다.)


5
+1. 속성은 필드의 구문을 가진 메서드이며 의미가 없습니다.
Nemanja Trifunovic

23
@Nemanja Trifunovic : type GetFoo() void SetFoo()만 번 쓴다면 완벽하게 이해됩니다 . 항상 C # 코드를 작성하면서 속성에 의해 혼동되지 않았습니다.
Ed S.

23
당신이 이미 당신의 마음을 구성한 것처럼 들립니다. 질문이 뭐야?
Dean Harding

9
@Nemanja Trifunovic : "게터와 세터는 일반적으로 나쁘다" 원하는만큼 여러 번 반복 할 수 있지만 사실이 아닙니다. 왜 그들이 나쁜 생각을 하는가? 기본 변수 이름 대신 속성 이름을 입력하여 SO가 충돌하는 한, 속성을 호출하자마자 프로그램이 중단되고 오류가 발생하기 때문에 오류를 놓치는 것은 불가능합니다. 그것이 일어날 때 나는 그것을 일으킨 원인을 정확히 알고 있으며 2 초 안에 고쳤습니다. 문제가 보이지 않습니다.
Ed S.

3
그냥 지나가는 것은 @NemanjaTrifunovic을 지적하는 것을 그 getter 및 setter 메소드는 악한 왜 기사가 꽤있다 오래된 ,에 관한 자바자바의 약점을 강조한다 :의 약점 특성을 갖는하지 . (따라서 구현 세부 사항이 너무 많음)… 여기에서 우리의 꼬리를 물고 있습니다. (그것은 getters 라는 제목이어야 하고 setter는 자바에서는 좋지 않다. 왜냐하면 우리는 이것에 대해 잘 생각 된 표준이 없기 때문이다 )
ZJR

답변:


44

왜 "속성에 대한 방법"입니까? 방법은 무언가를합니다. 속성은 객체의 멤버입니다. getter와 setter라는 두 가지 종류의 메서드가 속성에 해당하지만 완전히 다른 것입니다. 일반적으로 속성과 메서드를 비교하는 것은 의미가 없으므로 getter / setter에 대해 이야기한다고 가정합니다.

Getter와 Setter 메소드 쌍은 코드 ​​냄새입니다.

필자가 주장한 것은 아니지만, 두 가지 방법 모두 게터 / 세터 대 속성의 문제가 아니라 어느 쪽을 사용해야하는지의 문제이다. 또한 예를 들어 setX읽기 전용 속성을 만들 수있는 것처럼 부품을 제외 할 수 있습니다.

대상 소비자에게 중요한 것은 대상이 아닌 대상이하는 방식입니다. 그것의 행동은 그것이하는 일입니다. 그것의 상태는 그것을하는 방법입니다. 객체 상태에 관심이있는 경우 (영구를 제외하고 OO를 위반하더라도) 단순히 OOP를 수행하지 않고 그 이점을 잃어 버리는 것입니다.

매우 의심스러운 태도. GUI가 a로 보유한 데이터를 출력 DataStuffManagerImpl하려면 어떻게 든 그 숫자를 가져와야합니다 (응용 프로그램의 절반을 위젯 클래스에 넣는 것은 옵션이 아닙니다).

재산이 점점 복잡 해짐에 따라 재산 사용에 대한 성과 표시는 점점 더 진실 해 보이지 않습니다.

[방법은] 성능을 보장하지 않습니다. 메소드가 더 복잡 해지더라도 API는 진실성을 유지합니다. 소비자는 성능 문제가 발생하고 API에 의존하지 않는 경우 코드를 프로파일 링해야합니다.

거의 모든 경우에, 모든 검증 로직 등은 여전히 ​​효과적으로 O (1)이거나 비용면에서 무시할 수 있습니다. 그렇지 않다면 아마도 너무 멀리 갔을 때가 됐습니다. 그리고 getX()방법은 일반적으로 저렴하게 취급됩니다!

물론 myObject.Length를 입력하는 것이 myObject.Length ()를 입력하는 것보다 쉽지만 약간의 구문 설탕으로 해결할 수는 없습니까?

그 속성 구문 설탕입니다.

소비자가 생각하는 것은 적습니다. 이 속성에 세터가 있습니까? 방법은 확실하지 않습니다.

"이 게터를위한 세터가 있습니까?" 같은 차이가 있습니다.

API 프로그래머는 리턴 값이있는 메소드에 대해 더 깊이 생각하고 가능한 경우 이러한 메소드에서 오브젝트의 상태를 수정하지 않습니다. 가능하면 쿼리에서 명령을 분리해야합니다.

여기에 무엇을 말하려고하는지 잘 모르겠습니다. 속성의 경우 부작용을 일으키지 않는 더 강력한 기록되지 않은 법이 있습니다.


3
+1, 그리고 그것은 기록되지 않은 법이 아닙니다. MSDN의 자산 사용 지침에는 다른 많은 것들과 함께 쓰여 있습니다. OP가 많은 의심을 피하기 위해 그들을 통해 가야한다고 생각합니다. 전화로 작성 했으므로 여기에 링크를 게시 할 수 없지만 지침을 쉽게 찾을 수 있습니다.
decyclone


@delnan : 속성은 구문 설탕이 아닙니다. 속성은 필드처럼 취급 될 수 있습니다 (세터가있는 경우 할당 대상으로 사용할 수 있음). 방법은 없습니다.
xofz

1
@SamPearson :에 obj.x = y매핑 obj.setX(y)하고에 obj.x매핑합니다 obj.getX(). 어떻게 다른가요?

1
@SamPearson 당신은 서로 독립적으로 속성 설정자와 게터의 가시성을 변경할 수 있습니다. 나는 이것을 항상 Entity Framework 객체와 함께 사용합니다. 세터가 보호되므로 프레임 워크 만 값을 설정할 수 있습니다. 따라서 myObject.Length = 10을 허용하지 않고 int length = myObject.Length라고 말하는 것이 가능합니다.
Michael Brown

19

Getter와 Setter 메소드 쌍은 코드 ​​냄새입니다.

그것은 잘못된 가정이며 완전히 틀립니다. Get / Set 메서드는 데이터 멤버를 캡슐화하는 방법이며 "코드 냄새"가 아닙니다. 나는 어떤 사람들이 "코드 냄새"라는 용어를 던지는 방식을 정말로 싫어하지만 어쨌든 ...

이것은 주어진 재산에 대해 미래에 변할 수있는 것입니다. 릴리스 1.0에서 PropertyX에 액세스하면 단순히 필드가 반환됩니다. 릴리스 1.5에서 필드가 널인 경우 PropertyX는 널 오브젝트 패턴을 사용하여 새 널 오브젝트를 작성합니다. 릴리스 2.0에서는 필드가 PropertyX의 getter 메소드에 의해 추가 검증되고 있습니다.

재산이 점점 복잡 해짐에 따라 재산 사용에 대한 성과 표시는 점점 더 진실 해 보이지 않습니다.

제대로 디자인되지 않은 API처럼 들리지만 이것이 속성 구문의 결함 인 방법을 모르겠습니다.

C #의 속성은 프로그래머로서 우리의 삶을 조금 더 쉽게 만들어주는 매우 일반적인 패턴에 대한 단순한 구문 설탕이었습니다. 그러나 요즘 데이터 바인딩을 사용하려면 속성을 "필수"사용해야하므로 이제 구문 설탕보다 조금 더 있습니다. 나는 정말로 당신의 요점에 전혀 동의하지 않는 것 같아요. 왜 당신이 공통 패턴을 직접 지원하는 언어 기능을 싫어하는지 이해하지 못합니다.


1
코드 냄새보다 더 나은 용어를 내기 위해 현상금을 줄 것입니다. 약 1,000 번 사용되는 리팩토링에 관한 책을 읽으십시오. 칠판에있는 손톱과 같습니다.
JeffO

1
@ Jeff O : 네, 그 용어를 가장 많이 사용하는 사람들은 일반적으로 경험이 많지 않습니다.
Ed S.

6
@Jeff O 및 @Ed S : IME, "코드 냄새"는 사람들이 "정말 싫어하지만 실제로 이유가 없다"는 의미에서 사람들이 사용하는 용어가되었습니다.
Steven Evers

3
@SnOrfus : 그렇다. 또는 "종교적"관점을 갖고있을 때, "방법은 절대로 X 개 이상의 줄을 가져서는 안된다" 와 같이 실제로는 의미가 거의 없다 .
Ed S.

1
부적절 게터 / setter 메소드의 사용은 코드 냄새이지만, 너무 너무의 부적절한 사용되어야한다 아무것도 . 사용 사례가 좁은 경우에도 해당 사용 사례에 해당 코드를 사용하는 것은 코드 냄새로 간주되어서는 안됩니다. 모든 것을위한 세터를 만드는 것은 맹목적인 습관이되어서는 안되지만, 적절한 경우 그것들을 포함하는 것을 두려워해서는 안됩니다. 필요한 것은 상태를 바꿀 수있는 클라이언트에 대한 유용성과 균형을 유지하는 것보다 나중에 상태가 더 이른 것을 알 수있게하는 것입니다 (상태가 불변 인 경우 쉬움). 둘 다 유용하지만 코드는 하나를 선택해야합니다.
supercat 2019

10

당신의 전제는 잘못되었습니다.

속성은 결코 성능이나 내부 구현 또는 기타 계약에 해당되지 않습니다.
속성은 특수한 방법으로, 의미 적으로 속성을 나타냅니다. 따라서 유일한 계약은 속성이 예상 한대로 속성이 동작한다는 것입니다.
객체의 색상을 요청하면 일반 필드 액세스로 얻을 수 있는지 또는 제 시간에 계산되는지 여부를 가정하지 않습니다.
요점은 필드를 사용하든 접근자를 사용하든 인터페이스 소비자에게 투명하지만 메소드를 사용하여 속성의 동작을 노출 할 수 있다는 것입니다.

속성을 갖는 것 (그리고 속성이 필드와 반대되는 것처럼 구현을 숨기는 것)은 강력한 선언적 기능으로, 데이터 바인딩 및 기타 유용한 것들을위한 시각적 객체 검사기 및 기타 자동 뷰 생성을위한 기초입니다. 그리고 가장 중요한 것은이 정보를 동료 프로그래머에게도 명확하게 전달하는 것입니다.


6

소비자는 적절한 OOP 사고 방식을 생각하고 있습니다. API 소비자로서 객체의 동작과 상호 작용하는 데 관심이 있습니다. API에서 속성을 볼 때 상태와 매우 비슷합니다. 실제로 속성이 너무 많으면 속성도 아니어야하므로 실제로 API에있는 속성은 소비자에게 표시되는 상태입니다.

프로퍼티가되는 가정 상태가 될 수 있습니다. 기본 setter 또는 getter 코드 가 상태를 설정하거나 가져 오는 데 필요한 처리 에 크게 추가되도록 변경되면 실제로 더 이상 속성이 아니므 로 메소드로 대체 해야 합니다. 이것은 코드 개발자로서 귀하에게 달려 있습니다.

setter 또는 getter에 너무 많은 코드를 너무 많이 넣는 것은 잘못된 일이지만, 가능하기 때문에 모든 경우에 패턴을 버리는 이유는 아닙니다.


6

당신이 누락 한 가지는, 이것이 무지 때문인지 또는 의도적 으로이 세부 사항을 간과하는지 모른다는 것은 속성이 메소드라는 것입니다.

C #의 속성 구문을 사용하면 컴파일러는 속성을 이해하는 언어에 일급 구문 기능으로 이해하는 언어를 알려주는 메타 데이터를 사용하여 getter 및 setter 메서드를 자동으로 만듭니다. 그것은 사실, 당신이 요구하는 구문 설탕입니다. CLR에서 실행할 수있는 몇 가지 언어는이 세부 사항을 완전히 숨기지 않으며 (메모리가 나에게 도움이된다면 부와 일부 Lisp 구현) 게터와 세터를 명시 적으로 호출 할 수 있습니다.

속성은 때때로 변경 알림 이벤트 트리거 (예 : INotifyPropertyChanged) 또는 클래스의 인스턴스를 더티로 표시하는 등의 부작용이 있습니다. 구문을 정통한 매크로를 사용하는 Boo를 제외하고는 더 많은 작업을 수행하지만 실제 가치가있는 곳입니다.

이제 더 넓은 질문은 getter 및 setter 메소드가 실제로 A Good Thing인지 여부입니다. 분명히 절충점이 있습니다. 뮤 테이터 메서드를 사용하는 경우 스레드 동기화 문제를 처리해야하므로 코드의 병렬화가 본질적으로 줄어 듭니다. 또한 변경하기가 편리하기 때문에 뮤 테이터 메소드 (속성 또는 getter / setter 메소드라고도 함)를 사용하여 Demeter of Law Meter를 위반할 위험이 있습니다.

그러나 때로는 옳은 일입니다. 때때로 문제는 일부 소스에서 데이터를 가져 와서 약간 변경하고 업데이트 된 데이터를 사용자에게 제공하고 변경 사항을 저장하는 것입니다. 그 관용구는 속성에 의해 잘 제공됩니다. Allen Holub의 기사에서 알 수 있듯이 게터와 세터에 문제가 있다고해서 절대 사용해서는 안된다는 의미는 아닙니다. (Parroting abstract Guruspeak는 유해한 것으로 간주 됨). Class / Responsibilities / Collaborators 접근 방식을 따를 때에도 정보 또는 정보의 표현을 누군가에게 공개합니다. 요점은 얽힘의 표면적을 최소화하는 것입니다.

속성의 장점은 다른 개체가이를 쉽게 활용할 수 있다는 것입니다. 속성의 단점은 다른 객체를 사용하는 것이 매우 쉽고 쉽게 막을 수 없다는 것입니다.

객체 돌연변이는 컨트롤러 계층, 예를 들어 MVC 아키텍처에서 의미가 있습니다. 공동 작업자입니다. 뷰는 공동 작업자이기도하지만 책임이 다르기 때문에 객체를 직접 변경해서는 안됩니다. 비즈니스 코드에 프리젠 테이션 코드를 롤링하는 것이 게터 / 세터를 피하는 올바른 방법은 아닙니다.

순수한 OO 추상화가 아닌 기능적 기능을 사용하면 수식이 약간 변경되는데, 일반적으로 자유롭지는 않지만 몇 가지 변경 사항이있는 "레코드"개체의 사본을 만드는 것이 일반적입니다. 그리고 성능 보장을 얻으려고 할 때, 불변의 컬렉션을 게으른 재구성하는 것보다 일반적으로 속성을 예측할 수 있습니다.


5

내 책에서 속성을 사용하는 또 다른 중요한 이유는 가독성을 크게 높일 수 있기 때문입니다.

account.setBalance(Account.getBalance()+deposit);

보다 읽기 쉽지 않다

account.Balance += deposit;

6
잔액은 자산 변경이 아니라는 점을 제외하고는 자산이 아니어야합니다 (초과 체크 확인, 서비스 요금 청구, 거래 기록 등). 온도, 배경색 등)
Kate Gregory

9
왜 account.Deposit (amount)?
xofz

4
@ 샘 피어슨 : +1. 게터 / 세터가 종종 디자인이 좋지 않은 이유를 보여주는 완벽한 예입니다.
Nemanja Trifunovic

4

당신은 나에게 거의 반대되는 종교적 견해를 가지고 있습니다 :)

Delphi에서 Java로 옮길 때 속성이 부족하다는 것이 나에게 큰 어려움이었습니다. 나는 속성을 선언하고 개인 변수를 직접 가리 키거나 (보호 된) getter & setter를 작성한 다음 속성에 "배관"하는 데 익숙했습니다. 이것은 속성을 캡슐화하고 명확하고 명확한 방법으로 액세스하는 방법을 제어했습니다. 액세스 할 때 총계를 계산하여 "_getTotal ()"이 아닌 "Total"또는 이와 유사한 balloch라고하는 읽기 전용 속성을 가질 수 있습니다. 또한 추상 기본 클래스에서 속성을 보호 한 다음 공용으로 이동하거나 하위 클래스로 게시하여 속성에 대한 액세스를 제한 할 수 있습니다.

나에게 속성은 객체의 상태를 설정하고 얻는 더 자연스럽고 표현적인 방법입니다. 강화되지 않은 코딩 규칙에 의존하는 것은 속성을 비판하는 것보다 "코드 냄새"에 가깝습니다. 또한 다른 사람들이 말했듯이, 잘못 설계된 속성의 사용과 속성의 개념을 시도하고 무시하는 데 실패하는 것은 매우 나쁜 형태입니다. 속성의 나쁜 사용 만 보았고 그것이 내가 생각하는 방식이라고 가정 할 수도 있지만 너무 독단적이되기 전에 더 많은 연구를해야합니다.


+1 그것은 실제로 부동산의 실제 사용입니다. 좋은 대답입니다. " 또한 그것은 당신이 그것들을 추상 기본 클래스로 보호 한 다음 그것들을 퍼블릭으로 옮기거나 서브 클래스로 출판함으로써 속성에 대한 접근을 제한 할 수 있다는 것을 의미했습니다. "
Karthik Sreenivasan

델파이는 구역질을 잘못 사용합니다. 목록을 정렬하지 않고 sorted 속성을로 설정했습니다 true. 따라서 false원래 목록 을 제공 하도록 설정 하십시오. : D 아니면 무작위로 셔플합니까? : D 또는 어쨌든, 그것은 바보입니다. 또한 적절한 정렬 세트에 비해 속도가 느립니다. 속성은 나쁘지 않지만 매우 드물게 사용하는 법을 배웠습니다 (게터와 세터에 만족할 때까지는 주로 Java를 사용하고 있습니다).
maaartinus

1

Java Beans Framework에 속성이 도입 된 이유 중 하나는 IDE와의 통합을 허용하는 것이 었습니다. 이러한 구성 요소를 IDE로 드래그하고 속성 편집기를 사용하여 속성을 편집 할 수 있습니다.

(그 당시 그들은 정기적 인 게터와 세터 였고 명명 규칙에 의해서만 정의되었으며 실제로 냄새가났습니다)

오늘날 디버깅과 같은 일반적인 코드를 통해 속성에 액세스하고 수정하는 경우가 더 많습니다.


1

또 다른 각도-그들은 실제로 VB에서 나왔습니다. 20 세기의 어두운 시절에 .NET이 VB를 대체하는 손쉬운 대체 솔루션이라는 점이 강조되었습니다. VB 프로그래머는 물건을 웹폼에 끌어다 놓을 수 있습니다. VB에는 속성이 있으므로 제대로 번역하려면 해당 기능을 유지해야했습니다.


1
Anders Heljsberg는 C # (및 일부 IL)을 디자인하고 속성이있는 Delphi도 디자인했습니다.
Jesse C. Slicer

1

속성에는 최소한 두 가지 목적이 있습니다.

  • 그것들은 다르게 구현 되더라도 개념적 으로 필드와 동일합니다 . 게터는 객체의 상태를 변경해서는 안되며 부작용이 없어야합니다. 세터는 필드 수정과 개념적으로 유사한 방식으로 만 상태를 변경해야하며 다른 부작용이 없어야합니다.

  • 그것들은 구문 적으로 공개 (아마도 읽기 전용) 필드와 동일합니다. 즉, 발신자 수준에서 발신자를 차단하지 않고 공개 필드를 속성으로 변경할 수 있습니다.


예, 그러나 "해야한다"라는 단어에 주목하십시오. 게터가 부작용을 일으키는 것을 막는 속성에 대해서는 아무것도 없으며 실제로 그 경우가 많았던 경우를 보았습니다.
Nemanja Trifunovic

1
공용 필드를 속성으로 변경하면 이진 호환성 손상되고 소비 코드를 다시 컴파일해야합니다. 수정하지는 않았지만 추측하고있는 것은 :)
MattDavey

@MattDavey : 감사합니다. 그것이 제가 의미 한 바입니다. 편집했습니다.
dsimcha
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.