C ++의 모든 것에 객체 (기본 유형 대신)를 사용하는 것이 합리적입니까?


17

최근에 작업 한 프로젝트에서 다음과 같은 많은 기능을 사용해야했습니다.

static bool getGPS(double plane_latitude, double plane_longitude, double plane_altitude,
                       double plane_roll, double plane_pitch, double plane_heading,
                       double gimbal_roll, double gimbal_pitch, double gimbal_yaw, 
                       int target_x, int target_y, double zoom,
                       int image_width_pixels, int image_height_pixels,
                       double & Target_Latitude, double & Target_Longitude, double & Target_Height);

그래서 다음과 같이 보이도록 리팩토링하고 싶습니다.

static GPSCoordinate getGPS(GPSCoordinate plane, Angle3D planeAngle, Angle3D gimbalAngle,
                            PixelCoordinate target, ZoomLevel zoom, PixelSize imageSize)

이것은 첫 번째 방법보다 훨씬 더 읽기 쉽고 안전합니다. 그러나 수업 PixelCoordinatePixelSize수업 을 만드는 것이 합리적 입니까? 또는 std::pair<int,int>각각에 대해 사용 하는 것이 좋습니다 . 그리고 ZoomLevel수업 을 듣는 것이 합리적 입니까, 아니면 그냥double 입니까 합니까?

모든 것에 클래스를 사용하는 것에 대한 나의 직관은 다음과 같은 가정에 근거합니다.

  1. 모든 클래스가 있다면 ZoomLevel어디에서나 전달할 수 없습니다 .Weight 객체가 예상되는 하므로 함수에 잘못된 인수를 제공하는 것이 더 어려울 수 있습니다
  2. 마찬가지로 일부 잘못된 작업은 a GPSCoordinateZoomLevel다른 사람에 추가하는 등의 컴파일 오류를 일으킬 수 있습니다.GPSCoordinate
  3. 합법적 인 작업은 표현하기 쉽고 타이프 안전합니다. 즉, 두 GPSCoordinates를 빼면GPSDisplacement

그러나 내가 본 대부분의 C ++ 코드는 많은 기본 유형을 사용하며 그 이유가 있어야한다고 생각합니다. 무언가를 위해 객체를 사용하는 것이 좋습니까, 아니면 내가 모르는 단점이 있습니까?


8
"내가 본 대부분의 C ++ 코드는 많은 기본 유형을 사용한다"-두 가지 생각이 떠오른다. 많은 C ++ 코드는 추상화가 약한 C에 익숙한 프로그래머에 의해 작성되었을 수있다. 또한 철갑 상어의 법칙
congusbongus

3
프리미티브 유형이 단순하고 간단하고 빠르며 매끄럽고 효율적이기 때문이라고 생각합니다. 이제 OP의 예에서 새로운 클래스를 소개하는 것이 좋습니다. 그러나 제목 질문에 대한 답변 ( "모든 것"이라고 말하는 곳)은 놀랍습니다!
Mr Lister

1
복식을 @Max typedeffing하면 OP의 문제를 해결하는 데 아무런 도움이되지 않습니다.
Mr Lister

1
@CongXu : 나는 거의 같은 생각을했지만 "어떤 언어로든 많은 코드가 추상화를 작성하는 데 전혀 문제가없는 프로그래머에 의해 작성되었을 수 있습니다"라는 의미에서 더 많은 의미를가집니다.
Doc Brown

1
"17 개의 매개 변수를 가진 함수가 있다면 아마도 몇 가지를 놓쳤을 것입니다"라는 말이 나오듯이
Joris Timmermans

답변:


24

물론 이죠 너무 많은 인수를 사용하는 함수 / 방법은 코드 냄새 이며 다음 중 하나 이상을 나타냅니다.

  1. 기능 / 방법이 한 번에 너무 많은 일을하고 있습니다
  2. 함수 / 메소드는 일부 OO 디자인 법을 요구 하거나 하거나 위반 하지 않기 때문에 많은 것들에 액세스해야합니다.
  3. 논쟁은 실제로 밀접한 관련이 있습니다

마지막 사건이 사실이라면 (그리고 당신의 예가 분명히 암시한다면), 수십 년 전에 멋진 아이들이 오에 대해 이야기 했던 멋진 팬츠 "추상화" 를 할 시간 입니다. 사실, 나는 당신의 예보다 더 나아가서 다음과 같은 일을 할 것입니다 :

static GPSCoordinate getGPS(Plane plane, Angle3D gimbalAngle, GPSView view)

(GPS에 익숙하지 않으므로 이것이 올바른 추상화가 아닐 수 있습니다. 예를 들어 줌이 getGPS 있습니다.

두 데이터가 동일한 경우에도 PixelCoordinateover 와 같은 클래스를 선호하십시오 std::pair<T, T>. 그것은 의미 론적 가치와 약간의 추가 유형 안전을 추가합니다 (컴파일러는 둘 다 s 인 경우에도 a ScreenCoordinate를 전달하지 못하게합니다 .PixelCoordinatepair


1
말할 것도없이 모든 멋진 아이들이 시도하고 있지만 실제로는 안되는 작은 미세 최적화에 대해 더 큰 구조체를 전달할 수 있습니다.
ratchet freak

6

기권: C를 C ++보다 선호합니다

클래스 대신 구조체를 사용합니다. 구조체와 클래스가 거의 동일 하기 때문에이 시점은 기발합니다. ( 단순 차트 또는이 SO여기 를 참조 하십시오. 질문 ). 분화에는 장점이 있다고 생각합니다.

C 프로그래머는 그룹화 할 때 더 큰 의미를 갖는 데이터 블록으로 구조체에 익숙하지만 클래스를 볼 때 그 상태를 조작하는 내부 상태와 메소드가 있다고 가정합니다. GPS 좌표에는 상태가없고 데이터 만 있습니다.

귀하의 질문에 따르면, 이것이 당신이 찾고있는 것, 일반적인 컨테이너이며 상태 저장 구조가 아닙니다. 다른 사람들이 언급했듯이 Zoom을 자체 클래스에 넣는 것을 귀찮게하지 않을 것입니다. 나는 개인적으로 데이터 유형 (교수님이 만드는 사랑 잡아 내장 클래스 싫어 Height하고 Id클래스).

모든 클래스가 있으면 Weight 객체가 예상되는 위치에 ZoomLevel을 전달하는 것이 불가능하므로 함수에 잘못된 인수를 제공하는 것이 더 어려울 수 있습니다

나는 이것이 문제라고 생각하지 않습니다. 명백한 작업을 그룹화하여 매개 변수 수를 줄이면 이러한 문제를 방지하기에 헤더가 충분해야합니다. 정말로 걱정된다면 기본 요소를 구조체로 분리하면 일반적인 실수로 컴파일 오류가 발생합니다. 두 매개 변수를 서로 옆에 쉽게 교체 할 수 있지만 더 멀리 떨어져 있으면 더 어렵습니다.

마찬가지로 일부 잘못된 작업으로 인해 ZoomLevel 또는 다른 GPSCoordinate에 GPSCoordinate 추가와 같은 컴파일 오류가 발생할 수 있습니다.

운영자 과부하 사용.

합법적 인 작업은 표현하기 쉽고 타이프 안전합니다. 즉, 두 개의 GPSCoordinates를 빼면 GPS 변위가 발생합니다.

또한 작업자 과부하를 잘 사용합니다.

당신이 올바른 길을 가고 있다고 생각합니다. 고려해야 할 또 다른 사항은 이것이 프로그램의 나머지 부분에 어떻게 적용되는지입니다.


3

전용 형식을 사용하면 인수 순서를 정하는 것이 훨씬 어렵다는 장점이 있습니다. 예를 들어, 예제 함수의 첫 번째 버전은 9 개의 이중 체인으로 시작합니다. 누군가이 기능을 사용하면 GPS 좌표 대신 순서를 정돈하고 짐벌 각도를 전달하는 것이 매우 쉽습니다. 이것은 매우 이상하고 버그를 추적하기가 어려울 수 있습니다. 다른 유형의 인수를 세 개만 전달하면 컴파일러에서이 오류를 포착 할 수 있습니다.

사실 한 걸음 더 나아가 기술적으로는 동일하지만 의미 적 의미가 다른 유형을 소개하는 것을 고려합니다. 예를 들어, 클래스 PlaneAngle3d와 별도의 클래스 를 가짐으로써 GimbalAngle3d둘 다 3 개의 이중 모음입니다. 이것은 의도적이지 않은 한 하나를 다른 것으로 사용하는 것을 불가능하게합니다.

typedef double ZoomLevel그 이유뿐만 아니라 다른 이유로 기본 유형 ( )의 별칭 인 typedef를 사용하는 것이 좋습니다 . 나중에 유형을 쉽게 변경할 수 있습니다. 언젠가 사용하는 것이 메모리 float만큼 double효율적이고 CPU 효율적일 수 있다는 아이디어를 얻으면 수십이 아니라 한 곳에서 변경해야합니다.


typedef 제안에 +1 프리미티브 유형과 객체의 두 가지 장점을 모두 얻을 수 있습니다.
Karl Bielefeldt

typedef보다 클래스 멤버의 유형을 변경하는 것은 어렵지 않습니다. 또는 프리미티브와 비교 했습니까?
MaHuJa

2

여기에 좋은 답변이 있지만 추가하고 싶은 한 가지가 있습니다.

사용 PixelCoordinatePixelSize수업은 일을 매우 구체적으로 만듭니다. 일반 Coordinate또는 Point2D수업은 아마도 귀하의 요구에 더 잘 맞을 것입니다. A Point2D는 가장 일반적인 점 / 벡터 연산을 구현하는 클래스 여야합니다. (당신은 일반적으로 이러한 클래스를 구현할 수 Point2D<T>T가 될 수있다 int거나 double또는 뭔가 다른).

2D 포인트 / 벡터 작업은 많은 2D 지오메트리 프로그래밍 작업에서 매우 일반적이므로 그러한 경험을 통해 기존 2D 작업을 재사용 할 가능성이 높아집니다. 각 그들을 다시 구현하기위한 필요 피할 수 PixelCoordinate, GPSCoordinate"앞서 어떤"-Coordinate 클래스 또 다시합니다.


1
struct PixelCoordinate:Point2D<int>적절한 유형의 안전을 원할 경우 에도 가능합니다
래칫 괴물

0

그래서 다음과 같이 보이도록 리팩토링하고 싶습니다.

static GPSCoordinate getGPS(GPSCoordinate plane, Angle3D planeAngle, Angle3D gimbalAngle,
                        PixelCoordinate target, ZoomLevel zoom, PixelSize imageSize)

이것은 첫 번째 방법보다 훨씬 더 읽기 쉽고 안전합니다.

[더 읽기 쉽다]. 또한 좋은 생각입니다.

그러나 PixelCoordinate 및 PixelSize 클래스를 만드는 것이 합리적입니까?

서로 다른 개념을 나타내는 경우에는 의미가 있습니다 (즉, "예").

또는 각각 std :: pair를 사용하는 것이 좋습니다.

당신은 시작할 수 typedef std::pair<int,int> PixelCoordinate, PixelSize;있습니다. 이 방법으로 의미를 다루고 (클라이언트 코드의 std :: pairs가 아닌 픽셀 좌표 및 픽셀 크기로 작업하고 있음) 확장 해야하는 경우 typedef를 클래스로 바꾸면 클라이언트 코드가 최소한의 변경이 필요합니다.

그리고 ZoomLevel 클래스를 갖는 것이 합리적입니까, 아니면 더블을 사용해야합니까?

당신은 그것을 typedef 할 수는 있지만 double, 이중에 존재하지 않는 기능과 관련이 필요할 때까지 사용합니다 (예 : ZoomLevel::default값을 가지려면 클래스를 정의해야하지만 다음과 같은 것이있을 때까지) 즉, 이중으로 유지하십시오).

모든 것에 클래스를 사용하는 것에 대한 나의 직관은 이러한 가정에 기초하고있다 [간결하게 생략]

그것들은 강력한 논증입니다 (인터페이스를 올바르게 사용하기 쉽고 잘못 사용하기 어렵도록 항상 노력해야합니다).

그러나 내가 본 대부분의 C ++ 코드는 많은 기본 유형을 사용하며 그 이유가 있어야한다고 생각합니다.

이유가 있습니다. 많은 경우에, 그 이유는 좋지 않습니다. 이를 수행하는 한 가지 유효한 이유는 성능 일 수 있지만 이는 이런 종류의 코드를 규칙이 아니라 예외로보아야한다는 것을 의미합니다.

무언가를 위해 객체를 사용하는 것이 좋습니까, 아니면 내가 모르는 단점이 있습니까?

일반적으로 값이 항상 함께 나타나고 의미가없는 경우 게시물에서 언급 한 것과 같은 이유로 그룹화해야합니다.

즉, 항상 x, y 및 z가있는 좌표를 사용하는 경우 coordinate세 곳의 매개 변수를 전송 하는 것보다 클래스 를 갖는 것이 훨씬 좋습니다 .

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