포스트

[소프트웨어 공학] 설계원리

[소프트웨어 공학] 설계원리
  • 매우 간략하게 요약되어 있습니다.

요구분석 VS 설계

  • 요구 분석, what(무엇) 관점
    • “무엇을 만들 것인가?”
    • 기능을 식별하는 과정
    • 고객의 “요구”가 중심
  • 설계, how(어떻게) 관점
    • “어떻게 만들 것인가?”
    • 논리적인 구성을 결정하는 과정
    • 요구를 구현하는 “솔루션”이 중심

전통적인 설계 원칙

  • 추상화(abstraction)
  • 캡슐화(encapsulation)
  • 모듈화(modularization)

추상화

  • 구체적인 구현은 뒤로 미루고, 인터페이스(기능 정의)만 먼저 설정한다.
    • 예시: 함수 원형만 미리 정의하고, 구현은 나중에 진행
  • 객체지향에서는 객체들의 공통점을 뽑아 클래스라는 이름을 붙여놓은 것을 말한다.
  • 반대로 클래스로부터 객체를 생성하는 과정을 인스턴스화(instantiation)라고 한다.

  • 예시
    • 클래스 메서드들의 함수 원형을 결정하고
    • 구현 여부와는 관계 없이
    • 함수 원형, 정보만 이용해서 설계한다.

    클라이언트 <-> 서버 통신에서

    • 각 파트의 세부 구현 내용은 미뤄두고
    • 인터페이스에 해당하는 RESTful API를 먼저 정의한다.
    • 어떤 방식으로 어떤식으로 호출할지.

캡슐화

  • 내부 데이터나 로직을 숨기고, 외부에서 메서드로만 접근 가능하게 한다.
  • 정보 은닉 (Information Hiding)을 실현하는 방법

모듈화

  • 연관이 있는 소프트웨어 구성 요소들로 분활하는 방식
  • 반대로는 monolithic system이 있다.
    • monolithic system: 모듈화 없이 하나의 큰 덩어리로 되어 있는 시스템을 말한다.
      • 불필요한 것들이 같이 복사되고, 실행시간(로딩)이 오래걸린다.

장점

  • 각각의 모듈을 독립적으로 수정할 수 있다.
    • 유지보수가 용이하다.
  • 디버깅이 편리하다.
    • 문제 영역을 한정 가능하다.
  • 개발 생산성 향상 및 모듈 변경에 따른 영향을 최소화한다.
    • 의존성이 감소한다.

단점

  • 지나치게 세분화하면 모듈간 상호 작용을 이해하지 못해 내부 구조 파악이 어려울 수 있다.
    • 사용 용이도가 떨어진다.

좋은 모듈화가 기준은?

  • 결합도는 낮고, 응집도는 높아야 한다.

그렇다면 결합도와 응집도는 무엇인가?

결합도 (Coupling)

  • 모듈 간에 서로 의존하는 정도를 말한다.
  • 결합도가 높다?
    • 모듈 간 상호 작용이 많다. -> 이해하기 어렵다. -> 버그 발생률이 올라간다.
    • 변경 사항의 파급력이 크다 -> 생산성이 떨어지고 ,버그 발생률이 올라간다.
  • 낮은 결합도 = 독립적인 모듈 = 좋은 설계 = 좋은 소프트웨어
  • 결합도에 영향을 미치는 요소
    1. 모듈 외부로 노출되는 인터페이스 수
      • public class, public method, ……
    2. 결합도 종류:
      • 내용 결합 (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 라이센스를 따릅니다.