수업/Software Design

[Software Design] Moving to Design

hw-ani 2022. 11. 12. 12:50

앞서 과정까지 우리는 분석을 위해 requirements를 기반으로 여러 Analysis 모델을 iterative/incremental하게 만들었다.

분석에서 business needs를 정했다면, 디자인에선 어떻게 system을 만들지에 집중한다.

분석 과정을 통해 우리가 만들/보완할 system이 어떤 기능을 어떤 흐름으로 해야하는지, 내부구조가 어떻게 되는지, 각 class/object들이 어떻게 상호작용하는지를 알았다면,,

이제는 구현으로 넘어갈 수 있도록 Analysis 모델을 Design 모델로 발전시켜나가야한다. (특히 Class D를...)

이 글에선 그런 Design 과정의 전체적인 흐름을 보도록 하겠다.

 

Design 과정의 특징은 다음과 같다.

1. 구현을 위한 청사진을 제공한다.

2. Data가 어떻게/어디에 저장될지도 결정한다.

3. user가 system과 어떻게 상호작용할지 interface를 결정한다.

4. 사용할 physical architecture도 결정한다.

5. Analysis와 Design은 상당히 밀접하다. 왔다갔다하며 상호보완됨.

 

교수님께서 말씀하시길, 많은 기업에서 분석은 고사하고 설계조차도 제대로 하지 않고 구현부터 하는 경우도 있다고 하시는데 이는 매~우 좋지 않다고 하심. 물론 설계같은건 경력 좀 있는 사람들이 하기때문에 당장 취업해서는 쓸 일이 없겠지만, 전체적인 흐름을 이해하는 사람과 함수 헤더 던져주면 기능만 typing하는 코더는 다르다.

 

 

Design Process는 다음 과정으로 나뉜다.

● Analysis Models을 확인/검증한다. 서로 정보가 매칭되는지 등등

Design strategy를 정한다.

● Analysis models을 다양한 방법을 통해 Design models로 진화시킨다.

● Packages를 만든다. 이때 보통 package diagrams을 이용한다. (2번의 각 요소를 UML에서 표현하는 방법이 Package D이다.)

 

 

 

> Design Strategy

아래에서 우리는 Design 방법론(?)에 대해 알아볼건데, 사실 Design 단계부턴 여러 전략을 선택할 수 있다.

(의뢰 받은 팀이 Analysis까진 제대로 하는게 좋다고 하심)

 

1. Custom Development

Analysis한 팀에서 Design을 계속 진행하는 전략이다. 직접 분석을 한 팀이니 당연히 requirement나 시스템에 대한 이해도가 높다. 따라서 요구사항에 최대한 맞춰줄 수 있고, 어느정도 창의성이나 유연성을 발휘할 수도 있다.

우리 팀이 개발할 능력이 있거나, 없더라도 역량 강화에 도움이 되는 경우 이 전략이 좋다.

단, 성공/실패를 모르니 risk가 증가할 수 있고, IT staff들을 지치게 할 수도 있다.

 

2. Purchase packaged software

이미 작성된 software를 구매하여 사용하는 전략이다. 이미 검증된 것을 사용하므로 risk도 적고 효율적이다.

하지만 원하는 기능이 정확하지 않을 수도 있는데 이는 감수해야한다. 우리 system에 맞추기 위해 wrapper 같은게 필요할 수도 있다.

 

3. Hire an external vendor(outsource)

외부 업체에 맡기는 전략이다.

아웃소싱을 잘하려면, 상호간 소통이 잘돼야하고 신뢰와 정보교환이 필요하다. 또 외부 업체에 맡기는 것이니 Analysis를 확실히 해서 넘겨줘야한다.

단점으로는 control을 잃을 수도 있고, 비밀 정보 유출 위험도 있다는 것이다.

(control을 잃는다는 것은 제대로 관리하지 않는다는 말이다. 맡겨만두고 확인을 안해보면 system이 어떻게 흘러갈지는 아무도 모른다.)

계약 방식은 다양하다. 시간당 돈을 지불할 수도 있고, 수익의 특정 비율을 떼줄수도있고...

 

전부 아웃소싱으로 던져주고 그걸 받아와서 합치는 일을 하는 곳이 우리가 흔히 SI 업체라고 부르는 곳이다.
System Integration을 해야하니, 각 system간 소통을 위해 wrapper을 개발하기도하고 뭐 그런다.

 

아래는 Design strategy를 고를때 참고할 수 있는 표이다.

outsourcing 또한 highly skilled PM을 필요로 한다.

 

 

> Evolving the Analysis Models into Design Models

Analysis 모델은 functional requirements에 집중했다. 우선 system 기능을 먼저 보는게 맞으니 그렇게 했던 것이다.

Design models에선 non-functional requirements도 포함시켜서 표현한다.(성능, 환경, interface, DB 등...)

또한 System의 유지보수성이 있는지, 예산/능력 등이 충분한지, 효율적인지 충분히 고려해야한다.

Factoring, partitions&collaborations, layers이용해 Design models로 변경시킨다.

 

> Factoring

Factoring은 묶어낸다는 의미로, 이미 존재하는 특정 module에서 유사한 덩어리를 뽑아내 새로운 module을 추가로 만드는 과정이다. 여기서 module은 class도 될 수 있고, method도 될 수 있다.

예를들어 어떤 class 내에 비슷한 특성을 가진 attributes나 methods가 여러개 있다면, 얘네는 아예 따로 묶어내서 새로운 class로 만드는 것이다.

이 새로운 module이 기존 module과 inherit 관계라면 generalization(a-kind-of)이거나 aggregation(has-parts)일 것이다.

 

AbstractionRefinement라는 작업도 factoring과 연관된다.

Abstraction은 몇몇 ideas의 higher-level idea를 생각해내서 추가하는 것이고,

Refinement는 abstraction의 반대과정으로 더 상세한 class를 찾아내 추가하는 것이다.(factoring은 기존 구조를 변경하는거고, 얘네는 찾아서 추가하는거인듯?)

예를들어 abstraction에는 여러 상세 직업 class들을 보고서 Employee라는 class를 추가하는 것이고,

refinement는 Employee class를 보고서 secretary나 bookkeeper 같은 class를 추가하는 것이다.

 

(내생각)이렇게 factoring/abstraction/refinement를 통해 class 구조를 좀 더 명확하고 구체적으로 나타낼 수 있을 것이다.

그리고 얘는 아마 아래 두놈처럼 Package Diagram에서 표현된다기보단 Class Diagram에서 Class/method들을 조작하는거라 Class D에서 표현되겠지.

 

 

 

> Partitions&Collaborations

밀접하게 collaborate하는 class들의 sub-system을 만드는 것이 partition이다. 그냥 쉽게말해서 밀접하게 연관되는 애들끼리 묶어서 파티션을 나눈다는 말이다.

어떤 class들이 밀접하게 연관되는지 판단할때는 sequence diagram을 사용할 수 있다. 일반적으로, 서로 메시지를 많이보낸다면 그들은 같은 파티션안에 들어간다고 본다. 적게 보내는 관계라면 다른 파티션으로 분리해야할 것이고..

 

partitions&collaborations은 UML의 Package Diagram에서 표현될 수 있다.

 

 

 

> Layers

지금까진 Problem Domain에만 집중했다. 그런데 Design엔 System Environment 같은 정보도 추가돼야한다.

Layer을 이용하면 비교적 간단하게 이런 PD 외 정보들을 추가할 수 있다. Layer에서 System Environment같은 software architecture의 각 요소를 분리표현할 수 있기때문이다.

Layer을 통해 복잡한 system도 이해하기 쉽게 만들고, 각 Layer간 영향을 받지 않게하여 재사용을 최대화한다.

 

보통 아래 Layers을 추천한다.

1. Foundation (ex.container class 같은 library)

2. Problem Domain (ex.encapsulatoin, inheritance 등 OO를 적용해가며 지금까지 만든 ClassD가 여기해당)

3. Data Management (ex. 어떻게 data를 저장/회수할 것인지)

4. Human-Computer Interaction(User Interface) (ex. 데이터 입력 형식)

5. Physical architecture (ex. 특정 컴퓨터나 network)

 

Layers는 UML의 Package Diagram에서 표현될 수 있다.

 

이렇게 계층을 나누는 것은 Smalltalk의 MVC architecture에서 온 것이다.
같은 application을 interface만 바꿔서 쓸 수 있게, MVC(Model-View-Controller)로 나눈다.
Models은 application logic(problem domain)을 구현하고, Views는 output, Controllers는 input을 처리한다.
Layering은 각 계층별로 독립적이라 유지보수성도 좋고, 복잡한 시스템을 이해하기 쉽다는 장점도 있지만, 단점도 있다.
각 Layer의 목적은 다르지만, 수단이 비슷하면 그런게 겹칠수도있고, Layer들끼리 아예 분리를 해두면 특정 Layer에서 다른 Layer의 간단한 정보만 있으면 해결될 문제를 어느 정도 돌아가서 해결해야 할 수도 있다.
최적화 측면에선 좀 손해를 보는 것이다.

 

 

> Package

Package로 관계있는 unit들을 묶어낼 수 있다. 여기서 unit이라하면 class도 되지만, use-case 같은 애들도 복잡하고 많다면 묶을 수 있다. Package로 묶음으로써 model의 복잡도를 줄인다. 그렇게 각 package를 묶고, package들간의 관계를 표현한다. 각 Package에 이름도 지어야한다. 관계는 점선 화살표(Dependency)로 표현한다.

(각 package를 아무 관계없이 독립적으로 만드는 것은 사실상 불가능하다. 서로 영항은 주고 받는다.)

 

이런 Package는 UML에서 Package Diagram으로 표현되는데, Package Diagram을 통해 위에서 설명한 partitions&collaborations, layers도 표현할 수 있다. 참고로 Package Diagram에는 packages만 있어야한다.(세부 class들 표시하지 말란건가?)

(factoring은 class D에 추가/표현 된다고 보는게 맞을듯, 뭐 어쨌든 Package D가 여러 기법을 한번에 표현할 수 있으니 Design에서 제일 중요한 모델이긴 함)

 

위처럼 package내에 package가 있어도 되고,, 어쨌든 각 Class들을 묶어냈다.(partitioning)

class D 자체에서 관계가 association 선으로 나타나기도 하지만 Sequence D도 봐야 정확하게 묶어낼 수 있다.

 

Package"만" 표현해야된다고 하면 이게 맞는 것 같긴하다.

얘는 Package간 Dependency도 점선 화살표로 잘 표현돼있는데, 위에 세부 class까지 나와있는 놈은 점선 화살표도 없긴하다.

근데 강의자료에선 둘 다 Package Diagram이라고하니.. 뭐 작은 system은 위처럼 class까지 다 표현해도 되겠지만, 복잡해지면 얘처럼 간단하게 이름이랑 관계만 표현하는게 맞는듯.

그냥 저렇게 두 방법으로 표현할 수 있다고 알고 있으면 되지싶다. 정석대로하면 아래꺼가 맞는 것 같지만.

 

 

위에선 PD Layer만 나타냈지만 이렇게 다른 Layer도 package D에 같이 나타낼 수 있다.

 

 

위에서 본 5가지 추천 Layer들을 나타내 본 것이다.

여기서 package와 Layer의 중요한 점이 나온다. 이를 사용하는 이유는 독립적인 개발을 위해서이다.

위 그림을 보면, HCI은 다른 Layer에 영향을 주지 않는다.(화살표 방향으로 붙는다(?)고 생각하면 쉬운듯, 한 layer가 다른 layer에 붙어서 system이 커진다고 해야되나)

즉, HCI Layer의 어떤 요소가 바뀌더라도, 다른 곳엔 영향을 끼치지 않는다. 다시말해 UI에서 버튼 위치가 좀 바껴도 다른 Layer을 수정할 일이 있어선 안된다는 말이다.

(그래서 Design 단계 전까진 UI나 구현같은 사항을 생각하지 말라고 한 것..)

같은 논리로 Foundataion이 바뀌면 아마 많은 Layer가 수정돼야 할 것이다.(그래서 이름도 foundation이네,, 얘는 library 같은 진짜 수정될 일 없는 놈으로 해야겠네)

 

(구현관점)
A라는 Class 안에 Normalization을 하든 뭘 하든 해서 다른 B라는 Class의 object가 들어가게 된다면, A에서 B에 message를 보낼 수 있단 의미이므로 A는 B에 dependency가 있게 되는 것이다.(한쪽에만 object가 있으면 위 화살표처럼 단방향이 되는 것)

 

 

 

> Guidlines for Package D

● 내 design을 논리적으로 구조화하기위해 사용

● 수직적 위치 관계는 보통 상속을, 수평적 위치 관계는 보통 aggregation이나 assocation을 나타낸다.

 dependency를 정할때는 의미적인 관계도 살펴봐야한다.

 Use-case D에서 Packaging을 하고 싶다면 actor도 포함해라.

 각 Package는 이름을 잘 지어야한다.

 Package는 응집도(cohesive)가 높아야한다.

 

 

Package의 목적은 우리 컴퓨터의 folder가 있는 목적이랑 비슷하다.
그리고 실제로도 Java에선 Package가 folder로 구현된다.
Package는 각종 UML models에 적용할 수 있는 general construct라서 위에서 말했듯이 use-case D 같은 것을 묶는데도 사용할 수 있다.