이진 함수 assertEquals (예상, 실제)와 함께 발생하는 문제 해결


10

몇 년 동안 카우보이 코딩을 한 후 좋은 품질의 코드를 작성하는 방법에 대한 책을 집어 들기로 결정했습니다. Robert Cecil Martin의 Clean Code를 읽고 있습니다. 3 장 (기능)에는 이항 기능에 대한 섹션이 있습니다. 다음은이 책에서 발췌 한 것입니다.

명백한 2 차원 함수조차 assertEquals(expected, actual)문제가 있습니다. 실제 위치를 몇 번이나 실제 위치에 두었습니까? 두 가지 주장은 자연스러운 순서가 없습니다. 예상되는 실제 순서는 배우는 연습이 필요한 규칙입니다.

저자는 설득력있는 주장을합니다. 나는 기계 학습에서 일하고 항상 이것을 만납니다. 예를 들어, sklearn 라이브러리 (아마도 필드에서 가장 많이 사용되는 Python 라이브러리)의 모든 메트릭 함수를 사용하려면 입력 순서를주의해야합니다. 예를 들어 sklearn.metrics.homogeneity_score 는 입력 labels_true및을 사용 labels_pred합니다. 이 기능과 관련이없는 것은 입력 순서를 전환하면 오류가 발생하지 않는다는 것입니다. 실제로 입력을 전환하는 것은 라이브러리에서 다른 기능 을 사용하는 것과 같습니다 .

그러나이 책은와 같은 기능에 대한 현명한 해결책을 제시하지는 않습니다 assertEquals. assertEquals위에서 설명한 것과 같이 자주 접하는 기능 에 대한 수정 이나 생각을 할 수 없습니다 . 이 문제를 해결하기위한 모범 사례는 무엇입니까?

답변:


11

수정이없는 경우에도 가능한 문제를 인식하는 것이 좋습니다. 이러한 코드를 읽거나 쓸 때주의를 기울일 수 있습니다. 이 특정 예제에서는 잠시 후 인수 순서에 익숙해집니다.

매개 변수 순서에 대한 혼동을 방지하는 언어 레벨 방법이 있습니다 : 명명 된 인수. 불행히도 Java 또는 C ++와 같은 C 스타일 구문을 사용하는 많은 언어에서는 지원되지 않습니다. 그러나 파이썬에서 모든 인수는 명명 된 인수 일 수 있습니다. 대신 함수를 호출 def foo(a, b)foo(1, 2), 우리는 할 수 있습니다 foo(a=1, b=2). C #과 같은 많은 현대 언어는 비슷한 구문을 가지고 있습니다. 스몰 토크 언어 가족은 멀리 명명 된 인수를 촬영하고있다 : 어떤 위치 인수가 아니며 모든 것이 지정됩니다. 이로 인해 자연어에 매우 가까운 코드가 읽힐 수 있습니다.

보다 실용적인 대안은 명명 된 인수를 시뮬레이션하는 API를 작성하는 것입니다. 이들은 유창한 API이거나 자연스러운 흐름을 만드는 도우미 함수일 수 있습니다. assertEquals(actual, expected)이름이 혼동된다. 내가 본 몇 가지 대안 :

  • assertThat(actual, is(equalTo(expected))): 도우미 형식으로 일부 인수를 래핑하면 래핑 함수가 효과적으로 매개 변수 이름으로 사용됩니다. 단위 테스트 어설 션의 특정 경우에,이 기술은 확장 가능하고 구성 가능한 어설 션 시스템을 제공하기 위해 Hamcrest 매처 에서 사용됩니다 . 여기서 단점은 중첩이 많이 발생하고 많은 도우미 함수를 가져와야한다는 것입니다. 이것이 C ++의 기술입니다.

  • expect(actual).to.be(expected): 함수 호출을 함께 묶는 유창한 API. 추가 중첩을 피할 수는 있지만 확장이 쉽지 않습니다. 유창한 API가 잘 읽히는 것을 알지만, 유창한 API를 디자인하는 것은 콜 체인에서 비 터미널 상태에 대한 추가 클래스를 구현해야하기 때문에 내 경험에서 많은 노력을 기울이는 경향이 있습니다. 이 노력은 다음에 허용되는 메소드 호출을 제안 할 수있는 자동 완성 IDE의 맥락에서 실제로 돈을 지불합니다.


4

이 문제를 피하는 방법에는 여러 가지가 있습니다. 호출하는 메소드를 강제로 변경하지 않는 것 :

오히려

assertEquals( 42, meaningOfLife() ); 

사용하다

expected = 42;
actual = meaningOfLife();
assertEquals(expected, actual);

이렇게하면 컨벤션을 개방 상태로 강제 전환 할 수 있습니다. 쓰기 쉽지는 않지만 읽기 쉽습니다.

호출되는 메소드를 변경할 수 있으면 타이핑 시스템을 사용하여 읽기 쉬운 사용법을 강요 할 수 있습니다.

assertThat( meaningOfLife(), is(42) );

일부 언어에서는 매개 변수에 이름이 지정되어 있으므로이를 피할 수 있습니다.

assertEquals( expected=42, actual=meaningOfLife() );

다른 사람들은 그렇게 시뮬레이션하지 않습니다.

assertEquals().expected(42).actual( meaningOfLife() );

당신이 무엇을 읽을 때 그것이 올바른지 분명하게 만드는 방법을 찾으십시오. 컨벤션이 무엇인지 추측하지 마십시오. 내게 그걸 보여 줘봐.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.