인스턴스 필드에 의존하지 않는 메소드를 정적으로 만드십시오.


19

최근에 Java 프로젝트를 위해 통합 테스트 프레임 워크를 위해 Groovy에서 프로그래밍을 시작했습니다. Groovy 플러그인과 함께 Intellij IDEA를 사용하며 정적이 아니며 인스턴스 필드에 의존하지 않는 모든 메소드에 대한 경고로 놀랍습니다. 그러나 Java에서는 이것이 문제가 아닙니다 (적어도 IDE의 관점에서).

인스턴스 필드에 의존하지 않는 모든 메소드를 정적 함수로 변환해야합니까? 사실 인 경우, Groovy에만 해당됩니까, 아니면 일반적으로 OOP에 사용할 수 있습니까? 그리고 왜?


이러한 메소드가 다른 인스턴스 메소드를 호출합니까? 아니면 문자 그대로 그 클래스의 객체와 전혀 관련이 없습니까? 예를 들어 줄 수 있습니까?
Ray Toal

답변:


26

IDEA는 Java에 대해서도이 검사 를 수행하며 Method may''static '이라고합니다 .

이 검사는 안전하게 정적 인 방법을보고합니다. 메소드는 클래스의 비 정적 메소드 및 비 정적 필드를 참조하지 않고 하위 클래스에서 재정의되지 않은 경우 정적 일 수 있습니다 ...

Java 코드의 경우이 검사는 기본적 으로 해제되어 있습니다 (프로그래머는 임의로 재량으로 설정할 수 있음). 그 이유는 매우 권위있는 몇 가지 소스를 기반으로 이러한 검사의 유효성 / 유용성이 문제가 될 수 있습니다.

우선 공식 Java 튜토리얼 은 메소드가 정적이어야하는 시점에 다소 제한적입니다.

정적 메소드의 일반적인 용도는 정적 필드에 액세스하는 것입니다.

위에서 언급 한 바와 같이, 기본적으로 언급 된 검사를 켜는 것이 Java에서 권장되는 정적 수정자를 사용하지 않는다고 주장 할 수 있습니다.

게다가,이 검사의 배후에있는 아이디어를 사용하거나 심지어 낙담시키는 아이디어에 대한 신중한 접근을 제안하는 다른 출처도 있습니다.

예를 들어 Java World 기사 -Mr. Happy Object가 정적 메소드를 가르칩니다 .

인스턴스 상태와 독립적 인 모든 메소드는 정적로 선언 될 수 있습니다.

나는 "정적으로 선언 된 후보"라고 말합니다. 이전 예제 instances()에서도 정적 으로 선언하도록 강요하지 않습니다 . 정적이라고 선언하면 메소드를 호출하기 위해 인스턴스가 필요하지 않기 때문에 호출하는 것이 더 편리합니다. 때때로 인스턴스 상태에 의존하지 않는 메소드가있을 것입니다. 이러한 메소드를 정적으로 만들고 싶지 않을 수 있습니다. 실제로 인스턴스없이 액세스 해야하는 경우 정적으로 선언하고 싶을 것입니다.

또한 이러한 메서드를 정적 메서드로 선언 할 수 있지만 디자인에 영향을 미치는 상속 문제 때문에 원하지 않을 수 있습니다. 에서보세요 "효과적인 객체 지향 디자인" 당신이 직면하게되는 문제 중 일부를 볼 수 ...

구글 테스팅 블로그의 기사는 정적 메소드가 테스팅의 죽음 이라고 주장합니다 .

정신 운동을 할 수 있습니다. 애플리케이션에 정적 메소드 만 있다고 가정하십시오. (예, 이와 같은 코드를 작성할 수 있으며 절차 적 프로그래밍이라고합니다.) 이제 해당 응용 프로그램의 호출 그래프를 상상해보십시오. 리프 메서드를 실행하려고하면 상태를 설정하고 모든 경우를 주장하는 데 아무런 문제가 없습니다. 그 이유는 리프 메소드가 더 이상 호출하지 않기 때문입니다. 잎에서 멀어지고 근본 main()방법에 가까워 질수록 테스트에서 상태를 설정하기가 더 어려워지고 어설 션하기가 더 어려워집니다. 주장하는 것이 불가능해질 것입니다. 테스트가 점차 커질 것입니다. 당신이 도달하면main()더 이상 단위 테스트가 없습니다 (단위가 전체 응용 프로그램이므로) 이제 시나리오 테스트가 있습니다. 테스트하려는 응용 프로그램이 워드 프로세서라고 가정하십시오. 주요 방법으로 주장 할 수있는 것은 많지 않습니다 ...

때때로 정적 메소드는 다른 객체의 팩토리입니다. 이것은 테스트 문제를 더욱 심화시킵니다. 테스트에서 우리는 중요한 의존성을 모의 객체와 다르게 대체하여 객체를 연결할 수 있다는 사실에 의존합니다. new연산자가 호출 되면 하위 클래스로 메소드를 대체 할 수 없습니다. 이러한 정적 팩토리의 호출자는 정적 팩토리 메소드가 생성 한 구체적인 클래스에 영구적으로 바인딩됩니다. 다시 말해서 정적 메소드의 손상은 정적 메소드 자체를 훨씬 능가합니다. 객체 그래프 배선과 정적 코드로 객체 코드를 연결하는 것은 매우 나쁘다. 객체 그래프 배선은 테스트를 위해 물건을 분리하는 방법이기 때문이다.


위에서 언급했듯이 Java에 대해 언급 된 검사가 기본적으로 해제되어있는 것이 당연합니다.

IDE 개발자는 것 정말 그들이 그것을 널리 인정 권고 및 모범 사례에 대해 기본적으로 그것을 설정하도록 중요하다고 생각하는 이유 힘든 시간을 설명합니다.

Groovy의 경우 상황이 매우 다릅니다. Javalobby의 Groovy 기사에서 Mocking Static Methods 기사에 설명 된 것처럼 위에 나열된 인수, 특히 테스트 가능성에 대한 인수는 적용되지 않습니다 .

테스트중인 Groovy 클래스가 다른 Groovy 클래스에서 정적 메소드를 호출하는 경우 ExpandoMetaClass를 사용하여 메소드, 생성자, 특성 및 정적 메소드를 동적으로 추가 할 수 있습니다.

이러한 차이는 Groovy에서 언급 된 검사의 기본 설정이 반대 인 이유 일 수 있습니다. Java에서는 기본적으로 "on"이 사용자 혼란의 원인이지만 Groovy에서는 반대 설정으로 인해 IDE 사용자가 혼동 될 수 있습니다.

"이 방법이 인스턴스 필드를 사용하지 않는 이유는 무엇입니까?" 이 질문은 Java에 대해서는 쉽게 대답 할 수 있지만 (위에서 설명한대로) Groovy에는 설득력있는 설명이 없습니다.


그런데, ReSharper에서가 (C # / 비주얼 스튜디오를위한 JetBrains의 제품)은 같은 일을 제안
콘라드 Morawski

6
부작용이 있거나없는 정적 방법에는 중요한 차이점이 있습니다. Google 추출은 실제로 전자를 해결합니다.
assylias

@assylias 그것은하지만 공장 방법으로 테스트를 더 어렵게 만드는 방법에 대해 설명합니다 (응용 프로그램의 종속성을 밀접하게 결합하기 때문에). 종속성 주입 프레임 워크를 사용하는 것이 가장 좋은 해결 방법 중 하나이며 다른 많은 문제도 해결합니다.
Per Lundberg

5

이것이 성능에 눈에 띄는 영향을 줄 것이라고 상상하기는 어렵습니다. 내가 만들 수있는 유일한 이점은 static인스턴스 상태에 영향을 미치지 않는다는 시각적 표시를 제공한다는 것입니다. 다시 말해, 소스 코드를 읽는 사람에게 해당 메소드에 대한 "흥미로운"내용을 알려주는 것입니다. 실제 질문은 명확하거나 혼동됩니까? "이 메소드는 왜 정적입니까? 팩토리 메소드입니까? 오브젝트 인스턴스없이 호출 할 수 있습니까?"

또한 일부 사람들은 정적 메소드를 좋아하지 않습니다. 왜냐하면 그들은 당신이 그것들을 조롱 할 수 없다고 주장하기 때문에 테스트 할 수 없거나 그 라인을 따라 무언가를 요구하기 때문입니다. 확실히, 예를 들어 팩토리 메소드를 제공하는 것과 같은 일반적인 이유로 정적 인 경우, 나는 그게 전부입니다. 인스턴스 상태를 건드리지 않기 때문에 메소드를 정적으로 만드는 것이 확실하지 않습니다.


5
(Java 내에서) 정적 메소드를 재정의 할 수 없다는 것을 고려하십시오. 종종 문제는 아니지만 일부 하위 클래스는 나중에 해당 구현을 변경할 수 없습니다. 정적 메서드가 정답이 아니라 디자인 고려 사항의 일부라고 말하는 것은 아닙니다.

2
@ user40980 고려할 가치가 있지만 사실 상속은 종종 잘못 사용되는 서투른 도구 일 수 있으며 여러 주요 인물은 모든 클래스가 final상속을 염두에두고 특별히 설계 되어야한다고 주장합니다 .
sara

3

가능한 리팩토링을 발견 하는 것이 가능하다고 생각합니다 .

일단 메소드가 정적으로 만들어지면, 클래스에서 다른 클래스로 이동할 수 있음 이 분명 합니다.

또한 매개 변수 중 하나의 인스턴스 메소드로 쉽게 변환 할 수 있습니다. 종종 코드가 있어야하는 위치입니다.


-1

일부 인터페이스를 구현하는 상태 비 저장 클래스가있을 수 있습니다 (예 : java.lang.Runnable메서드를 정적으로 만들 수 없음. 일부 패턴 (예 : 전략)도 여러 메서드가있을 수있는 상태 비 저장 객체를 생성 할 수 있음에 유의하십시오.

스태틱은 싱글 톤의 첫 번째 사촌입니다. 나중에 정적에서 비 정적으로 옮기는 것은 실제로 어려울 것입니다. 따라서 상태를 추가해야 할 때 정적 변수를 도입하기를 원할 것입니다.


이것은 질문에 어떻게 대답합니까?
gnat

1
왜 비 국가에서 어떤 주로가는 것이 어려운가? 나는 그것이 다른 길이라고 말합니다. 오염 된 것을 정화하는 것보다 순수한 것을 오염시키는 것이 더 쉽습니다.
sara
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.