2011-08-10 5 views
2

캡슐화와 관련된 유지 관리 가능성과 관련하여 몇 가지 일반적인 질문이 있습니다. 다음은 구문 분석 트리를 구성하는 데 사용한 예제 클래스입니다. (나는 교육을 위해 STL을 피했다.)유지 관리 및 캡슐화를위한 C++ 클래스 계층 구조 구성

Node 클래스는 트리의 노드를 설명한다. 관리 클래스 ParseTree (표시되지 않음)은 Node 개체 컬렉션을 의미 있고 나무 같은 방식으로 작성 및 유지 관리해야합니다.

// contents of node.h, not including header guard or namespace 
class Token; 
class Node { 
public: 
    static const Node* FindParent(const Node* p_root, const Node* p_node); 
    static int Height(const Node* p_root); 
    static void Print(const Node* p_root); 
    Node(const Token * p_tok=0) : p_left_(0), p_right_(0), p_tok_(p_tok) {} 
    ~Node() { delete p_left_; delete p_right_; } 
    const Node* p_left(void) const { return p_left_; } 
    const Node* p_right(void) const { return p_right_; } 
    const Token* p_tok(void) const { return p_tok_; } 
private: 
    friend class ParseTree; 
    Node* p_left_; 
    Node* p_right_; 
    Token* p_tok_; 
}; 

다음 네 가지 주제는 캡슐화와 관련됩니다. 그들이 어떤 개인 멤버를 사용하지 않고 말로 표현 할 수 있기 때문에 Node 클래스

  1. 정적 방법은 정적 선언됩니다. 일반적인 네임 스페이스에서 Node 외부에 살 것인지, 아니면 ParseTree 내의 정적 멤버로 살 것인지 궁금합니다. 내 결정은 ParseTree이 나무를 담당한다는 사실에 의해 결정되어야하며 그 논리에 따라 기능은 ParseTree에 있어야합니까?

  2. 관련 메모에서 ParseTree 대신 정적 방법이 Node이 아닌 이유는 ParseTree이 많은 구성원으로 채워져 있기 때문입니다. 나는 클래스를 작고 민첩하게 유지하는 것이 유지 보수에 더 좋다는 것을 읽었습니다. 개인 멤버 액세스에 의존하지 않는 메서드를 찾고 클래스 정의에서 꺼내 클래스와 동일한 네임 스페이스 내에 그룹화 된 함수에 넣는 방법을 찾아야할까요?

  3. 내가 가지고 또한 캡슐화를 중단하는 경향이 있기 때문에 개인 회원에 뮤 테이터 방지에 관한 조언을 읽고, 그래서 만 가지고 접근을 종료하고, ParseTreeNode과의 우정을 사용하여 수정을 처리 할 수 ​​있습니다. 돌연변이가 있고 ParseTree으로 우정을 끝내는 것보다이게 낫지 않습니까? mutator를 추가하면 다른 우정을 추가하지 않고 Node을 다른 컨텍스트에서 재사용 할 수 있습니다.

  4. 내가 돌연변이를 추가하고 Node에서 정적 함수를 제거하면 데이터 멤버를 public으로 만들고 모든 접근 자/mutators/friend 선언을 제거 할 수 있다고 생각합니다. 나는 그러한 접근이 나쁜 형태라는 인상을 가지고있다. 각각의 개인 멤버에 접근 자/뮤 테이터 쌍이 있다면 디자인에 회의적이어야합니까?

  5. 내 접근 방식에 대해 내가 묻지 않을 것이 분명하고 이상한 점이 있다면 그것에 대해 듣고 싶습니다.

+1

당신의 논쟁은 원에서 돌아가고 있는데, 나는 이런 종류의 문제에 관해 생각할 때 저에게 무슨 일이 일어나는가에 대한 것입니다. 나는 그것에 대해 너무 걱정하지 않을 것입니다, 당신은 당신이하는 일을 알고있는 것처럼 보입니다. 그러나 매우 빨리 1) 노드에 있어야한다고 생각하지 않습니다. 2) 예, 글로벌 기능. 3) Node를 재사용 할 때 거의 이점이 없다. ParseTree에 묶여있는 것처럼 큰 가치는 없다. 4) 아니요, 노드처럼 단순한 것으로 모든 것이 공개 될 수 있기 때문입니다. – john

+0

'돌연변이', 예수님 Setters and Getters의 잘못된 점은 무엇입니까? – James

+0

나는 지난 몇 년 동안 저수준 작업 (IC 디자인, hdl, 임베디드 C의 자리)을하는 데 대부분을 보냈다. 절친한 친구는 객체 지향 디자인을 내게 설명 할 때 접근 자 (accessor)와 돌연변이 자 (mutators)를 가리키는 데 항상 사용되기 때문에 사적인 구성원과 상호 작용하는 public 멤버 함수에 관해 생각할 때 내 머리 속에서 가지고있는 것입니다. –

답변

1

노드 란 무엇인지 물어보십시오. 분명히, 그것은 부모, 왼쪽 아이 및 오른쪽 아이가있을 수 있습니다. 또한 일부 데이터에 대한 포인터를 보유합니다. 노드에 높이가 있습니까? 컨텍스트에 따라 달라 지므로 노드가 어느 시점에서주기의 일부가 될 수 있습니까? ParseTree는 높이 개념을 가지고 있습니다. 노드가 아닌 것처럼 보입니다.

솔직히 말해서, 프로그램 논리를 먼저 수정 한 다음 객체 유형 및 휘파람에 대해 걱정할 수 있습니다. 당신이 계속 진행할 때 묻는 질문은 아마도 스스로 답할 것입니다.

+0

감사합니다. 당신이 묻는 질문은 유용한 생각을하게 해줍니다. 그렇지만 프로그램을 마쳤지 만 조직이 적절하다고 느끼지 않았습니다. 그리고 저는 아직 잘 발달 된 직감이나 일련의 질문을 가지고 있지 않습니다. 제 코드 작성을 스스로 부탁 할 수 있습니다. 또한, 나는 나의 순진한 디자인이 나의 구현을 손상시키는 것을보기에 충분히 큰 문제를 해결하지 못했다. –

1

나는 노드 분명히 개인 회원을 노출의 단지 간접적 인 방법이 접근과 조금 너무 붐비 생각합니다. 나는이 정적 멤버들을 어플리케이션 네임 스페이스로 제거하는 것이 좀 더 깔끔할 것이라고 생각한다. 예 : 당신은 여전히 ​​글로벌 네임 스페이스를 오염 피할 수있는 방법으로

namespace mycompiler { 
    class Node { 
     ... 
    }; 

    class ParseTree { 
     ... 
    }; 

    const Node* FindParent(...); 
    int Height(...); 
    void Print(...); 
} 

,하지만 같은 시간에 노드 및 파스 트리 클래스 작은 유지. 또한 mycompiler:: 함수 (예 : Print())에 과부하로 클래스에 스틱을 넣지 않으려는 경우 네임 스페이스의 객체를 허용 할 수 있습니다. 이는 노드와 ParseTree를보다 지능적인 컨테이너로 만들지 만 관련 클래스에 대한 일부 외부 로직은 mycompiler::으로 격리 될 수 있습니다.