[소프트웨어 공학] 설계원리
[소프트웨어 공학] 설계원리
- 매우 간략하게 요약되어 있습니다.
요구분석 VS 설계
- 요구 분석, what(무엇) 관점
- “무엇을 만들 것인가?”
- 기능을 식별하는 과정
- 고객의 “요구”가 중심
- 설계, how(어떻게) 관점
- “어떻게 만들 것인가?”
- 논리적인 구성을 결정하는 과정
- 요구를 구현하는 “솔루션”이 중심
전통적인 설계 원칙
- 추상화(abstraction)
- 캡슐화(encapsulation)
- 모듈화(modularization)
추상화
- 구체적인 구현은 뒤로 미루고, 인터페이스(기능 정의)만 먼저 설정한다.
- 예시: 함수 원형만 미리 정의하고, 구현은 나중에 진행
- 객체지향에서는 객체들의 공통점을 뽑아 클래스라는 이름을 붙여놓은 것을 말한다.
반대로 클래스로부터 객체를 생성하는 과정을 인스턴스화(instantiation)라고 한다.
- 예시
- 클래스 메서드들의 함수 원형을 결정하고
- 구현 여부와는 관계 없이
- 함수 원형, 정보만 이용해서 설계한다.
클라이언트 <-> 서버 통신에서
- 각 파트의 세부 구현 내용은 미뤄두고
- 인터페이스에 해당하는 RESTful API를 먼저 정의한다.
- 어떤 방식으로 어떤식으로 호출할지.
캡슐화
- 내부 데이터나 로직을 숨기고, 외부에서 메서드로만 접근 가능하게 한다.
- 정보 은닉 (Information Hiding)을 실현하는 방법
모듈화
- 연관이 있는 소프트웨어 구성 요소들로 분활하는 방식
- 반대로는 monolithic system이 있다.
- monolithic system: 모듈화 없이 하나의 큰 덩어리로 되어 있는 시스템을 말한다.
- 불필요한 것들이 같이 복사되고, 실행시간(로딩)이 오래걸린다.
- monolithic system: 모듈화 없이 하나의 큰 덩어리로 되어 있는 시스템을 말한다.
장점
- 각각의 모듈을 독립적으로 수정할 수 있다.
- 유지보수가 용이하다.
- 디버깅이 편리하다.
- 문제 영역을 한정 가능하다.
- 개발 생산성 향상 및 모듈 변경에 따른 영향을 최소화한다.
- 의존성이 감소한다.
단점
- 지나치게 세분화하면 모듈간 상호 작용을 이해하지 못해 내부 구조 파악이 어려울 수 있다.
- 사용 용이도가 떨어진다.
좋은 모듈화가 기준은?
- 결합도는 낮고, 응집도는 높아야 한다.
그렇다면 결합도와 응집도는 무엇인가?
결합도 (Coupling)
- 모듈 간에 서로 의존하는 정도를 말한다.
- 결합도가 높다?
- 모듈 간 상호 작용이 많다. -> 이해하기 어렵다. -> 버그 발생률이 올라간다.
- 변경 사항의 파급력이 크다 -> 생산성이 떨어지고 ,버그 발생률이 올라간다.
- 낮은 결합도 = 독립적인 모듈 = 좋은 설계 = 좋은 소프트웨어
- 결합도에 영향을 미치는 요소
- 모듈 외부로 노출되는 인터페이스 수
- public class, public method, ……
- 결합도 종류:
- 내용 결합 (Content Coupling)
- 공통 결합 (Common Coupling)
- 제어 결합 (Control Coupling)
- 스탬프 결합 (Stamp Coupling)
- 데이터 결합 (Data Coupling) - 강한 결합:
- 더 많은 의존
- 더 많은 협력
- 더 많은 정보흐름 - 느슨한 결합:
- 느슨한 의존
- 느슨한 협력
- 느슨한 정보흐름
- 모듈 외부로 노출되는 인터페이스 수
내용 결합
- 다른 모듈의 내부 데이터를 직접 조작하는 경우(직접적인 의존성이 있는 경우)
- 예시: public 멤버 변수에 직접 접근
- 문제점: 변경 시 모든 의존 모듈을 수정해야 함
- 해결책: 직접 접근 대신 적절한 메서드를 제공하여 처리
- 팁: public 변수는 지양하고, 적절한 이름의 메서드로 동작을 유도하세요.
공통 결합
- 전역 변수(shared static 등)를 여러 모듈이 공유할 때 발생한다.
- 문제점: 어느 한 모듈의 변경이 전체에 영향을 미친다.
- 해결책: 전역 변수 대신 Singleton 객체로 공유 구조를 명확히 표현한다.
- 참고: Singleton: 오직 하나만 존재하는 객체
- 팁: 설정 정보는 Config 클래스 등으로 관리하자.
제어 결합
- 매개변수 등으로 다른 모듈의 제어 흐름 경로를 바꿀 수 있는 경우를 말한다.
- 문제점: 하나의 함수가 너무 많은 역할을 하게 된다.
- 해결책:
- 메소드를 세분화 하고 호출하는 측에서 의도에 따라 구분해서 호출한다.
- 클래스의 다형성을 이용한다.
- 예시: 부모 클래스에서 메서드 선언 후, 자식에서 override
- 이 때 부모는 abstract class나 interface로 변경한다.
스탬프 결합
- 복합 객체 전체를 넘기지만 실제로 일부 필드만 사용하는 경우
- 문제점: 필요한 데이터만 전달하지 않아, 모듈 간 의존성이 생김
- 실제 사용하는 필드만 파라미터로 넘기는 것이 좋다.
데이터 결합
- 단순 데이터(기본형, 문자열 등)를 매개변수로 전달
- 결합도 측면에서 가장 바람직한 형태
- 매개변수가 많을 땐 스탬프 결합으로 전환 고려
- 매개변수가 많아지면 코드 가독성이 떨어져 어려울 수 있다.
응집도
- 모듈 내부 요소들이 얼마나 하나의 목적에 집중되어 있는가?
- 응집도는 높을수록 좋음 (모듈 재사용성, 유지보수성 증가)
- 응집도가 높을수록 연관된게 많을수록 좋다. 즉 연관된 것만 넣는다.
- 응집도 종류 (낮음 → 높음):
- 우연적 (coincidental)
- 논리적 (logical)
- 시간적 (temporal)
- 절차적 (procedural)
- 교환적 (communicational)
- 기능적 (functional)
결합도, 응집도가 빌드에 미치는 영향은 무엇인가?
- 높은 결합도 → 빌드 및 테스트 시 의존성 증가 → 생산성 저하
- 높은 응집도 → 모듈 변경이 독립적 → 빌드 효율성 증가
- 빌드 시간 줄이기 위해선:
- 병렬 빌드
- 의존성 제거
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.