본문 바로가기
java

[Java] 개념은 제대로 알고가자 - 객체지향 무엇인가

by jinbro 2017. 9. 16.

[객체지향이란 무엇인가]

- 궁금해졌다. 클래스에 대해서 공부를 막 시작하는 와중에 객체지향에 대해서 난 설명할 수 있을까에 대해서 생각했다. 결론은 할 수 없었다.

  객체지향에 대해서 정확히 알지도 못하면서 객체지향언어로 프로그래밍을 한다? 누군가 개발해놓은 것 따라하는 것은 가능하나 스스로 못할 것이다.

  중요한 패러다임 자체도 이해하지못하면서 그 언어로 개발한다는 것은 장점을 활용하지않겠다는 것 혹은 흉내만 내고 사고 확장은 못한다는 것

  그래서 객체지향에 대해서 알아보기로 했다. 이후에 syntax 공부를 해도 늦지않다고 생각했다. 한번 할 때 제대로 하자

  한번에 모두 다 파악하기에는 힘들 것이지만 앞으로의 공부에 많은 도움이 될 것이라 생각했다.

  아래의 이야기는 객체지향의 사실과 오해 라는 책 + 구글링 + 그리고 여태껏 syntax에만 치중했던 경험에서 얻은 지식을 종합해서 썼다.

  보충할 내용이나 이런 쪽으로 더 바라봤으면 좋겠다는 내용이 있다면 댓글로 남겨주시면 좋겠습니다.


- 책을 읽은 목적은 객체지향 프로그래밍 패러다임에 대해 생각하는 시간 가지기, 지금보다 레벨업 하기



[객체지향이란 무엇인가 - 단계적으로 질문 던지기]

(1) 객체지향은 프로그래밍 패러다임

(2) 프로그래밍 패러다임? 프로그래밍의 원칙, 어떤 것을 기준으로 세워두고 프로그래밍 하는 것을 말함

(3) 다시 객체지향 : 프로그래밍할 때 객체를 중심에 두고 프로그래밍할 것임을 말하는 것

(4) 객체가 도대체 뭔데?

- 프로그램 기능 구성을 위해 존재하는 것 그리고 다른 객체와는 구별되는 것 : 객체는 서로 구별됨(각각이 다른 존재임을 인식할 수 있음)

- 프로그램 기능 구성을 위해 존재하는 객체가 가져야할 2가지가 있다 : 그 이유는 일단 5번부터 읽고 다시 밑에 적도록 하겠다.


(5) 그럼 그 객체를 가지고 어떻게 하겠다는 것?

- 프로그램을 만들 때 절차를 중심에 둘 것이 아니라 객체를 중심에 두겠다는 것

(5-1) 객체를 중심에 둔다는 것이 도대체 어떤 것? 프로그램을 만드는 이유를 생각해보세요

(5-2) 프로그램 만드는 이유

어떤 기능을 함으로서 목적을 달성하는 것, 예를 들어 은행 계좌 관리 프로그램의 목적은 은행 계좌 관리를 목적으로 만들어진 것

그런 목적을 달성하기위해 계좌 조회, 계좌 이체, 계좌 입금 등의 기능이 있어야하지

그런 거대한 기능을 여러 객체들이 힘을 합쳐 만들겠다는 것


(5-3) 프로그램, 기능, 객체? 

어떤 기능을 만듦에 있어서 1단계는 무엇을 하고 2단계는 무엇을 하고 이렇게 프로그래밍 하겠다는 것이 아니라 

그러한 기능을 만듦에 있어서 객체들의 협력 관점으로 만들겠다는 것

어떤 객체는 이 일을 하고, 어떤 객체는 저 일을 하고 분업화 하겠다는 것



(5-4) 예를 들자면 

우리가 조별과제를 할 때 생각해보자. 조별 과제가 떨어지면 우린 곧장하는 것이 자신들이 도맡을 역할을 분배하잖아 

조별과제 완성이라는 목적을 달성하기위해 역할을 분배하지

그것과 같은 것. 목적을 달성하기위해서 구성원이 모여 자신의 능력껏 역할을 맡아서 각자 일을 하되 협력을 하는거지

서로 서로가 식별가능한 객체들이 모여 하나의 기능을 만든다! 이거지

그러한 관점을 중심에 두고 설계부터 구현까지 하는 것을 객체지향 프로그래밍 이라고 하지


(6) 객체가 가져야할 2가지

1) 협력적이어야함 : 협력을 하려면 팀원들의 목소리를 잘 듣고 잘 요청할 수 있어야함

2) 자율적이어야함 

- 팀원들의 요청을 받을 수 있지만 객체는 주체적인 존재, 자신만의 방식으로 일을 처리할 수 있어야함

- 그리고 상태를 가짐 : 상태는 객체의 상태를 말해주는 것이고, 객체의 상태에 따라 팀원들의 요청을 처리할 수 있을지 없을지도 정하고 어떻게 처리할지도 정함


(7) 정리하자면 객체는!

- 목적을 달성하기위해 협력하는 존재, 무조건적으로 협력하는 것이 아니라 자신만의 상태를 가지고 협력 여부를 판단하고 협력할 때는 객체의 방식대로 처리

- 협력의 과정에서 역할을 부여받고 그 역할에 따라 행동하는 존재



[객체지향으로 생각해보자 - 커피 전문점 주문이라는 예시를 가지고]

(1) 프로그램의 기능을 구성할 객체 먼저 파악해보자

커피전문점 주문이라는 기능을 소프트웨어(프로그램)로 만들기위해서 어떤 객체가?

- 손님

- 점원

- 메뉴판

- 커피


(2) 필요한 메세지 정리하기 : 커피 주문에 필요한 메세지 정리

각 객체는 커피 주문이라는 목표를 달성하기위해 존재한다. 그리고 협력한다. 

협력 순서를 정하기에 앞서 어떤 협력이 필요한지 파악하는 단계이다.

다시 말하자면 목표 달성을 위해 필요한 메세지를 파악하고 그런 일을 담당할 객체를 고르는 단계다.

여기서 말하는 메세지를 다르게 표현하면 요청을 말한다.

요청을 받은 객체는 자신의 방법에 맞게(자율적인 객체) 요청을 처리하고 요청한 객체가 원하는 형태로 되돌려주면 된다. 

이 객체는 이런 필드를 가질거야 그러고 이 객체에 이런 메서드를 넣으면 되겠다고 생각한 이 책을 보기 전의 나를 생각하면 참........ 계속 변경되는 코드..


- 커피 메뉴를 파악해줘 : 주문을 하려면 메뉴를 파악해야하니깐!

- 커피를 주문해줘

- 커피를 제조해줘

=> 이 단계에서 협력 메세지를 받은 객체가 어떻게 처리할지는 고려하지말자! 상세하게 처리하는 것은 코드화에서 처리하면 된다.

     어떻게 처리해야할지는 협력의 흐름에서 중요하지않다. 각 객체가 협력의 요청을 받으면 알아서 처리하면 될 일이다.

    물론 프로그래머 입장에서는 어떻게 처리하는 것도 중요하겠지만 우선 객체지향적으로 설계부터가 제대로 되어야

    그에 맞는 처리(처리 - 응답)를 하지않겠는가? 코드화 단계에서 집중하자



(3) 메세지를 담당할 객체를 정하자 : 객체는 목적 달성을 위해 협력하는 존재, 요청을 받아서 처리하는 객체가 필요하겠지? 그것을 정하는 단계

다시 말하자면 기능 완성을 위해 필요한 요청 메세지를 누가 받아서 처리를 할 수 있을지 정하는 것


- 커피 메뉴를 파악해줘 : 메뉴판

- 커피를 주문해줘 : 손님(요청을 보내는 것은 실제 프로그램을 사용하고있는 사용자)

- 커피를 제조해줘 : (송) 점원, (수) 커피

=> 각 객체는 능동적이다. 실세계를 생각하면 커피가 어떻게 커피를 제조해달라는 요청을 받지 라는 생각을 하겠지만 프로그램에서는 아니다.

=> 메세지를 보낼 때에는 수신할객체.메세지요청() 으로 보낸다



(4) 객체의 타입화 : 3번 단계를 거치면서 각 객체가 존재하는 이유가 생겼음. 해야할 일이 중심이 된 존재 이유를 목록화 하는 것

여기서 생각해야할 것! 어제 점원이었던 사람이 오늘은 손님이 될 수 있고, 다른 가게에서 손님이 될 수도 있다.

현재의 커피전문점에 드러서서 주문하는 단계에 왔을 때 그 객체가 현재 역할이 무엇인지(어떤 요청을 받을 수 있는지)가 중요하다.

객체가 협력 관점에서 어떤 역할인지 그리고 그 역할이 어떤 요청을 받을 수 있는지 목록화하는 것이 객체의 타입화이다.

자바에서는 interface 라는 일종의 도구로 객체의 타입화를 할 수 있다.

손님만 타입화 해보겠음

public interface ICustomer{
public void order(String menuName);
}

- 객체의 타입화(interface syntax를 활용)로 손님 타입의 객체가 이러한 요청을 받을 수 있다는 것을 목록화하였음


(5) 구현하기 : 타입을 구체적으로 구현해야함, 처리 과정은 어떠한지 처리 과정에 필요하거나 고려해야될 상태가 없는지 등

여기 과정을 통해서 타입화 과정에서 혹은 메세지 파악 과정에서 빠뜨린 것은 없는지 제대로 된 타입화가 된 것이 맞는지 체크할 수 있음

구현의 도구로 자바 클래스가 존재함 : 객체지향을 배울 때 클래스를 중심으로 배우니 자바스크립트 객체지향 프로그래밍을 할 때 그렇게 헤맬 수 밖에........

객체지향은 객체 중심적 사고를 하고 코드로 녹여되면 되는 것인데... 도구만 바뀔 뿐 우린 객체의 협력 관계, 협력에서의 역할을 코드로만 녹여내면 될 뿐


<구현해야할 것들>

- 상태 : 필드라고 함, 요청에 대한 처리를 함에 있어서 고려해야할 객체의 상태나 처리 결과에 따라 변화되는 객체의 상태를 나타낼 데이터(값)

            상태의 종류에는 (1) primitive type 과 (2) reference type 의 데이터가 올 수 있음

     예를 들어 메뉴를 달라는 요청에 대해 메뉴판이 요청을 처리하기위해서는 메뉴 라는 상태가 필요함

     메뉴라는 상태는 reference type data


- 행동 : 요청을 받는다 -> 처리를 한다 : 메서드 라고 함, 객체 타입의 고유 처리 방식

             객체는 요청을 받아서 처리하는 방법은 자율적으로 정할 수 있다 : 즉 타 객체가 처리 방법에 대해서 관여할 수 없다는 것

             내부적으로 처리할 때 객체 타입이 가진 메서드를 활용해도되고 아예 상태에 따라 요청을 거절할 수도 있다.

             협력은 하지만 자유롭게 처리한다는 것을 알아야함


/* 객체의 타입화 : 협력의 관점에서 */
public interface ICustomer{

public void order(String menuName, Menu menu, Barista barista);
}

/* 구현체 */
class CoffeeCustomer implements ICustomer{

@Override
public void order(String menuName, Menu menu, Barista barista){
(1) 메뉴아이템 = 메뉴판.커피메뉴리스트줘(menuName);
(2) 바리스타.커피만들어줘(메뉴아이템);

/* 이후 처리는 생략 */
}
}


실제로 주문을 요청을 받고 주문 행위를 하기위해서 또다른 객체에 요청을 해야함
? Customer 객체의 역할은 주문 행위를 하는 것이지 커피를 만들지 않으니깐 커피를 제조하는 역할을 가진 객체에 요청을 해야함.

주문 행위 내부 처리 : 설계와 구현에서의 차이설계를 해두고 구현을 하면서 수정될  있음(그에 맞게 수정해나가면됨)
1) 인터페이스에서는 단순하게 주문할  추가적으로 들어가야할 메세지로 커피 메뉴명만 있으면 좋겠다고 생각함
2) 구현하면서 메뉴명에 맞는 메뉴 아이템을 받아와야하고 그러면 메뉴판 객체에 요청을 해야하기때문에 메뉴판 객체가 필요했음
3) 또한 받아온 메뉴아이템을 가지고 점원에게 커피 주문 요청을 해야하기때문에 점원 객체가 필요했음
4) order() 요청 처리에 필요한 구성요소들을 order() 매개변수로 명시해줌 : 인터페이스구현체 모두 변경(설계 - 구현을 거치면서 다듬어짐)

(1어떤 커피를 주문할지 정하기위해 커피메뉴에 무엇이 있는지 요청하기 
(2커피 제조 요청을 해야함
=> 커피 주문 요청 과정에서 또다른 요청이 발생함 : 객체지향 프로그래밍에서는 협력 요청과 응답의 연속


[지금 와닿는 객체지향 프로그래밍 특징]
(1요청은 송신객체가 하지만 요청 처리 권한은 송신 객체에게 :  바리스타에게 요청 처리와 내부 처리 어떻게할지 정하는 권한이 있음
order() 인터페이스명 자체는 변경되지않고 내부만 변경함으로서 코드 변경을 최소화시킬  있음
객체 - 객체 간의 요청 :  객체의 상태를 임의변경할  있는 여지가 없음(캡슐화)

(2CoffeeCustomer ICustomer 상세화한 구현체 
CoffeeCustomer 이외에도 HotelCustomer  여러 손님 형태를 제작할  있음 : order 내부 처리만 변경한다면(order 매개변수 표준화 신경써야함)
ICustomer  요청받을수 있는 메세지를 구현 : 다양하게 구현가능(다형성)



[생각]

(1) 작은 세상을 만들어나가는 느낌이 들었음 : 책에서 직접 그렇게 얘기하지만 책이 얘기한다고해서 와닿지 않으면 그렇게 느끼지 못했을텐데 

    책을 읽는 내내 작은 세상을 하나 만들어나가는 것 같았음. 프로그래밍이라는게 원래 그런 목적이 아닐까 생각함


(2) 모르는 단어가 나왔을 때에는 제대로 한번 알고 가는게 도움 완전 되더라

- 어느 한 부분에서 이해가 되지않기 시작하면 그것과 연관된 것들은 거의 다 이해되지않더라 

- 중요한 맥락 사이에 위치한 것인데 이해되지않는게 있으면 이해하기위해서 노력하려고 하는게 중요하더라!


(3) 배움을 얻었으니 내 것으로 만들기위해서 생각도 설계도 구현도 많이 해봐야겠다

(4) 그리고 읽는 것과 내가 다시 쓰는 것은 엄청난 차이가 있다 : 다시 정리해보는 것이 엄청난 공부가 된다.

- 사실 책을 읽으면서 이것 저것 터득하고 질문하고 하느라 책을 쭉 읽어보지는 못했음

- 그래서 내용 정리 겸 놓친 내용없나 체크 겸 확고한 나만의 견해를 가지기위해 다시 한번 읽어볼 것

- 객체지향 소프트웨어 공학, 누가 소프트웨어 심장을 만들었나 등 개념 혹은 원리 혹은 기원과 관련한 책들도 많이 읽어봐야겠다 재밌음!


댓글