CS
소프트웨어 공학(2)
Chap6. 설계원리
- 설계는 어떻게 만들 것인가를 구체적으로 결정하는 활동
- 아키텍쳐 설계 관점
- 아키텍처 설계 과정
- 품질 목표 설정
- 아키텍처 스타일 결정
- 서브시스템의 기능,인터페이스 명세
- 아키텍처 설계 검토
- 전통적 설계 원리
- Recurring concepts in design(설계에서 반복되는 개념?)
- 추상 : Hiding detail
- Top down decomposition : 큰 놈을 작은 놈으로 분해
- information hiding : hiding internal design
- seperation of concerns(우려사항 분리)(SoC) : encapsulating information
- interfaces : 그냥 코딩에서 interface
- modularity : large software를 small interconnected module들로 분리
- divied and conquer : 분할정복
- modularity 측정 방법
- Coupling : measure dependencies between modules
- Low coupling은 좋음
- High하다면, 한 모듈 변경하면 다른 애들도 조금씩 변경해야함, 모듈하나를 놓고 테스팅 힘듬
- 불필요한 관계를 제거해서 Low coupling을 만들어야 한다.
- Type of coupling(밑으로 갈수록 bad)
- Message coupling : 가장 Low, 모듈이 전부 의존적이지 않음
- Data coupling : parameter들로 모듈이 소통함, 추가적으로 필요한 부분이 없음
- Stamp coupling : 구조체같은 composite data가 모듈간에 왕래함, 구조체 전부가 아닌 구조체의 일부 정보만 사용됨
- Control coupling : 변수를 통해 다른 모듈의 logic을 제어함, 즉 모듈끼리 어떻게 동작하는지 알아야 함 →High
- Common coupling : Global data를 모듈간의 통신에 사용함
- Content coupling : 다른 모듈의 데이터를 변경, low level언어에 의해 주로 발생
- Cohesion : measure how strongly the elements in a module are related
- 하나의 task에 들어가는 element가 많은 정도
- 쉽게 보면 뭐 하나의 모듈내에서 자기알아서 혼자서 하는게 좋다는거지.
- Strong : Good
- Weak,low : Bad
- Type of cohesion (밑으로 갈수록 bad)
- Functional cohesion : 모든 element가 오직 하나의 task에서만 사용되고 해당 computation에 필수적임
- Sequential cohesion : 파일 read~ out처럼 element들이 하나의 활동에 연쇄적으로 사용됨, 한 활동의 output이 다음 활동의 input으로 쓰임
- Communicational cohesion : function이 같은 데이터를 만들어 내기 위해 사용됨 , 분리하는 것이 좋다
- Procedural cohesion : sequential과 비슷하지만 element들이 연관되어 있다는 부분만 다름, main program module에서 흔히 볼 수 있음
- Temporal cohesion : element are related in time, init이나 terminate에서 흔히 보임
- Logical cohesion : 논리적으로 element들이 연관되어 있음
- Coincidental cohesion : element들이 의미없는 관계를 가짐
- 객체지향 설계 5원칙 (SOLID)
- SRP(단일 책임의 원리)
- class가 변경되는 이유는 오직 하나여야 된다.
- 즉, 클래스가 의존하는 애들중 단 하나만 해당 클래스를 변경할 수 있다.
- OCP(open close principle)
- open for extension , but close for modification
- 모듈의 기능을 바꾸는 것은 ok, 근데 모듈의 아키텍쳐를 바꾸는 것은 안됨 연쇄적으로 전체 시스템을 변경할 가능성이 있기 때문
- Abstraction(추상화)를 해야 한다!
- 해당 클래스가 직접적으로 다른 클래스와 연관이 있을 때, 추상화를 통해 interface를 만들어 사용하면 다른 클래스와 연관을 끊고 다른 클래스와 연관을 맺을 때에도 본연의 클래스의 구조가 변경되지 않음
- 예를 들어 직원 클래스 밑에 staff,secretary등등이 자식으로 있고 부모에만 print가 있다면 새로운 직원이 들어오게 되면 부모의 아키텍처를 바꾸게됨(조건문 증가, print함수 증가)
- 이 대신, 부모는 interface만 가지고 자식이 이것을 implement한다면 새로운 직원이 add해도 부모의 아키텍처는 변하지 않음, open for extension close for modification
- LSP(Liskov substitution priciple,리스코프 교체의 원리)
- subtype이 basetype을 대체할 수 있어야 한다
- 위 사진처럼 Square 가 Rectangle을 상속할때 IS-A 관계라고함
- 위의 경우 Square가 Rectangle의 width,height간의 독립성을 violate함
- DBC(Design By Contract)
- subclass는
- superclass의 pre-condtion을 약화하거나 post-condition을 강화만 할 수 있다.
- preconditon은 해당 메소드를 실행하기 전에 참인 것
- post는 메소드 실행후에 참이 되는 것?
- ISP(Interface Segregation principle, 인터페이스 분리의 원리)
- Client들은 자신이 쓰지 않은 method에 의존을 강요받아서는 안된다
- 여러 client를 위한 함수들을 묶어 하나의 interface나class로 만드는 경우 불필요한 coupling이 생성된다.
- timed door가 timer,timerclient에 의존할 때, 모든 door가 timer를 사용하는 것이 아닌 분리해서 timed door인 경우에 또 중간자를 만들어서 timer,timer client를 다룸.. 그냥 pass
- DIP(Dependency Inversion principle,의존관계 역전의 원리)
- 상위 레벨의 모듈은 하위레벨의 모듈에 의존해서는 안된다
- 모듈은 추상화에 의존해야 한다.
- 추상화는 detail(구현?)에 의존해서는 안되고, detail은 abstraction에 의존해야 한다.
- 얘도 “추상화”를 통해서 즉,interface를 사용해라!
Chap 7. 아키텍처와 패턴
- 아키텍처 : 높은 수준의 구성요소,관계
- 시스템 전체의 효율성,재사용성,유지보수성을 결정함
- 주로 계층적 분할 방법으로 표현
- 아키텍처 스타일
- 클라이언트 서버형 : 클라이언트,서버로 이루어진 것
- 계층형 : 수직으로 상호작용하는 여러 층으로 분할
- 👍 추상화,캡슐화
- 👎 이웃 층과 커뮤니케이션이 제한적
- 이벤트 기반 아키텍처 : 이벤트 생산자가 스트림 생성, 이벤트 소비자는 이벤트 기다림
- MVC(model view controller) : 컨트롤러(모델에 명령을보내 모델의 상태 변경),모델(데이터 상태에 변화가 생기면 뷰와 컨트롤러에게 통보),뷰(결과를 표시하기 위해 모델로 부터 정보를 가져옴)로 분리
- 파이프 필터 : 필터사이에 데이터를 이동시ㅅㅇㅓ키ㅎ며 단계적으로 처리(컴파일러)
- 데이터 중심 아키텍처 : 공유 데이터 저장소,접근자로 구성
- Peer to Peer 스타일 : 각 컴포넌트가 동등하게 서버이자 클라이언트의 역할(블록체인)
- 👍 확장성,신뢰성
- 👎 중앙제어 불능,노드수 증가시 성능저하가능성
- 디자인 패턴
- 아키텍처 설계 수준보다 낮은 수준에서 재사용 가능한 솔루션을 제공
- a solution to a problem in a context
- 혜택
- 쉽게 재사용 가능
- 설계 쉬워짐
- 설계 관련 지식이 정리됨
- 의사소통 용이
- 객체 지향 설계 원리를 잘 따르게 됨
- 싱글톤 패턴
- 객체를 강제적으로 하나만 생성하려는 목적
- 클래스 자체를 static으로 선언, 생성자는 private
- 반복자 패턴
- 반복자(iterator)가 알아서 집합에 소속된 요소들에 접근해줌
- 어댑터 패턴
- 인터페이스를 클라이언트가 예상하는 인터페이스에 맞게 조정
- 즉, 어댑터 : 서비스가 제공하는 인터페이스를 클라이언트가 기대하는 인터페이스로 변환
- 데코레이터 패턴
- 팩토리 메소드 패턴
- 클라이언트에서 사용할 클래스의 객체를 추상클래스로 정의하고 실제로 구현하는 클래스도 따로 정의
- product class에서 NY_C_pizza,NY_V_pizza,CH_C_pizza,CH_V_pizza를 구현하는 추상 클래스 pizza, creator class에 NY_pizza,CH_pizza구현하는 실제 클래스 Pizzastore를 만드는 것
- product의 하위 추상클래스(ny c pizza ..)들은 다 하위 실제클래스 (nypizza..)에서 옴
- 추상 팩토리 패턴
- 추상 인터페이스를 이용해서 객체 패밀리를 생성
- 옵저버 패턴
- 데이터를 보관하고 있는 subject와 observer와 통신하며 느슨하게 결합
- 상태 패턴
- 상태에 따라 객체의 동작을 변경해야 하는 경우 사용
- 아키텍처 평가
- SAAM:시나리오 기반 평가
- ATAM : 여러가지 품질 속성에 초점을 맞추고 평가
Chap8.UI설계
- 사용성 : 시스템이 얼마나 사용하기 편한지를 나타내는 척도
- 요소
- 학습용이성
- 효율성
- 기억용이성
- 낮은 오류율
- 자신감과 만족
- 멘탈모델 : 현실 세계의 사물이나 과정이 어떻게 작동하는지에 대한 개인의 이해 수준
- 쿠팡의 장바구니가 쇼핑몰의 쇼핑카트에 물건을 담는것과 유사
- 멘탈 모델이 충분하지 않은경우 은유나 비유를 활용(휴지통)
- 피드백 : 뭐 깔거나 로딩하는데 걸리는 시간을 보여주는 것
- UI 설계 원리
- 단순하고 자연스럽게 만들라
- 안전한사용, 오류회복이 쉽게하라
- 단축 명령을 제공하라
- 인식하기 쉽게 만들라
- 설계 과정
- 사용자 분석 → UI 태스크 분석 → UI설계와 구현 → 사용성 테스트 → 사용자 분석
- 사용성 테스트 : 학습성,오류율,예측성,만족함 등을 사용자가 평가
Chap9. 코딩
- 자주 발생하는 코딩 오류
- 메모리 누수 : free없이 계속 할당
- 중복된 프리 선언
- NULL 사용 : null인 애를 접근
- 별칭의 남용
- 배열 인덱스, 수식예외(divide 0 , equal 연산은 항상 정수끼리만),하나차이 등등
- 코딩 표준
- 간결함, 읽기 쉬움이 목표
- 뭐 들여쓰기 , 변수명 표기 등등
- 연관의 구현
- 1:1 → A에서 B를 호출하는 경우 A가 B에대한 참조를 갖도록 구현(반대도 마찬가지)
- 1:n → A가 B를 호출하는 경우 A가 B의 참조를 모음으로 가지고 있도록 구현
- N:N → 연관 클래스 도입해서 1:N 두개로 나눠서 설계
- 리팩토링
- 결과의 변경 없이 코드의 구조를 재조정
- 가독성과 유지보수성을 높이기 위해 하는 것
- 코드 품질 향상 기법
- 코드 인스펙션 : 눈으로 확인
- 디버깅하고 난 뒤에 눈으로 보면서 결함을 찾는 것
- 정적 분석 : 데드코드, 선언되지 않고 사용된 변수가 없는지 확인
- 페어 프로그래밍 : 애자일 방법에서 두사람이 머신을 공유하며 코딩(걍 같이 코딩)
Chap10. 테스팅
- 테스트의 원리
- 테스트는 오류를 발견하려고 프로그램을 실행시키는 것
- 완벽한 테스트는 불가능하다
- 테스트는 창조적인 일이며 힘든 일이다
- 테스트는 오류의 유입을 방지할 수 있다
- 테스트는 구현과 관계없는 독립된 팀에 의해 수행되어야 한다
- 작업 과정
- 목표설정 → 방법결정 → 테스트 케이스 선택 → 테스트 케이스 작성 → 테스트 실행
- 블랙박스 테스트
- 경계값을 테스트에 잘 사용하는게 좋다잉
- 화이트박스 테스트
- 모듈의 논리적인 구조를 체계적으로 점검
- 과정
- 원시 코드를 통해 애플리케이션의 구조를 이해 (논리흐름도 이용)
- 논리흐름도는 모듈 내의 제어 흐름을 간선으로 표시한 그래프
- 검증 기준(커버리지)을 정한다
- 문장 커버리지 : 각 라인이 적어도 한번 실행되는지를 검증
- 모든 문장이 실행되는 테스트 케이스가 있다고 해도 오류가 존재할 수 있음
- 분기 커버리지 : if 문에는 true,false 두가지에 대해 검증
- 분기가 두개있으면 (TT,FF) (TF,FT) 두 케이스 중 하나면 ok
- 만약 OR조건으로 X>1이라고 적혀있어서 X=1을 두고 테스트했다면 경로는 제대로 체크되었다 해도, 사실 X<1인데 잘못 적어놓은 오류를 감지하지 못함
- 경로 커버리지 : 모든 실행 경로를 테스트하는 기준
- 분기문이 두개면 TT,TF,FT,FF 의 경로를 지나는 테스트 케이스 4개를 작성
- 조건 검증 : if,while안의 조건에 대한 검증
- 조건문 안에서 가능한 조건 조합을 모두다 적고, 해당 조건 조합들을 전부 통과하는 테스트 케이스를 찾는것
- 분기랑 통과조건은 같음
- 근데 위의 경우 a,b,x가 1,0,3 / 2,1,1 인 경우 모든 조건 조합을 만족하는데, 둘의 경로가 모두 abe임 즉, 감지하지 못하는 오류가 생김
- mutiple condition coverage
- 분기,조건 검증의 경우 많은 테스트 케이스에도 불구하고 오류가 발생할 수 있고 이를 감지하지 못할 수 있기에, AND,OR 조건을 나누어서 검증함
- 쉽게생각하면, 모든 경우의 수를 소규모로 쪼갈라서 보는 것
- 상태기반 테스팅
- 같은 입력에 대해 같은 동작을 보이며 동일한 결과를 생성하는 시스템
- 통합 테스트
- 여러 개발팀에서 개발한 각각의 단위 모듈간의 결합을 테스트
- 드라이버 : 시험 대상 모듈을 호출하는 간이 소프트웨어
- 스텁 : 시험 대상 모듈이 호출하는 다른 모듈
- 빅뱅 : 한번에 모든 모듈을 통합
- 장점 : 일정관리 편함
- 단점 : 오류의 위치,원인 찾기 어려움
- Top down(하향식) : 구조상 최상위 모듈부터 통합(bfs tree기준 위 level부터 통합테스트)
- 장점 : 중요한 모듈 조기 테스트 가능, 개발자 입장에서 용이
- 단점 : 입출력 모듈이 상대적으로 하위에 있음 : 테스트 케이스 작성 및 실행이 어려움
- Bottom up(상향식) : 반대
- 장점 : 점증적 통합 방식 : 오류발견 쉬움, 하드웨어 사용 분산
- 단점 : 초기에 시스템의 뼈대가 갖추어 지지 않음, 상위층의 중요한 기능을 마지막에 가서 확인가능
- Threads : 특정 기능을 수행하는 모듈의 최소단위(thread)로부터 시작, 상대적으로 중요한 모듈부터 개발
- 초기에 시스템 골격 형성, 시스템을 여러 프로그램에게 나누어 개발,진도확인이 가능
- 시스템 및 인수 테스팅 : 통합 후 수행하는 테스트 기법
- 테스트의 종류
- 기능 테스트 : 기능적 요구와 시스템 차이를 발견하기 위해 하는 테스트
- 성능 테스트 : 부하,처리량,반응시간 등을 테스트
- 보안 테스트 :보안 취약점을 찾아내려는 목적
- 사용성 테스트 : 인간 공학적인 기능 테스트(보고 느끼는 UI에대한 결함 테스트)
- 인수 테스트 : 의뢰자,대리인이 테스트 수행
- 설치 테스트
Chap 11. 유지보수
- 유지보수란 레거시 시스템(기존에 만든 시스템)의 버그제거, 여러 변화에 따른 대처를 위해 하는 것
- 유지보수의 유형
- 수정형 : 발견된 결함을 고치기 위해 수정
- 적응형 : 변경된 환경에서 사용하기위해 수정
- 완성형 : 기능을 추가해서 성능 개선
- 예방형 : 오류 발생 방지를 위해
- Lehman의 법칙
- 시스템의 타입은 E(계속 진화하는,evolution) 와 S(완전히 정의할 수 있는,static)타입으로 나눌 수 있음
- E타입에 적용되는 법칙임
- 지속적인 변경의 법칙
- 엔트로피,복잡도 증가의 법칙
- 자기 통제의 법칙 등등
- 유지보수 작업은 이해 중심의 작업( 문서작업이 중요하다 )
- 유지보수 프로세스 모델
- 즉시 수정 모델 : 코드를 수정해서 새로 만든 시스템을 다시 요구분석,설계,테스팅을 하는 것
- 반복적 개선 모델 : 테스팅 후, 다시 처음부터 요구분석,설계,코딩,테스팅 이렇게 반복하는 것
- 재사용 중심 모델 : 버전을 여러개 만들어서 컴포넌트 저장소에서 버전관리를 하는 것
- 형상관리 : 개발하는 동안 만든 문서관리, 문서와 결과물이 일치하게 유지해야 한다
- baseline : configuration item의 집합
- 절차
- 형상파악 : 문서종류, 생성 날짜, 버전 번호등을 파악
- 형상 변경 제어 : 변경 이유 파악,변경 분석, 변경 제안 및 평가, 변경
- 형상 감사 : 베이스라인 구축을 위한 메커니즘 정의, configuration item verification,validation
- 형상 상태 보관
- 역공학 : 구현한 원시 코드에서 소프트웨어 결과물들을 추출하는 것
- 용도
- 프로그램 이해
- 정형적 분석
- 테스트 케이스 생성
- 리엔지니어링 : 시스템,컴포넌트를 재구조화 하는 과정
Chap12.품질
- 품질
- 시스템,구성요소,프로세스가 지정된 요구 사항을 충족시키는 정도
- 시스템,구성요소,프로세스가 고객 또는 사용자의 요구나 기대를 충족시키는 정도
- 품질 속성
- 품질 관리
- 소프트웨어가 주어진 요구에 적합하다는 것을 보장하기 위해 필요한 활동
- 품질 계획 : 프로젝트 초반에 프로젝트에대한 품질 계획작성
- 품질 제어 : 프로젝트 전반에 걸쳐 품질 계획의 실행을 모니터링, 수정이 필요하면 품질 계획 수정
- 품질 측정
- 소프트웨어 측정 : 소프트웨어 속성의 객관적이고 정량적인 평가
- 소프트웨어 메트릭 : 표준화된 소프트웨어 측정 방법
- (전통적인 품질 메트릭, 시간 남으면 보셈)
- 프로세스의 성숙도를 평가 하기 위한 프레임워크
- MVC는 DI를 통해서, 트랜잭션은 AOP를 통해, 인증과 권한은 Servlet Filter