개요

 

UML@Classroom[1]의 Chater 4의 9절에 있는 Information System of a University의 예를 본다. 여기서는 요구 사항에서 Class Diagram을 추출하는것을 살펴 볼 수가 있다. 실제 예에서 볼 수 있는 몇가지 테크닉도 포함하고 있으므로, 참고할 만하다.

 

여기서 사용하는 절차는 요구 사항에서 클래스(Class)를 추출하고, 각 클래스의 속성을 추출한다. 그리고, 마지막으로 클래스 간의 관계를 설정하며 Class Diagram을 완성한다. 이를 한번에 완성하는 것으로 여기서는 설명하고 있지만, 잘 보면 한번에 나온다기 보다는 몇번의 반복을 통해서 완성 되는것이 맞아 보인다. 우선은 여기서는 최종 결과물만을 가지고 설명한다.

요구 사항

책에 포함되어 있는 요구사항까지 번역하는 것은 효용성이 떨어진다. 물론, 한글로 되어 있는 요구사항에서 이를 추출하는것은 또 다른 이야기가 될 수 있다. 하지만, 책의내용을 이해하기 위해서 번역하는 것도 이해도를 떨어 뜨릴 수 있다. 그러므로, 여기서는 우선 요구 사항을 그대로 두고, 살펴 보도록 하자

.

다음이 책에 있는 영문 요구 사항이다.

  •  A university consists of multiple faculties which are composed of various institutes. Each faculty and each institute has a name. An address is known for each institute.
  •  Each faculty is led by a dean, who is an employee of the university. 
  •  The total number of employees is known. Employees have a social security number, a name, and an e-mail address. There is a distinction between research and administrative personnel. 
  •  Research associates are assigned to at least one institute. The field of study of each research associate is known. Furthermore, research associates can be involved in projects for a certain number of hours, and the name, starting date, and end date of the projects are known. Some research associates teach courses. They are called lecturers.
  •  Courses have a unique number (ID), a name, and a weekly duration in hours. 

 

클래스 추출

첫째, 우리는 클래스를 식별 시스템 대학에서 발생하는 요소를 식별해야합니다. 이것들은 아래 그림과 같다. 요구 사항 중에서 명사로 되어 있는 것들을 추출하면 된다.

  •  A university consists of multiple faculties which are composed of various institutes. Each faculty and each institute has a name. An address is known for each institute.
  •  Each faculty is led by a dean, who is an employee of the university. 
  •  The total number of employees is known. Employees have a social security number, a name, and an e-mail address. There is a distinction between research and administrative personnel. 
  •  Research associates are assigned to at least one institute. The field of study of each research associate is known. Furthermore, research associates can be involved in projects for a certain number of hours, and the name, starting date, and end date of the projects are known. Some research associates teach courses. They are called lecturers.
  •  Courses have a unique number (ID), a name, and a weekly duration in hours. 

 
아래 결과에서 보면, 대학(University)은 별도의 Class가 아니다. 이는 잊어 버린 것이 아니라, 의도적으로 포함시키지 않은 것이다. 책에서는 대학을 Class Diagram으로 설명하고 있다. 그래서, 모델의 인스턴스에는 대학 내에서 발생하는 객체 (예 : Vienna University of Technology)에 포함된다고 볼 수 있으므로 제외한다고 보면 된다.

 

Dean (학과장)의 경우도 Class 추출에서는 자세한 설명이 없지만, 의도적으로 빼 놓고진행한 것으로 보인다. 이는 역할(Role)의 특성이 강한 것으로 보고있다. 즉, Faculty의 속성으로 볼 수 있지만, 결국에는 Class의 관계들을 설명하면서 추가한다.

 

인식된 Class들

속성 추출 (Identifing Attributes)

이제 속성을 사용하여 클래스를보다 자세히 설명 할 수 있다. 클래스의 속성은 아래 그림에 나타나있다.각 속성은 데이터 유형(Data Type)을 가지고 있다. 아래 요구 사항에 서 보이듯이 추출된 클래스의 속성도 클래스의 특징을 나타내는 명사로 추출 될 수있다.

 

  •  A university consists of multiple faculties which are composed of various institutes. Each faculty and each institute has a nameAn address is known for each institute.
  •  Each faculty is led by a dean, who is an employee of the university. 
  •  The total number of employees is known. Employees have a social security numbera name, and an e-mail address. There is a distinction between research and administrative personnel. 
  •  Research associates are assigned to at least one institute. The field of study of each research associate is known. Furthermore, research associates can be involved in projects for a certain number of hours, and the namestarting date, and end date of the projects are known. Some research associates teach courses. They are called lecturers.
  •  Courses have a unique number (ID)a name, and a weekly duration in hours

 

또한 모든 속성의 공개 여부를 공개(Public)로 설정 했으므로 이 단계에서는 외부에서 볼 수있는 속성과 그렇지 않은 속성을 생각할 필요가 없다. Employee 클래스의 속성 counter는 해당 값이 인스턴스에 속하지 않으므로 클래스 속성으로 정의된다. 이 속성은 Employee 클래스의 인스턴스가 생성 될 때 증가힌다.

연구원(Research Employee)의 프로젝트 참여시간도 속성이 될 수 있지만, 여기서는 포함하지 않고 나중에 관계 연계 시킬 때 최종 처리하기는 한다.

 

 

속성(Attributes) 추출

 

클래스 간의 관계 인지 (Identifying the relationship between classes)

클래스간의 관계를 추출하는 방법을 책[1]에서는 2가지로 설명하고 있다.

  • 일반화(Generalizations)
  • Associations and Aggregations

 

Generalization의 관점

결국, Administrative Employee와 Research Associate가 Employee의 더 상세한 구체화 이기 때문에 추상 클래스로 만들수 있다. 그리고, 교수(Lecturer)도 Research Associate의 일종이므로 Generalize된 것이라 볼 수 있다. 특히, 아래 요구사항 중 줄 친 항목들이 이 관계를 설명한다고 볼 수 있다.

 

 

  •  A university consists of multiple faculties which are composed of various institutes. Each faculty and each institute has a name. An address is known for each institute.
  •  Each faculty is led by a dean, who is an employee of the university. 
  •  The total number of employees is known. Employees have a social security number, a name, and an e-mail address. There is a distinction between research and administrative personnel
  •  Research associates are assigned to at least one institute. The field of study of each research associate is known. Furthermore, research associates can be involved in projects for a certain number of hours, and the name, starting date, and end date of the projects are known. Some research associates teach courses. They are called lecturers.
  •  Courses have a unique number (ID), a name, and a weekly duration in hours. 

 

 

Generalization

Associations and Aggregations

이 단계가 마지막 단계로 볼 수있고, 완성된 클래스 다이어그램이 아래와 같다. 줄 친 부분들이 이러한 관계들을 설명한다고 볼 수 있다.

 

  •  A university consists of multiple faculties which are composed of various institutes. Each faculty and each institute has a name. An address is known for each institute.
  •  Each faculty is led by a dean, who is an employee of the university. 
  •  The total number of employees is known. Employees have a social security number, a name, and an e-mail address. There is a distinction between research and administrative personnel. 
  •  Research associates are assigned to at least one institute. The field of study of each research associate is known. Furthermore, research associates can be involved in projects for a certain number of hours, and the name, starting date, and end date of the projects are known. Some research associates teach courses. They are called lecturers.
  •  Courses have a unique number (ID), a name, and a weekly duration in hours. 

 

 

완성된 클래스 다이어그램

 

결론

책에서의 결과물도 좋은 결과물이기는 하지만, 다른 견해가 있을 수 있다는 단서를 달아 놓고 있다. 즉, 정답은 없을 수 있다는 것이다.

 

참고 문헌

[1] UML@Classroon: An Introduction to Oject-Oriented Modeling 2015 Springer

 

 

개요


Factory Pattern은 Creational Pattern 중의 하나이다. 아래은 GoF의 Design Pattern Categorization이다. 여기서 Purpose는 Design Pattern의 목적과 관련된 것이다. 즉, Creation은 Class의 생성에 관련된 것이고 Structure는 Object 구조에 대한 것이고, Behavior는 Object의 동작에 관한 것이다. Scope은 Design Pattern이 적용되는 범위이다. 즉, Class의 경우는 class들 같으 관계에 관한 것으로 static하고 compile-time에 결정이 된다. 하지만, Object의 경우는 Object간의 관계에 관한 것이고 더 Dynamic하다.





여기서는 Factory Method에 대해서 살펴 보자. Factory Method은 Creational 이면셔 Class에 적용되는 패턴이다. 


Head First의 이야기

Head First[1]에서는 Pizza Restaurant를 예를 들어 Factory Method를 설명한다.


이야기 한데로, Head First에서는 Pizza 가게의 예를 들어 Design Pattern을 설명한다. 이야기의 흐름은 다음과 같다. 우선 Pizza를 주문하는 Method(orderPizza)를 생각해 보자. Pizza Instance를 생성하고, 준비(prepare), 굽고(bake), 자르고(cut), 포장하고(box) 그리고 완성된 Pizz를 제공하는 것이라고 하자. 그런데,리고, Pizza의 종류 또한 여러 가지가 될 수 있다. 여기서는 cheese, pepperoni, veggie와 같이 Pizza가 늘어 날 수록 orderPizza에서는 종류에 따라 다르게 생성하고 이를 추가해야 한다. 즉, Pizza가 추가 될 때마다 orderPizza가 계속 영향을 받게 된다. 그렇게 하기 위해서 다음 2가지를 수행해야 한다.

1. Pizza를 Abstraction한다.  (Pizza Abstract Class)

2. prepare, bake, cut, box를 지원하는 concrete pizza를 구현한다. (Concrete Pizza Classes)

3. Creation하는 부분을 분리한다. (Factory Method Class)


Class Diagram으로 표시하면 아래와 같은 구조가 된다. 여기까지가 Simple Factory이다. Factory까지 추상화 해야 Factory Method가 된다.



이제 이 장사 잘 되는 Pizza가게를 프렌차이즈로 만들어 보자. 하지만, 이 피자가게가 모두 같지 않고 지역별로 조금씩 특징이 있을 수 있다. 예를 들자면, New York, Chicago, California등이 그 예이다. 그러면, 이 Factory의 경우도 Abstraction이 필요하다 


여기까지 구현한 것이 Factory Method이다. 그래서, 아래와 같은 Class Diagram을 가질 수 있다.




GoF DP의 요약 과 Quick Reference

GoF 책[2]에서 설명하는 의도는 "하나의 object를 생성하려는 interface를 정의한다. 그리고, subclass가 어떤 class가 instantiate될지 결정하게 한다. 즉, Factory Method는 하나의class가 subclass들의 생성을 분리(defer)한다."라고 되어 있다. [3],에서 해당하는 class diagram은 아래와 같다. 사실 같은 내용이다.




관련 Object-Oriented Principle

Factory Method가 관련된 SOLID Principle은 Dependency Inversion Principle라고 할 수 있다. DIP에서 많이 드는 예는 Layered Architecture에서 하위 Interface를 상위에스 Reference하게 만드는 것이다. 아래의 예에서 상위 Layer는 하위 Layer에 Dependency를 가진다. 즉, 하위 Layer가 변경되면 상위 Layer도 영향을 받게 된다. 어떻게 이 Dependency를 끊을 수 있을까? 아래 그립과 같이 하위 Layer의 Interface를 만들어 상위 Layer에 두는 것이다. 즉, 하위 Layer가 상위 Layer에 Dependency가 생겨서 Inversion이 생겼다. 이 구조에서는 하위 Layer의 구조가 상위 Layer의 Interface에 제약되므로 이를 벗어날 수 없다. 아이러니하게도 상호 종속되어 나빠질 것 같지만, 서로에 약속에 의해서 제약된 것 이외에는 자유로워 졌다.



Factory Method에서는 Product와 Creator가 하위 Layer로 볼 수 있다. 그러므로 이것들의 Abstract인 Interface를 활용하면 이를 사용하는Client와 Product, Creator를 Loosely Coupling하게 할 수 있다.


References

[1] Eric Freeman and Elsabeth Freeman, "Head First Design Patterns," OReilly

[2] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, "Design Patterns: Elements of Reusable Object-Oriented Software," Adisson-Wesley

[3] Design Pattern Quick Reference: http://www.mcdonaldland.info/2007/11/28/40/

시작하며

Refactoring은 1999년의 Martin Fowler의 책[1]에서 소개 된 후, 계속 이야기 되고 있는 개념이다. Design Pattern과 같이 하나 하나 필요한 사례를 익히는 것도 시간이 걸리고 이를 실제로 활용하는데도는 더 많은 시간이 필요하다. 크게는 간단한 정의 및 Bad Smell에 대해서 살펴 본다. 실제 Technique은 옆에 두고 참고하기 위해서 따로 정리하였다.


정의

Refactoring은 Martin Fowler[1]가 제안한 코드 품질 향상 혹은 재설계의 방법이라고 할수 있다. Refactor라는 단의의 정의는 명사 및 동사의 의미를 가진다고 한다.


명사: a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.

동사: to reconstruct software by applying a series of refactoring without changing its observable behavior


즉, 존재하는 코드를 기능의 변화 없이 안전하게 디자인을 향상 시키는 기법이다. 기능을 추가하면서도 Refactoring을 할 수 있기는 한다. 이는 구조가 변화 해야 하므로 기능을 변화 시키지 않고 변형을 하여 테스트를 하여 문제가 없다는 것을 확인한 후에 거기에 기능을 추가하는 방법이 적절하다.


어떻게 수행하는 하는가? 우선 Band Smell을 찾는다. 이것이 Refactor해야 하는 부분으로 인지하고 Refactoring을 적용하는 것이다.


[1]의 2nd Author인 Kent Beck의 Test Driven Development에서 Test를 수행하면서 개선하는 방법을 제안한다. 이것에 대한 이야기는 다음에 기회를 보아 살펴 봐야겠다.


Bad Smell

Refactoring을 해야 하는 시작점으로 볼 수 있다. 즉, 설계의 문제점이나 심각한 문제점의 조짐이라고 볼 수 있다. 이것들은 Martin Fowler 책에서 소개 된 것들이지만, 분류는 [2], [3]에 따른 것이다. (M)은 Martin Fowler의 책에 소개된 항목들이고 나머지들은 다른 항목들이다.



Bloaters

부풀어 오름이라고 번역이 가능할 것 같다. 즉, 일반적이거나 정상적이지 못하게 커지거나 길어진 상태라고 보면 되겠다.

. Long Method: 말 그대로 Method가 너무 길어진 형태이다. 이를 나누거나 줄이는 작업이 필요하다.

. Large Class (M): 큰 Class이다. Responsibility가 여러 개가 들어 있을 수도 있다. 또한 중복 코드가 포함되어 있을 수 있다.

. Primitive Obsession (M): Object를 사용하기 보다는 Primitive Data를 사용하는 경우가 있다. 이를 Object/Class로 만드는 것이다. Class를 추출("Extract Class")하거나 Parameter 객체를 도입("Introduce Parameter Object")하거나 어레이를 객체로 치환("Replace Array with Object") 할 수 있다.

. Long Parameter List (M): 매개변수(Parameter)가 간결한 것은 이해하는데 큰 장점이다. 만일 데이터가 객체로 부터 나오는 것이면 객체를 전달("Preserve Whole Object")를 수행하거나 Parameter 객체를 도입("Introduce Parameter Object")를 수행할 수 있다.

. Data Clumps (M): [1]의 한국어 버전에는 데이터 뭉치로 번역이 되어 있다. Class 내에서 3~4개 이상의 데이터 항목이 뭉쳐 다니는 경우가 있다. 이런 경우는 Class 추출("Extract Class")을 수행하거나 Parameter 객체 도입("Introduce Parameter Object")를 수행할 수 있다.


Object-Oriented Abusers

Object-Oriented 개념이 잘 적용되지 못한 경우들이다.

. Switch Statements (M): switch문이 꼭 나쁜 것은 아니지만, Object-Oriented에서 확연히 줄어드는 것이 특징이다. switch문은 코드 중복을 만들기 쉬우므로 이를 Polymorphism등으로 제거하는 방법을 고려할 수 있다. 또한 긴 if 문도 코드 중복등이 있을 수 있다. Method 추출("Extract Method") 혹은 Method 이동 ("Move Method") 또는 복잡한 형태로 Subclass로 Type Code를 치환("Replace Type Code wit Subclass)하거나 State/Strategy로 Type Code를 치환("Replace Type Code with State/Strategy)하는 방법이 있을 수 있다.

. Temporary Field (M): 임시 변수로 중간 결과를 가지고 다른 동작이나 판단을 하는 코드의 경우이다. 이는 Method 추출(Extract Method)를 통해서 임시 변수를 대체 할 수 있다.

. Refused Bequest (M): 거부된 유산. Martin Fowler 책의 번역본에는 방치된 상속물이라고 번역되어 있다. 즉, Inheritance를 했지만, 실제로 Superclass의 Method들이 사용되지 않는 경우이다. 즉, 잘못된 계층 구조 때문일 수 있다. 이때는, Superclass의 변형을 고려하거나 Delegation 관계로 바꾸는(Replace Inheritance with Delegation)을 고려할 수 있다.

. Alternative Classes with Different Interfaces: 비슷한 역할의 Class이지만 제공하는 Interface가 다른 Class들인 경우이다. 같은 기능을 하는 Method들의 이름을 통일 시키고, 피요한 경우에는 Superclass를 추출해 내는 것이 필요하다.

Change Preventers

변화 방해 요인으로 볼 수 있다. 

. Divergent Change (M): 하나의 Class가 다양한 원인으로 인해 수정되는 경우이다. 이는 Single Responsibility Principle을 위배했을 가능성이 높다. 그러므로 Class를 분리("Extract Class")를 고려하는 것이 좋다. 

. Shotgun Surgery (M): Divergent Change와 유사해 보인다. 하지만, 반대의 개념으로 하나를 수정하려고 하는데 수정이 산발적으로 여러 곳에서 일어나는 경우이다. 이는 Method나 Member 변수의 위치가 적절하지 못하다고 볼 수 있다. Method를 이동("Move Method")하거나 Field를 이동("Move Field")를 수행할 수 있다.

. Parallel Inheritance Hierarchies (M): 한 Class의 Subclass를 만들 때 마다, 매번 다른 Class의 Subclass를 만들어야 하는 상황이다. Shotgun Surgery의 특수항 경우라고 볼 수 있다. Shotgun Surgery와 유사하게 Move Method와 Move Field를 활용한다.

Dispensables

말 그대로 불필요한 것들이다. 

. Comments (M): Method에 설명을 위한 코멘트가 많이 달려 있는 것이다. 코멘트 보다는 코드가 자실을 잘 설명하도록
Refactoring나는 것이 좋다. 코멘트는 코드의 원리 혹은 무엇을 해야 할지 확실하지 않은 경우에 표시하는 정도가 좋다.

. Duplicate Code: 중복된 코드는 공통 부분으로 추출하여 Method로 만드는 것이 좋다.

. Lazy Class (M): Lazy Class는 결국 사용되지 않는 Class이다 관리를 위해서라도 이런 Class는 삭제하는 것이 좋다.

. Data Class (M): Getter, Setter만 있는 Class를 가리킨다. Class가 독립적으로 동작하지 않을 경우가 있으니, 어떻게 분리하여 다른 Class로 배분할지 고민하는 것이 좋다.

. Dead Code: 한마디로 죽은 코드로 삭제하는 방향이 맞다.

. Speculative Generality (M): 이는 미래 지향 코드로 필요하다고 생각해서 미리 넣어 둔 코드들인데, 실제 동작하지 않는 경우이다. 이도 삭제하는 편이 좋다.

Couplers

Coupling에서 온 개념으로 Class간의 잘못된 Dependency에 의한 Bad Smell이라고 볼 수 있다.

. Feature Envy (M): Method가 자신이 포함된 Class의 Data보다 다른 Class의 데이터를 계속 접근하려 하는 것이다. 이렇다면, Method를 옮기는 것을 고려하는 것이 좋다.

. Inappropriate Intimacy (M): 이 것은 Class가 다른 Class의 Field와 Method를 사용하려고 하는 경우이다.

. Message Chains (M): a->b()->c()->d()와 같이 연속해서 참조하여 Method를 호출하는 경우이다. 이런 경우는 Refacotring을 통해서 한번에 호출 되도록 Method를 옮기는 등의 방법을 고민해야 한다.

. Middle Man (M): 어떤 Class가 다른 한 Class의 Delagation 역할만 하는 경우이다. 이 때, 삭제하는 것을 고민해 볼 필요가 있다. 이 때, OCP를 위해서 Interface로 변경하거나 확장에 큰 도움이 되지 않는다면 삭제하는 것도 고민할 수 있겠다.

. Incomplete Library Class (M): library에서 제공하는 method들이 완전하지 않은 경우이다. 이 때도, 원작자가 그 기능을 추가해주면 좋지만, 그렇지 않다면 어떻게 필요한 기능을 추가할지에 대한 Bad Smell이다.


Refactoring Techniques

실제 Refactoring Techniques들은 계속 참조 할 수 있도록 Quick Reference Sheet를 만들어 보았다. 다른 분들과도 나누기 위해서 첨부하여 둔다.



돌아 보며

서두에서 이야기 한 것과 같이 이 내용도 계속해서 살펴 봐야 하는 내용이다. 특히, Refactoring은 설계를 한 후에 설계에 대해서 개선하는 작업이기 때문에 점진적인 작업과 반복 작업에 도움이 된다. 늘 주변을 깨끗하게 하는 것은 도움이 된다.



References

[1] Martin Fowler, John Brant, William Opdyke, and Don Roberts, "Refactoring: Improving the Design of Existing Code," Addison Wesely
[2] Refacotoring Guru, https://refactoring.guru/
[3] Source Making, https://sourcemaking.com/




Design Pattern 배우기

Design Pattern은 Gang of Four (GoF: 중국 문화 혁명의 무소불위 권력자 사인방에서 따온 것이라 한다)가 1995년에 발표한 책[1]으로 부터 소개 되어 유명해 졌다. 이 책이 고전인 것이 30년을 넘어서도 계속해서 사람들이 읽고 배우고 있다. 나도 몇번의 시도를 하였지만, 업무를 하면서는 배우지 못했다. 결국은 강의를 들으면서 어느 정도 감은 잡았다고 할 수 있다. 하지만, 이것은 몸에 익히기 까지 해야 하는 것이라 돌아 보고 또 돌아봐야 하는 것이라고 생각된다.


강의를 들을 때, 교제로 사용한 책이 GoF의 책이 아니였다. 바로, Head First Design Pattern이었다. [2] 이 책은 주요한 Design Pattern을 Story와 연결하여 예를 들어 잘 설명하고 있다. 또한 이 예와 연결해서 Java Code도 제공하고 있다. 예를 들자면, Strategy는 Duck 예제, Observer는 기상 모니터링, Decorator는 커피 가게, Factory는 Pizza 가게, Command는 리모콘, State는 Gumball Machine 등 Pattern을 떠올리면 그 예제의 이이기와 요구 사항들이 떠오른다. 


즉, 접근법이 쉽고 예를 잘 설명하고 있다. 그렇기 때문에, Design Pattern을를 처음 접하는 사람에게 추천한다. 하지만 여기서 만족하고 멈춰서면 안된다. GoF의 Design Pattern을 사전 처럼 참고하는 것이 좋다. Head First를 읽어 보고 해당하는 내용을 GoF 책을 보면, 잘 정리되어 있기 때문에 또 다른 것을 배우게 된다. 즉, Head First로 친숙해 지고, GoF의 Design Pattern으로 정리하는 방식이다. 그래서도, 쉽지 않으므로, 혼자 공부하기 보다는 Study 혹은 강의를 먼저 듣기를 권한다. Internet에서 아직 좋은 강의를 아직 보지 못해서 안타까울 뿐이다.


여기서는, Design Pattern을 하나 하나 살펴 보기 보다는 그 뒤에 깔려 있는 Object-Oriented 설계의 Principles들을 살펴 본다. 


"The critical design tool for software development is a mind well educated in design principles. It is not the UML or any other technology."

- Craig Larman


이는 Craig Larman의 조언에 따라 내가 본 책들에서 주요하게 강조하는 원칙들을 정리해 본다. 위의 말 처럼 Design Pattern을 이해하기 이전에 Object Oriented(OO) Principle을 바탕으로 Design Pattern을 이해하면, 왜 그렇게 구조를 가지는에 대해서 잘 이해할 수 있다 생각하기 때문이다.


GRASP Design Principles

GRASP은 General Responsibility Assignment Software Pattern의 약자이다.[3] 이 Concept은 Design Pattern의 것은 아니지만, 기본적인 OO Principles이므로 살펴 본다. 아래는 GRASP의 Summary 내용이다. 요약을 읽어 보면 바로 알수 있지만, Class의 Responsibility를 어떻게 할당하는가에 관한 원칙이다.


"After identifying your requirements and creating a domain model, then add methods to the appropriate classes, and define the messaging between the objects to fulfill the requirements"

- Craig Larman


위와같이, OO Design할 때 method를 class에 할당하고 다른 Class들과 messaging을 통해서 연계 시키는 것이 설계이다. 거꾸로 이미 구현된 시스템이 이러한 원칙들을 잘 따르고 있는지 살펴 보는 것도 중요할 수 있다. 


내용 측면에서는 우선적으로는 Information Expert, Creator와 Controller까지는 살펴 본다. 그리고, Loose Coupling, High Cohesion 또한 기본적인 개념이므로 따로 논의 하고 넘어 가보자. 나머지는 아래 표를 참고하자.



Information Expert

Information Expert는 결국 Responsibility를 그 정보를 필요로 하는 class에 할당한다는 것이다. 아래의 예는 [2]에 있는 Information Expert의 예이다. Board 게임 예제 인데, 아래 그림과 같이 Board에 주사위 정보(Square)를 제공(getSquare)한다. Board는 Square의 정보(Information)을 가지고 사용하는 Object로서 Expert가 된다. 즉, Board가 Square object를 Aggregate하게 되면서, Responsibility를 가지는 Object가 되는 것이다.



Creator

Creator는 어떤 Object를 생성하는 Class가 Responsibility를 가진다는 것이다. 원칙으로 보면, B class가 A class에 대해서 아래 중 한가지 혹은 그 이상에 해당되면 적용 되는 것으로 볼 수 있다.

  • B "contains" or compositely aggregates A
  • B records A
  • B closely uses A
  • B has the initializing data for A

Controller

"UI 계층을 넘어서 시스템의 동작의 조정(Control)을 수신하고 조정하는 하는 첫번째 Object가 무엇인가?"라는 질문에 대한 솔루션을 제공하는 원칙이다. 시스템을 대표하는 시스템 이름을 가진 Object혹은 Root Object을 두는 것이다. 또는 Use Case Scenario별로 해당되는 Object(Use Case Controller 혹은 Session Controller)를 두는 것이다.


아래 그림은 [2]에 있는 예제이다. Monopoly Game에서 UI Layer인 Monopoly JFrame 이후에 시스템을 대표하는 Object를 두는데, 이 것이 Controller인 MonopolyGame Class가 된다.




Loose Coupling & High Cohesion

Loose Coupling은 Object들 간의 Dependency를 낮게 만드는 쪽으로 Responsibility를 할당하라는 원칙이다. 아래 그림을 보면, Register가 Payment가 Create를 하고 직접 쓰지 않고 Sale에 할당하는 구조이다. 이는 Register가 Sale과 Payment에 모두 관계하는 구조를 가지고 있다. 그러므로 Dependency가 높다. 이를 아래 그림 처럼 Register는 Sale만 관여하고 Sale이 Payment를 관여하게 바꾸면 Dependency가 줄어 들게 된다.



Cohesion은 응집도로 해석된다. Functional Cohesion이라고도 한다. Element가 Responsibility에 대해서 얼마나 강하게 관련되고 집중되는지의 척도로 정의 된다.  위의 예에서 Coupling을 낮추는 동작 중에서, Sale에서 Payment를 생성하는 동작이 결국은 Cohesion을 높이는 역할까지 수행한다고 볼 수 있다.


그래소, Loose Coupling과 High Cohesion은 일반적으로 같이 움직이는 경향이 있다. Loose Coupling의 최대치는 아무 Dependency를 가지지 않는 것이다. 하지만, 이것은 비현실적이다. 즉, 하나의 Dependency만 가지는 것이 가장 좋을 것이다. Cohesion은 관련이 있으면 포함되게 하는 것이 좋다. 하지만, 여기 저기 관련되는 Coupling은 나빠지니 그 부분도 또한 조심해야 한다.

SOLID Design Principles

SOLID는 아래 원칙들의 앞글자를 따서 만든 원칙이다[4]. 상세 내용을 살펴 보면 알게 되지만, 결국 Software가 계속 바뀐다는 가정하에 이러한 원칙들이 적용된다. 즉, 변경에 대해서 원칙들이 지켜져야 하고 이것들 때문에 Design Pattern들이 나오게 된다.

  • Single Responsibility Principle (SRP)
  • Open-Close Principle (OCP)
  • Liskov Substitution Principle (LSP)
  • Interface Segregation Principle (ISP)
  • Dependency Inversion Principle (DIP)

하나씩 살펴 본다.

Single Responsibility Principle (SRP)

하나의 Class의 수정해야 하는 이유가 단 한가지여야 한다는 것이다. 그래서, Responsibility를 고쳐야 하는 이유로 정의하기도 한다. Class가 한가지 역할 이상을 하게 되면 변경되어야 하는 이유가 늘기 때문에 좋지 않다는 것이다. 만일 여러 Responsibility가 있다면 분리된 Class가 되어야 한다는 것이 이 원칙이다.

그렇다면, Responsibility를 어떻게 구분할까? 이 부분도 Software가 변경되어야 할 때, 드러나기 쉽다. 중요한 것은 이 원칙이 있다하더라도 꼭 쪼개어야 하는지는 고민해야 하는 부분이다. 


Open-Close Principle (OCP)

이 원칙은 확장에는 열려 있고(Open to Extension), 변경에는 닫혀 있다는(Close to Modification) 원칙이다. 이상하게 들릴 수 있다. 하지만, 이원칙은 변경을 Localization하는 원칙이다. 다른 Pattern에도 많이 적용되지만, Strategy Pattern과 Template Pattern이 이를 가장 잘 활용하는 Pattern이다. 


좀 더 다르게 이야기 하면, 변경되어야 하는 부분을 추상화(Abstraction)으로 분리하여 다른 Class들은 영향을 받지 않도록 하고, 계속 변경되는 부분은 이를 기반으로 새롭게 구현하도록 하여 확장이 가능하게 하는 원칙이다.


아래 그림에서는 Strategy Pattern과 Template Pattern을 적용한 OCP 원칙을 보여 준다. Client-Server 구조에서 Server의 변경에 Client가 영향을 받지 않게 하기 위해서 연동하는 부분을 추상화(여기서는 Interface 사용)하였다. 그리고, 이를 통해서 Server를 연동하게 하였다. Template Pattern의 예는 Policy를 추상화화 하여 Implementation들이 변경하더라도 서로 영향을 받지 않도록 분리하는 역할을 한다.

 


Liskov Substitution Principle (LSP)

LisKov Substitution Principle은 Java 혹은 C++ 언어를 배웠다면 어렵지 않게 이해할 수 있다. 즉, Super Class의 타입을 통해서 Derived Class를 대체 가능해야 한다는 원칙이다. 


위의 코드와 같이 구현되어 있는 경우는 이 원칙을 잘 따른다고 볼 수 있다. 하지만, 만약에 함수 f()가 Ctype을 받았을 경우 오동작하게 되면 원칙을 위배하게 되는 것이다. 또한, f()가 Ctype의 내용을 가지고 내용을 접근한다고 하면 Open-Close Principle도 위배하게 된다.


Interface Segregation Principle

Client는 사용하지 않는 method들에 강제로 의존적이지 않아야 한다는 원칙이다. 여기서는 Fat interface를 말하는데, 결국 사용하지 않는 method도 포함하는 interface를 말한다. 이러한 경우는 이를 분리하는 것이 좋다.


[4]에서는 Security Door에 Timer를 연계하는 예를 보여 준다. 기존 문에 Timer를 장착하고 일정 시간이 지나면 알람을 울리게 하는 문이다. 특별히 고민 없이 한다면, Door가 Timer를 상속하게 하는 방법이 있을 수 있다. 하지만, 모든 Door가 Timer를 가지는 것이 아니기 때문에 부적절하다. 이를 오른쪽과 같이 DoorTimer를 Aggregate하게 하거나 아니면, 다중 상속을 하게 하는 방법도 가능하다. Java에서는 다중 상송이 안되므로, Interface를 가지게 하면 된다.



Dependency Inversion Principle(DIP)

"Don't call us, we'll call you"라고 이야기 하면서, 에이전트를 찾아 가는 것이 아니라, 찾아 오게 만들어야 한다는 의미에서 Hollywood Principle이라고도 불린다. 예로 든 것이, Layered 구조에서 상위 Level이 하위 Level에 Dependency를 가지는 구조이다. 아래 그림은 Policy -> Mechanism -> Utility 방향으로 Dependency를 가지는 원래 구조에 DIP를 적용한 모습이다. 하위 구조의 Dependency를 interface로 추출하여 상위 Level에 두고 하위 Level이 이를 상속하게 하여 Dependency를 Inversion시켰다. 이렇게 함으로써, 상위 Level은 하위 Level의 변화에도 영향을 받지 않게 된다. 사족이지만, 하위 Level은 상위 Level의 변화에 영향을 받지 않았다.




OO Basic and OO Principles

Head First에 나오는 기본 원칙들이다. 책에서도 이것 후에 Design Pattern들이 설명된다. 여기서는 Pattern에 가기 전에 기본이되는 2가지 기본과 원칙에 대해서 살펴 본다. 이미 나온 것들과 연결되는 것이 많아서 간단히 언급하고 연결해 본다.


OO Basics

Head First Design Pattern에서 이야기 하는 Object Oriented Basics는 "Abstraction, Encapsulation, Polymorphism, Inheritance" 이다. 



Abstraction (추상화): 이 부분은 OO Paradigm에서 Object를 표시하기 위해서는 Object의 data와 이를 다루는 method로 표시하는데 이것이 추상화라고 할 수 있다.


Encapsulation(캡슐화):  크게 이야기 하면, 추상화에서 이야기한 Data와 Method를 하나로 묶어 주는 것이 캡슐화라고 할 수 있다. 좀 더 좁게 이야기 하면, Class의 외부로 보이는 부분을 제한하고 내부의 상세 구현은 감추는 것을 말할 때도 있다. 이 때에는 정보 은닉(Information Hiding)이라고 표현하기도 한다.


Polymorphism(다형성): 같은 이름으로 여러 것들을 Refer할 수 있게 해주는 개념이다. Overloading과 Overriding이 있다. Overloading은 Static한 Polymorphism으로 Compile할 때 결전된다. Class내에서 같은 이름를 가지지만, 인자가 다른 경우이다. Overriding은 상속 과계에서 Runtime에 Dynamic하게 매핑이 되는 Polymorphism을 이야기 한다.


OO Principles

Head First Design Pattern에서는 개별 Pattern을 설명하면서, 여러 Principle들을 설명하고 있다. 이미 설명한 GRASP이나 SOLID 혹은 OO Basics를 기반으로 한 것이다.


Encapsulate what varies: 캡슐화는 같이 묶어 준다는 의미이다. 즉, 변화하는 것과 변화 하지 않은 것을 분리해서 묶어 준다고 이해할 수 있다.

Favor composition over inheritance: 상속은 비용이 비싸다. 이를 Aggregation 혹은 Composition으로 가능한 것인지 정말 Inheritance를 채용할 것인지 고민해봐야한다.

Program to interfaces, not implementations: Concrete한 구현을 보고 프로그램하지 말고, 추상화 된 Interface를 보고 하는 것이 Dependency를 줄이는 방법이다.

Strive for loosely coupled designs between objects that interact: 연동하는 object들 간의 느슨하게 연결된(coupled) 설계를 사용하라고 번역할 수 있겠다. 이는 연동에 최소한의 interaction을 가지는 구조로 설계하라는 GRASP의 Loose Coupling과 일맥상통한다.

Classes should be open for extension but closed for modification: SOLID의 OCP와 일맥상통한다.

Depend on abstraction. Do not depend on concrete classes: LSP와 일맥 상통한다.

Only talk to your friends: Don't talk to stranger라고도 한다. 다른 Object와 Dependency를 최소화 하는 의미로 생각할 수 있다.

Don't call us, we'll call you: SOLID의 DIP와 일맥상통한다.

A class should have only one reason to change: SOLID의 SRP와 일맥 상통한다.


돌아보며: Design Pattern 

Design Pattern의 Principle들을 돌아 보았다.  결국은 Object Oriented Principle들을 돌아보았다. 결국은 Design Pattern도 Object-Oriented Design의 반복되는 문제에대한 솔루션을 정리해 놓은 것이므로 일맥 상통한다. 배경이 되는 원칙들을 잘 이해하면 이 Pattern들도 잘 이해할 수 있다.


정말로 중요한 것은 이 원칙들을 아는 것이 아니다. 결국은 Software에 변화되는 요구 사항에 Software를 관리하기 편하고 유연한 구조를 가지게 하는 적절한 원칙과 그를 기반으로 하는 Design Pattern을 적용하는 것이 중요하다.


나중에 기회가 되면, Design Pattern들도 하나 둘 씩 정리해 볼 생각이다. 실재로 여기에는 이러한 Pattern을 써야겠네, 혹은 다른 사람의 코드에서 이런 패턴을 썼네 판단되어 참고가 필요하면 책을 꺼낼 수도 있지만, Reference Sheet로 잘 정리된 것이 있어 계속 참고하고 있다.[5]  요즘도 계속해서 이를 참조하게 된다.


References

[1] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, "Design Patterns: Elements of Reusable Object-Oriented Software," Adisson-Wesley

[2] Eric Freeman and Elsabeth Freeman, "Head First Design Patterns," OReilly

[3] Craig Larman, "Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development," Third Edition.

[4] Robert C. Martin, "Agile Software Development, Principles, Patterns, and Practices," Pearson

[5] Design Pattern Quick Reference: http://www.mcdonaldland.info/2007/11/28/40/

개요

UML의 여러 Diagram들 중 이전에 살펴본, Class Diagram은 정적인 모델을 보여 주는 Structure Diagram의 일종이다. 즉, Snapshot이나 건물의 설계도와 같은 스틸 사진과 같은 모습을 보여 준다. 즉, 동작 보다는 전체적으로 어떤 Class들이 있고, 어떻게 연관되어 있는지를 보여 준다. 반면, 어떻게 동작하는지는 파악하기 어렵다. 이를 담당하는 것을 Behavior Diagram이라고 한다. 이 중에서 System Model들의 상호 연동(Interaction)을 보여 주는 Diagram이 Interaction Diagram이다. [1]




그런데, 왜 Structure Model만으로는 충분하지 못하고 Behavior Diagram을 사용해야 할까? 이는 시스템이 필요로 하는 요구 사항 중 기능을 어떻게 수행하는지 보이기 위해서이다. 반대로, Behavior Diagram으로만 시스템을 보여 주면 안될까? 이 또한 몇가지 동작 만으로 시스템을 보여 주기 어렵기 때문에 정적 모델로 전체 모습을 보여 주기도 해야 한다. 


Behavior Diagram 중에서 시스템의 Model의 상호 연동에 대해서 설명하는 Diagram에는 Sequence Diagram, Timing Diagram, Communication Diagram, Interaction Overview Diagram이 있다. 여기서 무엇 보다도 Sequence Diagram이 가장 일반적으로 많이 쓰인다. 


기본 개념

Sequence Diagram은 Class의 Instance들이 어떻게 연동하여 원하는 기능을 수행하는지 보여 준다. 그렇기 때문에 Diagram별 수행하는 기능이 정해 져 있다. 보통은 Use Case나 Scenario가 그에 해당한다. Class의 Instance에 해당하는 것이 Lifeline이고 연동하는 방식이 Message이다. 여기서는 이 두 가지를 살펴 본다.


Lifeline은 아래와 같이 Box에 수직 점선으로 되어 있다. 아래 그림과 같이 여러 종류가 있다.[2] 특히 (a)는 Role로 Class의 Instance로 표시할 수 있다. (b)는 Professor Class의 이름을 붙이지 않은 Anonymous instance로 보면 된다. (c)는 이 둘을 합친 모습으로 보면 된다. 



Message는 화살표가 끝나는 쪽의 Method에 해당한다. 3가지 혹은 5가지 종류가 있다고 한다.[2][3] 3가지 종류에는 Synchronous Message와 Asynchronous Message가 있다. 그리고, 이에 대한 응답에 해당하는 Return Message혹은 Response Message가 있다. Synchronous는 Message 호출 후, 결과가 처리되고 바로 Return되는 형식이다. Asynchronous의 경우는 우선 Message의 수신은 끝나고 처리 결과가 이후에 전달되는 경우이다. 5가지로 분류 될 때에는 Lifeline을 생성(Create)하거나 종료(Terminate)하는 경우의 Message를 포함한다.




이야기 한데로, Message는 Method에 대응되기 때문에 화살표 쓰는 Syntax는 다음과 같다. [2] 결국 Name이 Message의 이름이고 Parameter는 처리를 위해서 전달되는 인자들이다. 처리가 완료 된 후에 돌아오는 반환값의 종류는 Return Value가 되고 이를 저장하는 변수(Variable)이 앞에 위치하게 된다.


몇가지 예를 들어 보자.


initialize(code)

initialize

d = getProductDescription(id)

d = getProductDescription(di:ItemID)

d = getProductDescription(id:ItemID) : ProductDescription


Message의 처리 순서

Sequence Chart의 기본적인 처리 순서에 대한 개념을 설명한다. 3가지 규칙이 있다. [2] 첫 번째로 (a)에서 설명하는 것과 같이 같은 Lifeline에서 발생하는 것은 순서가 위에서 아래로 결정된다. 즉, a가 먼저 수행되고 c가 수행된다. (b)와 같이 다른 lifeline인 경우는, a, b 순서와 b, a의 순서가 모두 가능하다. (c)와 같은 경우는 복합적이다. 하지만, 다른 쪽에서 들어온 경우는, 같은 Lifeline에서는 순서가 정해진다. 즉, (a)의 규칙까지 적용하여 a, b, c의 순서만 가능한 것이다. 





Combined Fragments: Branch와 Loop

Combined Fragments는 Sequence Chart에 Frame을 표시하고 연산자를 적용하여 다양한 Control을 표시할 수 있게 해준다. Frame들은 내부에 다른 Frame을 포함할 수 있다. 이를 Nested 가능하다고 한다. 아래 그림은 Combined Fragment의 일반적인 구조를 보여 준다.


Operator에는 아래와 같은 종류가 있다[2]. 여기서는 Branches and loops에 대해서 살펴 본다.






Combined Fragments의 Branches와 Loop관련 항목은 아래와 같다. alt는 우리가 알고 있는switch와 유사하다. [...]가 guard condition으로 이 조건이 만족하면 해당하는Operand 부분이 수행된다. alt는 여러 옵션들이 있으므로 해당 guard condition에 따라서 수행되는 부분이 다르다. opt는 if문과 같다. 



loop의 경우는 operator에 반복 횟수를 (min, max) 혹은 (min..max)의 syntax로 적는다. guard condition에 loop를 돌아야 하는 조건을 기술한다. break문은 guard condition이 참인 경우 해당 내용을 수행하고 현재 위치한 Fragment를 빠져 나간다. 

Combined Fragment는 책에 있는 예제를 많이 살펴 봐야 이해도를 높일 수 있으니 많이 봐야 한다. 또한, 필요한 경우에 작성하는 것도 도움이 많이 된다.

Combined Fragments: Concurrency와 처리 순서

seq fragment의 경우는 일반적인 처리를 지칭한다. 이는 strict fragment와 대비되는 것으로 보면된다. strict의 경우는 그려진 순서를 무조건 따른다. 즉, 기본적인 message의 순서(order)를 따르지 않고 그려진데로만 수핸된다고보면 된다. par fragment의 경우는 operand들이 나뉘어 진데로 병렬 수행한다고 보면 된다. critical은 다른 message들이 중간에 끼어 드리 않고 atomic하게 수행된다고 보면 된다.



돌아보며... : Sequence Diagram의 활용

재미있는 것 중에 하나는 Open Source들의 경우 Class Diagram은 쉽게 찾을 수 있지만, Sequence Diagram은 찾기가 쉽지 않다. 왜 일까? 내 개인적인 생각은 Code가 있기 때문이다. 반대로 이야기 하면, 잘 그려진 Sequence Diagram이 있으면 Code까지 만들어 내는 도구가 있다.


Code는 Pseudo Code가 아니면 말할려고 하는 부분을 추상화 (Abstraction)하여 설명하기가 쉽지 않다.  즉, 설명하고 싶은 것만 넣고, 빼고 싶은 것만 빼기는 쉽지 않다. 즉, Sequence Diagram은 내가 넣고 싶은 것만 넣고 보여 줄 수 있다. 그렇기 때문에 다음 용도로도 사용할 수 있다.


1. 커뮤니케이션 도구이다.

다시 말하자면, 코드를 전체적으로 주거나 정리해서 주지 않고, 설명할 수 있는 좋은 방법이다. 동작에 대해서 명확하게 소통하기 위해서는 이를 사용하는 것이 좋다.


2. 설계 도구이다.

요구 사항 특히 동작 요구 사항을 분석하고 설계하는데, Sequence Diagram을 많이 사용한다.



Sequence Chart는 꼭 UML 도구로만 그리는 것이 이니다. Java의 IDE의 도구들을 추가 설치하면 함수를 분석하여 Sequence Chart를 그려 주는 도구도 많다.


References

[1] Unified Modeling Language, https://en.wikipedia.org/wiki/Unified_Modeling_Language#Interaction_diagrams

[2] Martina Seidl, Marion Scholz, Christian Huemer, Gerti Kappel, "UML@Classroom An Introduction to Object-Oriented Modeling," 2015 Springer

[3] Russ Miles, Kim Hamilton, "Learning UML 2.0," 2006, O'reailly


UML의  유용한 Diagram들

전통적인 Software Engineering입장에서 Software를 구현하는 절차는 사용자의 요구 사항을 분석 요구 사항을 분석(Analysis)하고 이를 설계 (Design)를하고 구현(Implementation)을 한다. 요즘은 대부분 객체 지향을 기반으로 Software를 구현하므로, 이를 객체 지양 분석 설계(Object Oriented Analysis and Design)라고 한다. 절차(Process)상으로는 여러가지 방법이 분분하게 많지만, Software의 구조의 설계를 위한 도구로서 UML을 많이 사용하고, 이 중에서 특히 Class Diagram과 Interaction Diagram으로는 Sequence Diagram을 활용하여 설계를 하는데 사용한다. State Diagram도 제공되는 경우도 있다.


Open Source로 제공되는 많은 Software 혹은 Module들도 복잡한 경우에는 Class Diagram을 제공하기도 한다.  Android의 Multimedia Framework에 해당하는 Stagefright의 경우도, Googling해 보면 사람들이 작성해 놓은 Class Diagram[1]이 있다. Sequence Chart는 찾기 어렵다. Android Multimedia Framework와 관련된 State Diagram은 초기 부터 제공이 되었다. 이는 Media Player라 불리는 Application Interface를 이해를 돕기 위해서 지속적으로 제공 되고 있다 [2].


실무로 업무를 하게 되면 요구 사항을 바탕으로 개발을 하는 경우도 있지만, 기존 코드(Legacy Code)를 유지 보수 하거나 확장하는 작업을 하는 경우도 많다. 이렇게 되면, 자료가 잘 제공되는 경우도 있지만, 없는 경우도 많다. 내가 생각하기에 가장 기본적인 자료는 Class Diagram이다. 이는 Software의 기존 구조를 파악할 수 있는 조감도에 해당한다. 하지만, 동작의 상세를 제공하지는 못한다. State Diagram 혹은 Sequence Diagram이 있다면 동작에 관해서도 빠르게 이해할 수 있다. 이 자료들이 없다면, Class Diagram은 만들고 Sequence Diagram도 기본적인 정상 동작에 대해서 작성한다면, 빠른 이해에 도움이 된다.


여기서는 Class Diagram 에 대해서 여러 책에 있는 좋은 내용들을 정리해 보기로 하자. 우선은 Object Oriented Paradigm에 대해서는 이해를 한다고 생각한다. 적어도, Java 언어에 대해서는 공부하였다면, 어느 정도 이해할 수 있는 수준이라고 생각한다.


Object, Class 그리고 Syntax

UML@Classroom[3]에서는 내용이 쉽게 설명되어 있으며, Class의 Attribute와 Operation의 Syntax에 대해서 아주 자세히 그리고 도식화가 잘 되어 있다. Chapter 4가 Class Diagram을 다루고 있는데, 다음은 그 요약 내용이다. 


아래 그림은 Object와 Class를 이용한 표기 방법의 예이다. 아래 가장 왼쪽은  :Person은 Class를 Instantiate하면 maxMiller가 된 것을 보여준다. 위의 상자에서는 maxMiller라는 Instance만 보여 주고, 내부 상세 Attribute는 숨기고 있다. 아래 그림의 가운데는 왼쪽 그림에서 Class 종류까지 기술하여 표현하고 있다. 가장 오른쪽은 무명(anonymous) 객체로 Instance의 이름은 없으 Class가 생성된 것을 표현하고 있다.


우리가 잘 알고 있는 Java 언어와 UML의 Class를 표현하는 방식을 병행해서 비교하면 아래와 같다. Course가 Class의 이름이 되고, name, semester, hours가 Attribute그리고, getCredits(), getLecturer(), getGPA()가 operation이 되는 것이다.



아래 그램에서 볼 수 있듯이, 3가지 방식으로 Class를 표현할 수 있다. (a)는 가장 단순히 표현하는 방식이다. 하지만, attribute와 operation의 상세 내용은 알 수 없다. 좀 더 정보를 포함한 것이 (b)이다. attribute와 operation의 내용을 볼 수 있지만, 각 속성들은 보여 지지 않는다. (c)가 가장 상세한 기술 방법이다. Java와 같은 언어로 Class의 뼈대(Skeleton)은 구현할 수 있다. Star UML[4]과 같은 UML Tool들은 이러한 Skeleton Code를 자동으로 생성해 주는 기능도 제공한다.



Attribute의 상세 Syntax는 아래와 같다. Visibility는 아래 테이블까지 추가해 두었으니 참고 하면 된다. Multiplicity는 Array를 표시하는 것으로 [min..max]형식으로 표시한다. 상위 제약이 없는 경우, *를 사용한다. [*]의 경우는 [0..*]와 같은 의미이다. 




Property의 경우는 {readOnly, unique, non-unique, ordered, unordered}가 가능하다. 이 특징들을 조합하면 Attribute의 속성을 조정할 수 있다. 이를 표로 나타내면, 아래와 같다. 예를 들자면, Set의 경우는 일반적으로 정렬이 되지 않은 중복되지 않은 숫자의 모임이다. 

 

 {unique}

{non-unique} 

 {ordered}

 Ordered Set

List 

 {unordered}

 Set

 Multi-Set



Opeattion에 대한 기술 방법은 아래와 같이 요약될 수 있다.


Class 간의 Relationship

이 부분은 Class를 연결 시키는 선들로 기술된다. 이 부분은 Learning UML[5]에서 아주 요약하고 있는 그림이 있다. Local Value 혹은 Parameter로 사용되는 경우는 Dependency 혹은 Association으로 표현이 된다. Aggregation과 Composition은 시나리오에 따라 달라지기는 하지만, 모두 Member로 활용되는 경우이다. Inheritance는 상속으로 구현된다. 좀더 명확한 구분을 하고자 한다면, 책을 더 보도록 한다.



Class Diagram Syntax를 포함한 Diagram 예

Applying UML and Pattern[6]에는 위에서 설명한 Syntax와 Relationship를 예로서 잘 표현하는 그림을 포함하고 있다. 이 그림을 이해한다면, 위에서 정리한 내용도 모두 이해한다고 볼 수 있다. 이 그림을 손으로 그려보거나, UML 툴을 이용해서 그려 보는 것도 Class Diagram의 Syntax와 Relationship 표기 방법을 이해하는데 도움이 된다. 여기서는 <<interface>>를 표시하여 함수만을 Abstract하는 Interface도 표시하고 있다는 것을 참고하자.







Reference

[1] Stagefright player and its class diagram: http://infectiousansh.blogspot.com/2010/09/stagefright-player-and-its-class.html

[2] Developers Documentation Media Player: https://developer.android.com/reference/android/media/MediaPlayer

[3] UML@Classroon: An Introduction to Oject-Oriented Modeling 2015 Springer

[4] Star UML: http://staruml.io/

[5] Kim Hamilton and Russel Miles, Learning UML 2.0, O'Reaily Apr. 2006

[6] Craig Larman, Applying UML and Patterns 3rd Ed, Addison Wesley Perofessional Oct, 2004


+ Recent posts