: 우리는 소프트웨어 설계에 관해 정말 제대로 배우지 못했다.
코드에 적용되는 설계원칙
•
KISS : 제발 간단하게 클래스나 메서드를 만들라는 법칙
•
DRY : 반복되는 기능이나 객체를 하나로 만들어서 관리하라는 법칙
•
YAGNI : 코드를 적어나가다 보면 갑자기 머릿속에서 떠오르는 중요한 기능이 있어서 막 적지만 결국 안 쓴다는 법칙
: 원칙이라고 이런 것들을 구호나 주문처럼 간직하면서 코드를 작성, 볼 때마다 꺼내들곤 한다.
: 이런 것들을 지키지 못하고 코드를 짜면 죄책감 마저 든다.
객체지향 프로그래밍에 적용되는 설계원칙
•
SRP : 각 클래스는 하나의 정보만을 책임지고 각 클래스에서 공통적인 특성을 뽑아낼 수 있다면 이는 하나의 슈퍼 클래스로 옮긴 다음 변화하는 특성만 상속이나 구현으로 처리하는 원칙
•
OCP : 확장에는 열려 있으며 변경에는 닫혀 있어야 한다는 원칙
•
LSP : 인터페이스의 서브타이핑은 인터페이스에 정의된 형태를 최대한 유지해야한다는 원칙
•
ISP : 인터페이스는 최소한으로 유지하라는 원칙
•
DIP : 상위 레벨의 모듈이나 인터페이스가 서브 클래스나 타이핑에 영향을 받아서는 안 된다는 원칙
: 위의 다섯가지 원칙은 소프트웨어의 ‘유연성, 확장성, 유지보수성’을 갖추게 해주는 원칙들, 이러한 원칙들을 지키지 않으면 디자인 악취가 발생한다고 함
⇒ 왜? 하나의 정보만 책임져야하는가? 왜 확장엔 열려있고 변경에는 닫혀있어야 하는가?
디자인 악취
•
경직성 : 프로그램 변경이 어려워진다. 변경하려면 시스템의 다른 부분까지 많이 변경해야하기 때문입니다.
•
취약성 : 프로그램을 변경하면 변경 부분과 논리적으로 아무런 연관이 없는 부분에서 장애가 발생합니다.
•
부동성 : 프로그램에서 재사용할 수 있는 컴포넌트로 구분하기가 어려워집니다.
•
점착성 : 기존 디자인에 적용된 철학이나 방식을 지속적으로 유지하는게 어렵거나 개발 환경 자체가 느리고 비효율적인 경우를 말합니다.
•
불필요한 복잡성 : 쓸데없는 기반 구조가 디자인에 포함되어 있습니다.
•
불필요한 반복 : 단일 추상 개념으로 추상화가 가능한 반복적인 구조가 디자인에 포함되어 있습니다.
•
불투명성 : 직접 만든 사람이 아닌 경우 다른 사람이 코드를 읽고 이해하기가 어렵습니다.
: 이는 ‘원인’이 아닌 ‘결과’다, 즉 위의 원칙들과 정확한 인과 관계를 설명해주지 않으므로 이해하기가 어렵다.
우리는 코드를 설계하는 과정에 있어서 지금까지 어떠한 결과에 대해서만 학습했다.
어떤 원인이 어째서 그러한 결과를 불러오는지 그 인과 관계를 학습하지 못했다. 이는 제대로 배우지 못한 것
디자인 악취를 위해하기 위한 가정
•
소프트웨어는 ‘제대로’ 디자인하고 만들기에 늘 시간과 사람이 부족하다.
•
소프트웨어는 한 사람이나 팀이 처음부터 끝까지 개발하지 않고 언젠가는 전혀 히스토리를 모르는 사람이 개발을 맡게 된다.
•
소프트웨어는 한번 만들어지고 나면 아주 오랫동안 사용된다.
•
이미 릴리즈된 소프트웨어는 다음 버전이나 개선 때 더 빨리 만들 수 있다고 믿는다.
•
소프트웨어에 세계에서 변하지 않는 건 ‘시간/사람/돈에 대한 결핍’ 외에는 아무것도 없다.
•
소프트웨어에 대한 요구사항은 의도적이든 아니면 자연적이든 시간이 지남에 따라 늘 변한다.
: 소프트웨어나 프로그램을 둘러싼 상황이 늘 가변적이고 리소스가 계속 부족한 상태에서 코드를 만들어 완성해야 하는 일이 세상 모든 곳에서 발생
: 많은 사람이 망각의 축복을 만끽하는 바람에 하나의 기능이나 완결된 버전의 소프트웨어를 만들고 나면 그 이후에 발생하는 많은 요구사항과 기능을 더 적은 리소스로 해결하려 함
소결론
: 소프트웨어 디자인 또는 소프트웨어 생성에는 작은 단위인 코드, 클래스 프로그래밍에 적용되는 원칙도 중요하고 그다음 단계라고 할 수 있는 객체지향 프로그래밍에 필요한 디자인 원칙도 중요하다. 하지만 이런 원칙들이 꼭 훌륭한 소프트웨어 제품으로 연결되는 것은 아니므로 소프트웨어 제품이 잘 완성될 수 있게 하는 ‘디자인 원칙’이 필요하다.
디자인이란 무엇인가?
: 디자인이란 설계다. 설계란 계획을 세움, 건축물 설립이나 토지 공사, 기계의 제작 따위에서 그 목적에 따라 실제적인 계획을 세우고 구체적으로 도면을 그려 명시하는 일
: 2번이 주로 우리가 소프트웨어 제품을 개발할 때, 적용해볼 수 있는 의미로, 그 ‘목적’에 따라 ‘실제적인 계획’을 세우고 ‘구체적으로 도면’을 그려 명시하는 일이 설계
소프트웨어 설계
: 테스트주도 개발, 동작 주도 개발, 도메인 주도 개발 개념이 들어있음.
: 대부분의 경우 개발은 코드를 만들거나 작성하는 행위 자체를 의미하기 때문에 제품 생산 기술에 더 가깝고 테스트나 동작이 주도하는 것은 아니므로 테스트는 설계의 서브 개념이거나 설계의 결과물에 가까움
소프트웨어 설계 원칙 : 통합적으로 설계하라
: 최대한 많은 정보를 기반으로 요구사항을 정리해야 한다.
•
명시적 소프트웨어 설계
: 명시적 소프트웨어 설계는 기본적으로 명시적으로 요구사항과 연결되는 설계, 만들 것이 명확하게 정의되기 때문에 비교적으로 단순하게 그리고 직관적으로 설계가 가능하며 테스트 및 증명도 쉬움, 기능, 성능, 유지보수, 미적 설계 4가지의 항목으로 구성됨
◦
기능 설계
▪
새로 만들거나 개선할 기능을 SRS(기획서) 기반으로 정의하고 기능을 만족하는지 수치적으로 증명할 수 있는 조건도 정의
▪
대개는 이 과정에서 기능 정의와 관련된 데이터 종류, 클래스의 기능 테스트를 수행할 데이터나 방법을 정함
◦
성능 설계
▪
대부분의 기능 요구사항에 대응하는 설계의 결과물은 바이너리 형태가 되어서 기능을 만드는 사람과 사용자 모두 쉽게 파악할 수 있음
▪
하지만 성능에 대한 설계를 시작하면 매우 골치아파진다. 하루에 100명 정도가 접근하는 서비스와 100만 명이 접근하는 소프트웨어의 기능은 같을 수 있다.
▪
하지만 내부 구조는 완전히 바뀔 수 있다. 부하 분산기가 붙고 동시성을 보장하는 클래스/데이터/알고리즘이 추가되어야함
▪
설계의 결과물로 반드시 성능과 관련된 부분들도 표시 또는 기록해야 함
◦
유지보수 설계
▪
다양한 환경에서의 서비스를 지원하기 위해 이런 테스트 환경을 모두 마무리한 후 릴리즈해야 한다.
▪
이러한 설계는 배치뿐만 아니라 업그레이드, 컴퓨팅 용량 조절들도 가능하게 해야하며 유지보수에 필요한 수치적인 조건을 예상하고 정하는 일이 쉬워진다.
◦
미적 설계
▪
사용자에게 물리적, 심리적으로 즐거움과 편리함을 줄 수 있도록 제품을 미적으로 설계하는 것, 일반적으로 디자이너가 이 영역에서 작업
•
암묵적 소프트웨어 설계
◦
서비스 지속성 설계
▪
가용성 설계
▪
용량 설계
▪
연속성 설계
▪
보안 설계
◦
서비스 전환 설계
▪
변환 설계
▪
릴리즈 설계
▪
설정 관리 설계
◦
서비스 운영 설계
▪
장애 대비 설계
▪
요구 수행 설계
▪
문제 대응 설계
◦
서비스 개선 설계
▪
서비스 리포팅 설계
▪
서비스 측정 설계
▪
서비스 레벨 설계