2012-01-13 1 views
6

저는 복소수 배열 (실시간 재무 통계 발생시)에서 작동하는 숫자 알고리즘 집합에 대해 Java API를 설계하고 있습니다. 성능상의 이유로 API는 기본 배열을 사용해야하므로 List<Double> 등과 같은 옵션은 사용할 수 없습니다.배열에서 작동하는 함수에 대한 API 디자인

일반적인 사용 사례는 두 개의 입력 배열을 사용하고 두 입력에서 계산 된 결과가 포함 된 출력 배열을 반환하는 알고리즘 객체 일 수 있습니다.

나는 특히, 배열 매개 변수가 API에서 사용하는 방법에 대한 일관성있는 규칙을 설정하고 싶습니다 : 사용자가 더 큰 배열의 일부에 역할을 할 수 있도록

  • 내가 모든 기능과 오프셋을 포함해야 예 : someFunction(double[] input, int inputOffset, int length)
  • 함수에 입력 및 출력 매개 변수가 모두 필요한 경우 입력 또는 출력이 먼저 매개 변수 목록에 있어야합니까?
  • 호출자가 출력 배열을 할당하고 매개 변수 (잠재적으로 재사용 할 수 있음)로 전달해야합니까? 아니면 함수가 호출 될 때마다 출력 배열을 만들고 반환해야합니까?

목표는 API 내에서 그리고 일관된 협약을 통해 API 사용자와 일관성의 균형을 이루기위한 것입니다.

분명히 많은 옵션이 있으므로 전체적으로 가장 우수한 API 디자인은 무엇입니까?

답변

2

은 그래서 정말 세 가지 질문에 같은 소리 내 의견 :

2
  1. 그렇다면 기본 옵션도 제공하십시오 (0, 전체 길이에서 시작).
  2. 대부분의 사용자는 출력 2를 기대합니다. 그러나, 만약 당신이 varargs을 사용할 수도, 그건 당신의 마음을 바꿀 수 있습니다.
  3. 출력 배열에서 전달하는 호출자가 마음에 들지만 메서드에 할당 할 null을 나타내는 옵션이 있습니다.

vararg 주석을 정교하게 말하면 두 개의 배열을 추가 할 수있는 방법이 있다고 할 수 있습니다. 출력 배열 arg를 첫 번째 arg로두고 마지막에 2 개의 입력 배열을 넣으면 메서드를 확장하여 N 개의 배열을 추가하는 것이 간단합니다.

발신자가 출력 배열을 넘길 수 있도록 # 3을 정교화하면 때로는 더 효율적입니다. 그리고 이득이 무시할 만하다하더라도 원시 배열을 다루는 사용자는 아마도 C 또는 FORTRAN 배경에서 왔을 것이며 이득이 클 것으로 생각하고 "효율"이 없다면 불평 할 것입니다. :-)

2

스택이나 Eden에 할당 할 수있을만큼 작은 배열로 작업한다고 가정하면 할당 속도가 매우 빠릅니다. 따라서 함수가 결과를 반환하기 위해 자체 배열을 할당하도록하는 데 아무런 해가 없습니다. 이렇게하면 가독성이 크게 향상됩니다.

전체 배열에서 함수를 만들기 시작하는 것이 좋을 것입니다. 유용한 경우에만 배열의 조각으로 함수를 호출하는 옵션을 소개합니다. 그래서 여기

public List<Double> someFunction(List<Double> input) 
+0

저는 그가 자바로 작성하고 있다고 생각합니다. 따라서 "스택에"있는 주석은 그 맥락에서 의미가 없습니다. – user949300

+1

아니요, HotSpot은 스택에서 이탈하지 않는 작은 개체를 할당합니다. –

+0

그러나 이러한 배열은 결과로 반환되므로 절대 이스케이프 처리됩니다. – user949300

0

나는 방법이 새로운 List로 출력을 반환 List<Double>을 사용하고있을 것입니다.물론

이 매우 주관적이다 - 그래서 - 귀하의 마일리지가 다를 수 있습니다

  1. 예. 오프셋 길이는 항상 &입니다. 특정 기능에 대한 대부분의 사용 사례에 에 해당 매개 변수가 필요하지 않은 경우 입력에 & 길이가 필요하지 않도록 함수에 과부하가 걸립니다. 여기에 성능 차이가 가고

  2. (destPos가, INT 길이,로부터 srcPos을 int로 개체의 최종 도착, INT, 개체 SRC)

    arraycopy :

  3. 이 들어, 나는 arraycopy에 의해 사용되는 표준을 따를 것입니다 호출자가 유틸리티 함수를 반복적으로 호출하지 않는 한 무시해도됩니다. 그들이 단지 하나의 일이라면 아무런 차이가 없어야합니다. 반복적으로 호출되는 경우 호출자가 할당 된 배열을 보내야합니다.

+0

일반적으로 좋은 조언을하지만 내 경우에는 가능하지 않습니다 - 성능상의 이유로 API는 프리미티브 배열을 사용해야합니다 – mikera

1

여러 기능을 노출하는 API 디자인의 주요 특징은 내부 일관성입니다. 다른 모든 것은 먼 두 번째로 온다.

인덱스/길이 쌍을 전달할지 여부는 API 사용 방법에 따라 결정됩니다. 사용자가 System.arrayCopy에서와 같이 동일한 배열의 다른 세그먼트에 데이터를 가져 오거나 가져 오는 일련의 메서드 호출을 작성하려면 인덱스/길이 쌍이 필요합니다. 그렇지 않으면 잔인합니다.

첫 번째 입력 또는 출력은 사용자의 결정이지만 일단 작성하면 유사한 서명이있는 모든 방법에서이를 사용하십시오.

출력 버퍼를 전달하는 것은 클라이언트에서 버퍼가 다시 사용되는 경우에만 적절한 옵션입니다. 그렇지 않으면 추가 API 메소드 세트를 작성하고 유지 보수하는 데 낭비가됩니다. 물론이 결정은 인덱스/길이 쌍으로가는 선택과 밀접한 관련이 있습니다. 인덱스와 길이를 사용하면 출력 버퍼도 가져와야합니다.

1

저는 API 디자인이 주관적이며 API "유스 케이스"에 크게 영향을 받아야한다고 생각합니다. 반면에 API의 사용 사례는 전적으로 고객 코드에 달려 있습니다.

이 모든 것을 말해 두 겠는데, 개인적으로, 나는 메소드 오버로딩을 활용 다음과 같은 구조 갈 것 :

방법을 모든 매개 변수와 함께 :

void someFunction(int[] input1, int[] input2, int offset, int length, int[] output)

이 주요 기능이다. 다른 모든 함수는 적절한 매개 변수를 사용하여이를 호출합니다.

int[] someFunction(int[] input1, int[] input2, int offset, int length)

이 제 기능을 호출하지만 할당하고 호출자 대신 출력 배열을 반환한다.

void someFunction(int[] input1, int[] input2, int[] output)

일반적인 전략은 '선택'매개 변수를 제거하여 매개 변수 목록을 짧게하는 것입니다

int[] someFunction(int[] input1, int[] input2)

참고.

일반적으로 매개 변수 (출력 배열 등)가 null인지 여부에 따라 메서드 동작을 변경하지 않는 경향이 있습니다. 그렇게하면 미묘한 오류를 잡는 것이 더 어려워 질 수 있습니다. 따라서 출력 매개 변수가 제공되고 필요한 매개 변수와 메서드가 출력을 반환하는 매개 변수라는 두 가지 다른 호출 스타일을 선호합니다.