객체 분해

  • 불필요한 정보를 제거하고 현재의 문제 해결에 필요한 핵심만 남기는 것을 추상화라고 한다.
  • 큰 문제를 해결 가능한 작은 문제로 나누는 것을 decompoistion(분해)라고 한다.

프로시저 추상화, 데이터 추상화

  • 프로시저 추상화는 SW가 무엇을 해야 하는지를 추상화 한다.
  • 데이터 추상화는 SW가 무엇을 알아야 하는지를 추상화 한다.
  • 프로시저 중심 시스템 분화는 기능분해(functional decomposition), 기능 분해는 알고리즘 분해(algorithmic decomposition)이라고 한다.
  • 데이터를 중심으로 타입을 추상화(type abstraction)라고 한다. -> 추상 데이터 타입(Abstract Data Type)
  • 다른 하나는 데이터 중심으로 프로시저를 추상화하는 것이다.(procedure abstraction) -> 객체 지향(Object-Oriented)

프로시저 추상화

  • 내부의 상세한 구현 내요을 모르더라도 인터페이스만 알면 프로시저를 사용할 수 있기 때문이다.
  • 전통적 기능 분해 방법으로 Top-Down이 있다.
    • 시스템은 하나의 메인 함수로 구성돼 있지 않다.
    • 기능 추가나 요구 사항 변경으로 메인 함수를 빈번하게 수정해야 한다.
    • 비즈니스 로직이 사용자 인터페이스와 강결합한다.
    • 하향식 분해는 너무 이른 시기에 함수들의 실행 순서를 고정시키기 때문에 유연성과 재사용성이 저하된다.
    • 데이터 형식이 변경되면 사이드 이펙트를 가늠하기 어렵다.

    -> 따라서 데이터와 함께 변경되는 부분, 아닌 부분을 명확하게 분리하고 변경되는 부분을 하나의 구현 단위로 묶고 외부에는 함수만 제공하는 것이 좋다.

  • 기능을 중심으로 필요한 데이터를 결정한다.

모듈

  • 변경되는 부분을 하나의 구현 단위로 묶고 퍼블릭 인터페이스를 통해서만 접근하도록 만드는 것이다.
  • 기능을 기반으로 시스템 분해가 아니라 변경의 방향에 맞춰 시스템을 분해하는 것이다.
  • 정보 은닉은 모듈 단위로 분해하기 위한 기본 원리로 시스템에서 자주 변경되는 부분을 상대적으로 덜 변경되는 안정적인 인터페이스 뒤로 감춰야 한다는 것이 핵심이다.
  • 모듈은 변경될 가능성이 있는 비밀을 내부로 감추고, 잘 정의되고 쉽게 변경되지 않을 퍼블릭 인터페이스를 외부에서 제공해서 내부의 비밀에 함부로 접근하지 못하게 한다.
    • 복잡성 : 외부에 모듈을 추상화할 수 있는 간단한 인터페이스를 제공해서 모듈의 복잡도를 낮춘다.
    • 변경 가능성 : 변경 발생 시 하나의 모듈만 수정하면 되도록 변경 가능한 설계 설정을 모듈 내부로 감추고 외부에는 쉽게 변경되지 않을 인터페이스를 제공한다.

장점, 한계

장점
  1. 모듈 내부의 변수가 변경되더라도 모듈 내부에만 영향을 미친다.
  2. 비즈지스 로직과 사용자 인터페이스에 대한 관심사를 분리한다.
  3. 전역 변수와 전역 함수를 제거함으로써 namespace pollution을 방지한다.

데이터 추상화와 추상 데이터 타입

추상 데이터 타입

  • 추상 데이터 타입에서 익숙한 이름은 리스코프다.
  • 추상 데이터 타입을 구현하려면 프로그래밍 언어의 지원이 필요하다.
    • 타입 정의를 선언할 수 있어야 한다.
    • 타입의 인스턴스를 다루기 위해서 사용할 수 있는 오퍼레이션의 집합을 정의할 수 있어야 한다.
    • 제공한 오퍼레이션을 통해서만 조작할 수 있도록 데이터를 외부로부터 보호할 수 있어야 한다.
    • 타입에 대해 여러 개의 인스턴스를 생성할 수 있어야 한다.
  • 추상 데이터 타입은 시스템의 상태를 저장할 데이터를 표현한다.
  • 추상 데이터 타입의 기본 의도는 프로그래밍 언어가 제공하는 타입처럼 동작하는 사용자 저으이 타입을 추가할 수 있게 하는 것이다.

클래스

  • 추상 데이터와 클래스는 동일하지 않다. 핵심적이 차이는 클래스는 상속과 다형성을 지원한다. 그러나 추상 데이터 타입은 지원하지 않는다.
  • 상속과 다형성을 지원하면 객체 지향 프로그래밍이고 상속과 다형성을 지원하지 않는 추상 데이터 타입 기반의 프로그래밍 패러다임을 객체 기반 프로그래밍이라고 부른다.
  • 추상 데이터 타입이 오퍼레이션을 기준으로 타입을 묶는 방법이라면 객체 지향은 타입을 기준으로 오퍼레이션을 묶는다.
  • 객체 지향은 상속 다형성으로 절차에 대한 차이점을 감춘다. 즉 객체 지향은 절차 추상화(procedural abstraction)이다.

변경을 기준으로 선택하기

  • 클래스를 사용해서 구현한다고 객체지향이 아니다.
  • 타입을 기준으로 절차를 추상화해야 객체지향이다.
  • 객체가 메시지를 처리할 적절한 메소드를 선택한다.

방향성

  • 어떤 방향이 좋은 방향인가? 항상 절차를 추상화하는 객체 지향 설계를 따라야 하는가?
  • 설계는 변경과 관련된 것이다. 설계의 유용성은 변경의 방향성과 발생 빈도에 따라서 결정된다.
  • 추상 데이터 타입과 객체 지향 설계의 유용성은 설계에 요구되는 변경의 압력이 ‘타입 추가’에 관한 것인지, ‘오퍼레이션 추가’에 관한 것인지 달라진다.
    1. 타입 추가 압력이 강하다면 객체 지향의 손을 들어야 좋다. 추상 데이터 타입의 경우 새로운 타입을 추가하려면 타입 체크 코드를 일일이 수정해야 한다. 객체지향은 상속 계층을 추가해서 풀어낼 수 있다.
    2. 오퍼레이션을 추가하는 것이 주된 압력이라면 추상 데이터 타입을 주목해야 한다. 객체지향의 경우 새로운 오퍼레이션 추가를 위해서는 상속 계층에 속하는 모든 클래스를 한 번에 수정해야 한다.
  • 결과적으로 새로운 타입을 빈번하게 추가하면 객체지향, 새로운 오퍼레이션을 빈번하게 추가해야 한다면 추상 데이터 타입이다.

협력

  • 객체지향은 기능을 수행하기 위해서 객체들이 협력하는 방식에 집중한다.
  • 협력이라는 문맥 없이 고립시키고 오퍼레이션을 분배해서 개발하는 것은 그다지 좋은 방법이 아니다.