Allen Holub은 "get/set 함수를 절대 사용해서는 안 됩니다"라고 썼습니다. 그가 맞습니까?[복제하다]

StackOverflow https://stackoverflow.com/questions/996179

문제

이 질문에는 이미 답변이 있습니다.

Allen Holub은 다음과 같이 썼습니다.

결합 없이는 프로그램을 가질 수 없습니다.그럼에도 불구하고 OO(객체 지향) 원칙을 맹목적으로 따르면 결합을 상당히 최소화할 수 있습니다(가장 중요한 것은 객체의 구현이 이를 사용하는 객체로부터 완전히 숨겨져야 한다는 것입니다).예를 들어, 객체의 인스턴스 변수(상수가 아닌 멤버 필드)는 항상 비공개여야 합니다.기간.예외 없음.항상.진심이야.(가끔 보호된 메서드를 효과적으로 사용할 수 있지만 보호된 인스턴스 변수는 혐오스럽습니다.)

합리적으로 들리지만 그는 이어서 이렇게 말합니다.

당신은해야 get/set 함수를 절대 사용하지 마세요 같은 이유로 필드를 공개로 만드는 지나치게 복잡한 방법일 뿐입니다(반환된 객체의 클래스가 설계의 주요 추상화인 상황에서는 기본 유형 값이 아닌 완전한 객체를 반환하는 액세스 함수가 ​​합리적이지만) ).

솔직히 나에게는 미친 소리처럼 들린다.

나는 정보 숨김의 원리를 이해하지만 접근자와 변경자가 없으면 Java Bean을 전혀 사용할 수 없습니다.모델에 접근자 없이 MVC 디자인을 어떻게 따를지 모르겠습니다. 할 수 없다 뷰 렌더링을 담당합니다.

하지만 저는 젊은 프로그래머이고 매일 객체 지향 디자인에 대해 더 많이 배웁니다.아마도 경험이 더 많은 사람이 이 문제에 대해 의견을 제시할 수 있을 것입니다.

참고용 Allen Holub의 기사


관련 질문:

도움이 되었습니까?

해결책

나는 당신이 일반적으로 변화를 피해야한다고 말하는 Holub에 문제가 없습니다. 상태 대상이지만 대신이 목적을 달성하기 위해 통합 방법 (동작 실행)에 의지합니다. Corletk이 지적했듯이, 가장 높은 수준의 추상화에 대해 길고 열심히 생각하는 데는 지혜가 있으며, 캡슐화 주변에서 종료를 할 수있는 getters/setters로 무의식적으로 프로그래밍하는 것이 아닙니다.

그러나, 나는 당신이 당신이 당신이 "절대로"세트를 사용하지 말아야한다고 말하거나 원시 유형에 접근하지 말아야한다고 말하는 사람에게 많은 어려움을 겪고 있습니다. 실제로, 이러한 수준의 순도를 유지하는 데 필요한 노력은 모두 사례는 적절하게 구현 된 속성을 사용하는 것보다 코드에서 더 복잡해질 수 있습니다. 장기 통증을 희생하여 단기 이익을위한 규칙을 스커트 할 때 알기에 충분한 감각이 있어야합니다.

Holub은 당신이 그 차이를 알고 있다고 믿지 않습니다. 차이를 아는 것은 당신을 전문가로 만드는 것이라고 생각합니다.

다른 팁

그 기사를주의 깊게 읽으십시오. Holub은 Getters와 Setters가 시스템을 설계 할 때 미끄러지는 나쁜 습관 인 악의 "기본 반포"라는 점을 추진하고 있습니다. 우리가 할 수 있기 때문에.

사고 과정은 선을 따라야합니다. 이 대상은 무엇을합니까? 하다? 책임은 무엇입니까? 행동은 무엇입니까? 무엇을 알고 있습니까? 이 질문들에 대해 길고 열심히 생각하면 가능한 최고 수준의 인터페이스를 노출시키는 클래스 설계로 자연스럽게 이어집니다.

자동차가 좋은 예입니다. 잘 정의 된 표준화 된 고급 인터페이스를 노출시킵니다. 나는 나 자신을 걱정하지 않는다 setSpeed(60)... MPH 또는 KM/H입니까? 방금 가속, 순항, 감속. 세부 사항에 대해 생각할 필요가 없습니다 setSteeringWheelAngle(getSteeringWheelAngle()+Math.rad(-1.5)), 난 그냥 turn(-1.5), 세부 사항은 처리됩니다 후드.

"모든 클래스가 무엇을 사용 할 것인지, 무엇을하는지, 무엇을 나타내는 지, 그리고 그 요구 사항을 충족시킬 수있는 최고 수준의 인터페이스를 노출시킬 수 있습니다. getters and setter는 일반적으로 경찰이 될 때" 프로그래머는 각 클래스가 무엇인지 정확히 결정하는 데 필요한 분석을 수행하는 데 게으르기 때문에 우리는 "무엇이든 할 수 있습니다"라는 길을 따라갑니다. Getters와 Setters는 악합니다!

때로는 클래스의 실제 요구 사항이 미리 알 수 없습니다. 그것은 멋지고, 단지 경찰과 getter/setter antipattern을 사용하지만, 경험을 통해 수업이 사용되는 것을 알면 더러운 낮은 레벨 인터페이스를 복귀하고 정리하고 싶을 것입니다. "처음에 빨판을 쓸 때 알았던 것"을 기반으로 한 리팩토링은 코스의 동등합니다. 시작하기 위해 모든 것을 알 필요는 없습니다. 단지 더 많이 알수록 재 작업이 필요할 수 있습니다.

그것이 그가 홍보하는 정신입니다. 게터와 세터는 쉽게 쓰러지는 함정입니다.

예, 콩에는 기본적으로 getters and setter가 필요하지만 콩은 특별한 경우입니다. 콩은 명사, 사물, 유형 식별 가능한 (물리적이지 않은 경우) 물체를 나타냅니다. 많은 객체가 실제로 자동 동작을 가지고 있지 않습니다. 대부분의 경우 인간을 포함한 외부 세력에 의해 사물이 조작되어 생산적인 것들을 만들 수 있습니다.

daisy.setColor(Color.PINK) 완벽하게 이해됩니다. 너는 어떤 다른 일을 할 수 있니? 아마도 꽃을 만들기 위해 벌컨 마인드가 어쩌면 원하다 분홍색이 될까요? 흠?

getters와 setters는 그들의? 사악한가? 장소. 그것은 단지 정말 좋은 것들과 마찬가지로, 우리는 단순하고 친숙하기 때문에 우리는 그것들을 과도하게 사용하는 경향이 있습니다. 단순하고 단순하게 말할 것도 없기 때문에 멍청이가 적어도 그들에 대해 보거나 듣지 못하면 더 나을 수 있습니다. ' D는 마음을 사로 잡았다.

Allen Holub이 말하려고했던 것이 다시 말하면 이것 기사는 다음과 같습니다.

getters와 setter는 구체적으로 캡슐화하려는 변수에 유용 할 수 있지만 모든 변수에 사용할 필요는 없습니다. 실제로, 모든 변수에 그것들을 사용하는 것은 불쾌한 코드 냄새입니다.

문제 프로그래머가 가지고있는 문제는 Allen Holub이 그것을 지적하는 데 옳았습니다. 때로는 모든 변수에 Getters/Setter를 사용한다는 것입니다. 캡슐화의 목적이 손실됩니다.

(.NET "Property"angle 에서이 문제가 발생합니다)

글쎄, 간단히 - 나는 그와 동의하지 않는다. 그는 호출 코드를 깨뜨릴 수 있기 때문에 반환 속성 유형의 속성 유형에 대해 큰 소란을 겪습니다. 바로 그거죠 메소드 인수에도 동일한 인수가 적용됩니다. 그리고 방법을 사용할 수 없다면?

자, 방법 인수는 확대 전환으로 변경 될 수 있지만 .... 왜 ... 또한 ... C#에서 주목하십시오. var 키워드는이 인식 된 고통을 많이 완화 할 수 있습니다.

접근자는 ~ 아니다 구현 세부 사항; 그들은 공개 API / 계약입니다. 응, 피임을 끊으면 문제가 있습니다. 언제 놀라운가요? 마찬가지로, 접근자가 사소한 일이되는 것은 드문 일이 아닙니다. 즉, 그들은 단지 랩 필드; 계산, 논리 검사, 알림 등을 수행하고 상태의 인터페이스 기반 추상화를 허용합니다. 아, 다형성 - 등

접근자의 장점 (p3? 4?) - C#: public int Foo {get; private set;} - 작업이 완료되었습니다.

궁극적으로 모든 코드는 컴파일러에 대한 의도를 표현하는 수단입니다. 속성을 통해 유형-안전, 계약 기반, 검증 가능, 확장 가능한, 다형성 방식으로이를 수행 할 수 있습니다. 감사합니다. 왜 이것을 "고정"해야합니까?

게터와 세터는 개인 가변을 공개하기 위해 마스크 이상으로 사용됩니다.

Holub이 이미 말한 것을 반복하는 점은 없지만 그 요점은 클래스가 상태가 아니라 행동을 나타내야한다는 것입니다.

Allen Holub에 대해 추가로 인터넷 검색을 했는데, Java 커뮤니티에서 그와 비슷한 상대가 있는 것 같습니다.

마지막이 특히 지적됩니다.해설자의 텍스트는 이탤릭체로 되어 있습니다.

getIdentity는 "get"으로 시작하지만 단순히 필드를 반환하는 것이 아니기 때문에 접근자가 아닙니다.합리적인 동작을 갖는 복잡한 객체를 반환합니다.

아 그런데 잠깐...그러면 기본 유형 대신 객체를 반환하는 한 접근자를 사용해도 괜찮습니까?이제 그것은 다른 이야기입니다. 그러나 그것은 나에게도 마찬가지로 멍청합니다.때로는 객체가 필요할 때도 있고, 기본 유형이 필요할 때도 있습니다.

또한 나는 Allen이 동일한 주제에 대한 이전 칼럼 이후로 자신의 입장을 근본적으로 누그러뜨렸다는 것을 알았습니다. 여기서 "접속자를 절대 사용하지 마십시오"라는 진언은 단 한 번의 예외도 겪지 않았습니다.아마도 그는 접속자가 결국 목적에 부합한다는 것을 몇 년 후에 깨달았을 것입니다...

실제로 비즈니스 로직에 UI 코드를 넣지 않았다는 점을 명심하세요.저는 추상화 계층인 AWT(Abstract Window Toolkit) 또는 Swing 측면에서 UI 계층을 작성했습니다.

좋은 것.SWT에 지원서를 작성한다면 어떻게 될까요?이 경우 AWT는 얼마나 "추상적"입니까?그냥 직면하세요:이 조언은 단순히 비즈니스 로직에 UI 코드를 작성하도록 유도합니다.정말 훌륭한 원리입니다.결국, 우리가 이러한 관행을 프로젝트에서 내릴 수 있는 최악의 디자인 결정 중 하나로 확인한 지 불과 10년 정도밖에 되지 않았습니다.

내 문제는 초보 프로그래머가 때때로 인터넷의 기사를 우연히 발견하고 내가 해야 할 것보다 더 많은 신뢰를 제공한다는 것입니다.아마도 이것은 그러한 경우 중 하나입니다.

이와 같은 아이디어가 나에게 제공되면, 나는 내가 사용하고 사용하는 것을 좋아하는 라이브러리와 프레임 워크를 살펴보고 싶습니다.

예를 들어, 일부는 동의하지 않지만 Java Standard API를 좋아합니다. 나는 또한 스프링 프레임 워크를 좋아합니다. 이 라이브러리의 클래스를 살펴보면 내부 변수를 노출시키기 위해 세트와 게터가 거의 없다는 것을 알 수 있습니다. 방법이 있습니다 명명 된 getx, 그러나 그것이 기존의 의미에서 getter라는 것을 의미하지는 않습니다.

그래서, 나는 그가 요점이 있다고 생각합니다. 이것은 당신이 Eclipse에서 "Getters/setters"를 선택할 때마다 (또는 선택의 ID)를 선택하고 한 걸음 물러서서 무엇을하고 있는지 궁금해해야합니다. 이 내부 표현을 노출시키는 것이 정말 적절합니까, 아니면 어떤 단계에서 내 디자인을 엉망으로 만들었습니까?

나는 그가 Get/Set을 사용하지 않는다고 말하는 것이 아니라 오히려 필드에 Get/Set을 사용하는 것이 필드를 공개하는 것보다 낫지 않다고 생각합니다 (예 : 공개 문자열 이름 대 공개 문자열 이름 {get; set;}).

get/set을 사용하면 OO의 정보 숨기기를 제한하여 잠재적으로 잘못된 인터페이스에 잠글 수 있습니다.

위의 예에서 이름은 문자열입니다. 나중에 여러 이름을 추가하기 위해 디자인을 변경하려면 어떻게해야합니까? 인터페이스는 단일 문자열 만 노출되어 기존 구현을 중단하지 않으면 더 이상 추가 할 수 없습니다.

그러나 Get/Set을 사용하는 대신 처음에 Add (문자열 이름)와 같은 메소드가있는 경우 내부적으로 이름을 단수 적으로 처리하거나 목록에 추가하거나 추가하려는만큼 ADD 메소드를 여러 번 호출 할 수 있습니다. 더 많은 이름.

OO 목표는 수준의 추상화로 디자인하는 것입니다. 당신이 절대적으로해야 할 것보다 더 자세한 내용을 노출시키지 마십시오.

이 교리를 깨뜨린 Get/set과 함께 원시 유형을 감은 경우 기회가있을 가능성이 있습니다.

물론, 이것은 당신이 OO 목표를 믿는다면입니다. 나는 실제로는 실제로는 기능 코드를 그룹화하는 편의한 방법으로 객체를 사용하지 않는다는 것을 알았습니다.

공개 변수는 클래스가 실질적인 일관성이없는 데이터 묶음에 지나지 않거나 실제로 초등학교 (예 : 포인트 클래스) 일 때 의미가 있습니다. 일반적으로 클래스에 공개적이지 않아야한다고 생각하는 변수가있는 경우 클래스에 일관성이 있으며 변수는 유지 해야하는 특정 관계가 있으므로 모든 변수는 비공개 여야합니다.

게터와 세터는 일종의 일관된 아이디어를 반영 할 때 의미가 있습니다. 예를 들어, 다각형 클래스에서, 주어진 정점의 x 및 y 좌표는 클래스 경계 외부의 의미를 갖는다. 아마도 getters를 갖는 것이 합리적이며, 세터를 갖는 것이 합리적 일 것입니다. 은행 계좌 클래스에서 잔액은 아마도 개인 변수로 저장되며 거의 확실히 getter가 있어야합니다. 세터가있는 경우 감사를 보존하기 위해 로깅 내장이 있어야합니다.

공개 변수에 대한 게터와 세터에는 몇 가지 장점이 있습니다. 인터페이스와 구현의 분리를 제공합니다. 포인트에 a .getX() 기능은 X가 있어야한다는 의미는 아닙니다. .getX() 그리고 .setX() 방사형 좌표로 잘 작동하도록 만들 수 있습니다. 다른 하나는 세터 내에서 클래스를 일관되게 유지하는 데 필요한 모든 것을 수행함으로써 클래스 불변량을 유지할 수 있다는 것입니다. 다른 하나는 은행 계좌 잔고에 대한 로깅과 같이 세트에서 트리거링하는 기능을 가질 수 있다는 것입니다.

그러나보다 추상적 인 클래스의 경우 멤버 변수는 개인의 중요성을 잃고 맥락에서만 의미가 있습니다. 예를 들어 C ++ 스트림 클래스의 모든 내부 변수를 알 필요는 없습니다. 요소를 들어오고 나가는 방법과 다양한 다른 작업을 수행하는 방법을 알아야합니다. 정확한 내부 구조에 의존하면 컴파일러 나 버전마다 자의적으로 달라질 수있는 상세하게 적용됩니다.

따라서 개인 변수를 거의 독점적으로 사용하고 객체 행동에 실제 의미가있는 게터와 세터를 사용한다고 말합니다.

게터와 세터가 자주 과용한다고해서 쓸모가 없다는 것을 의미하지는 않습니다.

Getters/Setters의 문제는 가짜 캡슐화를 시도하지만 실제로 내부를 노출 시켜서 깨뜨립니다. 둘째, 그들은 두 가지 별도의 일을하려고 노력하고 있습니다 - 상태에 대한 접근과 통제를 제공하고 결국 잘하지 못했습니다.

get/set 메소드를 호출 할 때 먼저 변경하려는 필드의 이름 (또는 좋은 아이디어)을 알아야하며, 둘째는 유형을 알아야하기 때문에 캡슐화를 중단합니다. 당신은 전화 할 수 없었습니다

setPositionX("some string");

필드의 이름과 유형을 알고 세터가 공개적이라면 누구나 방법을 공개 필드 인 것처럼 메소드를 호출 할 수 있습니다. 더 복잡한 방법 일뿐입니다. 처음에는 공공 분야입니다.

상태에 대한 접근을 허용하지만 동시에 통제하려고 시도함으로써 Get/Set 방법은 사물을 혼란스럽게하고 쓸모없는 보일러 플레이트가되거나 실제로는 측면- 사용자가 기대하지 않을 수있는 영향. 오류 확인이 필요한 경우

public void tryPositionX(int x) throws InvalidParameterException{
    if (x >= 0)
        this.x = x;
    else
        throw new InvalidParameterException("Holy Negatives Batman!");
}

또는 추가 코드가 필요한 경우 전체 메소드가 수행하는 일에 따라보다 정확한 이름이라고 할 수 있습니다.

tryPositionXAndLog(int x) throws InvalidParameterException{
    tryPositionX(x);
    numChanges++;
}

IMHO는 무언가를 만들기 위해 getters/setter가 필요합니다. 종종 나쁜 디자인의 증상입니다. "Tell, Decond"원칙을 사용하거나, 왜 개체가 처음에 상태 데이터를 보내야 하는지를 다시 생각하십시오. 상태 대신 대상의 동작을 변경하는 방법을 노출시킵니다. 이점의 이점에는 유지 보수가 쉽고 확장 성이 향상됩니다.

MVC도 언급하고 모델이 그 견해에 대한 책임이 없다고 말합니다. Allen Holub은 "give-me-a-jcomponent-that-represents-your-evelity 클래스"를 가짐으로써 추상화 계층을 만드는 예를 제공합니다. 그는 "시스템의 나머지 부분에서 정체성이 표현되는 방식을 분리 할 것"이라고 말했다. 나는 그것이 작동하는지 아닌지에 대해 언급 할만 큼 충분히 경험이 없지만 표면에서는 괜찮은 아이디어로 들립니다.

공개 게스터/세터는 구현 세부 정보에 액세스 할 수있는 경우 나쁘다. 그러나 객체의 속성에 대한 액세스를 제공하고이를 위해 getters/setter를 사용하는 것이 합리적입니다. 예를 들어, CAR에 컬러 속성이있는 경우 클라이언트가 Getter를 사용하여 "관찰"하도록 허용됩니다. 일부 클라이언트가 자동차를 다시 검색 할 수있는 능력이 필요한 경우 클래스는 세터를 제공 할 수 있습니다 ( 'Recolor'는 더 명확한 이름입니다). 고객에게 특성이 객체에 어떻게 저장되는지, 유지 관리 방법 등을 알려주는 것이 중요합니다.

음 ... 캡슐화의 개념에 대해 들어 본 적이 없습니다. 클래스 멤버에 대한 액세스를 제어하기 위해 Getter 및 Setter 방법이 마련됩니다. 모든 필드를 공개적으로 보이게함으로써 ... 누구나 원하는 값을 쓸 수 있으므로 전체 객체를 완전히 무효화 할 수 있습니다.

캡슐화 개념에 대해 약간의 퍼지가있는 경우 여기에서 읽으십시오.

캡슐화 (컴퓨터 과학)

... 그리고 그들이 정말로 사악하다면 .net은 속성 개념을 언어로 구축 할 것인가? (조금 더 예쁘게 보이는 getter and setter 방법)

편집하다

이 기사는 캡슐화를 언급합니다.

"getters와 setter는 구체적으로 캡슐화하려는 변수에 유용 할 수 있지만 모든 변수에 사용할 필요는 없습니다. 실제로, 모든 변수에 그것들을 사용하는 것은 불쾌한 코드 냄새입니다."

이 방법을 사용하면 장기적으로 코드를 유지하기가 매우 어렵습니다. 필드를 캡슐화 해야하는 프로젝트의 절반을 알게되면 소프트웨어의 모든 곳에서 해당 필드의 모든 참조를 업데이트하여 혜택을 얻을 수 있습니다. 적절한 캡슐화를 앞에 사용하고 나중에 두통을 안전하게 안전하게 사용하는 것이 훨씬 더 똑똑하게 들립니다.

나는 getters와 setter가 클래스 밖에서 액세스하거나 변경 해야하는 변수에만 사용되어야한다고 생각합니다. 즉, 변수가 정적이 아닌 한 공개되어야한다고 생각하지 않습니다. 정적이 아닌 변수를 공개적으로 만들면 바람직하지 않게 변할 수 있기 때문입니다. 공개 변수를 부주의하게 사용하는 개발자가 있다고 가정 해 봅시다. 그런 다음 다른 클래스에서 변수에 액세스하고 의미없이 변경합니다. 이제 그는이 사고의 결과로 소프트웨어에 오류가 있습니다. 그렇기 때문에 나는 게터와 세터의 적절한 사용을 믿지만 모든 개인 또는 보호 된 변수에 대해 필요하지는 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top