728x90
반응형
소프트웨어 공학론
UML Diagram
더보기
UML Diagram은 프로그램의 구조를 그래프로 보기 쉽게 나타낸 것이다.
- Use-Case Diagram
- Actor(사용자, 센서 등), Use-case(사용할 기능), Scope(시스템의 범위)로 이뤄진 다이어그램이다.
- Use-case를 만드는 순서 : Actor의 구체화 → Use-case의 구체화 → 관계의 구체화 → Draw & Scope표시
- Pre-Condition : Use-case에 진입하기 위한 조건
- Post-Condition : Use-case 종료 시 보장되는 것 - Activity Digram
- Fork / Join : 노드가 분리되거나 통합됨을 알린다.
- Decision / Merge : 노드가 Condition에 따라 분리되거나 통합된다.
- 구획면 (Swim-lane) : 시스템의 진행 과정을 각 역할에 따라 분리배치한다. - Dynamic Modelling
- 각 다이어그램은 중점적으로 설명하고자 하는 것이 정해져 있다.
- 그러므로, 한 다이어그램만으로 모든 작동과정을 설명하기는 어렵다.
- 또한, 한 다이어그램을 다른 다이어그램으로 표현하고자 할 때에도 불편함이 있다.- Sequence Diagram : 객체들의 상호작용을 시간관계 순서대로 모델링한다.
- Communication Diagram : 객체들의 상호작용에 중점을 둔 다이어그램이다.
- State Diagram : 시스템의 상태, 변수의 값 등에 따른 상태 변화에 중점을 둔 다이어그램이다.
- Sequence Diagram : 객체들의 상호작용을 시간관계 순서대로 모델링한다.
- UML Tool
- UML를 그릴 수 있는 프로그램으로는 StarUML 등이 있다.
아키텍쳐 디자인
더보기
아키텍쳐(Architecture)란, '설계의 의사결정의 집합'으로 '시스템의 청사진'이다.
설계단계에서는 많은 창의성이 요구된다.
- 계층 아키텍처
- 인접된 계층끼리만 상호작용이 가능하며, 단계를 건너뛰는 것은 불가능하다.
예시] MFC ( Microsoft Foundation Classes ) - 컴포넌트 아키텍처
- 스스로 작동할 수 있는 단위 (컴포넌트)
예시] Android Components ( Activity - 창, Service-Bg서비스, Broadcast Receiver, Content Provider 등.. ) - 아키텍쳐 설계에서 중요한 점
- 비 기능적 요구사항으로부터 영향을 받는 Software Architecture 디자인은 피한다.
※ 3rd-party Component를 사용할 때, 유지보수를 위해 Wrapper를 사용해야 한다. - 비-기능적 요구사항에 대한 설계 방향
- 성능 : 성능에 큰 영향을 미치는 연산들을 모아 모듈간 상호작용을 최소화한다.
- 보안 : 계층적 아키텍처를 이용하여, 보안이 필요한 에셋들을 안쪽 레이어에 넣어둔다.
- 안전성 : 안전에 치명적인 기능들을 서브시스템에 모아서, 안전성 검증 비용을 최소화한다.
- 가용성 : 모듈을 많이 만들어서, 하나가 불능이 되더라도 서비스에 지장이 없게 한다.
- 유지보수 : 모듈화를 잘 해서, 고장난 부분만 교체할 수 있고, 새로운 부분의 추가가 쉽게 한다.
※ Perfomance, Security, Safety, Availability, Maintainability - 아키텍쳐 표현
- Package Diagram : 계층적으로 분할된 다이어그램
- Facade Design Pattern : 클라이언트와 서브시스템이 파사드를 두고 분리된다.
- 이외에도 Simple & Informal하게 다양한 표현 방식이 가능하다. - 디자인 아키텍쳐
- 계층적 구조 (Layered) : 각 계층에는 연관된 기능끼리 위치, 바로 위 계층에만 서비스 제공
장점 : 각 계층 별로 인증과정을 추가하면 신뢰성을 높일 수 있다.
단점 : 계층구분을 명확히 하지 못하거나, 접근 가능한 계층을 넘어서 접근할경우 성능 문제가 발생한다.
- 클라이언트-서버 구조 : 각 서버가 서로 다른 기능을 구현하고, 클라이언트는 원하는 기능에 맞게 조합해 이용
장점 : 네트워크로 서버를 분산배치할 수 있고, 모든 사용자가 서비스를 이용할 수 있다.
단점 : 성능이 컴퓨터 성능 + 네트워크 성능에 의존하며, DOS 공격에 취약하다. 또한 서버 소유를 여러 기관에서 할 경우 관리 문제가 발생할 수 있다.
- MVC 모델 : Model(데이터처리), View(데이터출력), Controller(사용자의 입력처리)로 분리한다.
장점 : 한 데이터를 여러 방법으로 보여주려고 할 때 유용하다.
단점 : 데이터 모델과 데이터 사용법이 간단할 때, MVC 모델을 적용하면 쓸데없이 복잡해질 수 있다.
- 이벤트기반 구조 : 여러 서브시스템이 하나의 메인시스템을 공유하며, 서브시스템간 참조는 메인시스템에 대한 이벤트로 요청한다. ( 메인시스템은 Handle 구현 )
장점 : 시스템 변경이 상태적으로 쉽다.
단점 : 이벤트가 언제 Handle될 지 예측할 수 없다.
- 저장소구조 : 각 서브시스템은 하나의 저장소를 공유하고, 서브시스템간 데이터 교환은 없다.
장점 : 각 컴포넌트가 독립적이고, 중앙 저장소의 변경이 전체에 적용된다. 일관성있게 관리 가능
단점 : 중앙 저장소의 문제가 전체에 영향을 주고, 비효율적이며, 분산하기 어렵다.
- 파이프&필터 구조 : 배치파일처럼 기능을 나열한 뒤 순차적으로 진행한다. (순서변경, 역순 등은 발생 X)
장점 : 이해하기 편하며, 재사용이나 변환에 용이하고, 비즈니스 처리구조에 적합하다.
단점 : 인접한 변환들 간 데이터 형식을 미리 약속해야하며, 이에 따른 변환작업이 필요해 오버헤드가 발생한다. - 설계의 원리 ( Design Principle )
- Step-wise Refinement : Level 1(간단한 정리), Level 2(세부 정리)로 나눠 정리한다.
- Abstraction : 필요한 것만 보여주고, 나머지는 모두 숨긴다.
※ 함수적 추상화 (Interface만 보여줌), 자원 추상화 (데이터 연산 Method만 보여줌)
- Modularization : 결합도(Coupling), 응집도(Cohesion)
- SOLID : SPR(한기능-한책임), OCP(코드변경없이확장가능), LSP(부모객체는 자식객체로 대체가능)
ISP(복잡한 클래스는 각 기능에 대한 인터페이스로 분리, 상속, 구현), DIP(고수준이 저수준에 의존X)
상세 설계 - 디자인 패턴
더보기
디자인 패턴이란, 반복해서 재사용 가능한 문제 해결 패턴으로
Creational(창조적), Structural(구조적), Behavioral(행동적)의 3가지 타입으로 나뉜다.
- Creational Design Pattern
- Factory Method
구체적인 클래스 이름을 직접적으로 명시하지 않고 객체를 생성하기 위한 수단이다.
실제 객체는 Factory class의 추상 메소드를 상속해서 구현한 자식클래스에서 생성된다.
객체의 클래스명 변경, 인수 개수 및 타입 변경 등으로 인해 발생할 의존성 문제를 예방한다. - Abstract Factory
여러 개의 Factory Method를 모은 class를 만드는 것이다. - Singleton
한 클래스가 작동과정에서 한 객체만 존재하게 하는 패턴으로, 유일성을 보장한다.
- Factory Method
- Structural Design Pattern
- Adapter Pattern
호환되지 않는 Legacy Class를 일관성있게 사용하기 위한 수단이다.
현재의 A.run()과 deprecated된 B.execute()에 대해, B_Adapter class에서 A를 상속받고,
B 오브젝트를 어댑터 내에서 구현한 뒤, B_Adapter.run()을 통해 B.execute()를 실행한다. - Composite Pattern
비슷한 구현을 가진 클래스들을 모아 사용하기 위한 수단이다.
특정 기계의 가격을 구할 때, 각 부품의 가격들의 합으로 구하려고 한다면 이를 사용할 수 있다.
각 기계와 부품이 abstract int getPrice();를 상속받고 구현한 뒤, 기계에서 부품들의 getPrice의 합을 구한다.
- Adapter Pattern
- Behavior Design Pattern
- Iterator Pattern
반복작업을 캡슐화하여, ArrayList내의 데이터 구성 방식이 변경되어도 일관적인 사용이 가능하다.
ArrayList는 Key 4의 접근을 위해 0.tail->1.tail->2.tail->3.tail->4의 방식으로 접근하고,
Iterator는 0번부터 next()를 통해 하나씩 순서대로 접근하므로, 참조시간이 빠르다.
그러나, 배열 내 내용들을 각 변수에 담아야 하므로 생성과정에서 시간이 걸려 큰 차이는 없다. - Observer Pattern
이벤트들에 대한 Listerner를 구현 한 후, Observer에 모두 등록해놓는다.
갱신이 필요할 때, Observer에서 등록된 Listerner들을 한번에 실행할 수 있다. - State Pattern
상태 변경을 switch-case를 통해 검사-변경 과정을 거치는 것이 아니라,
각 상태를 표현하는 객체를 만들고, 그 객체들이 버튼에 대한 작동을 구현한다.
abstract pressOn(); abstract pressOff(); 를 상속받아 구현하는 State들을 만들어 사용한다. - Facade Pattern
subClass들을 관리하는 FacadeClass를 구현하여, 클라이언트가 직접 관리하지 않고 facade에 인수를 전달하는 방식으로 간단하게 사용한다. - Decorator Pattern
객체의 결합을 통해 기능을 동적으로 유연하게 확장할 수 있게 해주는 패턴이다.
상위 개체를 상속하고 super()하는 방식으로 자주 사용한다.
수업에서는 예시로 내비게이터에서 지도에 표시될 것들을 정하는 느낌으로 사용됬다.
- Iterator Pattern
구현
더보기
UML Diagram을 분석한 후 코딩을 한다.
리팩토링은 코드 구성을 바꾸는 것으로, 필요에 따라 수행한다.
- Coding
- '+'는 public, '-'는 private, '#'은 protected를 나타낸다.
- ':'(콜론) 뒤의 타입은 반환형, 밑줄 표시는 static임을 나타낸다.
예시]
public void run() // +run()
private int calc(int a, int b) // -calc(a:int, b:int):int
public static void main() // +main()
- Inheritance ( 상속관계, extends )
Child class -----▷ Parent class
- Association ( 연계 관계, 전역변수 타입 ), [ 1대1, 1대다, 다대다 관계 ]
VarType class -----> Main class
만약, 자기 자신의 클래스를 재사용하면 Prerequisite관계로 표시한다.
- Aggregation ( 포함 관계, 생성자의 인자 타입으로 사용, 종속 X )
Argument class -----◇ Body class
- Composition ( 합성 관계, 객체를 생성, 종속 O )
Object class -----◆ Body class
- Dependence ( 의존 관계, 함수에서 사용한다 )
Body class - - - - -> Object class - Sequence Diagram → Code
- State Diagram → Code
- 리팩토링 ( Refactoring )
- 리팩토링을 하는 이유 ( Code-smell )
두 가지 이상의 이유로 수정되는 클래스 → 한 종류의 역할만 수행하도록 분리
한 기능에 대한 수정이 여러 클래스의 수정 → 그 부분들을 모아 한 클래스로 만듬
다른 클래스를 지나치게 애용 → 합친다.
유사 데이터들의 그룹 중복 → 독립된 클래스로 정의한다
switch문장이 지나치게 많은 case포함 → 다형성으로 구현한다.
별로 사용되지 않는 클래스 → 제거하거나 합병한다.
필요하지 않은 기능을 위해 만든 상속관계 → 상속 제거
if문의 조건문이 너무 복잡함 → 함수로 만들어서 호출함.
등...
- 위험 : 리팩토링을 한 후 새로운 오류가 발생할 수 있음.
- 비용 : 새로운 테스트 케이스를 만들어서 테스팅해야한다.
- 아무 이유없이, 단순히 오류가 있어서, 마감기한이 가까울 때 등의 상황에서는 리팩토링은 하지 않아야 한다. - 테스팅 ( Testing )
- 프로그램이 원하는대로 동작하는지 확인하는 것
- 코드 퀄리티 향상을 위해, 정적/동적 분석 및 Code Inspection(정적분석)을 한다.
- 테스팅 기법
Testing : 가짜 오류 발견 X, 모든 오류 발견 못할 가능성 존재
Static Verification : 모든 Input case를 준비하고 입력, 모든 오류 발견, 가짜 오류 발견 가능성 O
Inspection : 여러 사람이 모여 코드를 읽으면서 검사, 조직적이고 철저하지만, 비공식적이고 주관적이다.
Formal proofs of Correctness : 수학적 명세로 검증한다. 확실하지만 복잡하고 비싸다.
- Testing
Test Case : 입력값과 그 입력값에 대해 예상되는 출력값(Expected Output)
Test Suite : Test case들의 집합
Implementation Under Test(IUT) : 입력값을 받는 프로그램 부분
Test Environment (Test Harness) : IUT의 동작을 위해 준비되는 외부 환경 ( Driver & Stub )
Test Procedure : 위의 모든 과정들을 문서화한 내용
- 테스트 케이스 디자인
결함 발견의 목적으로, 완전하게 코드를 검사할 수 있어야 한다. 동시에 케이스의 수는 최소화되어야 한다.
비-정상적인 입력값을 넣어 오류상황에 오류가 제대로 발생하는지도 검사해야 한다.
한 번 오류가 발견됬던 곳에서 다시 오류가 발생할 가능성이 높다.
- 테스팅 vs 디버깅
테스팅 : 결함이 발생한다는 사실만 확인 가능
디버깅 : 결함이 발생하면, 그 발생한 위치를 확인할 수 있음.
- 테스팅의 종류
범위에 따른 분류 ( Granularity Levels )
Unit test : 프로그램 내 한 클래스만 검사
Integration test : 한 클래스와, 그 작동에 연관된 클래스에 대해 검사
System test : 프로그램 전체 검사
Acceptance test : 프로그램 전체에 대해 사용자 입장에서 검사
Regression test : 이전에 검사했던 케이스에 대해 회귀적 검사
테스트 참가자 성향에 따른 분류
Alpha test : 프로그램 내부자 테스트
Beta test : 프로젝트 외부자 테스트
※ Alpha test 참가자는 Beta test 참가자보다 오류에 대해 좀 더 관대하다.
내부 코드 작동 상황을 알 수 있는가에 따른 분류
Blackbox Testing
Whitebox Testing
728x90
반응형
'3-1공부 > 소프트웨어공학론' 카테고리의 다른 글
기말4. 코딩, 리팩토링, 테스팅 (0) | 2022.06.01 |
---|---|
기말3. 디자인 패턴 (0) | 2022.05.10 |
기말2. 아키텍쳐 (0) | 2022.05.10 |
기말1. UML Diagram 조금 (0) | 2022.05.10 |
6. 시스템 모델링 (0) | 2022.04.17 |