본문 바로가기
Book/자바,스프링 개발자를 위한 실용주의 프로그래밍

03. 행동 ( 행동과 역할, 인터페이스 .. )

by burning-man 2024. 9. 9.

💭 개요

객체는 단순한 데이터 덩어리가 아니다. 마치 자아를 가진 것 처럼 동작해야한다. 행동과 역할에 대해 알아보자.

 

💡 공부한 것

 

데이터 위주의 사고와 행동 위주의 사고

💡 자동차 클래스를 만들 수 있나요?

 

개발자 A - 데이터 위주의 사고

public class Car {

	private Frame frame;
	private Engine engine;
	private List<Wheel> wheels;
	private float speed;
	private float direction;

}

개발자A의 경우, 어떤 객체를 정의하는데 필요한 속성으로만 묶여 있다. 이러한 클래스는 절차지향 언어에서 구조적인 데이터 덩어리를 만드는데 사용하는 ‘구조체’와 다를바가 없다. 전혀 객체지향스럽지가 않다.

 

 

개발자B - 행동 위주의 사고

public class Car {

	public void drive(){}
	public void changeDirection(float amount){}
	public void accelerate(float speed){}
	public void decelerate(float speed){}
	
}

 

개발자B의 경우, 객체가 어떤 동작을 하는지 알 수 있다. 객체를 구분 짓는 요인은 데이터가 아닌 ‘행동’이다. 데이터보다 행동에 집중할 때 더 자연스러운 모델링이 될 수 있다. 행동을 먼저 고민하면 구체적인 이름보다 ‘역할’과 관련된 모델링이 된다.

행동을 고민하는 것은 자연스럽게 역할을 고민하게 만든다. 따라서 어떤 행동을 할 수 있는지가 곧 역할을 만든다. 그리고 이러한 여러 역할이 모여 객체를 정의한다.

💡 행동이 곧 역할을 정의하고, 역할이 곧 객체를 정의한다.

 

행동과 구현

메서드를 구현하려하니 클래스에 필요한 속성이 생겼다.

public class Car {

	private int degree; // 자동차의 각도 (구현을 고민했더니 속성이 생겼다.)
	
	public void drive(){}
	public void changeDirection(float amount){
	
		float result = (degree + amount) % 360;
		if ( result < 0 ){
			result += 360;
		}
		return result;
	}

}

행동의 구현을 고민했더니 결국 이 클래스가 어떤 값을 가지고 있어야 하는지 고민하게 되었다.

행동을 고민하는 순간에는 순수하게 이 클래스에 어떤 동작을 시킬 수 있을 것인지만 고민하는 것이 좋다.

→ 인터페이스를 사용하자.

 

자바의 인터페이스를 활용하면 구현 없이도 메서드를 정의할 수 있다. 심지어 인터페이스는 구현을 가질 수 없도록 강제해두었다. 오롯이 어떤 행동을 어떻게 시킬 수 있는지만 선언할 수 있다. 초기 설계 단계에서는 상세한 구현은 무시해도 괜찮다. 원하는 목적에만 맞게 굴러가면 된다. 내부 구현은 알 필요가 있나? 상세 구현을 맡은 개발자가 알아서 개발할 것이다. 그저 믿고 진행한다.

이런 믿음은 다른 개발자와의 협업을 용이하게 만들기도 한다.

 

하지만, 만약 팀원이 인터페이스를 제대로 지켜오지 않으면 어떻게 될까? ‘그래서는 안된다.’

우리는 이미 인터페이스를 기반으로 협력 방식을 정해 놓았기 때문에, 이렇게 될 경우 이해관계자들이 모여 설계를 다시 해야한다.

 

💡 인터페이스는 일종의 계약이다. 반드시 지켜져야한다.

 

인터페이스

인터페이스는 행동이 아니다. 그저 외부에서 어떤 객체에게 행동을 시키고자 할 때, 메시지를 보낼 수 있는 창구일 뿐이다. 인터페이스란 ‘나를 조작하고 싶다면 이런 메시지를 보내면 된다’ 라고 외부에 알려주는 수단이다.

 

여기서 ‘나’는 객체가 될수도 있고, 하나의 시스템이 될 수도 있다.

 

API 는 Application Programming Interface로 애플리케이션을 조작하고 싶을 때, 어떻게 메시지를 보내면 되는지 알려주는 것이다.

UI 는 User Interface로 사용자가 프로그램을 조작하고 싶을 때, 어떻게 메시지를 보내면 될지 알려주는 것이다.

자바의 인터페이스는 어떤 객체를 어떻게 사용하면 되는지 외부 객체에 알려주는 것과 같다.

 

인터페이스는 어떤 행동을 지시하기 위해 사용할 수 있는 행동들의 집합이다. 객체들끼리 서로 협력하려면 행동을 지시해야 하고, 필요에 따라 물어보기도 해야 한다. 인터페이스는 협력을 위한 창구이며, 협력을 위해 객체들은 인터페이스를 통해 메시지를 주고 받는다.

 

행동과 역할

우리는 실체에 집중할 때 데이터 위주의 사고를 하고, 역할에 집중할 때 행동 위주의 사고를 한다.

예를 들어, 자동차라는 실체에 집중하면 자동차를 이루는 부품이나 필요한 속성에 대해 생각하게 된다.

반면에 탈것 이라는 역할에 집중하면 탈것은 탑승할 수 있어야하고, 달릴 수 있어야하고, 멈출 수 있어야한다 같은 행동에 대한 정의를 생각하게 된다.

역할에 고민하지 않고 구현체에 집중하면 해당 클래스를 개발하는 개발자만의 생각이 반영된 클래스가 나오게 된다.

따라서 ‘자동차 클래스를 만들어주세요’ 라는 요청을 받았을 때, 이런 생각을 해보면 좋았을 것이다.

  • 자동차는 어떤 행동을 하는 객체인가요?
  • 꼭 자동차여야 하나요?
  • 자동차라는 클래스를 만들어서 달성하려는 목표가 무엇인가요?

💡 반복적이고 의식적으로 객체가 어떤 행동을 하는지 고민해야한다.

 

 

메서드와 함수의 차이

인터페이스란 ‘나를 조작하고 싶다면 이런 메시지를 보내면 된다’ 라고 외부에 알려주는 수단이다.

어떤 객체나 시스템을 다루는 외부 세계는 협력 대상과 소통하기 위해 메시지를 이용한다.

객체는 협력 객체에서 메시지를 건내고, 협력 객체는 메시지를 수신해서 행동한다.

인터페이스를 통해 메시지를 보내면서, 어떤 메서드가 실행될지 모른다.

class Car implements Vehicle {

	void ride() {}
	void run() {}
	void stop() {} 
	
}

class Bicycle implement Vehicle {

	void ride() {}
	void run() {}
	void stop() {} 
	
}

class User {

	void ride(Vehicle vehicle){
		// User 클래스는 어떤 객체의 메서드를 실행하는가?
		// Car의 ride 메서드? Bicycle의 ride 메서드?
	vehicle.ride()
	}

}

vehicle.ride() 를 호출하지만 코드가 실행되기 전까지는 실제로 어떤 메시지가 호출 될지 모른다.

 

메서드와 함수의 차이는 여기서 나타난다.

함수는 입력값과 출력값 사이의 대응 관계를 나타낸다. 함수의 각 입력값은 정확히 하나의 출력값으로 대응된다.

 

객제지향에서 객체들은 메시지를 통해 소통한다.

→ 이러이러한 인수들은 건네줄테니, 알아서 일을 처리해달라고 부탁한다.

협력 객체에 메시지만 보낼 뿐이다. 실제로 어떤 ‘방법’으로 일을 어떻게 처리할지는 객체가 정한다.

그래서 객체지향에서는 객체가 수행하는 함수를 메서드라 부른다.

 

💡 메서드란 어떤 메시지를 처리해달라는 요청을 받았을 때 이를 어떻게 처리하는지 방법을 서술하는 것이다.

 

🔠 Keyword 정리

행동, 구현, 역할, 데이터 위주의 사고, 행동 위주의 사고, 인터페이스, 메시지를 보낼 수 잇는 창구, 메시지로 소통, 함수, 메서드