이번은 저번 포스팅에 이어서, 남은 요소들과 관계에 대해서 설명 하려고 해요.
이야기 했다시피, 제가 현재 진행하고 있는 프로젝트로는 설명이 안되는 부분이 많아서 임의의 예시를 두었어요. 프로그래밍 업종에 종사하시거나 관련 전공을 배우시는 분들이 많이 볼 것 이라고 예상하지만 예시는 굉장히 일반적인 걸로 두었어요.(그래서 포스팅 준비하는데 시간 좀 걸렸네요 :D 절대 놀지 않았답니다!!)
예시가 적절치 않거나 틀렸거나 질문이 있으신 분들은 댓글을 달아 주시면 답글 바로 답니다 :) 저도 공부하면서 하는 입장이라서 잘못된 부분이 있을 수도 있으니까 함께 해요 ^^
전체 결과(box1)
클래스 요소를 만드는 것에 대해서는 저번 포스팅에서 상세히 언급 했으니까 대충 아실 거에요. 관계 부분이 상당히 난해 한 것들이 많지만 차근차근 제가 이해 한 대로 설명 할 게요.
-
인터페이스(Interface)
인터페이스라고 하는 것은 완전 추상화 객체에요. 이 포스팅은 UML 설계에 관련된 거라서 해당 부분에 대해서는 구체적으로 기술 하지는 않을 거지만, Java나 객체지향 설계 관련된 내용을 보시면 보다 많은 정보를 얻을 수 있을 거에요 :)
하지만 모르는 분이 계시면 설명이 이해가 되지 않을 테니까 썰만 풀고 넘어 갈게요.
프로그래밍 구현 상에 있어서 "선언"만 되어 있는 거라고 보시면 되요. Java는 아예 Interface라는 객체가 있어서 별로 상관 없지만, C++에서는 virtual 클래스가 대신 할 거 같네요.(아아.. 하나를 설명하면 하나의 설명거리가 더 늘어나는 프로그래밍의 세계여..ㅠㅠ)
코드로 풀어 쓰면 아래와 같은 형식이 될 거 같네요 :)
class cppInterface { public: virtual void DoSomething() = 0; // 가상(virtual) 소멸자를 만들지 않으면 메모리 누수가 발생 virtual ~cppInterface(){} };
그럼 위의 클래스(C++에서는 클래스로 인지하지만, 자바에서는 Interface라는 이름 그대로의 객체로 사용됩니다. 착오 없으시기 바래요^^)를 상속받는 자식 클래스에서는 저 내용을 "구현"({}안에 내용이 들어가는 거) 해야 겠죠.
보통은 "~를 할 수 있다"라는 의미의 내용을 많이 사용 해요(꼭 그렇게만 써야 한다는 의미는 아니에요).
생성하는 방법은 다른 요소들과 다르지 않으니 참고 하시길 바래요 :)
// 편의상 한글 변수와 한글 함수를 사용 하겠습니다. class 사냥할수있다 { public: virtual ~사냥할수있다(){} virtual void 사냥하다(포유류 임의동물) = 0; };
메인 윈도우에서의 인터페이스(Interface) 요소는 가지고 있는 변수(Attribute)나 함수(Operation)이 표기 되지는 않네요. 저는 그리는 대에만 사용 할 거기 때문에 그다지 상관은 없지만 나중에 code로 변환하는 기능을 사용 해야 하면 입력을 일일이 해야 하지 않을까 싶어요 :)
-
포트(Port)
인터페이스(Interface)를 생성 했는데 구현되는 내용을 임의의 클래스 요소가 가지고 있을 텐데 이러한 진입점으로 사용되는 것이 포트(port)라는 요소에요.
사실 포트에 대한 예시를 본건 컴퓨터 관련 내용 이었지만 현재 예시에서 끌어 내보려고 하는데 맞는 건지는 모르겠어요@_@
그리고 저러한 예시에서는 포트의 요소가 클래스의 맴버변수(Attribute)로 들어가 있어야 맞을거 같아요:)
육식동물과 사람은 다른 포유류를 사냥 할 수 있어요. 하지만 둘의 사냥 방법은 다르겠죠? 표현 방법에 따라서 포트(port)요소를 사용하기도 하고 그냥 연결 하기도 하는데 그 두 가지 표현을 모두 그려 봤어요.
인터페이스에서의 설명을 보면 알 수 있겠지만, "사냥하다"라는 함수(Operation)이 있잖아요. 각각의 객체가 사냥 하는 방법에 대해서 구현 하면 될거 같아요.(여기에서는 UML에 구지 가상함수(virtual function)까지 적진 않았지만 적어놓으면 더욱 확실하게 알아보기는 좋겠죠? :D)
인터페이스와 연결 시키는 부분은 실체화 부분을 먼저 참고 하세요 :)
-
연관(Association)
연관이라는 것은 클래스 요소가 서로를 참조 할 수 있다는 거에요. 이 부분은 제가 생각 할 때, reference라는 의미보다는 cooperates 라는 의미가 더욱 와닿을 거 같아서 저렇게 표기해 뒀어요.
물론 "협력"이라는 말이 반드시 긍정적인 의미는 아니에요. 하지만 완전히 단어 자체에서 오는 의미적인 표현 보다는 단순히 논리적으로만 따졌을 때 두 개의 "클래스"가 서로 어떠한 "처리"를 위해서 "협력" 한다라는 의미로 접근해야 해요.
코드상으로는 맴버 변수로서 가지고 있을 수도 있고, 단순히 어떠한 함수의 인자로만 사용될 수도 있고, 함수 내부적으로 일을 처리 할 때 사용 될 수도 있어요. 정말 말 그대로 포괄적인 관계를 의미하는 거에요:)
좀 더 디테일한 관계에 대해서는 다른 요소들이 있으니까 그렇게 구분지을 수 없을 때 사용 하는거 정도?ㅎㅎ 로 보면 될 거 같아요.
무슨 관계인지 명확하지 않을 때는 대부분 연관(Association)으로 표기를 하는게 정신적 스트레스를 받지 않는 다고 해요.
-
직접 연관(DirectedAssociation)
이 관계는 완전 일방적인 관계에요. 저는 이 관계를 화살표가 시작되는 요소(사람)이 화살표를 받는 요소(식기구)를 조정한다(control) 라고 표현 했어요. 프로그래밍 측면에서 봤을 때는 command 라는 표현이 맞을 거 같지만, 의미론적으로 접근한 용어 선정을 해봤어요.
사람은 식기구에 대해서 일반적으로 사용 하지만, 식기구의 입장에서는 누가 자신을 사용하고 있는지에 대해서는 "저---언혀" 알 필요가 없는 상태이죠.
보통은 맴버 변수로 사용되지만, setter 함수에 의해서 변경 될 수 있는 요소에서 많이 사용 된다고 하더라구요.
코드로 보면 아래와 같이 표현 가능 해요.
저는 다이어그램에 getter, setter는 표기 하지 않는 성향이 있어요. 어떠한 다이어그램이다 하더라도 핵심적인 매커니즘이나 없으면 설명이 되지 않는 요소들을 다른 사람에게 효과적으로 전달하고자 하는 목적이 있는데, 너무 당연히 있어야 되는 그런 내용까지 적어가면서 중요한 부분 외적으로 신경을 쓰게 만들 필요는 없겠죠? :D
class 사람 { private: 식기구 myFoodTool; public: void 식기구를바꾸다(const 식기구 &_something) { myFoodTool = _something; } };
-
집합(Aggregation)
컴퓨터 용어가 보통 있는 그대로 가져다 쓰는게 제일 확실해서 별도의 직역이 잘 되어 있지 않아서 사전에 있는 내용을 그냥 가져다가 썼어요.
집합이라는 의미의 어그리게이션(Aggregation)은 어떤 클래스가 활동하는데 필요로 하지만 언제든지 바꿔서 사용 할 수 있다는 의미라고 보면 되요. 바로 좀 전의 연관(Association)이랑 비교를 하자면 그럴거 같아요. 물론, 다중성으로 "'0..' 으로 표기해서 없어도 상관 없다." 이렇게 할 수도 있지만요.
사람은 옷을 필요로 하기 때문에 가지고 있어야 하지만(멤버변수(Attribute)로서), 옷은 갈아 입을 수도 있고, 속옷, 하의, 상의, 모자, 외투, 등등 1개 이상 가지고 있어야 하니까 아래와 같이 표현 했어요.
-<> 방향대로 읽어 본다면 "옷은 사람의 한 부분이다" 라는게 되겠죠.(옷 is part of 사람.)
그리고 방금전의 직접관계(DirectedAssociation)에 의하면 사람은 옷을 일방적으로 사용하는 입장이고 옷의 입장에서는 누가 자신을 사용했지는 신경을 전혀 쓰지 않는게 되죠. 그래서 보통은 집합(Aggregation)과 직접연관(DirectedAssocation)은 저런식으로 같이 사용 하게 되요.
이걸 코드로 구현하게 되면 아래와 같은 식으로 적을 수 있을거에요.
class 사람 { private: 식기구 myFoodTool; std::vector<옷> 입을거; public: 사람() {입을거.push_back(속옷);} // 실제 UML에서는 표기하지는 않은 // 예시를 위한 함수 입니다. void 옷을추가한다(const 옷 &_어떤옷); bool 옷을뺀다(const size_t &_몇번째옷); bool 옷을뺀다(const 옷 &_어떤옷); };
애초에 "한 개 이상의 옷은 무조건 가지고 있다"라는 다중성이 명시가 되어 있기 때문에 생성자에서 속옷 하나는 무조건 주었어요. 저 속옷이라는 변수는 어딘가에 const static 변수로 존재하는 거겠죠? :)
(코드에 대한 부분을 마구 짚지는 마세요~ 예시를 위해서 잠깐 써놓은 거니까 신경을 막~~ 쓰지는 않아도 되요.)
두 가지 방법을 각각 적용해 보면 위와 같은 결과를 얻을 수가 있어요.-
집합 그리기
-
직접연관 그리기
다중성(Multiplicity)을 입력하는 경우가 있으니까 한번만 설명 하고 넘어 갈게요.
- 다중성(Multiplicity)이 필요한 요소(현재 예시에서는 해당 선분)를 마우스 좌클릭 한다.
- 속성창(Properties)중에서 다중성(Multiplicity)를 주어야 하는 요소의 이름이 되어 있는 부분을 확인 한 후 옵션중 End#.Multiplicity 의 우측에 입력 필드를 마우스 좌클릭 한다.
- 원하는 수치를 클릭하거나 직접 입력한 후 엔터를 입력한다.
-
-
구성요소(Composition)
예시에서 보다시피 모든 포유류는 눈이 두 개 있어요. 그리고 이 눈 두개는 날 때부터 가지고 있고, 다른 개체를 입력해서 대채 할 수 있는 요소가 아니에요.
다른 인스턴스(instance)로 넣을 수가 없다는 거지 상태를 바꿀 수 없는 부분은 아니에요. 여기에서 구현은 하지 않았지만, 테레비를 많이 본다든가 하는 상태를 주게 되어서 소유하고 있는 눈의 건강상태가 나빠지는 "상태 변화"는 있을 수 있지만, 현재 자신이 가지고 있는 눈을 빼서 다른 눈으로 "교체" 한다는 상태는 없으니까요.(의료기술 드립은 자제 해주세요 :Dㅋㅋㅋ)
코드상으로는 setter가 존재 할 수 없다는 의미가 되요. getter의 경우는 가능 하죠. (방금 예시로는 눈을 빼서 가져오는게 아니라 CT촬영 즈음으로 내가 가진 눈의 상태를 체크한다 이런 의미로 말이죠.)
표현 방법은 집합(Aggregation)과 모양은 같지만, 아주 강한 정도를 가지고 있기 때문에 시꺼멓게 색칠을 한 모양이에요. 물론 포유류는 눈을 control 할 수 있으니까 직접연관(DirectedAssociation)을 같이 표기하게 되죠.
개인적으로는 1 짜리는 표기를 하지 않아요. 위의 예시에서는 포유류 하나당 눈은 두 개씩 가지고 있는 거니까 포유류 쪽의 '1'의 다중성은 표기 하지 않은 거 처럼요.
그럼 날 때부터 정해지는거니까 코드상으로는 생성자에서 만들어 지게 되는 거죠.
class 포유류 { private: 눈 myEye[2]; public: 포유류() { myEye = new 눈[2]; } // 예제상 눈에 관련된 함수(Operation)를 몇 개 넣어보자면, void 눈의상태가좋아진다(); void 눈의상태가나빠진다(); // 같은게 있을 수가 있겠죠 // 만약 아래와 같은 함수가 있다면, void 눈이식(const 눈 &_다른눈); // '눈' 이라는 요소는 이미 집합(Aggregation)으로 // 바뀌게 되겠죠? :D };
만드는 거는 생략 할게요, 직접 한번 만들어 보세요:)
-
일반화(Generalization)
유즈케이스 다이어그램(Usecase Diagram)에서도 보았듯이 상속에 관한 부분 이에요. "is a"의 개념으로 사용 하면 되는 요소이죠.
예제는 몇 개의 상속 파트로 나눠져 있는데, 이 부분은 굉장히 많이 사용되요. 구현상에 있어서는 뼈대가 되는 클래스를 만들어 놓고 그것으로 부터 약간씩 다른 파생(자식) 클래스들을 만들어서 사용 하게 되는 경우가 많은 거에요.
예제에서 보면,
사람은 포유류 이다.(사람 is a 포유류)
(사실, 동물이 포유류 이긴 하지만, 별도로 한번 더 나눠봤어요:D) 동물은 포유류 이다.(동물 is a 포유류)
초식동물은 동물이다.(초식동물 is a 동물)
육식동물은 동물이다.(육식동물 is a 동물)
수저는 식기구이다.(수저 is a 식기구)
젓가락은 식기구이다.(젓가락 is a 식기구)
생성과정은 어떻게 하는지 딱 봐도 아시겠죠? :D
-
의존(Dependency)
다른 많은 설명들이 있는데, 저는 그냥 간단하게 "use a" 라는 걸 붙여서 되는 것으로 생각해 버렸어요.
구현 상 맴버변수는 아니면서 함수(Operation)의 인자(Parameter) 또는 함수내에 지역변수로 사용 되는 객체들이라면 의존(Depndency)라고 생각하시면 되요.
포유류 클래스는 "먹을거" 클래스를 인자로 사용하기 때문에 의존(Dependency)관계에 있게 되고, 앞서 얘기한 동사를 넣어서 보면 "포유류는 먹을거를 사용한다."라는 얘기로 풀어 쓸 수 있는거죠~
이 때, "먹을거" 라는 클래스의 변수(Attribute)나 함수(Operation)가 바뀌게 되면, 당연히 포유류에 영향이 미쳐지겠죠.
물론 집합(Aggregation)이나 구성(Composition) 관계 역시 클래스가 바뀌면 영향을 받지만, 맴버변수(Attribute)로서 집합관계가 명확하게 떨어지는 거라서 다른 의미로 사용 되는 거구요.
-
실체화(Realization)
실체화를 알기 위해서는 추상적이다라는 개념을 알고 넘어갈 필요가 있어요. 일반화와 비슷합니다만 "확정 되지 않은 거!" 라고 생각 하는 게 제일 좋을 거 같아요.
공부하는 와중에 아래와 같이, 같은 예시였는데 접근 방법에 따라 표현 역시 달리 하는 거를 봤어요.
뭐가 맞다, 틀리다는 없어요. 그냥 '다를 뿐' 인거죠. 개념(Concept)이 어떠냐에 따라서 둘 다 맞는 방식이 되니까요.
저는 이 관계를 "is came from"이라고 생각해요.
어찌보면 '어원' 같은 거죠. '현재' 사용되고 있는 말은 완전 실체화 되어진거고, 그 말은 '과거'에 우리가 단순히 상상으로만 존재하는 것으로 부터 왔던 거다. 라는 접근이에요. is made of 라고 생각했지만 좀 더 추상적인 거에 가까운 느낌의 단어를 골라 봤어요 :)
구현 상에 있어서 차이점 역시 있지만, 일단 다이어그램 상에서의 차이점만 보자면, 실선이 아닌 점선으로 표기가 되요. 화살표를 받는 추상적인 개념은 기울임체로 표기 되는 거죠.
풀때기는 먹을거로 부터 왔다.
꼬기는 먹을거로 부터 왔다.
C++ 에서는 interface와 abstract class가 별도로 구분 된거는 아니기 때문에 코드는 인터페이스(Interface) 부분을 참고 하세요 :D
-
관계 클래스(AssociationClass)
여태까지 많은 관계에 대해서 알아봤는데 이러한 관계가 새로운 클래스로의 관계로 표현 될 수 있을 때 사용되는 요소가 관계 클래스(AssociationClass)라고 해요.
- 툴 박스(Toolbox)에서 관계클래스(AssociationClass)를 마우스 좌클릭 한다.
- 메인윈도우(Main window)에서 원하는 요소(여기서는 "애완동물")를 마우스 좌클릭 한 후, 원하는 요소(여기서는 "사람"과 "초식동물"간 연관(Association))까지 마우스를 드래그 한다.
-
마우스 좌버튼을 땐다.
그럼, 사람과 초식동물간에 새로운 클래스가 관계클래스(AssociationClass)가 형성이 되요.
초식동물은 사람과 그 자체만으로 이미 연관(Association) 관계에 있지만, 특별히 애완동물로서 관계를 가질 수 있다는 거죠. 다른 예시로 회사와 사람간에 직업이라는 관계도 있어요 :)
신호(Signal)과 예외(Exception)는 클래스 요소간에 주고받는 요소를 클래스화 되어서 오고 갈 때를 위한 요소에요. 이 부분은 디테일 한 설명을 요할 때 사용하는 거라서 별 다른 설명없이 넘어가도록 할게요.
오브젝트요소는 하나의 클래스가 변수로 사용 될 때, 표기하는 요소에요. 클래스라는게 그 자체로 쓰이는게 아니라 데이터타입의 하나로 변수를 만들어서 사용 하는거니까, 이 역시 디테일한 설명을 할 때 사용 되는 요소에요. 자세한 설명은 생략~ ;9
'Programming > Architecture' 카테고리의 다른 글
05 Sequence Diagram (2) | 2012.07.14 |
---|---|
04 Statechart Diagram (2) | 2012.07.10 |
03 Class Diagram 1 (0) | 2012.05.26 |
02 Activity Diagram (0) | 2012.05.10 |
01 UseCase Diagram (3) | 2012.04.29 |