숫자 알고리즘을 캡슐화하기 위해 클래스를 사용하는 데 따른 장점과 단점은 무엇입니까?


13

과학 컴퓨팅에 사용되는 많은 알고리즘은 수학적으로 덜 집중적 인 형태의 소프트웨어 엔지니어링에서 일반적으로 고려되는 알고리즘과는 다른 고유 구조를 가지고 있습니다. 특히, 개별 수학적 알고리즘은 종종 수백 또는 수천 줄의 코드를 포함하는 매우 복잡한 경향이 있지만 그럼에도 불구하고 상태를 포함하지 않으며 (즉, 복잡한 데이터 구조에 영향을 미치지 않음) 프로그래밍 방식의 관점에서 종종 중단 될 수 있습니다. 인터페이스-배열 (또는 2 개)에 작용하는 단일 함수.

이것은 클래스가 아닌 함수가 과학 컴퓨팅에서 발생하는 대부분의 알고리즘에 대한 자연스러운 인터페이스임을 암시합니다. 그러나이 주장은 복잡한 멀티 파트 알고리즘의 구현이 어떻게 처리되어야하는지에 대한 통찰력을 제공하지 못한다.

전통적인 접근 방식은 단순히 여러 다른 함수를 호출하는 하나의 함수를 가지고 관련 인수를 전달하는 반면 OOP는 알고리즘을 클래스로 캡슐화 할 수있는 다른 접근 방식을 제공합니다. 명확성을 위해, 클래스에 알고리즘을 캡슐화함으로써, 알고리즘 입력이 클래스 생성자에 입력 된 클래스를 작성하고 나서 공개 메소드가 호출되어 실제로 알고리즘을 호출합니다. C ++ psuedocode에서 멀티 그리드의 이러한 구현은 다음과 같습니다.

class multigrid {
    private:
        x_, b_
        [grid structure]

        restrict(...)
        interpolate(...)
        relax(...)
    public:
        multigrid(x,b) : x_(x), b_(b) { }
        run()
}

multigrid::run() {
     [call restrict, interpolate, relax, etc.]
}

내 질문은 다음과 같습니다 : 수업이없는보다 전통적인 접근법과 비교할 때 이런 종류의 연습의 장점과 단점은 무엇입니까? 확장 성 또는 유지 관리 성 문제가 있습니까? 분명히, 나는 의견을 요구하려는 것이 아니라, 그러한 코딩 방법을 채택하는 다운 스트림 효과 (즉, 코드베이스가 상당히 커질 때까지 발생할 수없는 영향)를 더 잘 이해하고자한다.


2
수업 이름이 명사가 아닌 형용사 인 경우 항상 나쁜 징조입니다.
David Ketcheson

3
클래스는 복잡성을 관리하기 위해 함수를 구성하기위한 상태 비 저장 네임 스페이스 역할을 할 수 있지만 클래스를 제공하는 언어의 복잡성을 관리하는 다른 방법이 있습니다. (C ++의 네임 스페이스와 파이썬의 모듈이 떠오른다.)
Geoff Oxberry

@GeoffOxberry 나는 이것이 좋은지 나쁜지에 대해 말할 수 없다-이것이 처음에 묻는 이유이다. 그러나 네임 스페이스 나 모듈과 달리 클래스는 그리드 계층과 같은 "임시 상태"를 관리 할 수있다 멀티 그리드에서는 알고리즘 완료시 삭제됩니다.
Ben

답변:


13

15 년 동안 수치 소프트웨어를 사용해 본 결과 다음과 같이 분명하게 말할 수 있습니다.

  • 캡슐화가 중요합니다. 데이터 저장 구성표를 노출하므로 데이터에 대한 포인터를 제안대로 제안하지 않습니다. 스토리지 구성표를 표시하면 전체 프로그램의 데이터에 액세스하기 때문에 다시 변경할 수 없습니다. 이를 피할 수있는 유일한 방법은 데이터를 클래스의 개인 멤버 변수로 캡슐화하고 멤버 함수 만 수행하도록하는 것입니다. 귀하의 질문을 읽으면 행렬 항목에 대한 포인터를 인수로 사용하고 어떤 방식으로 고유 값을 반환하는 행렬의 고유 값을 상태 비 저장으로 계산하는 함수를 생각합니다. 나는 이것이 잘못된 생각이라고 생각합니다. 필자의 관점에서이 함수는 클래스의 "const"멤버 함수 여야합니다. 매트릭스를 변경하기 때문이 아니라 데이터로 작동하는 함수이기 때문입니다.

  • 대부분의 OO 프로그래밍 언어를 사용하면 개인 멤버 기능을 가질 수 있습니다. 이것은 하나의 큰 알고리즘을 더 작은 알고리즘으로 분리하는 방법입니다. 예를 들어, 고유 값 계산에 필요한 다양한 도우미 함수는 여전히 행렬에서 작동하므로 기본적으로 행렬 클래스의 전용 멤버 함수가됩니다.

  • 다른 많은 소프트웨어 시스템과 비교할 때 클래스 계층이 그래픽 사용자 인터페이스보다 덜 중요하다는 것이 사실 일 수 있습니다. 숫자 소프트웨어에는 분명히 눈에 띄는 곳이 있습니다 .Jed는이 스레드에 대한 다른 대답, 즉 행렬 (또는 일반적으로 유한 차원 벡터 공간의 선형 연산자)을 나타낼 수있는 많은 방법을 설명합니다. PETSc는 매트릭스에서 작동하는 모든 작업에 대한 가상 기능을 사용하여 매우 일관되게 수행합니다 ( "가상 기능"이라고 부르지는 않지만 그것이 바로 그 기능입니다). 일반적인 유한 요소 코드에는 OO 소프트웨어의이 설계 원칙을 사용하는 다른 영역이 있습니다. 떠오르는 것은 많은 종류의 직교 공식과 많은 종류의 유한 요소입니다. 모두 자연스럽게 하나의 인터페이스 / 많은 구현으로 표현됩니다. 물질 법 설명도이 그룹에 속합니다. 그러나 그것이 그것에 관한 것이고 유한 요소 코드의 나머지 부분은 GUI 에서처럼 상속을 광범위하게 사용하지 않는다는 것이 사실 일 수 있습니다.

이 세 가지 점에서만 객체 지향 프로그래밍이 숫자 코드에도 가장 확실하게 적용 가능하며이 스타일의 많은 이점을 무시하는 것은 어리석은 것이 분명해야합니다. BLAS / LAPACK이이 패러다임을 사용하지 않는 것이 사실 일 수도 있지만 (MATLAB에 의해 노출되는 일반적인 인터페이스도 사용하지 않음), 지난 10 년 동안 작성된 모든 성공적인 수치 소프트웨어가 실제로는, 객체 지향.


16

과학 컴퓨팅의 확장 가능한 라이브러리 에는 캡슐화 및 데이터 숨기기가 매우 중요합니다 . 행렬과 선형 솔버를 두 가지 예로 고려하십시오. 사용자는 연산자가 선형이라는 것을 알아야하지만 희소성, 커널, 계층 적 표현, 텐서 제품 또는 Schur 보완과 같은 내부 구조를 가질 수 있습니다. 모든 경우에 Krylov 메소드는 연산자의 세부 사항에 의존하지 않으며 MatMult함수 의 동작 (및 아마도 인접) 에만 의존합니다 . 마찬가지로 선형 솔버 인터페이스 (예 : 비선형 솔버)의 사용자는 선형 문제가 해결되는 것만 신경 쓰며 사용되는 알고리즘을 지정하거나 지정하지 않아도됩니다. 실제로 그러한 것을 지정하면 비선형 솔버 (또는 다른 외부 인터페이스)의 기능이 방해를받습니다.

인터페이스 가 좋습니다. 구현 에 따라 나쁘다. C ++ 클래스, C 객체, Haskell 유형 클래스 또는 다른 언어 기능을 사용하여이를 달성하는지 여부는 중요하지 않습니다. 인터페이스의 기능, 견고성 및 확장 성은 과학 라이브러리에서 중요합니다.


8

클래스는 코드 구조가 계층 구조 인 경우에만 사용해야합니다. 알고리즘에 대해 언급 했으므로 자연 구조는 개체의 계층 구조가 아니라 순서도입니다.

OpenFOAM의 경우, 알고리즘 부분은 다른 유형의 수치 체계를 사용하여 기본적으로 다른 유형의 텐서에서 작동하는 추상 함수 인 일반 연산자 (div, grad, curl 등)로 구현됩니다. 이 코드 부분은 기본적으로 클래스에서 작동하는 많은 일반 알고리즘으로 작성됩니다. 이를 통해 클라이언트는 다음과 같은 내용을 작성할 수 있습니다.

solve(ddt(U) + div(phi, U)  == rho*g + ...);

전송 모델, 난류 모델, 차이 체계, 기울기 체계, 경계 조건 등과 같은 계층 구조는 C ++ 클래스 (다시 말해서 텐서 수량에 일반)로 구현됩니다.

CGAL 라이브러리에서 비슷한 구조를 보았습니다. 여기에서 다양한 알고리즘이 기하학적 정보와 함께 번들로 제공되어 기하학적 커널 (클래스)을 형성하는 함수 객체 그룹으로 묶여 있습니다. 포인트 데이터 유형의면).

계층 구조 ==> 클래스

절차 적 흐름도 ==> 알고리즘


5

이것이 오래된 질문이더라도 Julia 의 특정 솔루션을 언급 할 가치가 있다고 생각합니다 . 이 언어가하는 것은 "클래스없는 OOP"입니다. 주요 구성은 유형, 즉 struct상속 관계가 정의 된 C 와 유사한 복합 데이터 객체 입니다. 유형에는 "멤버 함수"가 없지만 각 함수에는 유형 서명이 있으며 하위 유형을 허용합니다. 예를 들어, 추상 가질 수 Matrix유형 및 하위 유형을 DenseMatrix, SparseMatrix그리고 일반적인 방법이 do_something(a::Matrix, b::Matrix)전문화와를 do_something(a::SparseMatrix, b::SparseMatrix). 다중 디스 패칭 은 호출 할 가장 적합한 버전을 선택하는 데 사용됩니다.

이 방법은 클래스 기반 OOP보다 강력합니다.이 방법은 "메소드가 this첫 번째 매개 변수 와 같은 함수"라는 규칙을 채택하는 경우 (예 : Python에서) 첫 번째 인수에 대한 상속을 기반으로 디스패치하는 것과 같습니다 . C ++에서 어떤 형태의 다중 디스패치가 에뮬레이트 될 수 있지만 상당한 왜곡이 있습니다.

주요 차이점은 메서드가 클래스에 속하지 않지만 별도의 엔터티로 존재하며 모든 매개 변수에서 상속이 발생할 수 있다는 것입니다.

일부 참고 문헌 :

http://docs.julialang.org/en/release-0.4/manual/methods/

http://assoc.tumblr.com/post/71454527084/cool-things-you-can-do-in-julia

https://thenewphalls.wordpress.com/2014/03/06/understanding-object-oriented-programming-in-julia-inheritance-part-2/


1

OO 접근법의 두 가지 장점은 다음과 같습니다.

  • βαcalculate_alpha()αcalculate_beta()calculate_alpha()α

  • calculate_f()f(x,y,z)zset_z()zcalculate_f()z

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