객체 분해
- 불필요한 정보를 제거하고 현재의 문제 해결에 필요한 핵심만 남기는 것을 추상화라고 한다.
- 큰 문제를 해결 가능한 작은 문제로 나누는 것을 decompoistion(분해)라고 한다.
프로시저 추상화, 데이터 추상화
- 프로시저 추상화는 SW가
무엇을 해야 하는지
를 추상화 한다. - 데이터 추상화는 SW가
무엇을 알아야 하는지
를 추상화 한다. - 프로시저 중심 시스템 분화는 기능분해(functional decomposition), 기능 분해는 알고리즘 분해(algorithmic decomposition)이라고 한다.
- 데이터를 중심으로 타입을 추상화(type abstraction)라고 한다. -> 추상 데이터 타입(Abstract Data Type)
- 다른 하나는 데이터 중심으로 프로시저를 추상화하는 것이다.(procedure abstraction) -> 객체 지향(Object-Oriented)
프로시저 추상화
- 내부의 상세한 구현 내요을 모르더라도 인터페이스만 알면 프로시저를 사용할 수 있기 때문이다.
- 전통적 기능 분해 방법으로 Top-Down이 있다.
- 시스템은 하나의 메인 함수로 구성돼 있지 않다.
- 기능 추가나 요구 사항 변경으로 메인 함수를 빈번하게 수정해야 한다.
- 비즈니스 로직이 사용자 인터페이스와 강결합한다.
- 하향식 분해는 너무 이른 시기에 함수들의 실행 순서를 고정시키기 때문에 유연성과 재사용성이 저하된다.
- 데이터 형식이 변경되면 사이드 이펙트를 가늠하기 어렵다.
-> 따라서 데이터와 함께 변경되는 부분, 아닌 부분을 명확하게 분리하고 변경되는 부분을 하나의 구현 단위로 묶고 외부에는 함수만 제공하는 것이 좋다.
- 기능을 중심으로 필요한 데이터를 결정한다.
모듈
- 변경되는 부분을 하나의 구현 단위로 묶고 퍼블릭 인터페이스를 통해서만 접근하도록 만드는 것이다.
- 기능을 기반으로 시스템 분해가 아니라 변경의 방향에 맞춰 시스템을 분해하는 것이다.
- 정보 은닉은 모듈 단위로 분해하기 위한 기본 원리로 시스템에서 자주 변경되는 부분을 상대적으로 덜 변경되는 안정적인 인터페이스 뒤로 감춰야 한다는 것이 핵심이다.
- 모듈은 변경될 가능성이 있는 비밀을 내부로 감추고, 잘 정의되고 쉽게 변경되지 않을 퍼블릭 인터페이스를 외부에서 제공해서 내부의 비밀에 함부로 접근하지 못하게 한다.
- 복잡성 : 외부에 모듈을 추상화할 수 있는 간단한 인터페이스를 제공해서 모듈의 복잡도를 낮춘다.
- 변경 가능성 : 변경 발생 시 하나의 모듈만 수정하면 되도록 변경 가능한 설계 설정을 모듈 내부로 감추고 외부에는 쉽게 변경되지 않을 인터페이스를 제공한다.
장점, 한계
장점
- 모듈 내부의 변수가 변경되더라도 모듈 내부에만 영향을 미친다.
- 비즈지스 로직과 사용자 인터페이스에 대한 관심사를 분리한다.
- 전역 변수와 전역 함수를 제거함으로써 namespace pollution을 방지한다.
데이터 추상화와 추상 데이터 타입
추상 데이터 타입
- 추상 데이터 타입에서 익숙한 이름은 리스코프다.
- 추상 데이터 타입을 구현하려면 프로그래밍 언어의 지원이 필요하다.
- 타입 정의를 선언할 수 있어야 한다.
- 타입의 인스턴스를 다루기 위해서 사용할 수 있는 오퍼레이션의 집합을 정의할 수 있어야 한다.
- 제공한 오퍼레이션을 통해서만 조작할 수 있도록 데이터를 외부로부터 보호할 수 있어야 한다.
- 타입에 대해 여러 개의 인스턴스를 생성할 수 있어야 한다.
- 추상 데이터 타입은 시스템의 상태를 저장할 데이터를 표현한다.
- 추상 데이터 타입의 기본 의도는 프로그래밍 언어가 제공하는 타입처럼 동작하는 사용자 저으이 타입을 추가할 수 있게 하는 것이다.
클래스
- 추상 데이터와 클래스는 동일하지 않다. 핵심적이 차이는 클래스는 상속과 다형성을 지원한다. 그러나 추상 데이터 타입은 지원하지 않는다.
- 상속과 다형성을 지원하면 객체 지향 프로그래밍이고 상속과 다형성을 지원하지 않는 추상 데이터 타입 기반의 프로그래밍 패러다임을 객체 기반 프로그래밍이라고 부른다.
- 추상 데이터 타입이 오퍼레이션을 기준으로 타입을 묶는 방법이라면 객체 지향은 타입을 기준으로 오퍼레이션을 묶는다.
- 객체 지향은 상속 다형성으로 절차에 대한 차이점을 감춘다. 즉 객체 지향은 절차 추상화(procedural abstraction)이다.
변경을 기준으로 선택하기
- 클래스를 사용해서 구현한다고 객체지향이 아니다.
- 타입을 기준으로 절차를 추상화해야 객체지향이다.
- 객체가 메시지를 처리할 적절한 메소드를 선택한다.
방향성
- 어떤 방향이 좋은 방향인가? 항상 절차를 추상화하는 객체 지향 설계를 따라야 하는가?
- 설계는 변경과 관련된 것이다. 설계의 유용성은 변경의 방향성과 발생 빈도에 따라서 결정된다.
- 추상 데이터 타입과 객체 지향 설계의 유용성은 설계에 요구되는 변경의 압력이 ‘타입 추가’에 관한 것인지, ‘오퍼레이션 추가’에 관한 것인지 달라진다.
- 타입 추가 압력이 강하다면 객체 지향의 손을 들어야 좋다. 추상 데이터 타입의 경우 새로운 타입을 추가하려면 타입 체크 코드를 일일이 수정해야 한다. 객체지향은 상속 계층을 추가해서 풀어낼 수 있다.
- 오퍼레이션을 추가하는 것이 주된 압력이라면 추상 데이터 타입을 주목해야 한다. 객체지향의 경우 새로운 오퍼레이션 추가를 위해서는 상속 계층에 속하는 모든 클래스를 한 번에 수정해야 한다.
- 결과적으로 새로운 타입을 빈번하게 추가하면 객체지향, 새로운 오퍼레이션을 빈번하게 추가해야 한다면 추상 데이터 타입이다.
협력
- 객체지향은 기능을 수행하기 위해서 객체들이 협력하는 방식에 집중한다.
- 협력이라는 문맥 없이 고립시키고 오퍼레이션을 분배해서 개발하는 것은 그다지 좋은 방법이 아니다.