우리 학교의 CS 프로그램은 객체 지향 프로그래밍에 대한 언급을 피하므로 직접 Bertrand Meyer의 객체 지향 소프트웨어 구성 을 보완하기 위해 독자적으로 독서를 해왔습니다 .
Meyer는 클래스가 가능한 한 구현에 대한 많은 정보를 숨겨야한다는 점을 반복해서 지적합니다. 특히 그는 속성 (즉, 정적, 계산되지 않은 클래스의 속성)과 루틴 (함수 / 프로 시저 호출에 해당하는 클래스의 속성)은 서로 구별 할 수 없어야한다는 주장을 반복적으로 주장합니다.
클래스가 예를 들어, Person
속성을 가지고 age
, 그는 여부, 표기법에서 얘기하는 것은 불가능해야한다는 주장 Person.age
에 대응 내부적으로 같은 것으로 return current_year - self.birth_date
하거나 return self.age
, self.age
일정한 속성으로 정의되어 있습니다. 이것은 나에게 의미가 있습니다. 그러나 그는 계속해서 다음을 주장합니다.
클래스의 짧은 형식으로 알려진 클래스의 표준 클라이언트 문서는 주어진 기능이 속성인지 함수인지를 나타내지 않도록 고안 될 것입니다.
즉, 그는 클래스 의 문서 조차도 “getter”가 계산을 수행하는지 여부를 지정하지 않아야한다고 주장합니다 .
나는 따르지 않는다. 문서가 사용자에게이 구별을 알리는 것이 중요한 장소가 아닙니까? Person
객체로 채워진 데이터베이스를 디자인하려는 Person.age
경우 비싼 통화 인지 여부를 아는 것이 중요 하지 않으므로 일종의 캐시를 구현할지 여부를 결정할 수 있습니까? 그가 말한 것을 잘못 이해 했습니까? 아니면 OOP 디자인 철학의 극단적 인 예일까요?
답변
Meyer의 요점은 비싼 작업을 할 때 사용자에게 말해서는 안된다는 것입니다. 함수가 데이터베이스에 도달하거나 웹 서버에 요청하고 컴퓨팅에 몇 시간을 소비하는 경우 다른 코드에서이를 알아야합니다.
그러나 클래스를 사용하는 코더는 구현했는지 여부를 알 필요가 없습니다.
return currentAge;
또는:
return getCurrentYear() - yearBorn;
이 두 가지 접근 방식 간의 성능 특성은 매우 적으므로 중요하지 않습니다. 클래스를 사용하는 코더는 실제로 어떤 것을 신경 쓰지 않아야합니다. 이것이 요점입니다.
그러나 항상 그런 것은 아닙니다. 예를 들어 컨테이너에 크기 방법이 있다고 가정하십시오. 그것은 구현 될 수 있습니다 :
return size;
또는
return end_pointer - start_pointer;
또는 다음이 될 수 있습니다.
count = 0
for(Node * node = firstNode; node; node = node->next)
{
count++
}
return count
처음 두 가지의 차이는 중요하지 않습니다. 그러나 마지막 것은 심각한 성능 저하를 초래할 수 있습니다. STL과, 예를 들어, 그 말한다 이유 .size()
입니다 O(1)
. 크기가 어떻게 계산되는지 정확하게 설명하지는 않지만 성능 특성을 제공합니다.
따라서 : 성능 문제를 문서화하십시오. 구현 세부 사항을 문서화하지 마십시오. std :: sort가 적절하고 효율적으로 수행되는 한 내 항목을 정렬하는 방법에 관심이 없습니다. 또한 클래스는 계산 방법을 문서화해서는 안되지만 예상치 못한 성능 프로파일이있는 경우이를 문서화하십시오.
답변
학계 또는 CS 순수 주의자 입장에서 볼 때, 기능 구현의 내부에 대한 내용은 문서에 설명하지 않은 것은 물론입니다. 클래스의 사용자는 클래스의 내부 구현에 대해 어떠한 가정도하지 않아야하기 때문입니다. 구현이 변경되면 이상적으로 사용자가 눈치 채지 못할 것입니다.이 기능은 추상화를 생성하고 내부는 완전히 숨겨져 있어야합니다.
그러나, 대부분의 실제 프로그램은 조엘 Spolsky`s 고통 “새는 추상화의 법칙” 라고하는,
“모든 사소한 추상화는 어느 정도 누설된다.”
즉, 복잡한 기능의 완전한 블랙 박스 추상화를 만드는 것은 사실상 불가능합니다. 그리고 이것의 전형적인 증상은 성능 문제입니다. 따라서 실제 프로그램의 경우 호출 비용이 높고 비싸지 않은 것이 매우 중요 할 수 있으며, 좋은 문서에는 해당 정보가 포함되어야합니다 (또는 클래스 사용자가 성능에 대한 가정을 할 수있는 위치와 그렇지 않은 위치를 말해야 함). ).
따라서 내 조언은 : 실제 프로그램에 대한 문서를 작성하는 경우 잠재적으로 비싼 전화에 대한 정보를 포함하고 성능 고려 사항을 유지해야한다는 점을 고려하여 CS 과정의 교육 목적으로 만 작성하는 프로그램의 경우 제외하십시오. 의도적으로 범위를 벗어났습니다.
답변
주어진 통화가 비싸거나 그렇지 않은 경우 쓸 수 있습니다. 더 나은이 같은 이름 지정 규칙을 사용하여 getAge
신속하게 액세스 및 위해 loadAge
또는 fetchAge
고가의 조회에. 메소드가 IO를 수행하고 있는지 확실히 사용자에게 알리고 싶습니다.
문서에 제공하는 모든 세부 사항은 클래스가 준수해야하는 계약과 같습니다. 중요한 행동에 대해 알려 주어야합니다. 종종 O 표기법이 큰 복잡도 표시가 나타납니다. 그러나 일반적으로 짧고 요점을 밝히기를 원합니다.
답변
Person 객체로 채워진 데이터베이스를 디자인 할 경우 Person.age가 비싼 호출인지 아닌지 아는 것이 중요하지 않습니까?
예.
그렇기 때문에 Find()
호출하는 데 시간이 걸릴 수 있음을 나타내는 함수를 사용 하는 경우가 있습니다. 이것은 다른 것보다 더 많은 관습입니다. 이 프로그래머들 사이 있지만 그것을 반환하는 함수 나 속성에 걸리는 시간은 프로그램에 차이를 (이 사용자에 대한 수도 있지만)도하지 않습니다 이다 이 속성으로 선언 된 경우, 비용이해야 호출 할 수 있다는 기대가 낮은.
어쨌든 코드 자체에는 어떤 것이 함수인지 속성인지를 추론하기에 충분한 정보가 있어야하므로 문서에서 실제로 말할 필요가 없습니다.
답변
이 책의 첫 번째 판은 1988 년 OOP 초기에 작성되었다는 점에 유의해야합니다. 이 사람들은 오늘날 널리 사용되는보다 순수한 객체 지향 언어를 사용하고있었습니다. 오늘날 가장 널리 사용되는 OO 언어 (C ++, C # 및 Java)는 초기의보다 순수한 OO 언어가 작동하는 방식과는 상당한 차이가 있습니다.
C ++ 및 Java와 같은 언어에서는 속성 액세스와 메소드 호출을 구별해야합니다. instance.getter_method
와 사이에는 차이가 instance.getter_method()
있습니다. 하나는 실제로 당신의 가치를 얻고 다른 하나는 그렇지 않습니다.
좀 더 순수하게 OO 언어, 스몰 토크 또는 루비 설득 (이 책에서 사용 된 에펠 언어 인 것 같습니다)에 대해 작업 할 때 완벽하게 유효한 조언이됩니다. 이러한 언어는 암시 적으로 메소드를 호출합니다. instance.attribute
와 사이에는 차이가 없습니다 instance.getter_method
.
나는이 점을 땀내거나 너무 독단적으로 받아들이지 않을 것이다. 의도는 좋으며 클래스의 사용자가 관련이없는 구현 세부 사항에 대해 걱정하지 않기를 원하지만 많은 현대 언어의 구문으로 명확하게 번역되지는 않습니다.
답변
사용자는 무언가가 어떻게 구현되는지 알 필요가 없습니다.
성능이 문제라면 클래스 구현 내부에서가 아니라 무언가를 수행해야합니다. 따라서 올바른 조치는 클래스 구현을 수정하거나 관리자에게 버그를 제출하는 것입니다.
답변
루틴 / 방법의 복잡성 비용에 대해 프로그래머에게 알리지 못하는 프로그래머 중심의 문서에는 결함이 있습니다.
-
우리는 부작용이없는 방법을 생산하려고합니다.
-
방법의 실행 시간 복잡도 및 / 또는 이외의 메모리 복잡도를 실행 한 경우
O(1)
, 메모리 – 시간 또는 제약 환경에서 부작용이 고려 될 수있다 . -
방법이 완전히 예기치 않은 작업을 수행하는 경우 ( 최소한의 놀라움 의 원칙은 이 경우 메모리를 낭비하거나 CPU 시간을 낭비하는 경우) 위반됩니다.