본문 바로가기
독서 기록

[오브젝트] 7장 - 객체 분해

by 워냥 2024. 4. 14.

내용 정리: 20240410 TIL


1. 개요

복잡한 문제를 단번에 해결하는 것은 어렵다.

그 문제를 해결하기 위해서는 너무 많은 정보가 필요하고, 우리의 머리는 이를 버티지 못한다.

이처럼 문제 해결에 필요한 정보가 용량을 초과하는 경우를 인지 과부하(congitive overload)라고 한다.

 

인지 과부하를 막기 위해 우리는 복잡하고 큰 문제를 해결할 수 있는 작은 문제로 나눈다.

추상화를 사용해 정보의 핵심만을 남기며 문제를 분해(decomposition)한다.

 

프로그래밍 언어도 추상화를 통해 복잡성을 극복하며 발전해 왔다.

기계어는 어셈블리어로 추상화되고, 어셈블리어는 고수준 언어로 추상화되었다.

프로그래밍 패러다임도 추상화와 분해의 관점에서 살펴보자.


2. 프로시저 추상화와 데이터 추상화

프로시저 추상화

프로시저 추상화(procedure abstraction)는 소프트웨어가 무엇을 해야 하는지를 추상화한다.

소프트웨어는 프로시저(함수)를 통해 데이터를 조작한다.

프로시저라는 기능을 중심으로 거대한 시스템을 분리하는 것이 바로 프로시저 추상화이다.

 

데이터 추상화

데이터 추상화(data abstraction)는 소프트웨어가 무엇을 알아야 하는지를 추상화한다.

 

추상화는 타입을 추상화하는 방식과 프로시저를 추상화하는 방식으로 나뉜다.

타입 추상화를 추상 데이터 타입(Abstract Data Type), 프로시저 추상화를 객체지향(Object-Oriented)이라고 부른다.


3. 프로시저 추상화와 기능 분해

개발 분야의 초기에는 기능을 기준으로 시스템을 분해했다.

거대한 시스템을 프로시저(함수)를 단위로 하여 분해해 나가는 방식이다.

 

프로시저 추상화는 하향식 접근법(Top-Down Approach)으로 볼 수 있다.

전체 시스템을 하나의 메인 함수라고 생각하고 이 메인 함수를 더 작은 함수들로 나누는 과정으로 이뤄진다.

 

단점 1: 설계가 유연하지 못함

하향식 기능 분해는 설계가 유연하지 못하다는 단점이 있다.

대부분의 시스템에서 하나의 메인 기능이라는 개념은 존재하지 않기에 하향식 접근법을 적용하기 어렵다.

 

하향식 접근법은 설계를 시작하는 시점부터 무엇보다는 어떻게 동작하는지에 집중한다.

'어떻게'에 집중하면 처음부터 구현을 고려하여 설계를 하게 된다.

따라서 새로운 요구사항이 생겼을 때 기존 설계를 재사용하기 어렵다.

 

단점 2: 데이터를 추적하기 어려움

하향식 기능 분해는 각 데이터를 어떤 함수가 사용하고 있는지 추적하기가 매우 어렵다.

함수들이 어떤 데이터에 의존하고 있는지 알고 싶다면, 모든 함수의 코드를 보며 데이터를 사용하고 있는 부분을 확인해야 한다.

 

이러한 특성 때문에 데이터 변경으로 인해 발생하는 영향을 예측하기 어렵다.

변경의 결과를 운에 맡기게 되고 이는 버그로 이어지게 된다.

 

하향식 분해를 사용하는 경우

여러 단점을 이야기했지만 하향식 분해가 무조건 안 좋은 것은 아니다.

하향식 방법론은 이미 완전히 이해된 사실을 서술하기에 적합하다.

예를 들어, 작은 알고리즘을 구현할 때는 하향식을 사용하면 좋다.

 

하지만 새로운 것을 개발하고 설계할 때는 하향식보단 다른 방법을 선택하는 것이 좋다.

문제가 이미 해결되지 않은 경우 하향식을 사용하면 부정적인 영향을 줄 수 있다.


3. 모듈

모듈이란?

모듈은 변경의 방향에 맞춰 시스템을 분해한다는 관점에서 출발한 기법이다.

변경에 유연하려면 자주 변경되는 부분을 숨겨야 한다.

이를 정보 은닉(information hiding)이라고 부른다.

 

모듈의 장점과 한계

모듈은 자주 변경되는 부분을 그 내부에 위치시킨다.

따라서 모듈 내부의 변수가 변경되더라도 그 영향이 외부에 전달되지 않는다.

모듈은 감춰야 할 데이터를 결정하고 이를 조작하는 데 필요한 함수를 결정할 수 있다.

 

하지만 모듈은 변경을 관리하기 위해 나온 구현기법이므로 인스턴스라는 개념을 제공하지 않는다.

추상화 관점에서는 한계가 명확하다.


4. 추상 데이터 타입

데이터 추상화(data abstraction)는 추상 객체의 클래스를 정의한 것이다.

추상 데이터 타입을 구현하기 위해서는 타입(type)을 프로그래머가 정의할 수 있어야 한다.

 

추상 데이터 타입은 모듈과는 다르게 개별 대상의 인스턴스를 생성할 수 있다.

인스턴스를 통해 프로그래머는 표현할 수 있는 범위가 더 넓어진다.


5. 클래스

클래스는 추상 데이터 타입일까?

추상 데이터 타입과 클래스 모두 외부에서 내부 속성에 접근할 수 없고 인터페이스를 통해서만 소통할 수 있다.

그러나 클래스는 상속과 다형성을 지원하지만 추상 데이터 타입은 지원하지 못한다는 차이점이 있다.

 

객체지향 프로그래밍(Object-Oriented Programming)은 상속과 다형성을 지원한다.

객체기반 프로그래밍(Object-Based Programming)은 상속과 다형성을 지원하지 않는 추상 데이터 타입 기반이다.

 

변경을 기준으로 선택하기

추상 데이터 타입과 객체지향은 차이점이 존재하지만 무엇이 더 좋다고 할 수는 없다.

 

타입 추가라는 변경의 압력이 강한 경우 객체지향을 선택하자.

객체지향은 다형성을 사용해 타입을 구분할 수 있다.

이런 특성 덕분에 타입 추가라는 변경이 있을 때 코드를 수정하지 않아도 된다.

 

반면 오퍼레이션 추가라는 변경의 압력이 강한 경우 추상 데이터 타입을 선택하자.

새로운 오퍼레이션이 추가된 경우 객체지향은 상속 계층에 있는 모든 클래스를 수정해야 한다.

하지만 추상 데이터 타입은 구현 코드가 하나의 구현체 내에 있기에 비교적 간단하게 수정할 수 있다.

 

어떤 변경이 예상해 보고 이에 따른 적절한 구조를 선택하자.

객체지향적 접근법이 항상 올바른 해결 방법은 아니다.


6. 느낀 점

분해의 관점에서 하향식 기능 분해, 추상 데이터 타입, 객체지향이라는 구조를 살펴보았다.

각 구조가 무엇에 초점을 맞추고 있는지, 어떤 장단점을 가지고 있는지 알 수 있었다.

 

과거 C로 프로젝트를 진행할 때 하향식 기능 분해를 주로 사용했다.

이때 하나의 변수를 수정하게 되면 그 영향이 예상하지 못한 함수까지 가게 되었다.

하향식 기능 분해를 사용하며 불편했던 경험이 변수가 어떤 함수에서 사용되는지 찾기 어려웠기 때문임을 알게 되었다.

 

하지만 각 구조는 모두 자신만의 장단점을 가지고 있다.

구조들을 좋고 나쁨으로 구분하는 것은 성급한 판단이다.

내가 처한 상황에 적절한 구조를 선택할 수 있는 넓은 시야를 가지는 것이 중요할 것 같다.

댓글