Graphviz로 Uml 표현하기

Graphviz의 3요소
- graph(그래프)
- node(노드)
- edge(엣지)
위 3요소를 가지고 모든 그래프를 그릴 수 있다.

그래프(graph) : 방향성이 없는 그래프, 방향성을 포함한 그래프...
노드(node) : 그래프에서 보여지는 각각의 객체 ( 프로그래머 입장에서 이해하기 쉽도록 설명. )
엣지(edge) : 각 객체를 연결하는 선

우선 UML에서는 어떻게 매칭되는지 알아보자.
    1. 각각의 객체는 노드로 처리한다. - node
    2. 객체의 연관관계를 선(엣지)으로 표현한다. - edge
    3. 연관 관계에 방향성을 가져야 한다. - 방향성 있는 그래프(digraph)
이론상으로 1:1 매칭이 되기 때문에 UML을 표현할 수 있는 기반이 마련되었다.

그렇다면 이제 UML을 표현할 샘플을 구해야하는데...
객체지향을 배울때 많이 쓰는 CShape, CRect, CCircle, CTriangle을 표현해 보도록 하자.

우선 CShape는 도형을 추상화한 클래스이다.
CRect, CCircle, CTriangle은 CShape를 상속받은 클래스이다.
digraph Shape
{
	CRect -> CShape;
	CCircle -> CShape;
	CTriangle -> CShape;
}

아직 UML 모양은 갖추지 못했지만 최소한 CShape에서 상속받으려는 의도는 표시하였다.

이제 각 노드의 모양을 바꾸어보자.
digraph Shape
{
	node [ shape="record" ];
	CRect -> CShape;
	CCircle -> CShape;
	CTriangle -> CShape;
}
노드의 모양을 바꾸고 나니 화살표가 눈에 거슬린다.
UML에서는 상속을 받을때 안이 비어 있는 화살표를 사용하는 것이 원칙이다.
이번엔 각 edge 속성을 바꾸어 보자.
digraph Shape
{
	node [ shape = "record" ];
	edge [ arrowhead = "empty" ];
	CRect -> CShape;
	CCircle -> CShape;
	CTriangle -> CShape;
}
이제 어느정도 UML 모양새를 갖추기 시작하였다.
CShape public void draw() 함수를 만들고 각각 상속 받은 모양을 넣어보자.
digraph Shape
{
	node [ shape = "record" ];
	edge [ arrowhead = "empty" ];
	
	CShape [ label="{CShape||+ draw() : void\n}" ];
	
	CRect -> CShape;
	CCircle -> CShape;
	CTriangle -> CShape;
}
label : node의 이름을 재설정한다.
{ } :  태그로 묶은 부분을 하나의 Column으로 표시한다.
| : Row 단위로 나누기 위한 구분선을 표시한다.
\n : 다음 라인으로 넘긴다.
digraph Shape
{
	node [ shape = "record" ];
	edge [ arrowhead = "empty" ];
	
	CShape [ label="{CShape||+ draw() : void\n}" ];
	CRect [ label="{CRect||+ draw() : void\n}" ];
	CCircle [ label="{CCircle||+ draw() : void\n}" ];
	CTriangle [ label="{CTriangle||+ draw() : void\n}" ];
	
	CRect -> CShape;
	CCircle -> CShape;
	CTriangle -> CShape;
}
음... 상속까지 받았는데 뭔가 부족하다.
상속받은 클래스끼리 묶어서 그룹을 만들어 주자.
digraph Shape
{
	node [ shape = "record" ];
	edge [ arrowhead = "empty" ];
	
	CShape [ label="{CShape||+ draw() : void\n}" ];
	
	subgraph clusterDerivedObjectsFromCShape
	{
		label = "Derived Objects From CShape";
		
		CRect [ label="{CRect||+ draw() : void\n}" ];
		CCircle [ label="{CCircle||+ draw() : void\n}" ];
		CTriangle [ label="{CTriangle||+ draw() : void\n}" ];
	}
	
	CRect -> CShape;
	CCircle -> CShape;
	CTriangle -> CShape;
}
 
그룹핑을 하기 위해서 중요한 사항은 다음과 같다.
subgraph clusterXXX <-- cluster라는 이름으로 subgraph를 만들어야 한다.
{
    그룹으로 묶어줄 node들.
}
위와 같이 적용하면 그룹도 묶을 수 있다.

음... UML은 다 만들었는데... 꺼꾸로 뒤집혀 있어서 참 애매하다.
graphviz 는 항상  -> 화살표 방향으로 rank(순위)가 표현되기 때문에 CShape가 아래로 내려올 수 밖에 없다.
( <- 역방향 연산자는 지원하지 않는다. -_-; )

그렇다면 꺼꾸로 뒤집으면 될꺼 같은데... 다음과 같이 수정하면 된다.
digraph Shape
{
	rankdir = "BT"
	node [ shape = "record" ];
	edge [ arrowhead = "empty" ];
	
	CShape [ label="{CShape||+ draw() : void\n}" ];
	
	subgraph clusterDerivedObjectsFromCShape
	{
		label = "Derived Objects From CShape";
		
		CRect [ label="{CRect||+ draw() : void\n}" ];
		CCircle [ label="{CCircle||+ draw() : void\n}" ];
		CTriangle [ label="{CTriangle||+ draw() : void\n}" ];
	}
	
	CRect -> CShape;
	CCircle -> CShape;
	CTriangle -> CShape;
}

rankdir = BT 랭크 방향을 Bottom -> Top으로 꺼꾸로 뒤집으니 좀더 보기 좋은 그래프가 완성되었다.
Top = T
Bottom = B
Left = L
Right = R

위와 같이 상하좌우 방향을 바꿀 수 있으므로 각각의 옵션을 조절하면 된다.
2010/06/13 01:56 2010/06/13 01:56

덧글을 달아 주세요