[OPP] 객체지향프로그래밍

seheo·2022년 7월 17일
0

Software Engineering

목록 보기
2/5

객체지향 프로그래밍이란?

  • 프로그래밍 개발방법론
  • 사람이 현실을 인식하는 방법을 개발에 접목
    • 직관적으로 이해하기 쉽다
    • 유지 보수를 용이하게 만든다
  • 추상화, 캡슐화, 상속, 다형성을 골고루 사용해 프로그래밍하는 방법

장점

  • 코드의 재활용성이 높음
  • 코딩이 절차지향보다 간편함
  • 디버깅이 쉬움

단점

  • 처리속도가 절차지향보다 느림
  • 설계에 많은 시간소요가 들어감

객체란?

실제로 존재하는 것(건물, 사람, 자동차), 추상적인 것(날짜) 중에서 자신의 속성과 동작을 가지는 모든 것을 말한다.
객체는 속성(필드)과 메소드(동작)로 구성된 자바 객체로 모델링할 수 있다.

객체간의 관계

객체 지향 프로그램에서는 객체는 다른 객체와 다른 객체와 관계를 맺고 있다.

  • 의존(dependency): 한 클래스가 다른 클래스에서 제공하는 기능을 사용할 때 나타낸다.
    • 한 클래스가 다른 클래스에서 제공하는 기능을 사용할 때 표시
    • 연관 관계와의 차이점은 관계가 지속되는 시간이 더 짧게 유지
  • 연관(association): 클래스들이 개념상 서로 연결되었음을 나타낸다.
    • 한 클래스가 다른 클래스에서 제공하는 기능을 사용할 때 표시
  • 집합(composition, aggregation): 클래스들 사이의 전체 또는 부분 같은 관계를 나타낸다.
    • 집약 관계와 합성 관계가 존재
  • 일반화(generalization): 객체지향 개념에서는 상속 관계라고 한다.
    • 속이 빈 화살표로 표시
    • 한 클래스가 다른 클래스를 포함하는 상위 개념(IS-A) 관계

티켓 판매 어플리케이션 구현하기

public class Invitation {
	//초대장(이벤트 당첨 자)
}

public class Ticket {
	//티켓 직접 티켓 구매 
}

public class Bag {
	//관람객의 소지품을 보관
}

public Audience {
	//관람객
}

public class TicketOffice {
	//매표소 
}

public class TicketSeller {
	//판매원
}
public class Theater {
	private TicketSeller ticketSeller;
	
	public Theater(TicketSeller ticketSeller){
		this.ticketSeller = ticketSeller;
	} 
	
	public void enter(Audience audience){
		if (audience.getBag().hasInvitation()){
			Ticket ticket = ticketSeller.getTicketOffice().getTicket();
			audience.getBag().setTicket(ticket);
		}
		else{
			Ticket ticket = ticketSeller.getTicketOffice().getTicket();
			audience.getBag().minusAmount(ticket.getFee());
			ticketSeller.getTicketOfiice().plusAmount(ticket.getFee());
			audience.getBag().setTicket(ticket);
		}
	}
}

소프트웨어 모듈이 가져야하는 세 가지 기능

  • 모든 모듈은 제대로 실행 되어야한다
  • 변경이 용이 해야한다
  • 이해하기 쉬워야한다 (코드를 읽는 사람과 의사소통하는 것)

이 프로그램은 제대로 동작하지만 변경 용의성과 읽는 사람과의 의사 소통이 떨어진다.

Theater의 기능

  1. Theater는 getBag의 Bag를 열어 Invitation이 있는지 확인
  2. Bag에 Invitation이 있으면 Bag에 ticket을 가방으로 옮김
  3. Bag에 Invitation이 없으면 Audience의 가방에서 Ticket의 fee만큼 amount를 꺼내 tickestSeller가 가 TicketOffice에 적립한다
  4. ticketSeller는 Bag에 Ticket을 넣는다.

이 코드의 문제점

  1. 관람객의 가방을 Theater 가져가서 함부로 돈을 넣고 빼고 있다.Theater는 매표소에 보관 중인 티켓과 현금에도 마음대로 접근할 수 있다.
  2. 매표소에 보관중인 티켓과 현금에도 Theater가 마음대로 접근 할 수 있다.

변경 용의성

  • Audience와 TicketSeller를 변경할 경우 Theater도 함께 변경
  • 관람객이 가방을 들지 않고 않다면?
    • Audience 클래스에서 Bag 제거
    • Theater의 enter메서드 수정
    • Theater는 Audience가 가방이 있다는 것과 TicketSeller가 매표소에서 판매를 할 것이라는 것이라는 세부적인 사실에 지나치게 의존적
    • Audience나 TicketSeller를 바꿀려면 Theater도 함께 변경해줘야 된다.
  • 이런 경우를 객체 사이의 의존성이 높다고 한다.
    • 객체 사이 의존성이 과한 경우를 결합도가 높다고 한다.

이해하기 쉬운 코드

  • 이해 가능한 코드란 그 동작이 우리의 예상과 비슷해야한다
  • 현실의 관람객은 직접 자신의 가방에서 초대장을 꺼내 판매원에게 건낸다.
  • 현재 코드는 우리의 상식과 다르게 동작

개선 하기

public class Invitation {
	//초대장, 초대일자를 (이벤트 당첨 자)
}

public class Ticket {
	//티켓 직접 티켓 구매 
}

public class Bag {
	//관람객의 소지품을 보관
}

public Audience {
	//
	private Bag = bag;
	
	public Audience(Bag bag){
		this.bag = bag;
	}
	
	public Long buy(Ticket ticket){
		if (bag.hasInvitation()){
			bag.setTicket(ticket);
			return 0L;
		}
		else{
			bag.setTicket(ticket);
			bag.minusAmount(ticket.getFee());
			return ticket.getFee();
		}
	}
}

public class TicketOffice {
	//매표소 
}

public class TicketSeller {
	private TicketOffice ticketOffice;

	public TicketSeller(TicketOffice ticketOffice){
		this.ticketOffice = ticketOffice;	
	}	

	public void sellTo(Audience audience){
		ticketOffice.plusAmount(audience.buy(ticketOffice.getTicket()));
	}
}
public class Theater {
	private TicketSeller ticketSeller;
	
	public Theater(TicketSeller ticketSeller){
		this.ticketSeller = ticketSeller;
	} 
	
	public void enter(Audience audience){
		ticketSeller.sellTo(audience);
	}
} 

캡슐화

  • TicketSeller, Audoence는 스스로 매표소에 접근하고, 가방을 확인한다.
  • 제 3자가 접근하는걸 허락하지 않는다.
  • 개념적이나 물리적으로 객체 내부의 세부적인 사항을 감춤
  • 캡슐화 목적은 변경하기 쉬운 객체를 만드는것
    • 캡슐화를 통해 객체 내부로의 접근을 제한하면 객체 사이의 결합도를 낮춰 설계를 더 쉽게 변경 가능하다

개선 결과

변경 용이성

  • 캡슐화하여 TicketSeller와 Audience 사이의 결합도가 낮아짐
  • Audience의 구현을 수정하더라도 TicketSeller에는 영향을 미치지 않는다

코드를 읽는 사람과의 의사소통

  • Audience아 TicketSeller는 자신이 가지고 있는 소지품을 직접 관리

응집도와 결합도

개선을 통해 응집도를 높이고 결합도를 줄일 수 있다.

  • 객체 내부의 상태를 캡슐화하고 객체 간에 오직 메시지를 통해서 상호작용
  • 캡슐화를 통해 밀접하게 연관된 작업만을 수행하고 연관성 없는 작업은 다른 객체에게 위임
  • 객체가 스스로 자신의 데이터를 책임져야, 외부의 간섭을 배제하고 메시지를 통해서만 협력하는 자율적인 객체들의 공동체를 만드는 것이 훌륭한 객체지향 설계를 얻을 수 있는 지름길이다.

의인화

현실의 직관에서도 관람객과 판매원은 스스로 자신을 책임진다. 그렇기 때문에 코드로도 이해하기 쉽다.

극장은 어떤가?

  • 극장은 실세계에서 자유롭지 않다.
  • 극장에 관람객이 입장하기 위해서는 누군가 문을 열고 입장을 허가 시켜줘야한다.

그렇다면 극장에서 문을 열어주고 허가 시켜주는 사람 객체가 또 필요한것 일까?

  • NO
  • 작성한 코드에서는 극장은 마치 관람객같은 생물처럼 다룬다
  • 무생물 역시 스스로 행동하고 자기 자신을 책임지는 자율적 존재로 취급한다

객체지향의 세계에서는 수동적인 존재도 능동적이고 자율적인 존재로 바뀌어야한다. 이것을 의인화라고 한다.

참고자료


[10분 테코톡] 🍟 웨지의 OOP

위키북스, 오브젝트 코드로 이해하는 객체지향 설계, 조영호

0개의 댓글