순수한 기능을 비공개로 만들어야 할 이유가 있습니까?


25

나는 동료와 약간의 토론이있었습니다. 간단히 말해서 순수한 함수를 숨기거나 캡슐화 할만한 이유가 있습니까?

"순수"란 위키피디아 정의를 의미합니다 .

  • 항상 동일한 입력에서 동일한 결과를 반환합니다. (이 의미에서 가치 의미론이 Foo Create(){ return new Foo(); }없다면 이 논의 는 불완전한 것으로 간주됩니다 Foo.)
  • 변경 가능한 상태 (로컬 변수 제외) 또는 I / O를 사용하지 않습니다.
  • 부작용을 일으키지 않습니다.

26
그러한 함수를 클래스의 멤버로 만들지 않는다는 주장이있을 수 있습니다.
Pieter B

6
@PieterB-실제로 모든 언어가 지원하는 것은 아니지만 일부 언어는 무료 기능을 위해 내부 모듈을 허용합니다.
Telastyn

3
당신의 의견은 무엇입니까? 함수의 순도는 공용 API에 속하는지 여부와 관련이 없다고 생각합니다.
Andres F.

@andresF. -논란의 여지가없는 검증 규칙을 공개해야하는지에 대한 토론이 실제로 진행되었습니다. 나는 그것이 순수한 기능이기 때문에 거의 해가 없다고 주장했다. 이 특별한 경우에, 그것은 테스트 가능성을 돕고 재사용 될 가능성이있었습니다. 이 질문은 그 주장이 얼마나 광범위하게 적용될 수 있는지에 관한 것입니다.
Telastyn

2
@Telastyn 재사용 가능하지만 현재 클래스 책임의 일부가 아닌 경우 별도 클래스 / 모듈 / 언어가 무엇이든 관계가있을 것입니다. 그런 다음 새로운 클래스 / 모듈의 책임의 일부이므로 반드시 공개해야합니다. 테스트에 대해 언급 했으므로 그렇게 할 때 메소드를 반드시 모방 할 필요는 없습니다. "구현 세부 사항"으로서 테스트 중에 조롱하면 거의 이점이 없습니다.
jpmc26

답변:


76

순수한 함수는 여전히 구현 세부 사항이 될 수 있습니다. 이 기능은 (중요한 불변량 / 계약을 깨뜨리지 않는 관점에서) 해를 끼치 지 않을 수 있지만, 해당 클래스 / 모듈 / 패키지의 작성자와 사용자 모두에게 노출되면 손실됩니다. 이제 구현이 변경되어 더 이상 기능이 유용하지 않아도이를 제거 할 수 없기 때문에 작성자가 손실됩니다. 사용자는 API를 이해하기 위해 API 사용과 관련이없는 추가 기능을 조사하고 무시해야하므로 손실됩니다.


33
+1. 수업의 공개 멤버는 API입니다. "공개하는 경우 나에게 상처를 줄 수 있습니까?"라는 질문이 아니라 "API의 일부 여야합니까?"라는 질문이 아닙니다.
Ordous

1
내가 추가 할 유일한 것은 다른 위치에서 비슷한 함수가 나타나기 시작하면 다른 클래스로 리팩터링하여 여러 클래스가 사용할 수 있다는 것입니다. 또는 처음에 관심이 있다면, 별도의 클래스로 정의하여 시작하십시오.
jpmc26

1
나는 확장되지 않은 공개 수업을 봉인 할 것입니다.
Den

+1 함수 (또는 클래스)를 숨기거나 표시하는 것은 주로 API를 보호하고 유지 관리해야하는 문제이며 코드 유형과는 관련이 없음을 지적합니다.
Marco

42

문제는 거꾸로입니다.

비공개 기능을 수행 할 이유를 찾지 않습니다. (제 생각에) 시작하는 것은 잘못된 생각입니다. 추론은 다른 방향으로 가야합니다.

다시 말해서 "왜 내가 비공개로 만들어야합니까?"라고 묻지 마십시오. "왜 그것을 공개해야합니까?"

의심스러운 경우 노출시키지 마십시오. 그것은 Ockham의 면도기와 같습니다-필요 이상으로 질식을 번복하지 마십시오.

편집 : @Telastyn이 제기 한 반론에 대한 의견을 제시합니다 (확장 토론을 피하기 위해).

나는 시간이 지남에 따라 꽤 오랫동안 그것을 간첩했지만 내 경험상 사물은 너무 사적인 경향이 있습니다.

예, 클래스가 상속을 위해 열려 있으면 때로는 고통 스럽지만 일부 개인 메서드 (이 동작을 변경하려는)를 재정의 할 수는 없습니다.

그러나 protected충분 - 그리고 여전히 비공개입니다.

그것은 "공개해서는 안되는 것들"에 도달하기 위해 많은 코드 복제 및 오버 헤드를 가져 오지만 어쨌든 간접적으로 액세스됩니다.

문제가된다면 공개하기 만하면됩니다! 내가 이야기 할 필요성이 있습니다 :)

내 요점은 당신이 경우에 (YAGNI와 모두) 그것을해서는 안된다는 것 입니다.

개인 기능을 공개로 가져 오는 것보다 개인 기능을 공개하는 것이 항상 쉽습니다. 후자는 기존 코드를 손상시킬 수 있습니다.


나는 시간이 지남에 따라 꽤 오랫동안 그것을 간첩했지만 내 경험상 사물은 너무 사적인 경향이 있습니다. 그것은 "공개해서는 안되는 것들"에 도달하기 위해 많은 코드 복제 및 오버 헤드를 가져 오지만 어쨌든 간접적으로 액세스됩니다.
Telastyn

3
@Telastyn IMHO, 응용 프로그램에 약간의 디자인 오류가있는 것처럼 들립니다. 개별 코드 경로에서 메소드를 호출해야하기 때문에 메소드를 노출하려는 경향이있는 경우,이 메소드가 적절한 위치에 삽입하거나 포함 할 수있는 고유 한 모듈로 분리되어야한다는 신호일 수 있습니다. 특히 순수한 함수 인 경우 .
leo

@ leo-죄송합니다. 팔로우하지 않습니다. 보다 작은 정수와 같은 함수를 고려하십시오. 이것은 적절한 곳에 주입하여 포함 (또는 간단히 사용) 할 수 있기 때문에 특별히 노출되는 훌륭한 순수 기능입니다.
Telastyn

5
@Telastyn 제 생각에 이것은 모든 것이 객체 / 클래스라는 철학의 증상이며 일부 OOP 언어에는 클래스 이외의 복합 데이터 유형이 없다는 사실과 결합됩니다. 누군가가 동시에 두 가지 값을 전달 해야하는 즉시 수업을 마친 다음 모든 동료 및 스타일 검사 소프트웨어가 해당 필드를 비공개로 설정하도록 지시합니다.
Doval

@ 텔라 스틴 맞아. 의미하는 것은 'integerLessThan'메서드가 공개 메소드의 캡슐화 된 구현 세부 정보로 시작되었지만 다른 위치에서 개인 메소드를 호출해야한다는 것을 알게되면 아마도 개인 메소드가 다른 것에 속한다는 신호 일 것입니다 이를 호출하는 로직과 독립적으로 가져올 수 있도록 모듈 / 패키지 / 클래스. 단순히 메서드를 그대로 공개하면 메서드가 유용한 첫 번째 모듈에 임의로 배치됩니다.
leo

6

함수를 숨기거나 캡슐화하려는 결정이 순도에 달려 있다고 생각하지 않습니다. 기능이 순수하다고해서 외부인이이를 알아야한다는 의미는 아닙니다. 흥미롭게도 함수가 순수하고 공개되어야하는 경우 인터페이스의 인스턴스 멤버가 아니어도 정적으로 더 적합 할 수 있습니다. 그러나이 모든 것은 계약의 의도와이 경우 기능의 순수성이 아니라 기능의 논리적 그룹화에 달려 있습니다.


5

수업은 단일 책임 원칙을 준수해야합니다 . 클래스가 목표를 달성하기 위해 다른 기능을 호출해야 할 수도 있지만, 단일 책임의 일부인 기능 만 노출해야합니다.

다음은 가시성 문제를 일으킬 있는 사례 중 하나 입니다.

위젯을 약화시키는 클래스를 고려하십시오. 약자 코드의 일부로 문자열을 구문 분석하는 유틸리티 함수가 필요할 수 있습니다. 아마도 표준 문자열 함수가 지원하지 않는 방식으로 위젯 이름을 변환해야합니다.

이것은 순수한 함수 (문자열이 들어오고 어떻게 든 변환하고 새로운 문자열을 반환 함)이므로 결과없이 공개 또는 비공개 일 수 있습니다. 아니면 할 수 있습니까?

frobnicating 위젯 : 당신이 그것을 공개 할 경우, 지금 클래스는 두 가지 책임이있다 변형 문자열을. 이것은 SRP를 위반하며 다른 클래스가 함수에 의존하는 경우 문제를 일으킬 수 있습니다. 이것은 클래스 내부에서만 사용되는 것으로 생각되므로 인터페이스 또는 가시성을 변경할 수 있습니다. 이제 시스템의 다른 부분에있는 클래스가 깨졌습니다.

이 함수를 비공개로 유지함으로써 아무도 클래스의 단일 책임에 속하지 않는 코드에 의존 할 수있는 기회가 없습니다.


2
나는 단지 노출이 아니라 단일 책임의 일부인 함수 만 포함 해야한다고 주장한다 .
Telastyn

1
회색 부분이 있다고 생각합니다. StringTransformer한곳에서만 사용되는 두 줄 또는 세 줄의 코드를 캡슐화하기 위해 실제로 별도의 클래스가 필요 합니까? 일단 코드가 여러 곳에서 사용되면 한 번의 책임으로 새로운 클래스로 분리하는 것이 가장 좋지만 트레이드 오프가 있다는 데 동의합니다.

확실히. 지침은 규칙이 아니라 지침입니다.
Telastyn

자바 이외의 @ @ snowman은 함수 라이브러리를 만듭니다.
Pieter B

@PieterB 그것은 Java v.에 관한 것이 아닙니다. 진정으로 OO로 만들려면 팩토리, 추상 클래스 등이 필요합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.