2010-06-16 3 views
4

다양한 변경 가능한 데이터 (예 : 스크롤 위치, 사용자 데이터, 파일 이름, 선택된 도구 옵션 등)를 필요로하는 Swing + Clojure의 GUI 응용 프로그램에서 작업하고 있습니다. .지도에 대한 참조 대 다중 참조에 대한 매핑

I의 데이터 세트 처리 적어도 세 가지 방법으로 볼 수 있습니다

(def data (ref { 
    :filename "filename.xml" 
    :scroll  [0 0] })) 

개별 데이터에 심판의지도 만들기 :

모든 데이터의지도에 심판을 만들기를 요소 :

:

(def datamap { 
    :filename (ref "filename.xml") 
    :scroll  (ref [0 0]) })) 

네임 스페이스의 각에 대해 별도의 심판 만들기

참고 :이 데이터는 동시에 액세스됩니다. 백그라운드 처리 thread 또는 Swing 이벤트 처리 thread. 그러나 여러 요소의 일관된 트랜잭션 업데이트가 필요하지는 않습니다.

추천 방법은 무엇이며 그 이유는 무엇입니까?

답변

6

첫 번째로 하나의 가변 상태 또는 여러 독립적 인 조각을 사용하면 (결국 "하나가 다른 것과 일치하는지 묻지 않는다"와 같이 독립), Refs가 아닌 Atoms로 이동하십시오. ? 오버 헤드를 상당히 줄였습니다. 많은 업데이트를하면 실제로 문제가 될 수 있습니다.

두 번째로, 별도의 Ref (Atoms는 아님)에 파일 이름, 스크롤 위치 등을 저장하는 것은 트랜잭션을 신중하게 설계하는 한 괜찮습니다. 즉 관련된 모든 참조를 언급해야하며 일부는 ensure 등이되어야합니다. - 일관성없는 상태가 발생하면 트랜잭션은 반드시 실패해야합니다. 이러한 트랜잭션을 신중하게 설계하는 것은 GUI 상태를 거의 관리하지 않는 경우 거의 낭비하지 않을 수 있습니다 (스크롤 위치 및 버퍼 내용 외에도 실제로 자주 변경 될 가능성이있는 항목은 무엇입니까? 답은 최종 디자인을 결정해야 함). 여러 개의 참조 유형 객체를 갖는 것이 시나리오보다 많을 수 있습니다. 기본 GUI 상태를 관리하는 것이 그 중 하나인지는 잘 모르겠습니다. :-)

참조 유형 개체에 포함 된 중첩 구조에 대한 업데이트를 수행하는 것은 Clojure에서 매우 깨끗합니다. (아톰을 사용) :

;; assuming that state-o-matic is an Atom which holds a map, 
;; which holds the key of :foo, with which a vector is associated, 
;; whose first item is another vector, whose first item is a map 
;; which holds the key of :bar associated to a number, 
;; the following increments said number 
(swap! state-o-matic update-in [:foo 0 1 :bar] inc) 

get-in & assoc-in를 참조하십시오.

+0

감사합니다. Michal, very interesting! 가장 좋은 모델은 실제로 원자 내부의 단일 맵일 수 있습니다. 나는 이것이 모든 동시성 요구 사항을 충족시키고 오버 헤드가 적어야한다고 말한 것처럼 생각합니다. – mikera

+1

그럴 가능성이 매우 높습니다.또한 시작하는 것이 좋은 시점입니다. 올바른 코드를 작성하는 것이 쉬우 며 그렇게할만한 이유가있을 때 나중에 나눌 수 있습니다. –

1

동시성이없는 경우에는 차이가 없습니다.

하지만 다른 스레드에서 사용할 수 있다면 첫 번째 경우가 더 좋습니다. 그것은 당신에게 일관된 상태를 보장하기 때문입니다.

+0

감사합니다. 예 : 확실히 첫 번째 옵션의 일관성 장점을 좋아합니다. 다른 옵션은 코딩 스타일, 유지 보수성 및/또는 성능면에서 몇 가지 장점을 가지고 있다고 생각합니까? – mikera

+0

다른 옵션의 장점이 보이지 않습니다. –