공부기록/객체지향

오브젝트 7장 - 객체 분해

DGL 2022. 1. 15. 18:16

문제 해결에 필요한 요소의 수가 단기 기억의 용량을 초과하는 순간 문제 해결 능력은 급격하게 떨어지고 만다. → 인지 과부하

큰 문제를 작은 문제로 나누는 것 ⇒ 분해

추상화를 더 큰 규모의 추상화로 압축시킴으로써 단기 기억의 한계를 초월할 수 있다.

프로시저의 추상화와 데이터 추상화

시스템을 분해하는 방법으로 둘 중 하나를 선택해야함

프로시저 추상화 → 기능 분해의 길, 알고리즘 분해

데이터 추상화 → 타입 추상화(추상 데이터 타입), 데이터를 중심으로 프로시저를 추상화(객체지향)

객체지향이 전통적인 기능 분해 방법에 비해 효과적이라고 하는 이유는 무엇일까?

(전통적인 기능 분해 방법) → 객체지향 분해 방법에 이르는 좌절과 극복의 역사

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

전통적인 기능 분해 방법은 하향식 접근법을 따른다. 상위 기능은 하나 이상의 더 간단하고 더 구체적이며 덜 추상적인 하위 기능의 집합으로 분해된다.

)전통적인 기능 분해 → 하나의 프로세스를 잘게 쪼개는 느낌.. 하나의 프로세스를 여러개의 함수로 나누어 처리하는 느낌(어떻게 보면 본능적인 것)

그런데 이것이 유지보수에 다양한 문제를 야기??

→ 현실은 이상적으로, 규칙적으로 나누어 떨어지지 않는다?

문제점

  • 하나의 메인 함수로 구성돼 있지 않음

→ 대부분의 시스템에서 하나의 메인 기능이란 개념은 존재하지 않는다.

→ 하향식 접근법은 알고리즘이나 배치 처리를 구현하기에는 적합하지만, 현대적인 상호작용 시스템을 개발하는 데는 적합하지 않다.

  • 기능 추가나 요구사항 변경으로 인해 메인 함수를 빈번하게 수정해야 한다.

→ 새로운 함수의 적절한 위치를 확보하기 위해, 메인 함수의 구조를 바꿀 수 밖에 없으며, 기존 코드를 수정하는 것은 버그를 만들어낼 확률을 높인다.

  • 비즈니스 로직이 사용자 인터페이스와 강하게 결합된다.

→ 사용자 인터페이스는 가장 자주 변경되는 부분, 비즈니스 로직은 잘 변경되지 않는다.

⇒ 함께 섞어두면, 사용자 인터페이스를 바꿀 때, 비즈니스 로직도 변경하게 된다.

(하향식 접근법은 사용자 인터페이스와 비즈니스 로직을 한데 섞어 두게 된다.)

→ 이렇게 되면 사용자 인터페이스를 변경하는 방법은, 전체 구조를 재설계하는 것뿐이다.

→ 하향식 접근법에서 관심사의 분리는 어렵다.

  • 하향식 분해는 너무 이른 시기에 함수들의 실행 순서를 고정시키기 때문에 유연성과 재사용성이 저하된다.

→ 무엇을 해야하는 지가 아니라, 어떻게 동작해야 하는지에 집중하도록 만든다.

⇒ 시간적인 제약에 대한 미련을 버리고 좀 더 안정적인 논리적 제약을 설계의 기준으로 삼는다.

→하향식 설계와 관련된 모든 문제의 원인은 ‘결합도’. 함수는 상위 함수가 강요하는 문맥에 강하게 결합된다. 강한 결합도는 시스템을 변경에 취약하게 만들고 이해하기 어렵게 만든다.

→ 함수들이 데이터와 강하게 결합된다는 것이 문제

  • 데이터 형식이 변경될 경우 파급효과를 예측할 수 없다.

→ 어떤 데이터를 어떤 함수가 사용하고 있는지를 추적하기 어렵다.

→ 데이터 변경으로 인해 발생하는 함수에 대한 영향도를 파악하는 것이 생각보다 쉽지 않다는 것.

→ 코드가 성장하고 라인 수가 증가할수록 전역 데이터를 변경하는 것은 악몽으로 변해간다.

하향식 접근법과 기능 분해가 가지는 근본적인 문제점은 변경에 취약한 설계를 낳는다는 것

→ 데이터 변경으로 인한 영향을 최소화하려면 데이터와 함께 변경되는 부분과 그렇지 않은 부분을 명확하게 분리해야 한다. 이를 위해 데이터와 함께 변경되는 부분을 하나의 구현 단위로 묶고 외부에서는 제공되는 함수만 이용해 데이터에 접근해야 한다. 즉, 잘 정의된 퍼블릭 인터페이스를 통해 데이터에 대한 접근을 통제해야 하는 것이다.

데이비드 파나스는 기능 분해가 가진 본질적인 문제를 해결하기 위해, 퍼블릭 인터페이스를 통해 데이터에 대한 접근을 통제해야 하는 것. 정보 은닉과 모듈이라는 개념을 제시하기에 이르렀다.

언제 하향식 분해가 유용한가?

→ 설계의 다양한 측면을 논리적으로 설명하고 문서화하기에 용이하기 때문

명확한 아이디어를 가지고 있다면 머릿속에 있는 것을 종이에서술하기 위해 하향식을 사용할 수 있다.

하향식 분해는 작은 프로그램과 개별 알고리즘을 위해서는 유용한 패러다임으로 남아 있다.

그러나 실제로 동작하는 커다란 소프트웨어를 설계하는 데 적합한 방법은 아니다.

모듈

정보은닉과 모듈

퍼블릭 인터페이스로만 접근하게 하고, 구현은 감추기. 기능을 해결하는 것을 모듈로 묶기.

모듈은 서브 프로그램이라기보다느 책임의 할당.

시스템을 모듈로 분해한다. 각 모듈 내부를 구현하기 위해 기능 분해를 적용할 수 있다.

모듈은 두 가지 비밀을 감춰야 한다. - 복잡성, 변경 가능성

모듈의 장점과 한계

모듈 내부의 변수가 변경되더라도 모듈 내부에만 영향을 미친다

비즈니스 로직과 사용자 인터페이스에 대한 관심사를 분리한다

전역 변수와 전역 함수를 제거함으로써 네임스페이스 오염을 방지한다

모듈은 기능이 아니라 변경의 정도에 따라 시스템을 분해하게 한다.

모듈 내부는 높은 응집도를 유지한다. 모듈과 모듈 사이에는 퍼블릭 인터페이스를 통해서만 통신해야 한다. 낮은 결합도를 유지한다.

모듈은 인스턴스의 개념을 제공하지 않는다. 좀 더 높은 수준의 추상화를 위해서는 직원 전체가 아니라 개별 직원을 독립적인 단위로 다룰 수 있어야 한다.

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

타입이란 변수에 저장할 수 있는 내용물의 종류와 변수에 적용될 수 있는 연산의 가짓수

프로시저 추상화의 한계를 발견 → 데이터 추상화의 개념을 제안(리스코프)

리스코프의 업적은 소프트웨어를 이용해 표현할 수 있는 추상화의 수준을 한 단계 높였다는 점

추상 데이터 타입을 지원하려면...

  • 타입 정의를 선언할 수 있어야 한다.
  • 타입의 인스턴스를 다루기 위해 사용할 수 있는 오퍼레이션의 집합을 정의할 수 있어야 한다.
  • 제공된 오퍼레이션을 통해서만 조작할 수 있도록 데이터를 외부로부터 보호할 수 있어야 한다.
  • 타입에 대해 여러 개의 인스턴스를 생성할 수 있어야 한다.

추상 데이터 타입은 사람들이 세상을 바라보는 방식에 좀 더 근접해지도록 추상화 수준을 향상시킨다.

여전히 데이터와 프로세스가 분리되어 있음

클래스

클래스는 추상 데이터 타입인가?

명확한 의미에서 동일하지 않다. 클래스는 상속과 다형성을 지원하는 데 비해 추상 데이터 타입은 지원하지 못한다. 추상 데이터 타입 = 타입을 추상화한 것, 클래스 = 절차를 추상화한 것

클래스를 이용한 다형성은 절차에 대한 차이점을 감춘다.

변경을 기준으로 선택하라

절차를 기준으로 추상화하지 않았다면 그것은 객체지향 분해가 아니다.

조건문을 다형성으로 대체한다.

‘타입 추가’의 압력 → 객체지향

‘오퍼레이션 추가’의 압력 → 추상 데이터 타입의 승리

협력이 중요하다

객체지향에서 중요한 것은 역할, 책임, 협력이다.