////
Search
Duplicate
🀄

Chapter 01. 절차지향과 비교하기

다음과 같은 표현을 보고 어떤 의미인지 생각해 보자.
자바를 사용하면서도 절차지향적인 코드가 나올 수 있다.
⇒ 하나의 동작을 하나의 클래스의 메소드에 다 때려박는다면 하나의 동작을 나타내는 메소드들이 유연하게 연결되지 않고 강하게 절차적으로 연결될 것이다.
객체지향에 대해 말해보기에 앞서 절차지향이 뭔지부터 이해할 필요가 있다.
절차지향이라는 말을 들어봤다면 앞서 순차지향이라는 패러다임이 존재했음도 알고 있을 것이다.
그렇다면 절차지향과 순차지향의 다른 점은 뭘까?
대부분의 개발자는 순차지향 프로그래밍을 코드가 위에서 아래로 순차적으로 실행되는 프로그래밍 방식 정도로 이해한다.
이는 각 패러다임의 원래 명칭을 보면 쉽게 알 수 있다. 순차지향 프로그래밍의 원래 명칭은 Sequential oriented programming이고 절차지향은 Procedure oriented programming이다.
순차지향 프로그래밍의 Sequential은 순차적으로라는 듯이니 말 그대로 코드를 위에서 아래로 일겠다는 의미가 맞다.
절차지향 프로그래밍의 Procedure는 직역 시 절차가 맞으나 컴퓨터 공학에서 Procedure는 사실 함수다. 따라서 절차지향 프로그래밍은 사실상 함수 지향 프로그래밍이라고 볼 수 있다.
⇒ 다시 말해 절차지향 프로그래밍은 함수 위주로 생각하고 프로그램을 만드는 패러다임이다.
순차지향 언어인 어셈블리어로 작성된 코드에는 함수의 개념이 존재하지 않는다. 그저 코드를 위에서 아래로 순차적으로 읽을 뿐이다.
대신 목적의 주소를 나타내는 레이블이라는 개념과 jmp, goto를 사용해 실행 위치를 해당 주소로 옮기는 방식으로 코드가 동작한다.
절차지향 언어인 C로 작성된 코드에는 함수가 존재한다.
절차지향 프로그래밍은 함수를 만들어서 프로그램을 만드는 방식이다. 복잡한 문제를 개별 함수로 분해하고 여러 함수를 이용해 문제를 해결하는 방식이다.
스프링을 사용하면서도 객체에 적절한 책임을 부여하지 않고 서비스 계층에서 모든 비즈니스 로직을 처리한다면 이는 절차지향적으로 프로그래밍하고 있는 것이다.
객체지향은 가독성보단 책임에 좀 더 집중한다. 소프트웨어가 달성하려는 거대한 목적을 위해 객체들이 책임을 나눠 가져야 한다.
이런 식으로 작업을 수행하면 병렬로 처리할 수 있게 된다. 세세한 구현은 동료들에게 맡기고 개개인은 자신이 담당하는 객체의 책임만 제대로 구현하면 된다. 따라서 객체지향 프로그래밍에서는 책임이 강조된다.
책임은 계약이다. 수많은 객체가 협력하는 객체지향 프로그래밍에서는 협력 객체들이 계약을 제대로 지키는 것을 가정하고 프로그램을 만들게 된다.
이때 사용할 수 있는 것이 테스트 코드다. 최초의 요구사항을 충족하는가? 기존 요구사항은 여전히 만족하는가?를 검사할 수 있는 테스트코드는 책임을 계약으로 만드는 가장 확실한 방법이자 시스템의 계약 명세이다.

1. 책임과 역할

절차지향적인 코드는 책임을 제대로 구분할 수 없는 걸까? 아니다 절차지향에서는 함수 단위로 책임을 지면 된다.
책임이란 객체지향의 중요한 부분이지만 객체지향만의 특징은 아니다. 일반적인 함수에도 책임은 존재한다.
다시 말해 객체지향은 책임을 함수가 아닌 객체에 할당하는 프로그래밍 방법이다.
그렇다면 구조체를 지원하는 C 언어는 왜 객체지향 프로그래밍 언어가 아닌 것일까?
엄밀히 말하자면 객체지향에서는 책임을 객체에 할당하지 않는다. 객체를 추상화한 역할(interface)에 책임을 할당한다.
그리고 이는 C 언어가 지원하지 못하는 기능이다. C 언어의 구조체는 추상의 개념을 지원하지 못하므로 C 언어는 절차지향 언어인 것이다.
이는 곧 다형성과 연결된다.
구현과 역할을 분리하고 역할에 책임을 할당하는 과정은 객체지향에서 정말 중요한 부분이다.
이는 매우 중요한 장점 중 하나인데, 역할을 이용해서 통신하면 실제 객체가 어떤 객체인지 상관하지 않아도 되기 때문이다.
내가 부탁한 책임과 역할을 할 수 있는 객체라면 협력자가 구체적으로 어떤 객체인지 신경 쓰지 않아도 된다는 의미이다.
절차지향은 절대 객체지향에 비해 뒤떨어진 방법론이 아니다. 각 패러다임에는 저마다 장단점이 있으므로 이를 이해하고 문제를 해결할 때 어떤 방법론을 적용시킬 것인지는 그때그때 정해야한다.

2. TDA 원칙

객체지향적인 사고를 하도록 만들 수 있는 가장 쉬운 방법은 TDA 원칙이다.
TDA 원칙이란 ‘Tell, Don’t Ask’의 줄임말이다. 객체에게 값에 관해 물어보지 말고 일을 시키라는 의미다.
객체가 가지고 있는 상태를 받아서 연산에 사용하지 마라. 객체에게 연산을 요청하라.
단편적으로 이야기하면 TDA 원칙은 무분별하게 사용되는 getter와 setter르 줄이라는 의미로 해석될 수도 있으며 실제로도 이들은 개발자의 객체지향적 사고를 방해하며 절차지향적 사고를 하게 만드는 주요한 요인이다.
객체지향을 실천해 보고 싶다면 이 단순한 원칙을 적용해보는 것이 좋다. TDA는 간단하면서도 객체지향을 꽤나 관통하는 원칙이기 때문이다.
그렇다고 객체에게 모든 일을 시킬 수 만은 없다. getter는 분명히 필요한 메소드이며 객체에게 일을 최대한 시키려해도 어딘가에선 협력을 위해 getter를 사용해야만 하는 상황이 발생한다.