λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
μ›Œλ°μ—…ν΄λŸ½3κΈ° - λ°±μ—”λ“œμ½”λ“œ

μ„Ήμ…˜5. 객체 μ§€ν–₯ μ μš©ν•˜κΈ°

by kyunge_ev 2025. 3. 11.

1. 상속과 μ‘°ν•©

πŸ“Œ 상속보닀 쑰합을 μ‚¬μš©ν•˜μž!

  • 상속은 μ‹œλ©˜νŠΈμ²˜λŸΌ κ΅³μ–΄μ§€λŠ” ꡬ쑰둜 μˆ˜μ •μ΄ μ–΄λ ΅λ‹€.
    • λΆ€λͺ¨μ™€ μžμ‹μ˜ 결합도가 λ†’λ‹€. → λΆ€λͺ¨μ˜ κΈ°λŠ₯을 μžμ‹μ΄ κ·ΈλŒ€λ‘œ κ°€μ Έκ°€μ„œ μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έ
    • μžμ‹μ΄ λΆ€λͺ¨μ˜ λͺ¨λ“  ν–‰μœ„μ™€ κΈ°λŠ₯을 μ•Œκ³  μžˆμ–΄μ•Όν•œλ‹€. → μΊ‘μŠν™”κ°€ κΉ¨μ§€λŠ” 것
    • λΆ€λͺ¨μ˜ ν–‰μœ„μ™€ κΈ°λŠ₯이 μ‘°κΈˆμ΄λΌλ„ λ³€κ²½λ˜λ©΄ λͺ¨λ“  μžμ‹λ“€μ΄ λ‹€ 영ν–₯을 λ°›λŠ”λ‹€.
  • μ‘°ν•©κ³Ό μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν™œμš©ν•˜λŠ” 것이 μœ μ—°ν•œ ꡬ쑰
    • 상속을 ν†΅ν•œ μ½”λ“œμ˜ 쀑볡 μ œκ±°κ°€ μ£ΌλŠ” 이점보닀 쀑볡이 생기더라도 μœ μ—°ν•œ ꡬ쑰 섀계가 μ£ΌλŠ” 이점이 더 크닀.
    • κ³Όκ±°μ—” ν•˜λ“œμ›¨μ–΄μ˜ μ„±λŠ₯이 따라와주지 μ•ŠμœΌλ‹ˆ μ½”λ“œμ˜ 쀑볡 제거λ₯Ό 톡해 νš¨μœ¨μ„ μ–»λŠ” 것이 효과적인 ν˜•νƒœμ˜€μœΌλ‚˜ ν˜„μž¬λŠ” ν•˜λ“œμ›¨μ–΄ μ„±λŠ₯이 λ›°μ–΄λ‚˜κΈ° λ•Œλ¬Έμ— μ‘°ν•©μ΄λ‚˜ μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν™œμš©ν•˜μ—¬ μœ μ§€λ³΄μˆ˜ν•˜κΈ° μ‰¬μš΄ μœ μ—°ν•œ μ½”λ“œλ₯Ό μž‘μ„±ν•˜λŠ”κ²Œ μ’‹λ‹€.
  • 상속ꡬ쑰λ₯Ό μ‚¬μš©ν•΄μ•Όλ§Œ 효율적인 κ΅¬μ‘°λŠ” 상속을 μ‚¬μš©ν•˜κ³ , μ›¬λ§Œν•˜λ©΄ μ‘°ν•©κ³Ό μΈν„°νŽ˜μ΄μŠ€ ꡬ쑰둜 μœ μ—°ν•˜κ²Œ ν’€μ–΄λ‚΄μž.

2. Value Object (VO)

  • κΈ°λ³Ένƒ€μž…μ„ 객체둜 κ°μ‹Έμ„œ 의미λ₯Ό λΆ€μ—¬ν•˜κ³  μΆ”μƒν™”ν•˜λŠ” 기법
  • λ„λ©”μΈμ˜ μ–΄λ–€ κ°œλ…μ„ μΆ”μƒν™”ν•˜μ—¬ ν‘œν˜„ν•œ κ°’ 객체
  • 객체λ₯Ό κ°’μœΌλ‘œ μ·¨κΈ‰ν•˜κΈ° μœ„ν•΄ λΆˆλ³€μ„±, 동등성, μœ νš¨μ„± 검증 등을 보μž₯ν•΄μ•Όν•œλ‹€.
    • λΆˆλ³€μ„± : final ν•„λ“œ, setter μ‚¬μš© κΈˆμ§€
    • 동등성 : μ„œλ‘œ λ‹€λ₯Έ μΈμŠ€ν„΄μŠ€μ—¬λ„(동일성이 달라도), λ‚΄λΆ€μ˜ 값이 κ°™μœΌλ©΄ 같은 κ°’ 객체둜 μ·¨κΈ‰ν•œλ‹€.
      → equals() & hashCode() μž¬μ •μ˜ ν•„μš”
    • μœ νš¨μ„± 검증 : 객체가 μƒμ„±λ˜λŠ” μ‹œμ μ— 값에 λŒ€ν•œ μœ νš¨μ„±μ„ 보μž₯
      → μƒμ„±μžμ—μ„œ κ²€μ¦λ‘œμ§μ„ μΆ”κ°€

Entity와 VO 차이

β–Ό Entity

class UserAccount {
	private String userId; // μ‹λ³„μž!!!
    private String 이름;
    private String 생년월일;
    private Address μ§‘μ£Όμ†Œ;
}

 

β–Ό VO

class Address {
	private String μ‹œλ„;
    private String μ‹œκ΅°κ΅¬;
    private String λ„λ‘œλͺ…;
    private String 건물번호;
}
  • 제일 큰 차이점은 μ‹λ³„μžμ΄λ‹€.
    • Entityμ—λŠ” μ‹λ³„μžκ°€ μ‘΄μž¬ν•œλ‹€.
      • μ‹λ³„μžκ°€ μ•„λ‹Œ λ‹€λ₯Έ ν•„λ“œμ˜ 값이 달라도, μ‹λ³„μžκ°€ κ°™μœΌλ©΄ λ™λ“±ν•œ 객체둜 μ·¨κΈ‰ν•œλ‹€.
    • equals() & hashCode()도 μ‹λ³„μž ν•„λ“œλ§Œ κ°€μ§€κ³  μž¬μ •μ˜ν•  수 있음
      • μ‹λ³„μžκ°€ 같은데 μ‹λ³„μžκ°€ μ•„λ‹Œ ν•„λ“Έμ˜ 값이 μ„œλ‘œ λ‹€λ₯Έ 두 μΈμŠ€ν„΄μŠ€κ°€ μžˆλ‹€λ©΄, 같은 Entityκ°€ μ‹œκ°„μ΄ 지남에 따라 λ³€ν™”ν•œ κ²ƒμœΌλ‘œ 이해할 수 있음
        • ex) userIdκ°€ λ™μΌν•œ μƒνƒœμ— νœ΄λŒ€ν°λ²ˆν˜Έκ°€ λ³€κ²½λ˜μ–΄ phonNumber ν•„λ“œκ°€ μˆ˜μ •λλ‹€κ³  ν–ˆμ„ λ•Œ, λ‹€λ₯Έ 객체둜 λ³΄λŠ” 것이 μ•„λ‹ˆλΌ μ‹λ³„μžκ°€ λ™μΌν•˜λ‹ˆ λ™μΌν•œ 객체둜 λ³Έλ‹€.
    • VOλŠ” μ‹λ³„μžκ°€ μ—†λ‹€.
      • λ‚΄λΆ€μ˜ λͺ¨λ“  값이 λ‹€ κ°™μ•„μ•Ό λ™λ“±ν•œ 객체둜 μ·¨κΈ‰λœλ‹€.
      • κ°œλ…μ μœΌλ‘œ 전체 ν•„λ“œκ°€ λ‹€ 같이 μ‹λ³„μž 역할을 ν•œλ‹€κ³  λ³Ό 수 μžˆλ‹€.

3. 일급 μ»¬λ ‰μ…˜

일급 μ‹œλ―Ό

  • λ‹€λ₯Έ μš”μ†Œμ—κ²Œ μ‚¬μš© κ°€λŠ₯ν•œ λͺ¨λ“  연산을 μ§€μ›ν•˜λŠ” μš”μ†Œ
    • μ‚¬μš©κ°€λŠ₯ν•œ λͺ¨λ“  μ—°μ‚°μ΄λž€? μ•„λž˜μ™€ 같은 경우λ₯Ό 일급 μ‹œλ―Όμ΄λΌκ³  λΆˆλ¦°λ‹€.
      • μ–΄λ–€ μš”μ†Œκ°€ λ³€μˆ˜λ‘œ ν• λ‹Ή λ˜κ±°λ‚˜
      • μ–΄λ–€ μš”μ†Œκ°€ νŒŒλΌλ―Έν„°λ‘œ μ „λ‹¬λ˜κ±°λ‚˜
      • μ–΄λ–€ μš”μ†Œκ°€ ν•¨μˆ˜μ˜ 결과둜 λ°˜ν™˜λ˜κ±°λ‚˜
    • ex) 일급 ν•¨μˆ˜
      • ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ ν•¨μˆ˜λŠ” 일급 μ‹œλ―Όμ΄λΌκ³  λ³Ό 수 μžˆλ‹€.
        ν•¨μˆ˜λŠ” λ³€μˆ˜μ— 할당될 수 있고, 인자둜 전달될 수 있고, ν•¨μˆ˜μ˜ 결과둜 ν•¨μˆ˜κ°€ λ°˜ν™˜λ  수 μžˆλ‹€.

일급 μ»¬λ ‰μ…˜

  • μ»¬λ ‰μ…˜(List, Set, Map)을 포μž₯ν•˜λ©΄μ„œ μ»¬λ ‰μ…˜λ§Œμ„ μœ μΌν•˜κ²Œ ν•„λ“œλ‘œ κ°€μ§€λŠ” 객체λ₯Ό λ§ν•œλ‹€.
    • 단 ν•˜λ‚˜μ˜ μ»¬λ ‰μ…˜ ν•„λ“œλ§Œ κ°€μ§„λ‹€.
  • μ»¬λ ‰μ…˜μ„ λ‹€λ₯Έ 객체와 λ™λ“±ν•œ 레벨둜 λ‹€λ₯΄κΈ° μœ„ν•΄ μ‚¬μš©λœλ‹€.
  • μ»¬λ ‰μ…˜μ„ κ°μ‹Έλ©΄μ„œ μΆ”μƒν™”ν•˜μ—¬ 의미λ₯Ό 담을 수 있고, 가곡 둜직의 λ³΄κΈˆμžλ¦¬κ°€ 생긴닀.
    • 가곡 λ‘œμ§μ— λŒ€ν•œ ν…ŒμŠ€νŠΈλ„ μž‘μ„±ν•  수 μžˆκ²Œλœλ‹€.
      → μ»¬λ ‰μ…˜ 자체만 μ½”λ“œ 내에 λŒμ•„λ‹€λ‹ˆλ©΄ 의미λ₯Ό 담을 μˆ˜λ„ ν…ŒμŠ€νŠΈλ₯Ό ν•  μˆ˜λ„ μ—†λŠ” μ½”λ“œκ°€ λœλ‹€.
      이λ₯Ό VO처럼 ν•œλ²ˆ κ°μ‹Έμ„œ 가곡 둜직처럼 λ‘œμ§μ— λ‹΄λŠ” 것이닀.
  • μ‚¬μš© 주의 사항!
    • λ§Œμ•½ getter둜 μ»¬λ ‰μ…˜μ„ λ°˜ν™˜ν•  일이 생기면 μ™ΈλΆ€ μ‘°μž‘μ„ ν”Όν•˜κΈ° μœ„ν•΄ κΌ­ μƒˆλ‘œμš΄ μ»¬λ ‰μ…˜μ„ μƒμ„±ν•˜μ—¬ λ°˜ν™˜ν•΄μ•Όν•œλ‹€.
      → μ™ΈλΆ€μ—μ„œ getter둜 μ»¬λ ‰μ…˜μ„ λ³€κ²½ν•  수 μžˆλ‹€λ©΄ μ •λ³΄μ˜ 일관성이 κΉ¨μ§€κΈ° λ•Œλ¬Έ(같은 λ©”λͺ¨λ¦¬ μ£Όμ†Œλ₯Ό κ³΅μœ ν•˜κΈ° λ•Œλ¬Έ)
public List<CellPosition> getPositions() {
	return new ArrayList<>(positions);
}

4. Enum의 ν™œμš©

  • μƒμˆ˜μ˜ μ§‘ν•©μœΌλ‘œ μƒμˆ˜μ™€ κ΄€λ ¨λœ λ‘œμ§μ„ 담을 수 μžˆλŠ” 곡간이닀.
    • μƒνƒœμ™€ ν–‰μœ„λ₯Ό ν•œ κ³³μ—μ„œ 관리할 수 μžˆλŠ” μΆ”μƒν™”λœ 객체
  • νŠΉμ • 도메인 κ°œλ…μ— λŒ€ν•΄ κ·Έ μ’…λ₯˜μ™€ κΈ°λŠ₯을 λͺ…μ‹œμ μœΌλ‘œ ν‘œν˜„ν•΄μ€„ 수 μžˆλ‹€.
    • ex) 레인보우 컬러 Enum 클래슀라면? λΉ¨,μ£Ό,λ…Έ,초,파,남,보λ₯Ό μƒμˆ˜λ‘œ μ •μ˜ν•  수 μžˆλ‹€.
  • Enum의 μƒμˆ˜ κ°’μ΄λ‚˜ νƒ€μž…μ˜ 변경이 μž¦μ€ 경우 Enum 보단 DB둜 κ΄€λ¦¬ν•˜λŠ”κ²Œ 더 μ‰¬μšΈμˆ˜λ„ 있음

5. λ‹€ν˜•μ„± ν™œμš©ν•˜κΈ°

  • 반볡적인 if문을 λ‹¨μˆœν•˜κ²Œ λ§Œλ“€μ–΄λ³Ό 순 μ—†μ„κΉŒ?
private String decideCellSignFrom(CellSnapshot snapshot) {
    CellSnapshotStatus status = snapshot.getStatus();
    if (status == CellSnapshotStatus.EMPTY) {
        return EMPTY_SIGN;
    }
    if (status == CellSnapshotStatus.FLAG) {
        return FLAG_SIGN;
    }
    if (status == CellSnapshotStatus.LAND_MINE) {
        return LAND_MINE_SIGN;
    }
    if (status == CellSnapshotStatus.NUMBER) {
        return String.valueOf(snapshot.getNearbyLandMineCount());
    }
    if (status == CellSnapshotStatus.UNCHECKED) {
        return UNCHECKED_SIGN;
    }

    throw new IllegalStateException("확인할 수 μ—†λŠ” μ…€μž…λ‹ˆλ‹€.");
}
  • μ–΄λ–€ 쑰건을 λ§Œμ‘±ν•˜λ©΄ κ·Έ 쑰건에 ν•΄λ‹Ήν•˜λŠ” ν–‰μœ„λ₯Ό μˆ˜ν–‰ν•œλ‹€! → 이 κΈ°λŠ₯을 if문을 톡해 반볡적으둜 μ‚¬μš©ν•˜κ³  μžˆλ‹€.
  • ꡬ체와 좔상을 톡해 λ‹€ν˜•μ„±μ„ ν™œμš©ν•  수 μžˆλ‹€.
  • λ³€ν™”ν•˜λŠ” 것 ↔ λ³€ν•˜μ§€ μ•ŠλŠ” 것
    • 쑰건 & ν–‰μœ„ ↔ 쑰건을 λ§Œμ‘±ν•˜λŠ”κ°€?, ν–‰μœ„λ₯Ό μˆ˜ν–‰ν•œλ‹€.
    • λ³€ν™”ν•˜λŠ” 것은 μœ λ™μ μœΌλ‘œ ν•΄κ²°ν•΄μ£Όμ–΄μ•Όν•˜κ³ , λ³€ν•˜μ§€ μ•ŠλŠ” 것은 μ§€μΌœμ•Ό OCPλ₯Ό μ§€ν‚€λŠ” ꡬ쑰가됨
    • λ³€ν•˜μ§€ μ•ŠλŠ” 것을 μΈν„°νŽ˜μ΄μŠ€ν™”ν•˜κ³ , λ³€ν•˜λŠ” 것을 ꡬ체클래슀둜 μƒμ„±ν•˜μ—¬ λ‹€ν˜•μ„±μ„ ν™œμš©ν•œλ‹€.
    • Enum을 ν™œμš©ν•  μˆ˜λ„μžˆλ‹€.

6. 숨겨져 μžˆλŠ” 도메인 κ°œλ… λ„μΆœν•˜κΈ°

  • 도메인 지식은 λ§Œλ“œλŠ” 것이 μ•„λ‹ˆλΌ λ°œκ²¬ν•˜λŠ” 것이닀.
  • 객체 μ§€ν–₯은 ν˜„μ‹€μ„ 100% λ°˜μ˜ν•˜λŠ” 도ꡬ가 μ•„λ‹Œ ν‰λ‚΄λ‚΄λŠ” κ²ƒμœΌλ‘œ ν˜„μ‹€ μ„Έκ³„μ—μ„œ μ‰½κ²Œ μΈμ§€ν•˜μ§€ λͺ»ν•˜λŠ” κ°œλ…λ„ λ„μΆœν•΄μ„œ μ‚¬μš©ν•΄μ•Ό ν•  λ•Œκ°€ μžˆλ‹€.
  • 섀계 ν•  λ–„λŠ” κ·Όμ‹œμ , κ±°μ‹œμ  κ΄€μ μ—μ„œ μ΅œλŒ€ν•œ 미래λ₯Ό μ˜ˆμΈ‘ν•˜κ³ , μ‹œκ°„μ΄ μ§€λ‚˜ λ§Œμ•½ ν‹€λ Έλ‹€λŠ” 것을 μΈμ§€ν•˜λ©΄ μ–Έμ œλ“  λŒμ•„μ˜¬ 수 μžˆλ„λ‘ μ½”λ“œλ₯Ό μž‘μ„±ν•΄μ•Όν•œλ‹€.

πŸ“Œ μ™„λ²½ν•œ μ„€κ³„λŠ” μ—†λ‹€. κ·Έ λ‹Ήμ‹œμ˜ μ΅œμ„ μ΄ μžˆμ„ 뿐


좜처 : μΈν”„λŸ°, μ›Œλ°μ—…ν΄λŸ½3κΈ° - λ°±μ—”λ“œ μ½”λ“œ
πŸ“Ž Readable Code: 읽기 쒋은 μ½”λ“œλ₯Ό μž‘μ„±ν•˜λŠ” 사고법
πŸ“Ž Practical Testing: μ‹€μš©μ μΈ ν…ŒμŠ€νŠΈ κ°€μ΄λ“œ