[김영한의 실전 자바 - 기본편] 절차 지향 프로그래밍 & 객체 지향 프로그래밍
인프런 김영한님의 실전 자바 - 기본편을 수강하다가 이건 내가 꼭 기록해야겠다 싶다고 생각했다.
흔히들 자바(Java)를 객체 지향 언어라고 부른다. 그럼 우리는 자바로 프로그래밍을 할 때 객체 지향적으로 프로그래밍을 잘하고 있을까?
우테코 프리코스를 진행하면서 주차별 피드백 중 "객체는 객체스럽게 사용한다"라는 사항이 있었다. 즉, 객체가 일을 하도록 사용하라는 의미다. 그만큼 객체 지향 프로그래밍을 중요시 한다는 얘기다. 우선 절차 지향 프로그래밍과 객체 지향 프로그래밍이 각각 뭔지, 예시와 함께 알아보자.
절차 지향 프로그래밍
- 이름 그대로 절차를 지향한다. 실행 순서를 중요하게 생각하는 방식이다.
- 프로그램의 흐름을 순차적으로 따르며 처리하는 방식이다. 즉 "어떻게"를 중심으로 프로그래밍 한다.
다음은 김영한님의 실전 자바 - 기본편에 나오는 코드 중 일부이다.
public class MusicPlayerData {
int volume = 0;
boolean isOn = false;
}
우선 위와 같은 속성을 가지는 MusicPlayerData 클래스가 있다.
public class MusicPlayerMain3 {
public static void main(String[] args) {
MusicPlayerData data = new MusicPlayerData();
on(data);
volumeUp(data);
volumeUp(data);
volumeDown(data);
showStatus(data);
off(data);
}
static void on(MusicPlayerData data) {
data.isOn = true;
System.out.println("음악 플레이어를 시작합니다.");
}
static void off(MusicPlayerData data) {
data.isOn = false;
System.out.println("음악 플레이어를 종료합니다.");
}
static void volumeUp(MusicPlayerData data) {
data.volume++;
System.out.println("음악 플레이어 볼륨: " + data.volume);
}
static void volumeDown(MusicPlayerData data) {
data.volume--;
System.out.println("음악 플레이어 볼륨: " + data.volume);
}
static void showStatus(MusicPlayerData data) {
System.out.println("음악 플레이어 상태 확인");
if (data.isOn) {
System.out.println("음악 플레이어 ON, 볼륨: " + data.volume);
} else {
System.out.println("음악 플레이어 OFF");
}
}
}
위 코드는 MusicPlayerData의 속성값을 인스턴스 변수로 받아 main() 메서드 내에서 음악 플레이어 시작/종료, 볼륨 Up/Down, 음악 플레이어 상태 확인을 담당하는 메서드를 구현한 코드이다.
물론 메서드를 분리하고 중복을 줄였기에 가독성이나 유지보수 하기에 좋은 코드로 보일 수 있다. 하지만 만약 MusicPlayerData의 데이터가 변경된다면 MusicPlayerMain3의 메서드들도 같이 변경해야 한다. 즉, 두 번 일하는 것이다. 이는 객체를 객체스럽게 사용하지 못해 발생하는 문제점이다.
객체 지향 프로그래밍
- 이름 그대로 객체를 지향한다. 객체를 중요하게 생각하는 방식이다.
- 실제 세계의 사물이나 사건을 객체로 보고, 이러한 객체들 간의 상호작용을 중심으로 프로그래밍하는 방식이다. 즉 "무엇을" 중심으로 프로그래밍 한다.
위에서 작성된 절차 지향적으로 프로그래밍 된 MusicPlayerMain3을 객체 지향적으로 프로그래밍 해보자. 다음도 김영한님의 실전 자바 - 기본편에 나오는 코드 중 일부이다.
public class MusicPlayer {
int volume = 0;
boolean isOn = false;
void on() {
isOn = true;
System.out.println("음악 플레이어를 시작합니다.");
}
void off() {
isOn = false;
System.out.println("음악 플레이어를 종료합니다.");
}
void volumeUp() {
volume++;
System.out.println("음악 플레이어 볼륨: " + volume);
}
void volumeDown() {
volume--;
System.out.println("음악 플레이어 볼륨: " + volume);
}
void showStatus() {
System.out.println("음악 플레이어 상태 확인");
if (isOn) {
System.out.println("음악 플레이어 ON, 볼륨: " + volume);
} else {
System.out.println("음악 플레이어 OFF");
}
}
}
위 코드를 보면 기존 절차 지향적으로 프로그래밍한 MusicPlayerData 클래스에서 속성만 선언했던 것과 달리 MusicPlayer 클래스에서는 음악 플레이어의 속성과 음악 플레이어가 갖는 기능에 대해 구현해놓은 것을 볼 수 있다.
public class MusicPlayerMain4 {
public static void main(String[] args) {
MusicPlayer player = new MusicPlayer();
player.on();
player.volumeUp();
player.volumeUp();
player.volumeDown();
player.showStatus();
player.off();
}
}
따라서 MusicPlayerMain4 클래스에서 음악 플레이어의 기능에 대한 메서드 구현없이 MusicPlayer 클래스에서 구현된 속성과 기능만 가져다가 사용하면 되는 것이다.
절차 지향 프로그래밍과 객체 지향 프로그래밍의 예시만 봐도 객체 지향적 프로그래밍이 무엇인지 한눈에 알 수 있다. 우리는 지금껏 자바라는 언어를 사용하면서 절차 지향 프로그래밍을 해온 것이다. 이게 잘못된 것은 아니지만 '객체 지향적 언어의 대표적인 자바를 사용하면서 객체 지향 프로그래밍을 해야하지 않나?'라는 생각을 했다.
우테코 프리코스를 진행하면서 getter를 무분별하게 사용했던 기억이 있다. 나는 본질을 잊고 프로그래밍을 했던 것이다. 이처럼 절차 지향이 아닌 객체 지향적 프로그래밍을 하면서 객체에게 물음을 던지고 객체가 일을 하도록 구현을 하자.