open:uml-for-java

UML for Java Programmers

UML의 주요 다이어그램은 세 종류로 나뉜다.

  • 정적 다이어그램(static diagram)은 클래스, 객체, 데이터 구조와 이것들의 관계를 그림으로 표현행서 소프트웨어 요소에서 변하지 않는 논리적 구조를 보여준다.
  • 동적 다이어그램(dynamic diagram)은 실행 흐름을 그림으로 그리거나 실체의 상태가 어떻게 바뀌는지 그림으로 표현해서 소프트웨어 안의 실체가 실행 도중 어떻게 변하는지 보여 준다.
  • 물리적 다이어그램(physical diagram)은 소스 파일, 라이브러리, 바이너리 파일, 데이터 파일 등의 물리적 실체와 이것들의 관계들을 그림으로 표현해서 소프트웨어 실체의 변하지 않는 물리적 구조를 보여준다.
어떤 것이 실제로도 잘 작동하는지 알아보려고 만드는 것이 모델이다.

반드시 코딩을 시작하기에 앞서 포괄적인 설계를 해야 하는가

메타포1)

다이어그램을 그려야 할 경우
  • 여러 사람이 동시에 작업하기 때문에 모두 설계에서 특정한 부분의 구조를 이해해야 할 때 그려라. 모든 사람이 다 이해했다고 동의하면 그때 멈춘다.
  • 두 명 이상이 특정 요소를 어떻게 설계해야 할지 의견을 달리하고, 팀의 의견을 모을 필요가 있을 때 그려라. 논쟁에 시간 제한을 두고, 투표나 객관적인 심판 같이 결정을 내릴 수단을 준비해라. 제한된 시간이 되거나, 결정이 내려지면 그 때 멈춘다. 그리고 다이어그램을 지운다.
  • 어떤 설계 아이디어로 이것저것 시도해 보고 싶을 때 그린다. 다이어그램은 그 아이디어를 생각하는 일에 도움을 줄 것이다. 핵심을 깨닫게 되어서 여러분의 생각을 코드로 옮길 수 있을 정도로 만족스럽게 종결지을 수 있을 때 멈춘다. 그리고 다이어그램을 버린다.
  • 누군가에게 또는 여러분 자신에게 코드 일부분의 구조를 설명할 때 그려라. 코드를 직접 보는 편이 더 잘 이해된다고 느끼는 시점에 다다르면 다이어그램을 그리는 작업을 멈춘다.
  • 프로젝트 마지막에 가깝고 여러분의 고객이 다른 사람을 위한 문서에 포함하기 위해 다이어그램을 요구할 때 다이어그램을 그려라.

클래스

연관

상속

UML 다이어그램의 세계에서는 차이점보다 공통점이 훨씬 중요하다.

정말 코드만으로 어떤 시스템의 일부분을 설명할 수 있을까? 사실 그것이 개발자와 설계자의 목표여야 한다. 개발팀은 표현력이 강하고 가독성이 좋은 코드를 작성하기 위해 노력해야 한다. 코드만으로 설명하기 쉬울수록 필요한 다이어그램의 수도 줄어들고, 전체 프로젝트도 나아질 것이다.

기본흐름

대체흐름

나쁜 설계의 냄새

  1. 경직성 : 무엇이든 하나를 바꿀 때마다 반드시 다른 것도 바꿔야 하며, 그러고 나면 또 다른 것도 바꿔야 하는 변화의 사슬이 끊이지 않기 때문에 시스템을 변경하기 힘들다.
  2. 부서지기 쉬움 : 시스템에서 한 부분을 변경하면 그것과 전혀 상관없는 다른 부분이 작동을 멈춘다.
  3. 부동성 : 시스템을 여러 컴포넌트로 분해해서 다른 시스템에 재사용하기 힘들다.
  4. 끈끈함 : 개발 환경이 배관용 테이프나 풀로 붙인 것처럼 꽉 달라붙은 상태다. 편집-컴파일-테스트 순환을 한 번 도는 시간이 엄청나게 길다.
  5. 쓸데없이 복잡함 : 괜히 머리를 굴려서 짠 코드 구조가 굉장히 많다. 이것들은 대개 지금 당장 하나도 필요 없지만 언젠가는 굉장히 유용할지도 모른다고 기대하며 만든 것이다.
  6. 필요 없는 반복 : 코드를 작성한 프로그래머 이름이 마치 '복사'와 '붙여넣기'같다.
  7. 불투명함 : 코드를 만든 의도에 대한 설명을 볼 때 그 설명에 '표현이 꼬인다'라는 말이 잘 어울린다.

2)
3)

어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.

클래스는 오직 하나만 알아야 한다. 오직 하나의 책임만 져야 한다. 더 핵심적인 말로 바꿔 보면, 어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.

소프트웨어 엔티티(클래스, 모듈, 함수 등)는 확장에 대해서는 개방되어야 하지만, 변경에 대해서는 폐쇄되어야 한다.

모듈 자체를 변경하지 않고도 그 모듈을 둘러싼 환경을 바꿀 수 있어야 한다.

OCP를 지키는 시스템이라면 GUI를 조작하는 부분과 데이터를 조작하는 부분을 구분해 놓는다.

서브타입은 언제나 자신의 기반 타입(base type)으로 교체할 수 있어야 한다.

A. 고차원 모듈은 저차원 모듈에 의존하면 안 된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야 한다.
B. 추상화된 것은 구체적인 것에 의존하면 안 된다. 구체적인 것이 추상화된 것에 의존해야 한다.

만약 어떤 클래스에서 상속받아야 한다면, 기반 클래스를 추상 클래스로 만들어라.
어떤 클래스의 참조(reference)를 가져야 한다면, 참조 대상이 되는 클래스를 추상 클래스로 만들어라.
만약 어떤 함수를 호출해야 한다면, 호출되는 함수를 추상 함수로 만들어라.

추상 클래스와 인터페이스는 보통 자신에게서 유도된 구체적인 클래스보다 훨씬 덜 변한다.
우리가 의존하면 안 되는 것은 '자주 변경되는' 컨크리트 클래스다.

UML을 사용하면 이 원칙을 지키는지 매우 쉽게 검사할 수 있다. UML 다이어그램의 화살표마다 따라가서 모두 인터페이스나 추상 클래스를 가리키는지 확인하면 된다. 만약 컨크리트 클래스에 의존하는데 그 클래스가 자주 변경된다면 DIP를 어기는 것이며, 따라서 시스템도 변화에 민감하게 되어 버릴 것이다.

클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다.

사용자에게 딱 필요한 메서드만 있는 인터페이스를 제공해서 필요하지 않는 메서드에서 사용자를 보호하라.

  1. SRP - 어떤 클래스를 변경해야 할 이유는 오직 하나뿐이어야 한다.
  2. OCP - 클래스를 변경하지 않고도 그 클래스의 환경을 바꿀 수 있어야 한다.
  3. LSP - 유도된 클래스의 메서드를 퇴화시키거나 불법으로 만드는 일을 피하라. 기반 클래스의 사용자는 그 기반 클래스에서 유도된 클래스에 대해 아무것도 알 필요가 없어야 한다.
  4. DIP - 자주 변경하는 컨크리트 클래스 대신 인터페이스나 추상 클래스에 의존하라.
  5. ISP - 어떤 객체의 사용자에게 그 사용자한테 필요한 메서드만 있는 인터페이스를 제공하라.

    이 원칙들을 적용하는 가장 좋은 방법은 능동적으로 적극 적용하는 것이 아니라, 문제가 생겼을 때 그에 대한 반응으로써 적용하는 것이다.

    단위 테스트를 엄청나게 작성해 보는 것이 아픈 지점을 찾는 가장 좋은 방법 가운데 하나다. 테스트 대상 코드보다 테스트를 먼저 작성하면 더 좋다.

여러분에게 당장 필요하고 중요한 문서만 만들어라.

자바 프로그래머에게 중요한 패키지는 두 종류다.

  • 하나는 자바의 package 키워드로 나타내는 소스코드 패키지고,
  • 다른 하나는 .jar 파일로 나타내는 바이너리 컴포넌트다.

패키지 릴리스/재사용 등가 원칙(Release/Reuse Equivalency Principle, REP)

결국, 여러분이 재사용할 코드의 가장 작은 단위는 누군가 계속 발표하고 유지 보수하는 데 노력을 기울일 생각이 있는 크기보다 작을 수 없다. 그러므로 재사용의 가장 작은 단위는 릴리스의 가장 작은 단위다.

공통 폐쇄 원칙(Common Closure Principle, CCP)

만약 어떤 것을 변경해야 한다면, 그것 때문에 바꾸어야 할 클래스들이 단 한 패키지에만 몰려 있기를 원한다. 변경할 이유가 같은 클래스들은 한 패키지에 들어가야 한다. 이렇게 하면, 무엇을 바꿔야 할 경우 의존 관계 구조 안의 패키지들 가운데 매우 적은 수만 변경하면 된다.

공통 재사용 법칙(Common Reuse Principle, CRP)

의존 관계 비순환 원칙(Acyclic Dependencies Principle, ADP)

해결 방법은 패키지 의존 관계 그래프에서 순환을 제거하는 것이다. 직접 손으로 해도 되고, jDepend4)와 같은 도구를 써도 된다.

안정된 의존 관계 원칙(Stable Dependencies Principle, SDP)

안정된 추상화 원칙(Stable Abstractions Principle, SAP)

UML에서 유한 상태 기계(Finite State Machine, FSM)를 설명하기 위한 표기법이 풍부하다.



1)
(옮긴이)잘 모르거나 새로운 사물이나 개념을 이해하기 위해 잘 알고 친숙한 사물이나 개념에 빗대 표현하는 것을 메타포(metaphor)라고 한다. 컴퓨터 화면을 책상에 빗대 데스크탑이라 부르고 파일 삭제를 휴지통에 종이를 던지기에 빗대는 것이 그 예다.
2)
Agile Software Development : Principles, Patterns, and Practices
4)
www.clarkware.com을 방문해 보아라
  • open/uml-for-java.txt
  • 마지막으로 수정됨: 2020/06/02 09:25
  • 저자 127.0.0.1