2

많은 사람들이 정보를 얻는 기능이있어서 나쁜 것을 암시하는 테스트 주도 개발 사람들로부터 자주 듣습니다. 나는 이것이 테스트 관점에서 나쁘다는 것을 알 수 있었지만 때때로 캡슐화 관점에서 필요하지 않은가? 다음 질문은 마음에 온다 : 알려진 매개 변수를 전달하지 않아 캡슐화를 암시 적으로 위반합니까?

Is using Random and OrderBy a good shuffle algorithm?

은 기본적으로 누군가가 무작위로 배열을 임의 재생으로 C#에서 함수를 만들고 싶었습니다. 몇몇 사람들은 난수 생성기가 매개 변수로 전달되어야한다고 말했습니다. 이것은 테스트를 더 쉽게 만들지라도 캡슐화에 대한 심각한 위반처럼 보입니다. 배열 셔플 알고리즘이 배열 이외의 다른 모든 상태를 요구한다는 사실은 호출자가 신경 쓰지 않아도되는 구현 세부 사항을 셔플하고 있습니까? 이 정보를 암시 적으로 얻을 수있는 올바른 위치가 아니겠습니까? 스레드 로컬 싱글 톤 (thread-local singleton)?

+1

질문은 상당히 앞서 가고자하는 의도입니까? "해야"한다는 정의에 따라 캡슐화가 깨지는 알려진 매개 변수를 전달합니다. 그래서 예를 들어 이것의 크기를 벡터의 멤버 함수로 넘겨주지 마십시오. 그러나 예를 들어, 무작위의 출처가 셔플 알고리즘에 대해 내부적으로 알려 져야한다는 것이 매우 의심 스럽습니다. 비교 함수가 "내부"에 있어야합니다. 질문은 진술 된대로 대답 할 수 있습니다. 또는 무작위의 출처가 분명히 내부적으로 알려지지 않아야하는 셔플 같은 경우에 대해 대답 할 수 있습니다 ;-) –

답변

4

예, 깨지므로 encapsulation입니다. 대부분의 소프트웨어 설계 결정과 마찬가지로, 이것은 2 개의 반대 세력 간의 트레이드 오프입니다. RNG를 캡슐화하면 단위 테스트를 위해 변경하기가 어려워집니다. 매개 변수를 만들면 사용자가 RNG를 쉽게 변경할 수 있습니다 (잠재적으로 잘못 될 수 있음).

내 개인적인 취향은 테스트하기 쉽도록 만든 다음 기본 구현 (이 경우 고유 한 RNG를 만드는 기본 생성자)과 최종 사용자를위한 훌륭한 문서를 제공하는 것입니다. 이 방법의 가장 일반적인 사용 사례를 돌봐 것 자사의 씨앗으로 현재 시스템 시간을 사용하여 Random를 만들어 서명

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source) 

과 방법을 추가. 원래 방법

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng) 

이 테스트에 사용 할 수있는 사용자들이 안전한 암호화 RNG를 필요로 결정 드문 경우에도 (알려진 씨와 Random 객체를 전달)합니다. 1 매개 변수 구현에서는이 메서드를 호출해야합니다.

10

캡슐화가 중단되지 않는다고 생각합니다. 배열의 유일한 상태는 데이터 자체입니다. "임의성의 소스"는 본질적으로 서비스입니다. 배열이 자연스럽게 임의성의 원인을 가져야하는 이유는 무엇입니까? 왜 싱글 톤이어야합니까? 요구 사항이 다른 여러 상황 (예 : 암호는 암호 학적으로 임의성을 확보합니까? java.util.Random에는 SecureRandom 서브 클래스가있는 이유가 있습니다. 아마도 셔플의 결과가 많은 노력과 관찰로 예측 가능한지 여부는 문제가되지 않을 수도 있습니다. 컨텍스트에 따라 다르므로 셔플 알고리즘이 신경 쓰지 않아야하는 정보입니다.

일단 서비스로 생각하면 종속성으로 전달된다는 의미가 있습니다.

예, 스레드 로컬 싱글에서 그것을 얻을 수있다 (그리고 실제로 나는 정확히 다음 몇 일에 대한 블로그거야)하지만 발신자가 얻을 수 있도록 나는 일반적으로 코딩 것 그 결정을 내린다.

"서비스로서의 무작위성"개념의 한 가지 이점은 반복성에 대한 것입니다. 테스트에 실패하면 특정 시드와 함께 Random을 전달할 수 있으며 항상 동일한 결과로 디버깅이 쉬워집니다.

물론 항상 Random을 옵션으로 설정하는 옵션이 있습니다. 발신자가 자신의 정보를 제공하지 않는 경우 스레드 로컬 싱글 톤을 기본값으로 사용하십시오.

+0

+1, 저를 구해주었습니다. 내가 보는 방식은 배열의 임의성 (배열 순서)을 적용하는 알고리즘입니다. 따라서 자연 입력은 배열이고 임의적입니다. 함수가 임의의 임의성을 생성하는 함수는 특정 실제 목적을 위해 쓸모 없게 만듭니다. 즉, 무작위로 안전하지 않거나 안전하지만 모든 시스템 엔트로피를 소비하므로 경박하게 사용할 수 없습니다. 테스트 할 때의 가치와는 별도로, 의존성 주입은보다 유연하고 일반적인 함수로 연결됩니다. –

+0

-1 질문은 임의로 배열을 뒤섞는 함수에 관한 것입니다. 배열 자체는 임의성의 소스와는 아무런 관련이 없습니다. 클라이언트가 랜덤 화기를 선택할 수 있도록 요구하지 않는 한, *로 전달하면 캡슐화가 중단됩니다 (IMO). –

+1

@Rogerio : "임의로 배열을 뒤섞다"는 말은 배열과 임의성에 대한 이야기입니다. 무작위의 출처가 분명히 필요합니다. 객체 내에 생성 되었건 전달 되었건간에. 클라이언트가 지정할 수없는 경우, 그것은 저에게 불필요한 강성처럼 들립니다. 물론, 그것은 당신이 겨냥하고있는 캡슐화의 레벨에 달려 있습니다. 만약 당신이'IShuffler' 인터페이스를 구현하고자한다면, 무작위성의 소스가 생성시에 제공되어 인터페이스가 무작위로 남겨지는 것이 타당합니다. 단일 독립형 방법의 경우 IMO에 전화하는 것이 더 어렵습니다. –

1

캡슐화를 위반하지 않는다고 생각합니다.

귀하의 예

내가 RNG를 제공 할 수있는 것은 클래스의 특징이라고 말할 것입니다. 분명히 그것을 필요로하지 않는 방법을 제공 하겠지만 무작위 화를 복제하는 것이 유용한 시간을 볼 수 있습니다.

배열 생성기가 레벨 생성을 위해 RNG를 사용하는 게임의 일부라면 어떻게 될까요? 사용자가 레벨을 저장하고 나중에 다시 재생하려면 RNG 시드를 저장하는 것이 더 효율적일 수 있습니다. 이 같은 단일 작업을

일반 케이스

간단한 클래스는 일반적으로 자신의 내부 동작을 누설에 대해 걱정할 필요가 없습니다.그들이 캡슐화하는 것은 해당 논리에 필요한 요소가 아니라 작업의 논리입니다.

관련 문제