Globals를 없애시겠습니까?
-
09-06-2019 - |
문제
저는 깊이가 20년대 어딘가에 있는 나무 개체 세트를 가지고 있습니다.이 트리의 각 노드는 해당 트리의 루트에 액세스해야 합니다.
몇 가지 솔루션:
- 각 노드는 루트에 대한 참조를 직접 저장할 수 있습니다(메모리 낭비).
- 런타임에 "상승"(폐기물 사이클)하여 근을 계산할 수 있습니다.
정적 필드를 사용할 수 있습니다(그러나 이는 전역 필드에 해당합니다).
전역(어떤 변형이든)을 사용하지 않지만 메모리나 사이클 모두에서 #1이나 #2보다 더 효율적인 디자인을 누군가 제공할 수 있습니까?
편집하다: 나무 세트가 있기 때문에 나무를 구별하기 어렵기 때문에 단순히 정적으로 저장할 수는 없습니다.(maccullt에게 감사드립니다)
해결책
루트를 필요한 노드의 함수에 매개변수로 전달합니다.
편집하다:옵션은 실제로 다음과 같습니다.
- 노드에 루트 참조를 저장합니다.
- 루트 참조를 전혀 저장하지 마십시오
- 루트 참조를 전역에 저장
- 스택에 루트 참조를 저장합니다(내 제안, 방문자 패턴 또는 재귀).
나는 이것이 모든 가능성이라고 생각하며 옵션 5는 없습니다.
다른 팁
왜 글로벌을 없애야 할까요?나는 전역이 나쁘다는 오명을 이해하지만 때로는 모든 요소가 포함된 전역 데이터 구조를 갖는 것이 가장 빠른 솔루션입니다.
당신은 절충안을 만듭니다:코드 명확성과 향후 성능 문제 감소.'아직 최적화하지 마세요'라는 의미입니다.최적화 단계에 있기 때문에 때로는 성능을 위해 가독성과 좋은 프로그래밍 방식을 생략해야 하는 경우도 있습니다.내 말은, 비트 해킹은 읽을 수 없지만 빠르다는 것입니다.
얼마나 많은 나무 개체가 있는지 잘 모르겠지만 개인적으로는 옵션 1을 사용하고 싶습니다.수천 개가 넘는 나무를 다루지 않는 한 포인터는 실제로 몇 개의 문자열보다 훨씬 더 많은 양이 되지 않습니다.메모리가 정말 중요한 문제라면 두 가지 방법을 모두 시도해 보고(구현하기가 매우 간단해 보임) 프로파일러를 통해 실행해 보세요.아니면 우수한 것을 사용하십시오 프로세스 탐색기.
편집하다:제가 작업 중인 앱 중 하나에는 약 55,000개의 노드가 포함된 노드 트리가 있습니다.우리는 트리 구조를 구축하고 O(1) 조회를 위한 배열도 유지합니다.재귀적인 FindNodeByID 메서드를 사용할 때 얻은 O(m*n)보다 훨씬 좋습니다.
일반적으로 루트를 매개변수로 전달하는 것이 가장 좋습니다.트리를 탐색하기 위해 일종의 반복자를 사용하는 경우 대안은 거기에 루트에 대한 참조를 저장하는 것입니다.
포인트 #1은 조기 메모리 최적화입니다.#2는 조기 성능 최적화입니다.메모리 또는 CPU 병목 현상이 문제를 일으키는지 확인하기 위해 앱을 프로파일링해 보셨나요?그렇지 않다면 사용자에게 도움이 되지 않는 "최적화"를 위해 유지 관리가 용이한 디자인을 희생할 이유가 무엇입니까?
#2를 선택하는 것이 좋습니다.대신 계산할 수 있는 것을 저장할 때마다 수행하는 작업은 캐싱입니다.캐싱을 사용하는 것이 좋은 경우도 있지만 유지 관리가 골치 아픈 경우도 있습니다.(예를 들어, 부모를 변경하여 노드를 한 트리에서 다른 트리로 이동했지만 루트 필드도 업데이트하는 것을 잊어버린 경우 어떻게 될까요?) 꼭 필요하지 않다면 캐시하지 마세요.
TreeView에서 클래스를 파생시킨 다음 싱글톤 정적 속성을 추가할 수 있습니다.이렇게 하면 클래스의 단일 인스턴스를 참조하는 전역 필드를 효과적으로 추가할 수 있지만 해당 클래스로 네임스페이스 범위가 지정된다는 이점이 있습니다.
내부 클래스에 대한 혐오감을 무시하고 Tree 클래스를 정의하고 노드를 내부 클래스로 정의할 수 있습니다.각 노드는 루트를 포함하여 트리의 상태에 액세스할 수 있습니다.
이는 Java가 노드를 상위 노드와 연결하는 방식에 따라 #1과 동일하게 될 수 있습니다.(잘 모르겠으니 프로필을 작성해야겠습니다)