결합도, 응집도, 캡슐화 중점 발표
결합도
기능간의 결합도가 높아지면 유지보수가 어려워집니다.
여기서 유지보수가 어려워진다를 크게 2가지로 볼 수 있습니다.
- 연관된 다른 클래스가 변경되면 함께 변경되어야 합니다.
- 다른 프로그램의 클래스에서 재사용이 힘들어 집니다.
결합도를 높이는 코딩 방식은 객체지향의 사실과 오해 4주차 - 정리글에서 확인하실 수 있습니다.
현재는 모든 결합도 방식을 설명하지 않고 저희들이 흔히 사용 하는 내용 결합도에 대해 설명하려 합니다.
사실 저희가 흔히 사용하는 내용 결합도는 가장 많이 사용하는 Getter/Setter이기도 하고, 한편으로는 가장 결합도 높은 방식의 코딩이기도 합니다.
class Trump{
private int height = 10;
private int weight = 10;
public Trump(){
}
public getHeight(){
return height;
}
public setHeight(int height){
this.height = height;
}
...
}
class TrumpGuardA{
public void do(){
Trump trump = new Trump();
int width = trump.getHeight() * trump.getWeight();
}
}
위의 방식은 제가 이전에 스터디를 하며 정리한 내용입니다.
이 방식이 높은 결합도를 가지는 이유는 결국 Trump의 private 필드를 getter와 setter를 이용해 수정을 할 수 있다는 것에 있습니다.
이는 다른 객체에서 해당 객체의 수정을 할 수 있음을 의미하고 결국 각 프로그램간의 의존성을 높이는 결과를 가져옵니다.
응집도
이와 같은 문제를 해결하기 위해 응집도라는 개념이 나옵니다.
결합도와는 반대로 응집도는 높을 수록 객체의 기능의 변경이 유연해지고 다른 프로그램에서 재사용이 편리해집니다.
이게 가능한 것은 객체 스스로가 자신과 관련된 기능만 관리한다는 것에 있습니다.
흔히 기존에 public으로 구현했던 부분을 private로 접근을 제어해 내부의 구현만으로 기능을 사용할 수 있게 하는 것이 하나의 방법입니다.
// 예제 코드는 있다면 추후 하나를 추가하겠습니다.
캡슐화
그리고 응집도가 높아지면 자연스럽게 객체의 캡슐화가 잘 이루어지게 됩니다.
캡슐화의 목적은 정보은닉입니다. 다시 말해 필요한 인터페이스만 외부에 공개하고 필요 없는 부분은 외부에 노출시키지 않는 다는 것입니다.
이 3가지 관점을 토대로 다음의 기능을 설명합니다.
너무 많은 클래스에 의존하는 Theater
극장(Theater)에 입장하는 과정에서 관람객(Audience), 가방(Bag) ..등 모든 객체들은 극장에 의존해 모든 작업을 처리하게 됩니다.
이런 과정의 문제는 극장에 의존도가 너무 높다는 것에 있고 이전에 설명한 높은 결합도로 인해 변경이나 재사용에 문제가 생깁니다.
그리고 현재 높은 결합도를 만드는 것은 여러가지가 있겠지만 극장에서 다른 객체로의 이동이 쉬운 즉 getter를 사용해 가장 높은 결합도를 만들었습니다.
당연히 결합도가 높아지면서 각 객체들간의 자율성은 낮아지게 됩니다.
Theater의 결합을 낮춘 설계
극장(Theater)의 의존성을 낮추고 티켓판매자(TicketSeller)의 자율성을 높였습니다.
이 과정에서 극장과 연관된 객체들의 의존성은 없어지고 단순히 티켓 판매자(TicketSeller)에만 의존하도록 설계를 변경한 것을 확인할 수 있습니다.
하지만 여전히 티켓판매자의 의존성이 높은 것을 확인할 수 있습니다.
자율적인 Audience와 TicketSeller로 구성된 설계
객체들이 티켓 판매자(TicketSeller)의 의존성을 줄이기위해 관람객(Audience)에게 티켓의 관리와 티켓 금액을 리턴할 것을 전달합니다.
이 과정에서 티켓 판매자의 의존성이 줄어들게 됩니다.
또한 한번 더 결합도를 줄이기 위해 관람객(Audience)이 가방(Bag)의 기능을 처리하던 부분을 가방이 온전히 처리할 수 있도록 변경합니다.
이 과정에서 가방에 공용 메서드였던 초대장 확인(hasInvitation), 금액 입력(plusAmount) 등과 같은 메서드들이 private로 바뀌면서 응집도가 높아지고 자연스럽게 캡슐화가 이루어지게 됩니다.
이후 티켓 판매자(TicketSeller)가 티켓판매소(TicketOffice)의 티켓 금액 입력업무를 대신하던 것을 티켓판매소로 넘기려 하지만 결론적으로 티켓 판매소에 Audience라는 새로운 의존성이 생기면서 이 기능은 사용하지 않게 됩니다.
기존의 Theater에 의존된 프로그래밍 vs 책임이 분산된 객체 지향 프로그래밍
전체 과정에서 우리가 배울 수 있었던 것은 객체들간의 결합을 높인 getter를 없애가면서 점점 각 객체들이 자신의 업무를 할 수 있도록 유도하고 있다는 것을 알 수있습니다.
그리고 getter를 없애는 과정 속에서 기존엔 절차적 프로그래밍이었던 부분이 점차 책임이 분산된 객체지향 프로그래밍으로 바뀐 다는 것을 볼 수 있습니다.
마무리
저희는 이번 object를 통해 결합도 높은 프로그램이 얼마나 시스템에 악영향을 끼치는지 알 수 있게 되었습니다.
하지만 실제 프로젝트는 결합도 높은 경우가 많습니다.
그렇다면 우리는 어떻게 실제 프로젝트에서도 응집도 높은 프로그램을 만들 수 있도록 노력할 수 있을까요?
발표 후 조언
- 코드를 비교하는 사진을 추가하면 조금 더 좋았을 것 같습니다.
- 절차 지향적인 코드가 어떻게 객체 지향적으로 변경되었는지를 직관적으로 바꼈는지 보여줬으면 좋겠습니다.
- 캡슐화를 하면서 자율성이 높아지고, 결합도가 낮아지면서 응집도가 높아집니다.
- Spring Boot 테스트에선 @SpringBootTest는 컨테이너를 올리는 작업을 하기에 Spring 기능을 사용하지 않으면 사용안해도 됩니다.
'Study > Object' 카테고리의 다른 글
object 메시지와 인터페이스 (0) | 2023.08.13 |
---|---|
object 책임 할당하기 (0) | 2023.08.08 |
object 협력, 책임, 역할 발표 (0) | 2023.07.25 |
object 설계 품질과 트레이드오프 발표 (0) | 2023.07.25 |
Object 객체지향 프로그래밍 발표 (준비중) (0) | 2023.07.18 |