ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [오브젝트 - 2 ] 캡슐화 응집도 결합도 데이터중심설계
    개발/프로그래밍 2022. 6. 1. 17:09

    데이터 지향 설계와 객체 지향 설계의 차이를 비교하기 위해서

    캡슐화 응집도 결합도를 기준삼을수 있다.

    캡슐화

    변경가능성이 높은 부분을 “구현”

    상대적 안정적인 부분을 “인터페이스"라한다.

    구현과 인터페이스를 구분하고 객체 외부에서는인터페이스에 의존하도록 관계를 조절해야한다.

    정리하여 캡슐화란 변경 가능성이 높은 구현부분을 객체 내부로 숨기는 것이다.

    응집도

    모듈 내 요소들이 “하나"의 목적을 위해 협력한다면 그 모듈은 높은 응집도를 가진다. 따라서 한 객체가 가진 책임들이 서로 얼마나 관련이 높은지를 의미한다.

    응집도가 높다면 변경이 발생할때 모듈 내부에서 많은 변경에 일어날것이고 외부에 영향을 주지 않느다.

    결합도

    한 모듈이 다른모듈에대해 얼마나 많은 지식을 가졌는지 척도이다.

    다른모듈의 세세한 부분까지 다 알고있다면 높은 결합도를 가졌다 한다.

    이 세가지 요소는 서로 연관되어있다. 캡슐화의 정도가 응집도와 결합도에 영향을 준다.

    데이터 지향 설계

    class Movie{
    	private Money fee;
    	
    	func getFee() -> Money {
    		return fee
    	}
    	func setFee(fee:Money) {
    		self.fee = fee
    	}
    }
    

    위의 Movie 클래스는 데이터 지향설계로 되어있다.

    fee라는 데이터를 기준으로 get set 메서드를 구현했고 fee는 외부에서 접근불가한 private이므로 캡슐화를 잘 지켰다고 볼수 있을까?

    아니다 get set 메서드를 통해 fee 라는 Money 타입 변수가있음을 드러내고있다. 접근자와 수정자를 가지으로인해 캡슐화를 위반한다고 봐야한다.

    이를 “추측 설계 전략"이라 한다. 이 객체의 협력을 생각하지 않고

    해당 객체의 fee가 다양한 곳에서 사용될것이라는 “추측"으로 진행한 설계이다.

    class ReservationAgency{
    	func reserve(screening:Screening, customer:Customer,audienceCount:Int) -> Reservation  {
    		let movie = screening.getMovie()
    		let discountAmount : Int
    		switch movie.getMovieType() {
    		case .amount : discountAmount = movie.getDiscountAmount()
    		case .percent : discountAmount = movie.getFee() * movie.getDiscountPercent()
    		}
    		let fee : Money
    		fee = movie.getFee() - discountAmount * audienceCount
    	
    		...
    	}
    }
    

    위의 함수에서 movie.getFee()메소드를 사용하고있다.

    이때 fee의 타입을 변경한다고 가정해보자

    그러면 getFee() 반환 타입이 변경되어야하고

    위 메소드도 변경되어야한다.

    또한 위의 메소드는 다른 데이터 객체에 의존하고있으므로 (Screening, Movie)

    의존한 다른 객체의 변경시 해당 메소드도 다 변경을 해줘야한다.

    코드를 생략했지만 만약 ReservationAgency가

    할인 조건, 할인 정책에대한 데이터를 가지고있고

    reserve 함수 안에 해당 조건을 switch 문을 통해 분기처리했다면

    할인 조건, 할인 정책이 변경되거나 추가될때마다 reserve함수가 변경되어야한다.

    class ReservationAgency{
    	func reserve(screening:Screening, customer:Customer, audienceCount:Int) -> Reservation  {
    		
    		let fee:Money = screening.caculateFee(audienceCount)
    		return Reservation(customer,screening,fee,audienceCount) 
    	}
    }
    
    class Screening{
    	private movie : Movie
    
    	func cacultateFee(audienceCount: Int) -> Money {
    		switch movie.getMovieType() {
    		case .amount : return movie.getDiscountAmount()
    		case .percent : return movie.getFee() * movie.getDiscountPercent()
    	}
    

    위의 reserve 메소드는 할인조건이나 할인 정책이 변경,추가되어도 영향을 받지 않는다.

    왜냐하면 할인금액이 모두 적용된 fee 가

    screening.caculateFee() 에 넘어갔기 때문이다.

    할인금액을 계산하는 책임을 Movie 객체가 가지고 더 강한 결합도를 가지게 하였고 reserve 메소드는 movie에 의존하지 않게 되었다.

    댓글

Designed by Tistory.