설계는  tradeoff와 우선순위에 관한 것이다.

설계는 제약이 따른다.

설계는 발견적 학습과정이다.

설계는 창발적이다.(갑작스럽게 튀어나오는)

전체 프로그램을 한번에 구성하는 것이 아니라 한 부분을 집중할수 있게 프로그램을 구성하도록 해야 한다.

최종목표는 한번에 생각해야 하는 프로그램의 양을 최소화하는 것이다.

복잡한 하나도나 여러개의 간반한 정보를 이해하는 것이 빠르다.

바람직한 설계의 특징

  • 복잡성 최소화
  • 유지관리의 편리함
  • 느슨한 결합
  • 확장성
  • 재사용성
  • 높은 fan-in 주어진 클래스를 사용하는 클래스의 수가 많음을 의미한다
  • 낮은fan-out 주어진 클래스가 다른 클래스를 적게 사용하는 것을 의미한다.
  • 이식성
  • 간결성
  • 계층성
  • 표준기술들

 

설계를 시작하기 전에 서브시스템 간의 커뮤니케이션은 "알아야 할 필요성" 이 있을때에만 가능하도록 한다. 그런 연후에 차츰 그 제한을 풀어가는 쪽으로 바꾸어야 한다.서브시스템간의 커뮤니케이션을 모두 가능하게 시작하여 제한하기 시작할 경우에 너무 많은 노력과 부작용이 발생한다.

공통적인 서브시스템

  • 비지니스 규칙 - 시스템에 입력하는 모든 자료
  • 사용자 인터페이스 - 사용자 인터페이스를 독립적으로 작성한 서브시스템은 프로그램의 나머지 부분에 영향을 받지 않고 발전할수 있다
  • 데이터베이스 접근 - 데이터베이스 연산을 한 곳에 집중시킬수 있고 데이터를 다룰 때 오류가 발생할 가능성도 줄인다.

    객체와 클래스. 스키마와 인스턴스

    설계수준

1수준 소프트웨어 수준

2수준 서브시스템이나 패키지로 분할

3수준 클래스로 분할

4수준 루틴으로 분할

5수준 내부 루틴 설계 : 설계는 의사코드를 작성하고 참고서적에서 알고리즘을 살펴보고 루틴 내의 코드 단락을 어떻게 구성할 것인지를 결정하고 프로그래밍 언어로 코드를 작성하는 활동으로 구성된다.

 

-좋은 class interface는 해당 클래스의 내부적인 작업에는 신경 쓸 필요없이 인터페이스에 집중할수 있는 추상화이다.

-추상화를 통해서 얻을수 있는 주요한 이득은 관련없는 세부사항들을 무시할수 있다는 것이다.

-객체들 간의 유사성과 차이점을 정의하는 것을 "상속"이라고 부른다. 왜나하면 특정한 정규직과 계약직 직원은 일반적인 직원타입의 특성을 상속받기때문이다.상속의 이득은 추상화 개념과 시너지 효과를 갖는다는 점이다. 추상화는 서로 다른 수준에서 객체를 다룬다. 상속은 프로그래밍을 단순화시킨다. 예를 들어 문(door)에 대한 일반적인 특성에 의존하는 일반적인 루틴을 작성한 다음에 특정한 종류의 문에 대한 특정한 연산을 처리하는 특정한 루틴을 작성할 수 있다. 이런 연산을 지원하기 위한 능력이 "다형성" 이다.

-정보은닉은 복잡성을 감추는 능력을 가지는 것이다. 클래스 인터페이스를 벗어나는 범위에 영향을 끼쳐서는 안된다. 클래스를 설계하는데 있어서 중요한 것은 어떤 기능들이 클래스외부에 알려야 하고, 어떤 기능들이 은닉되어야 하는지를 결정하는 것이다. 무엇을 숨겨야 한느지에 대한 질문은 모든 수준에서 좋은 설계결정에 도움을 준다.구현수준에서는 리터럴대신 명명된 상수를 사용하도록한다. 이것은 클래스 내부에서 좋은 루틴과 좋은 매개변수 일므을 생성하는데 도움을 준다. 또한, 시스템 수준에서는 클래스와 서브시스템의 분해 및 상호연결에 대한 결정에 도움을 준다. "내가 무엇을 숨겨야 하지?"란 의문을 늘 갖도록 한다.

변경될 가능성이 있는 것을 고립시키기 위한 3단계.

1.변경될 것처럼 보이는 항목들을 규명한다

2.변경될 것같은 항목을 분류한다

3.변경될 것처럼 보이는 항목을 고립시킨다.

변할 것 같은 영역들

비지니스 규칙 - 가장 빈번한 소프트웨어 변경의 원인. 고립시켜야 한다

하드웨어 의존성 - 하드웨어에 의존하는 서브시스템과 클래스만 고립시킨다

입려과 출력

비표준언어기능

어려운설계와 구현부분.

상태변수 - 프로그램의 상태를 가릨고 다른 데이터들보다 자주 변경되는 경향이 있다. 상태변수를 사용하는데 있어서 유의점

> boolean변수를 상태변수처럼 사용하지 말라. 대신 열거형을 사용하라!!!!상태변수에서 새로운 상태를 추가하는 일은 흔히 발생하며, 열거형에 새로운 타입을 추가하면 변수를 검사하는 모든 코드를 검토하는 대신 컴파일만 다시 하면 된다.

> 변수를 직접적으로 접근하는 대신 접근 루틴을 사용하라! 변수 대신 접근 루틴을 검사하게 함으로써 보다 정교하게 상태를 검사할수 있다. 예를 들어, 오류상태변수와 현재함수의 상태 변수 조합을 검사하고 싶을때, 만약 테스트가 루틴에 숨겨져 있다면 그 작업이 쉬워지겠지만, 프로그램 전체에 걸쳐서 복잡한 테스트가 입력되어 있다면 작업이 어려워 질 것이다.

  • 느슨한 결합을 유지하라. coupling은 클래스나 루틴이 다른 클래스나 루틴과 얼마나 밀접하게 연관되어 있는지를 기술한다. 다른 클래스와 루틴보다 작고, 직접적이며, 눈에 띄고, 유연한 관계를 갖는 클래스와 루틴을 생성하는 것이 목표이며, 이를 "loose coupling"이라 한다.결합의 기준은

    크기. 가시성, 유연성 등이 있다. 느슨한 결합의 핵심은 효율적인 모듈이 추가적 추상화 수준을 제공한다는 점이다. 이는 전체적인 프로그램의 복잡성을 줄이고 한번에 한가지에 집중할 수 있도록 한다. 하지만 만약 어떤 모듈을 사용하기 위해서 한번에 하나 이상의 것을(내부 작업에 대한 이해, 전역데이터의 수정, 불확실한 기능)에 집중해야 한다면, 추상적인 효과는 사라지고 복잡성을 관리하는데 도움을 주기 위한 모듈의 능력은 줄어들거나 사라져버린다.

 

일반적으로 널리 사용되는 패턴을 찾아라.

  • 패턴은 이미 만들어진 추상화를 제공함으로써 복장성을 줄인다
  • 패턴은 일반적으로 널리 사용되는 해결책의 세부사항들을 규정함으로써 오류를 줄인다
  • 패턴은 설계대안들을 제안함으로써 발견적 학습의 기치를 제공한다 - 내 설계문제가 적합한  패턴이 어떤 것이지? 대해 물을수 있고 잘 알고 있는 대안들을 살펴보는 것은 옷을 설계하기 위해서 디자인을 직접 만드는 것과는 비교할수 없을 만큼 쉽다. 그리고 익순한 패턴을 이용하여 작성한 코드는 완전히 직접 작성한 코드보다 다른 사람이 이해하기 더 쉽다.
  • 패턴은 설계 대화를 보다 높은 수준으로 옮김으로써 의사소통을 원할하게 한다.

    패턴을 사용함에 있어서 주의할 것은 패턴을 사용하기 위해 코드를 억지로 끼워맞추는 것이다. 그러다 보면 오히려 복잡성이 증가할수 있다.

 

설계방법

  • 반복
  • 분할정복 > 하향식 접근 방법에 대한 찬성론(Top down) - 분할정복 프로세스는 두가지 면이 반복적이다. 한가지 수준이 아닌 여러 수준에서의 분할이 이루어져야 하고, 어떻게 분해하는 것이 효율적인가를 반복적으로 고려해보아야 하기때문이다. 프로그램을 분해하는 것보다 코드 작성이 쉬워지는 단계까지 분해했다면 작업이 완료된다.

    >상향식 접근 방법에 대한 찬성론(Bottom up) - "이 시스템은 무엇을 해야 하는가?"에 대한 질문에 답할수 있는 보다 구체적인 클래스를 작성하는 것으로 시작한다. 여러가지 저 수준의 책임을 규명한 다음에 상위수준으로 올라가는 것이다.

설계작업기록하기

  • 설계문서를 코드 자체에 넣어라 - 최신으로 유지하기가 쉽다
  • 설계에 대한 논의와 결정을 wiki(혹은 그에 준하여 편집이 쉬운 웹게시물집합?)에 기록하라
  • e-mail로 요약하라 - 설계논의를 끝낸 후, 누군가가 설계에 대한 요약을 작성하여 프로젝트 팀원에게 메일을 보낸다. 그리고 메일의 복사본을 프로젝트 공용 이메일 폴더에 저장하라.
  • 디지털카메라를 사용하라 - 문서화에 한계가 있다. 다양한 방법은 기록의 지루함을 덜어준다
  • 설계플립차트를 보관하라
  • CRC(클래스, 책임, 협력자)카드를 사용하라.- 인덱스카드를 사용하는 것이다. 각각의 카드위에 설계자는 클래스의 이름, 클래스의 책임,그리고 협력자(해당 클래스와 협력하는 다른 클래스)를 기록한다. 그러면 설계 그룹은 그들이 좋은 설계를 작성했다는 것에 만족할때까지 그 카드로 작업한다. 그 시점이 되면, 나중에 참조하기 위하여 카드를 보관할 수 있다.
  • 적절한 상세수준에서 UML 다이어그램을 작성하라.

 

  • 요점정리 중에서.

    • 소프트웨어의 일차적인 기술적 의무는 복잡성을 관리하는 것이다. 이것은 단순함에 초점을 맞춘 설계의 도움을 받을수 있다
    • 단순함은 두 가지의 일반적인 방법으로 달성할수 있다. 누군가가 한번에 처리해야 하는 본질적인 복잡성의 양을 최소화하고 부수적인 복잡성이 불필요하게 증가하지 않도록 하는 것이다
    • 설계는 발견적 학습이다. 어떠한 단일 방법론에 독단적으로 집착하면 상상력과 프로그램에 해를 입는다
    • 좋은 설계는 반복적이다. 여러번 시도할수록, 마지막 설계는 더 좋아질 것이다
    • 정보은닉은 중요하다. "무엇을 숨겨야 하지?"라는 질문이 해결하기 어려운 설계 상의 문제들을 해결해준다
    • 설계에 대해서 더 많이 보고 공부해야 한다.!

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 1. 19. 17:07