1장 - 잘못된 구조의 문제 깨닫기

  • 수많은 악마를 만들어 내는 데이터 클래스
    • 데이터와 로직 등이 분산 되어 있는 것을 응집도가 낮은 구조라 함
      • 응집도가 낮음으로 생길 수 있는 문제
        1. 코드 중복 - 같은 로직을 여러 곳에 구현해버림
        2. 수정 누락 - 사양 변경시, 중복된 코드를 모두 고쳐야함
        3. 가독성 저하 - 관련된 코드를 찾는데 시간이 오래 걸림
        4. 초기화 하지 않은 객체 (쓰레기 객체) - 초기화 하지 않으면 쓸모가 없거나 초기화 하지 않은 상태가 발생할 수 있음
        5. 잘못된 값 할당 - 값이 잘못 됨, 이를 위해 검사 로직을 추가할 수 있지만 여러 곳에 중복 가능성이 있음

        데이터 클래스 하나의 이유로, 이러한 응집도가 낮은 문제로 개발 생산성을 떨어트릴 수 있음


2장 - 설계 첫 걸음

  • 단순 나열이 아니라, 의미 있는 것을 모아 메서드 만들기
    • 의미 있는 로직을 모아서 메서드(함수)로 구현하는 것이 좋음
      • 대표 예시
        // 데미지 평가
        int estimateDamage(int totalPlayerAttackPower, int totalEnemyDefence) {
        	int damegeAmount = totalPlayerAttackPower - (totalEnemyDefence / 2)
        	if (damegeAmount < 0) {
        		return 0;
        	} 
        	return damageAmount
        }
        
        --- 추후 ---
        
        int dealingAmount = estimateDamage(공격량, 적의 방어력) 
        들어온 파라미터들도 그대로 쓰는 것이 아닌, 하나의 의미를 담은 변수 (damegeAmount)로 만들고, 로직까지 처리하며 결과적으로 return 되는 값을 읽고 이해하기 훨씬 쉬워짐
  • 클래스 활용시 - 이러한 의미 있는 메서드들을 모아 클래스를 구현
    • 메서드의 이름들처럼 클래스의 이름과 관련된 비슷한 로직을 담고 있음
    • 서로 밀접한 데이터를 모아둔다면 찾아다니지 않아도 됨
    • 범위를 벗어난 값을 거부하는 로직이 존재하여, 잘못된 값이 유입되지 않게 되면 버그로부터 안전한 클래스 구조가 됨

3장 - 클래스 설계

  • 잘 만들어진 클래스
    • 인스턴스 변수
    • 메서드 (인스턴스 변수에 올바른 값이 들어가도록 & 정상적 조작)
  • 성숙한 클래스로 성장시키는 설계비법
    1. 생성자에서 초기화 하기

      • 코드 예시
        class Money {
        	int amount;
        	Currency  currency;
        	// 여기까지가 초기
        	
        	**1. 생성자에서 초기화 하기
        	Money(int amount, Currency currecncy {
        		this.amount = amount;
        		this.currency = curreny; 
        	}**
        }
    2. 유효성 검사 내부 정의

      • 코드 예시
        class Money {
        ~ 생략 ~
        	
        	Money(int amount, Currency currecncy {
        
        		**2. 유효성 검사 내부 정의
        		if (amount < 0) {
        			throw 돈 더 갖고 오셈
        		}
        
        		if (curruncy == null) {
        			throw 통화 단위 지정 바람
        		}**
        
        		this.amount = amount;
        		this.currency = curreny; 
        	}
        }
    3. 계산 로직도 데이터를 가진 쪽에

      • 코드 예시
        class Money {
        	~ 생략 ~
        	
        	**3. 계산 로직도 데이터를 가진 쪽에
        	void add(int other) {
        		amount += other
        	}**
        }
    4. 불변 변수로 만들어 예상치 못한 동작 막기

      • 코드 예시
        class Money {
        	**4. 불변 변수로 만들어 예상치 못한 동작 막기**
        	final	int amount; // 재할당 불가
        	final	Currency  currency; 
        
        **// Money money = new Money(100, won); // 생성자에 가드를 함께 활용시 UP**
        	
        	~ 생략 ~	
        	**}**
        }
    5. 변경하고 싶다면 새로운 인스턴스 생성하기

      • 코드 예시
        class Money {
        	~ 생략 ~
        
        **5. 변경하고 싶다면 새로운 인스턴스 생성하기**
        	Money add(int other) {
        		int added = amount + other;
        		return new Money(added, currency);
        	}
        }
    6. 매개변수도 변경하지 않는 것이 좋음
      - 코드 예시

          ```jsx
          
          class Money {
          ~ 생략 ~
          
          **6. 매개변수도 변경하지 않는 것이 좋음**
          Money add(final int other) {
          		int added = amount + other;
          		return new Money(added, currency);
          	}
          }
          ```
          

      이 밖에도

    • 엉뚱하지 않는 값전달하지 않도록 하기…
    • 의미 없는 메서드 추가하지 않기…

이런 것들을 통해 중복 코드, 수정 누락, 가독성 저하, 쓰레기 객체, 잘못된 값, 생각하지 못한 부수 효과, 값 전달 실수 등을 막아 설계 효과를 증명해볼 수 있었음

→ Money 클래스의 디자인 패턴

  • 완전 생성자 : 잘못된 상태로부터 클래스를 보호
  • 값 객체 : 특정한 값과 관련된 로직의 응집도를 높임
profile
기록, 꺼내 쓸 수 있는 즐거움

0개의 댓글