게터 허용과 관련하여 정확한 문제는 무엇입니까?


15

나는 의미론에 대한 의견을 찾지 않고 단순히 게터를 현명하게 사용하는 것이 실제 장애가되는 경우를 찾고 있습니다. 어쩌면 그것은 나를 결코 의존하지 않는 나선형으로 나를 던질 수 있습니다. 어쩌면 대안은 더 깨끗하고 게터를 자동으로 처리하는 것 등입니다.

나는 모든 주장을 들었습니다. 나는 그들이 당신을 객체를 데이터 소스로 취급하도록 강요하기 때문에 그들이 나쁘다는 것을 들었습니다. 많이 받아 들여라 "

그러나이 이유를 전혀 합리적인 이유 getData사실, 나쁜 일이 몇 사람들은 의미에 대해 많은 별 자체 미세 같은 게터,하지만 그냥 이름없는 주장 getX, 나에게,이 적어도 재미 .

게터를 현명하게 사용 하면 객체의 무결성이 깨지지 않는 데이터에 대해 의견이없이 깨지는 한 가지는 무엇입니까 ?

물론 무언가를 암호화하는 데 사용되는 문자열에 게터를 허용하는 것은 어리석은 일이지만 시스템이 작동 해야하는 데이터에 대해 이야기하고 있습니다. 어쩌면 당신의 데이터가 완전히 당기지 Provider객체에서하지만, 여전히 개체가 여전히 허용 할 필요가 Provider을 수행하는 $provider[$object]->getData, 그것의 주위에 방법이 없습니다.


내가 묻는 이유 : 게터, 현명하게 사용하고 "안전한"것으로 취급되는 데이터는 신이 보낸 것으로, 내 게터의 99 %가 코드를 통해 요청한 것처럼 객체를 식별하는 데 사용됩니다 Object, what is your name? Object, what is your identifier?. 프로그래밍에 관한 거의 모든 것이 정체성이고 다른 것 자체가 객체 자체보다 더 잘 아는 사람이기 때문에 객체를 다루는 사람은 객체에 대해 이러한 것들을 알아야합니다. 그래서 당신이 순수자가 아니라면 실제 문제를 보지 못합니다.

"getters / setters"가 나쁜 이유에 대한 모든 StackOverflow 질문을 살펴 봤는데 99 %의 경우 setter가 실제로 나쁘다는 데 동의하지만 getter는 운율 때문에 동일하게 취급 할 필요는 없습니다.

세터는 객체의 아이덴티티를 손상시키고 누가 데이터를 변경하고 있는지 디버깅하기가 매우 어렵지만 게터는 아무것도하지 않습니다.


2
나의 충고는 대부분의 OO 이론을 잊어 버린다. 연습. 많은 코드를 작성하고 유지하십시오. 잘 작동하는 것과 실제로 무언가를 한 다음 몇 달 후에 다시 돌아 가지 않는 것에 대해 훨씬 더 많이 배울 것입니다.
jpmc26

1
@ jpmc26 어머니의 것 .... 실제로 우리 중 누구도 실제로 OOP를 올바르게 수행하지 않는다는 것을 결코 깨닫지 못했습니다. 나는 항상 객체의 필드와 관련된 캡슐화 개념을 가지고 있었지만 객체 자체는 상태이며 현재 존재하고 있습니다. 자유롭게 공유. 실제로 모든 사람이 OOP를 잘못하고 있거나 패러다임이 대상이라면 OOP가 불가능합니다. 나는 시스템이 어떻게 작동하는지 표현하기 위해 OOP를 엄격하게 사용하며 결코 성 배나 SOLID로 취급하지 않았습니다. 그것들은 내가 개념의 합리적으로 (구현을 통해) 정의하기 위해 주로 사용하는 도구 일뿐입니다. 이것이 옳은지 읽습니까?
coolpasta

2
--cont, 내가 더 많이 쓸수록 프로그래밍은 코드베이스에 대해 추론하고 다른 사람들에게 추론 하기 위해 필요한만큼 추상화 할 수 있다는 것 입니다. 물론 이것의 기술적 측면은 올바른 점검을 수행하고 올바른 규칙을 설정하는 것입니다. 사실, 다른 사람들이 자신의 코드를 더 잘 이해하도록 만드는 사람은 누구나 이길 수 있습니다. 읽는 사람에게 의미가 있는지 확인한 다음, 인터페이스를 사용하여 객체를 올바르게 세그먼트 화하고, 추론하기가 더 쉬운 다른 패러다임으로 전환하여 실패하지 않도록하십시오.
coolpasta

2
이것은 나에게 빨대처럼 보인다. 실제로 사용 가능한 코드를 작성하는 심각한 개발자는 게터를 현명하게 사용하는 것이 문제라고 주장하지는 않습니다. 이 질문은 게터가 현명하게 사용될 수 있음을 암시하며, 이는 게터가 현명 할 수 있음을 암시합니다. 게터를 현명하게 사용하지 않는다고 말하는 사람을 찾고 있습니까? 당신은 잠시 기다릴 것입니다.
JimmyJames

2
@coolpasta 당신이 맞아요. 순수한 OOP인지는 신경 쓰지 않습니다. 더 좋아 인간이 이해할 수있는 깨진 코드와 해독 할 수없는 완벽한 CPU 사랑 코드 중에서 선택할 수 있으며 매번 인간 친화적 인 코드를 취할 것입니다. OOP는 한 번에 생각해야 할 것들의 수를 줄일 때만 유용합니다. 그것이 바로 절차적인 절차보다 그것을 좋아하는 유일한 이유입니다. 그것 없이는 아무 이유없이 여러 소스 코드 파일을 뛰어 넘을 수 있습니다.
candied_orange 2

답변:


22

게터 없이는 좋은 코드를 작성할 수 없습니다.

게터가 캡슐화를 깨뜨리지 않기 때문에 왜 그렇지 않습니까? 게터가 사람들이 OOP를 따르지 않도록 유혹하지 않기 때문에 행동하는 데이터로 메소드를 넣을 수 있습니다. 그들이하다. 아니요, 경계 때문에 게터가 필요합니다.

캡슐화 및 메서드 유지 방법과 메서드가 작동하는 데이터는 메서드 이동을 방해하는 경계에 도달하면 작동하지 않으므로 데이터를 이동해야합니다.

정말 간단합니다. 경계가 없을 때 게터를 사용하면 실제 객체가 없습니다. 모든 것이 절차적인 경향이 있습니다. 어느 것이나 잘 작동합니다.

진정한 OOP는 어디에나 퍼질 수있는 것이 아닙니다. 그것은 그 경계 내에서만 작동합니다.

그 경계는 얇지 않습니다. 그들은 그들 안에 코드를 가지고 있습니다. 이 코드는 OOP 일 수 없습니다. 기능도 할 수 없습니다. 이 코드는 우리의 이상을 제거하여 가혹한 현실을 다룰 수 없습니다.

마이클 페터스 (Michael Fetters)는이 부분을 ​​오렌지색 부분으로 묶은 흰색 결합 조직에 이어이 코드 근막 이라고 불렀 습니다.

이것은 그것에 대해 생각하는 훌륭한 방법입니다. 동일한 코드베이스에 두 종류의 코드가 모두 적합한 이유를 설명합니다. 이러한 관점이 없다면 많은 새로운 프로그래머들이 자신의 이상에 강하게 집착하고, 첫 경계에 부딪 칠 때 그들의 마음을 상하게하고이 이상을 포기하게됩니다.

이상은 적절한 장소에서만 작동합니다. 그들이 모든 곳에서 일하지 않기 때문에 포기하지 마십시오. 그들이 일하는 곳에 사용하십시오. 그 장소는 근막이 보호하는 수분이 많은 부분입니다.

경계의 간단한 예는 모음입니다. 이것은 무언가를 가지고 있으며 그것이 무엇인지 전혀 모릅니다. 컬렉션 디자이너는 보류중인 개체의 동작 기능이 무엇을 보유할지 모를 때 컬렉션으로 어떻게 이동할 수 있습니까? 당신은 할 수 없습니다. 당신은 경계에 반대합니다. 컬렉션에 게터가있는 이유가 여기에 있습니다.

알았다면, 그 행동을 움직일 수 있고 상태를 이동하지 않아도됩니다. 알면 알아야합니다. 당신은 항상 모른다.

어떤 사람들은 이것을 실용적이라고 부릅니다. 그리고 그건. 그러나 왜 우리가 실용적이되어야하는지 아는 것이 좋습니다.


당신은 의미 론적 주장을 듣고 싶지 않다고 말했고 "현명한 게터"를 어디에나 두는 것을 옹호하는 것처럼 보인다. 당신은이 아이디어에 도전을 요구하고 있습니다. 아이디어가 프레임 방식에 문제가 있음을 보여줄 수 있다고 생각합니다. 하지만 거기에 왔기 때문에 어디에서 왔는지 알고 있습니다.

어디서나 getter를 원하면 Python을 살펴보십시오. 비공개 키워드가 없습니다. 그러나 파이썬은 OOP를 잘 수행합니다. 어떻게? 그들은 시맨틱 트릭을 사용합니다. 그들은 밑줄이있는 개인용으로 이름이 지정됩니다. 책임을 진다면 읽을 수 있습니다. "우리는 모두 성인입니다"라고 종종 말합니다.

그렇다면 Java 또는 C #의 모든 것에 게터를 두는 것의 차이점은 무엇입니까? 미안하지만 의미 론적입니다. Pythons 밑줄 표시 규칙은 직원들에게 문 밖에 숨어 있다는 것을 분명히 알려줍니다. 모든 것을 습득하면 그 신호를 잃게됩니다. 리플렉션을 사용하면 어쨌든 개인을 제거하고 의미 신호를 잃지 않을 수 있습니다. 여기서는 구조적으로 논쟁의 여지가 없습니다.

우리가 남긴 것은 "직원 전용"표시를 어디에 둘 것인지 결정하는 일입니다. 사적인 것으로 간주되어야하는 것은 무엇입니까? 당신은 "현명한 게터"라고 부릅니다. 내가 말했듯이, 게터에 대한 최고의 정당화는 우리를 우리의 이상으로부터 멀어지게 만드는 경계입니다. 그것은 모든 것에 게터가되지 않아야한다. 게터가 발생하면 동작을 보호 할 수있는 수분이 많은 비트로 이동시키는 것을 고려해야합니다.

이러한 분리로 인해 몇 가지 용어가 생겼습니다. 데이터 전송 개체 또는 DTO에는 동작이 없습니다. 유일한 메소드는 getter 및 때로는 setter이며 때로는 생성자입니다. 이 이름은 실제 개체가 아니기 때문에 불행합니다. 게터와 세터는 실제로 중단 점을 설정할 수있는 디버깅 코드입니다. 그것이 필요가 없다면 공공 장소 일뿐입니다. C ++에서는 구조체를 호출했습니다. C ++ 클래스와의 유일한 차이점은 기본적으로 public이었습니다.

DTO는 경계 벽 위로 던져서 다른 방법을 안전하게 수분이 많은 행동 오브젝트에 유지할 수 있기 때문에 좋습니다. 진정한 객체. 위반하는 게터가 없으면 캡슐화입니다. 내 행동 객체는 DTO를 Parameter Objects 로 사용하여 먹을 수 있습니다 . 때로는 변경 가능한 공유 상태 를 막기 위해 방어적인 복사본 을 만들어야합니다 . 경계 내 수분이 많은 부분 안에 가변 DTO를 퍼 뜨리지 않습니다. 나는 그들을 캡슐화합니다. 나는 그들을 숨 깁니다. 그리고 마침내 새로운 경계에 부딪 치면 새로운 DTO를 회전시켜 벽에 던지므로 다른 사람의 문제가됩니다.

그러나 당신은 정체성을 표현하는 게터를 제공하고자합니다. 경계를 찾은 것을 축하합니다. 엔터티 에는 참조를 넘어서는 정체성이 있습니다. 즉, 메모리 주소를 넘어선 것입니다. 따라서 어딘가에 보관해야합니다. 그리고 그것은 무언가를 정체성으로 언급 할 수 있어야합니다. 정체성을 나타내는 게터는 완벽하게 합리적입니다. 해당 Getter를 사용하여 엔티티 자체가 결정할 수있는 결정은 아닙니다.

결국 그것은 잘못된 게터의 존재가 아닙니다. 그들은 공공 장소보다 훨씬 낫다. 나쁜 것은 그들이 당신이 아닌 객체 지향되는 척하는 데 사용되는 때입니다. 게터는 좋다. 객체 지향이 좋습니다. 게터는 객체 지향적이지 않습니다. 게터를 사용하여 객체 지향의 안전한 장소를 개척하십시오.


이것이 바로 제가 요청한 이유이며 Robert와 대화를 볼 수 있는지 잘 모르겠습니다. 또한 "현명한 게터"를 사용하는 것이 분명히 상처를주는 특정 사례를 찾으려고 노력했습니다. 나는 저 자신 에게 세터에 동의하지 않습니다. 왜냐하면 적어도 나 자신에게는 이런 행동에 소유권을 부여하기가 매우 어렵 기 때문에 모든 것에 세터를 사용하고 너무 많은 객체로 인해 영향을받을 때 1 세터조차도 깨달았습니다. 나 ... 나는 모든 것을 다시 써야했다. 철저한 테스트를 거친 후 게터를 현명하게 사용하면 순수하지 않은 사람에게는 심각한 단점이 없습니다.
coolpasta

1
@coolpasta 데이터 소유자 객체를 만들 수 있습니다. 데이터 소유자 개체는 데이터 개체이지만 데이터를 명확하게 소유하도록 설계되고 이름이 지정됩니다. 물론 이러한 객체에는 게터가 있습니다.
rwong

1
@rwong 무슨 뜻 clearly인가요? 데이터가 무언가, 가치의해 나에게 전달 되면 분명히 내 객체가 데이터를 소유하지만 의미 론적으로 아직이 시점에서 다른 사람의 데이터를 얻지 못했습니다. 그런 다음 해당 데이터를 변환하는 조작을 수행하여 자체 데이터를 작성하고 데이터를 터치하는 순간 의미를 변경해야합니다. 데이터 이름이 지정 $data_from_request되었으므로 이제 데이터 를 조작 했습니까? 이름을 지정하십시오 $changed_data. 이 데이터를 다른 사람에게 노출 하시겠습니까? getter를 작성하면 getChangedRequestData소유권이 명확하게 설정됩니다. 아니면?
coolpasta 2016

1
"게터 없이는 좋은 코드를 작성할 수 없습니다." 경계에는 본질적으로 게터가 필요하다는 개념과 마찬가지로 이것은 완전히 잘못되었습니다. 이것은 실용주의가 아니라 게으름입니다. 사용 사례를 생각하고 좋은 행동 API를 디자인하는 것은 어렵습니다.
Robert Bräutigam 19

2
훌륭한 답변!
cmaster-monica reinstate

10

Getters는 Hollywood 원칙을 위반합니다 ( "전화하지 마십시오. 전화하겠습니다").

Hollywood Principle (일명 Inversion of Control)에서는 작업을 수행하기 위해 라이브러리 코드를 호출하지 않습니다. 오히려 프레임 워크가 코드를 호출합니다. 프레임 워크가 사물을 제어하기 때문에 내부 상태를 클라이언트에 브로드 캐스트 할 필요가 없습니다. 당신은 알 필요가 없습니다.

가장 교활한 형태로 Hollywood Principle을 위반하면 getter를 사용하여 클래스 상태에 대한 정보를 얻은 다음 획득 한 가치에 따라 해당 클래스를 호출 할 메소드를 결정합니다. 최고의 캡슐화 위반입니다.

게터를 사용한다는 것은 실제로 필요하지 않을 때 해당 값이 필요하다는 것을 의미합니다 .

실제로 성능 개선이 필요할 수 있습니다

가능한 최대 성능을 가져야하는 가벼운 개체의 극단적 인 경우 게터가 부과하는 매우 작은 성능 저하를 지불 할 수 없습니다 (매우 가능성은 낮음). 이것은 99.9 %의 시간이 걸리지 않습니다.


1
이해할 필요가 없다는 것을 이해하고 나는 당신의 진실로 날아갈 것입니다. . 그러나 나는 필요한 곳에 도달했습니다. Generator모든 객체를 반복 하는 객체 가 있고 각 Items객체를 호출 getName하여 Item추가 작업을 수행합니다. 이 문제는 무엇입니까? 그런 다음 답례로 Generator서식이 지정된 문자열을 뱉어냅니다. 이것은 내 프레임 워크 내에 있으며 사용자가 프레임 워크를 건드리지 않고 사용자가 제공하는 모든 것을 실행할 수있는 API를 사용할 수 있습니다.
coolpasta

3
What is the issue with this?내가 볼 수있는 것은 없습니다. 그것은 본질적으로 map함수가하는 일입니다. 그러나 그것은 당신이 묻는 질문이 아닙니다. 당신은 본질적으로 "저기 어떤 게터가 권할 수 있습니다되는 조건은." 나는 두 가지로 대답했지만 그것이 세터를 완전히 버리는 것을 의미하지는 않습니다.
Robert Harvey

1
당신은 잘못된 사람에게 그 질문을하고 있습니다. 나는 실용 주의자입니다. 나는 내 특정 프로그램에 가장 적합한 것을하고, 그들이 제 목적을 달성하지 않으면 "원칙"에 많은 주식을 넣지 않습니다.
로버트 하비

2
@ jpmc26 : 프레임 워크. 도서관이 아닙니다.
Robert Harvey

2
프레임 워크는 범용 언어를 도메인 별 언어로 바꾸려는 시도입니다. 라이브러리는 재사용 가능한 알고리즘의 모음입니다. 둘 중 하나에 의존하도록 요청할 것입니다. 종속성을 하드 코딩하거나 종속성을 쉽게 대체 할 수있게하는 것은 사용자에게 달려 있습니다.
candied_orange

2

Getters 유출 구현 세부 사항 및 중단 추상화

치다 public int millisecondsSince1970()

당신의 클라이언트는 "오, 이것이 INT이다"생각하고 그것이라고 가정 할 gazillion 호출이있을 것이다 INT 당신이 필요 실현하면 ... 등 날짜를 비교하는 정수 수학을하고, 많이있을 것입니다, 문제가있는 레거시 코드. Java 세계 @deprecated에서 API에 추가 하면 모든 사람이 API를 무시하고 더 이상 사용되지 않는 버그가있는 코드를 유지해야합니다. :-( (다른 언어가 비슷하다고 가정합니다!)

이 특별한 경우에는 더 나은 옵션이 무엇인지 잘 모르겠으며 @candiedorange 답변이 완전히 제자리에 있고 getter가 필요할 때가 여러 번 있지만이 예제는 단점을 보여줍니다. 모든 공개 게터는 사용자를 특정 구현에 "고정"시키는 경향이 있습니다. 당신이 진정으로 "경계를 넘어야"할 필요가있을 때, 가능한 한 적게주의하고 신중하게 사용하십시오.


이것은 사실이지만 데이터 유형 / 구조를 객체의 변수뿐만 아니라 해당 변수에 대해 게터를 사용하는 모든 것에 적용하는 패턴 솔루션은 무엇입니까?
coolpasta 2016

1
이 예는 다른 현상, 원시적 강박 관념을 보여줍니다. 요즘 대부분의 라이브러리와 프레임 워크는 대표 클래스가 timepoint하고 timespan각각을. ( epoch특정 값이다 timepoint.) 이러한 클래스, 그들은 같은 게터 제공 getInt하거나 getLong또는 getDouble. 시간을 조작하는 클래스가 (1) 이러한 객체와 메소드에 시간 관련 산술을 위임하고 (2) getter를 통해 이러한 시간 객체에 액세스 할 수 있도록하는 경우 getter를 제거 할 필요없이 문제가 해결됩니다. .
rwong

1
요약하면 게터는 API의 일부이므로 게터는 과거, 현재 및 미래의 결과를 포함하여 모든 결과를 충분히 고려하여 설계해야합니다. 그러나 이것이 게터의 수를 피하거나 최소화한다는 결론으로 ​​이어지지는 않습니다. 실제로, 나중에 getter가 생략 된 특정 정보에 액세스해야하는 경우 라이브러리 측 API 변경 및 코드 변경이 필요했을 것입니다. 따라서, 특정 게터가 구현되어야하는지 또는 피해야하는지에 대한 결정은 예방 이유가 아니라 도메인 및 의도에 기초해야한다.
rwong

1
"millisecondsSince1970"나는 :-) 그것을 사용하는 많은 코드가있을 것입니다 의심 있도록 월 1970 년 말 이전에 32 개 비트의 int에 대한 작동이 중지
gnasher729

1
@rwong 다소 정확하지만, 시점을 나타내는 선호 라이브러리가 안정적이라고 가정합니다. 그들이 아닌. 예 : moment.js
user949300

1

첫 번째 열쇠는 절대성이 항상 잘못되었음을 기억하는 것입니다.

단순히 사람들의 연락처 정보를 저장하는 주소록 프로그램을 고려하십시오. 그러나 올바르게하고 컨트롤러 / 서비스 / 리포지토리 계층으로 나눕시다.

거기가 될 것 Person등의 이름, 주소, 전화 번호 .. : 실제 데이터를 보유 클래스 AddressPhone우리가 지원을 미국 이외의 방식으로 나중에 다형성을 사용할 수 있도록, 역시 클래스이다. 이 세 클래스는 모두 Data Transfer Objects 이므로 getter 및 setter 일뿐입니다. 그리고, 그 의미가 있습니다 : 그들은 무시를 넘어 그 안에 어떤 논리를 가지고하지 않을거야 equalsgetHashcode ; 완전한 개인 정보를 제공하도록 요청하는 것은 말이되지 않습니다 : HTML 프리젠 테이션, 사용자 정의 GUI 앱, 콘솔 앱, HTTP 엔드 포인트 등을위한 정보입니까?

컨트롤러, 서비스 및 리포지토리가 제공됩니다. 이러한 모든 클래스는 종속성 주입 덕분에 로직이 많고 게터가 가벼워 질 것입니다.

컨트롤러는 서비스를 주입 할 것이며 , getand와 같은 메소드를 노출시킬 것입니다 save. 둘 다 합리적인 인수를 취할 것입니다 (예 : get이름으로 검색하거나 우편 번호로 검색하거나 모든 것을 얻습니다. save아마도 걸릴 것입니다. 싱글Person 및 저장). 컨트롤러에는 어떤 게터가 있습니까? 구체적인 클래스의 이름을 얻을 수 있으면 로깅에 유용 할 수 있지만 주입 된 상태 이외의 상태는 무엇입니까?

마찬가지로 서비스 계층에는 리포지토리가 주입되므로 실제로 가져오고 유지할 Person수 있으며 "비즈니스 로직"이있을 수 있습니다 (예 :Person 객체에 적어도 하나의 주소 또는 전화가 있어야 함) 번호). 그러나 다시 : 주사 된 것 이외의 다른 상태는 무엇입니까? 다시 한 번

리포지토리 계층은 상황이 조금 더 흥미로워지는 곳입니다. 예를 들어, 스토리지 위치에 대한 연결을 설정합니다. 파일, SQL 데이터베이스 또는 메모리 내 저장소 여기서 파일 이름이나 SQL 연결 문자열을 가져 오기 위해 getter를 추가하려는 유혹이 있지만 클래스에 주입 된 상태입니다. 저장소에 데이터 저장소에 성공적으로 연결되었는지 여부를 알려주는 게터가 있어야합니까? 아마도 저장소 클래스 외부의 정보는 어떤 용도로 사용됩니까? 리포지토리 클래스 자체는 필요한 경우 데이터 저장소에 다시 연결을 시도 할 수 있어야합니다. 이는 isConnected속성이 이미 의심스러운 값 임을 암시합니다 . 또한, isConnected속성이 가장 옳 아야 할 때만 잘못 될 수 있습니다.isConnected데이터를 가져 오기 / 저장하기 전에 "실제"호출이 수행 될 때 리포지토리가 계속 연결되어 있다고 보장 할 수 없으므로 어딘가에서 예외 처리의 필요성을 제거하지 않습니다 ( 이 질문의 범위).

단위 테스트도 고려하십시오 (단위 테스트를 작성하고 있습니까?). 서비스는 특정 클래스가 주입 될 것으로 예상하지 않고 인터페이스의 구체적인 구현이 주입 될 것으로 기대합니다. 따라서 응용 프로그램이 서비스에 주입 된 리포지토리를 교체하지 않고 데이터를 저장하는 전체 변경 사항으로 응용 프로그램을 사용할 수 있습니다. 또한 모의 저장소를 주입하여 서비스를 단위 테스트 할 수 있습니다. 이것은 클래스가 아닌 인터페이스 측면에서 생각하는 것을 의미합니다. 리포지토리 인터페이스에 게터가 표시됩니까? 즉, 모든 저장소에 공통적이고 저장소 외부에서 유용하며 저장소에 주입되지 않는 내부 상태가 있습니까? 나는 나 자신을 생각하기가 힘들다.

TL; DR

결론 : 데이터를 전달하는 것이 유일한 목적인 클래스 외에, 스택의 다른 어떤 것도 게터를 넣을 장소가 없습니다.


이 사고 방식은 C # 속성의 올바른 사용에 대한 토론과 매우 유사합니다. 요컨대, 속성 (게터 전용 또는 게터-세터 쌍일 수 있음)은 "설정 한 것이 무엇을 얻는가", "게터는 대부분 부작용이 없어야합니다", "getter는 오류 발생을 피해야합니다"등 결론과 달리 속성 (또는 getter)으로 노출되는 것이 유리한 많은 객체 상태가 있습니다. 여기에 인용하기에는 예가 너무 많습니다.
rwong

2
@rwong 몇 가지 예를 알고 싶습니다. 한 팀에서 구현 한 "일반" "엔터프라이즈"응용 프로그램을 예로 들어 보겠습니다. 또한 단순성을 위해 관련된 제 3자가 없다고 가정 해 봅시다. 캘린더, 애완 동물 가게 등 원하는 모든 것을 갖춘 독립형 시스템입니다.
Robert Bräutigam 18

1

게터를 현명하게 사용하면 객체의 무결성이 깨지지 않는 데이터에 대해 의견이없이 깨지는 한 가지는 무엇입니까?

가변 회원.

객체에 게터를 통해 노출되는 사물 모음이 있으면 컬렉션에 추가되는 잘못된 사물과 관련된 버그에 노출 될 수 있습니다.

게터를 통해 노출되는 가변 객체가있는 경우 예상치 못한 방식으로 객체의 내부 상태가 변경 될 가능성이 있습니다.

실제로 나쁜 예는 현재 값을 변경 가능한 참조로 노출하는 1에서 100까지의 수를 세는 객체입니다. 이를 통해 제 3 자 오브젝트가 값이 예상 범위를 벗어날 수있는 방식으로 Current의 값을 변경할 수 있습니다.

이것은 대부분 가변 객체를 노출 할 때 발생하는 문제입니다. 구조체 나 불변 개체를 노출시키는 것은 전혀 문제가되지 않습니다. 그에 대한 변경은 복사본을 대신 변경합니다 (일반적으로 구조체의 경우 암시 적 복사본 또는 불변의 개체의 경우 명시 적 복사본).

차이를 쉽게 볼 수있는 은유를 사용합니다.

꽃에는 독특한 것들이 많이 있습니다. 그것은 Color꽃잎을 가지고 있으며 많은 꽃잎 (NumPetals)을 가지고 있습니다. 내가 실제로 그 꽃을 관찰하고 있다면, 그 색을 분명히 볼 수 있습니다. 그런 다음 해당 색상을 기반으로 결정을 내릴 수 있습니다. 예를 들어, 색상이 검은 색인 경우 여자 친구에게 제공하지 말고 색상이 빨간색 인 경우 여자 친구에게 제공하십시오. 우리의 객체 모델에서, 꽃의 색은 꽃 객체에 게터로 노출 될 것입니다. 그 색을 관찰하는 것은 내가 수행 할 행동에 중요하지만 꽃 물체에 전혀 영향을 미치지는 않습니다. 나는 그 꽃의 색을 바꿀 수 없어야한다. 마찬가지로 색상 속성을 숨기는 것은 의미가 없습니다. 꽃은 일반적으로 사람들이 색을 관찰하는 것을 막을 수 없습니다.

꽃을 염색하면 꽃에 대해 ReactToDye (Color dyeColor) 메서드를 호출해야합니다. 그러면 내부 규칙에 따라 꽃이 바뀝니다. 그런 다음 ColorReactToDye 메서드가 호출 된 후 속성을 다시 쿼리하고 변경 내용에 반응 할 수 있습니다. Color내가 꽃의 꽃 을 직접 수정하는 것은 잘못이며 , 가능하다면 추상화가 무너졌습니다.

때때로 (빈번하지만 언급 할만한 가치가있는 경우가 많음) 세터는 매우 유효한 OO 디자인입니다. 고객 객체가 있으면 해당 주소에 대한 세터를 노출하는 것이 매우 유효합니다. 당신이든 그 전화 setAddress(string address)또는 ChangeMyAddressBecauseIMoved(string newAddress)단순히 string Address { get; set; }의미의 문제이다. 해당 객체의 내부 상태를 변경해야하며이를 수행하는 적절한 방법은 해당 객체의 내부 상태를 설정하는 것입니다. 에 Customer거주했던 주소 기록이 필요하더라도 세터를 사용하여 내부 상태를 적절히 변경할 수 있습니다. 이 경우에는 Customer불변 인 것이 의미 가 없으며 주소를 변경하는 데 더 좋은 방법은 없습니다.

게터와 세터가 나쁘거나 객체 지향 패러다임을 깨뜨릴 것을 누가 확신하는지 모르겠지만, 그렇게 할 경우 사용하는 언어의 특정 언어 기능에 대한 응답으로 그렇게 할 수 있습니다. 나는 이것이 자바 "모든 것이 하나의 객체"문화에서 생겨났다는 느낌을 받는다. .NET 세계에는이 논의가 전혀 없습니다. Getter 및 Setter는 언어로 응용 프로그램을 작성하는 사람들뿐만 아니라 언어 API 자체에서도 사용되는 최고급 언어 기능입니다.

게터를 사용할 때는주의해야합니다. 잘못된 데이터 조각을 노출하고 싶지 않으며 데이터를 잘못된 방식으로 노출하고 싶지도 않습니다 (예 : 변경 가능한 객체, 소비자가 내부 상태를 수정할 수있는 구조체에 대한 참조). 그러나 외부 소비자가 개체를 사용하고 동일한 소비자가 잘못 사용하지 못하도록 데이터를 캡슐화 할 수 있도록 개체를 모델링하려고합니다. 종종 게터가 필요할 것입니다.

요약하자면, Getter와 Setter는 유효한 객체 지향 디자인 도구입니다. 그것들은 모든 구현 세부 사항이 노출되도록 자유롭게 사용되지는 않지만 객체 소비자가 객체를 효율적으로 사용할 수 없도록 드물게 사용하고 싶지는 않습니다.


-1

게터를 사용하면 의견이없는 한 가지는 깨질 것입니다 ...

유지 보수성이 손상됩니다.

언제든지 (거의 항상 말해야합니다) 기본적으로 요청받은 것보다 더 많이주는 게터를 제공합니다. 이것은 또한 요청 된 것보다 많은 것을 유지해야한다는 것을 의미하며, 실제 이유없이 유지 보수성을 낮추어야합니다.

@candied_orange의 Collection예를 들어 봅시다 . 그가 쓴 것과 달리 게터가 Collection 없어야합니다 . 컬렉션은 매우 특정한 이유로 존재하며, 특히 모든 항목 을 반복 해야합니다. 이 기능은 누구나 놀랄 일이 아니므로 사용자에게 사이클을 사용하거나 게터를 사용하거나 사용하지 않는 등의 명백한 사용 사례를 푸시하는 대신에 구현 해야 합니다 Collection.

공정하게하기 위해 일부 경계 에는 게터 필요합니다. 실제로 무엇을 사용할지 모르는 경우에 발생합니다. 예를 들어 Exception, 오늘날 사람들 이 프로그래밍 방식으로 스택 트레이스를 얻을 수 있는데, 사람들이 작성하지 않았거나 상상할 수 없었던 모든 종류의 호기심 많은 이유에서 사람들 이 스택 트레이스 를 사용하기를 원했기 때문입니다.


1
반례. Collection에서처럼 두 개의을 동시에 반복해야하는 함수를 고려하십시오 (A1, B1), (A2, B2), .... "zip"의 구현이 필요합니다. 반복 기능이 둘 중 하나에 구현 된 경우 "zip"을 어떻게 구현 Collection합니까? 다른 하나의 해당 항목에 어떻게 액세스합니까?
rwong 님

@rwong 라이브러리 작성 방법에 따라 자체적 Collection으로 구현 zip해야합니다. 그렇지 않은 경우이를 구현하고 라이브러리 작성자에게 풀 요청을 제출하십시오. 나는 어떤 경계에는 때때로 게터가 필요하다는 데 동의했다. 나의 진짜 문제는 게터가 오늘날 어디에나 있다는 것이다.
Robert Bräutigam

이 경우 라이브러리는 Collection적어도 자체 구현을 위해 객체에 게터가 있어야 함을 의미합니다 zip. (즉, getter는 최소한 패키지 가시성을 가져야한다.) 이제 풀 요청을 수락하는 라이브러리 작성자에 의존한다.
rwong

나는 당신을 잘 이해하지 못합니다. 는 Collection분명히 자신의 내부 상태에 액세스 할 수 있습니다, 또는 더 정확하게하기 위해 Collection인스턴스의 다른 내부 상태에 액세스 할 수 있습니다. getter가 필요없는 동일한 유형입니다.
Robert Bräutigam 18

나도 당신의 말을 듣지만 다시 게터에게 더 나은 해결책은 무엇입니까? 나는 그것이 질문의 범위를 벗어난 것을 알고 있습니다.
coolpasta
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.