•
다음과 같은 표현을 보고 어떤 의미인지 생각해 보자.
◦
자바를 사용하면서도 절차지향적인 코드가 나올 수 있다.
⇒ 하나의 동작을 하나의 클래스의 메소드에 다 때려박는다면 하나의 동작을 나타내는 메소드들이 유연하게 연결되지 않고 강하게 절차적으로 연결될 것이다.
•
객체지향에 대해 말해보기에 앞서 절차지향이 뭔지부터 이해할 필요가 있다.
◦
절차지향이라는 말을 들어봤다면 앞서 순차지향이라는 패러다임이 존재했음도 알고 있을 것이다.
•
그렇다면 절차지향과 순차지향의 다른 점은 뭘까?
◦
대부분의 개발자는 순차지향 프로그래밍을 코드가 위에서 아래로 순차적으로 실행되는 프로그래밍 방식 정도로 이해한다.
•
이는 각 패러다임의 원래 명칭을 보면 쉽게 알 수 있다. 순차지향 프로그래밍의 원래 명칭은 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를 사용해야만 하는 상황이 발생한다.