πŸ€ Knowledge/객체지ν–₯섀계

[객체지ν–₯섀계] 쒋은 객체에 λŒ€ν•œ 섀계

TIlearn 2024. 1. 31. 19:33

ν΄λž˜μŠ€μ™€ 객체

 

 

 

ν”νžˆλ“€ λΆ•μ–΄λΉ΅κ³Ό λΆ•μ–΄λΉ΅ ν‹€, 섀계도와 건물과 같은 μ‹μœΌλ‘œ ν΄λž˜μŠ€μ™€ 객체λ₯Ό μ„€λͺ…ν•΄μ™”λ‹€. λ‚˜ μ—­μ‹œ λΉ„μŠ·ν•œ μˆ˜μ€€μœΌλ‘œ ν΄λž˜μŠ€μ™€ 와 객체에 λŒ€ν•΄ μ΄ν•΄ν•˜κ³  μžˆμ„ λΏμ΄μ—ˆλ‹€. λ‹€λ§Œ, κ·ΈλŸ¬ν•œ μˆ˜μ€€μœΌλ‘œ ν΄λž˜μŠ€μ™€ 객체의 관계와 κ·Έ 자체λ₯Ό μ΄ν•΄ν•˜λŠ” 것은 μ •ν™•ν•˜μ§€ λͺ»ν•˜λ‹€.

 

클래슀의 μ±…μž„μ€ 객체λ₯Ό μƒμ„±ν•˜κ³ , μ μ ˆν•œ λ•Œμ— νŒŒκ΄΄ν•˜λŠ” 것이닀. λ˜ν•œ 클래슀의 μžμ‹λ“€μ΄ μ–΄λ–€ λͺ¨μŠ΅μ΄λ©° μ–΄λ–€ 행동을 ν•΄μ•Ό ν•˜λŠ” μ§€ 적어놓은 "계약"에 λŒ€ν•΄μ„œ μ•Œκ³  μžˆλ‹€. κ°μ²΄λŠ” 계약에 λŒ€ν•œ μžκ²©μ„ κ°–μΆ”κΈ° μœ„ν•΄ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜ν•¨μœΌλ‘œμ¨ 이λ₯Ό μ€€μˆ˜ν•˜κ²Œ λœλ‹€. λ¬Όλ‘  μΈν„°νŽ˜μ΄μŠ€λŠ” 좔상화λ₯Ό 톡해 λ‹€ν˜•μ„±μ΄ 보μž₯된 λ‹€λŠ” μ μ—μ„œλ„ μ˜λ―Έκ°€ μžˆκΈ΄ν•˜λ‹€.

 

 

 

 

 

κ°μ²΄λŠ” 생λͺ…체이닀.

 

 

μ˜¬λ°”λ₯Έ κ°μ²΄λŠ” κ·Έ 자체둜 생λͺ…체이닀. ν˜„μ‹€ μ„Έκ³„μ˜ ν”Όμ‘°λ¬Όμ˜ λŒ€λ¦¬μž κ·Έ 자체이며, 생λͺ…주기와 ν–‰μœ„, μŠ΅κ΄€μ„ μ§€λ‹Œ 것이닀. 예λ₯Ό λ“€μ–΄, μ§μ›μ΄λ‚˜ λΆ€μ„œ, HTTP μš”μ²­μ΄λ‚˜ 파일 등이 μ μ ˆν•œ 객체이닀.

 

HTTP μš”μ²­μ΄λ‚˜ 파일 등은 컴퓨터λ₯Ό μΌœμ•Όν•˜λŠ” κ°€μƒμ„Έκ³„μ—μ„œλ§Œ μ‘΄μž¬ν•˜λŠ” 것이 μ•„λ‹Œκ°€ 생각할 수 μžˆλ‹€. κ·Έλž˜μ„œ ν˜„μ‹€μ„Έκ³„μ˜ μ •μ˜λ₯Ό 쑰금 λ‹€λ₯΄κ²Œ 생각해야 ν•œλ‹€. ν˜„μ‹€μ„Έκ³„λŠ” 객체가 μ‚΄μ•„κ°€λŠ” ν”„λ‘œκ·Έλž¨ λ²”μœ„μ—μ„œ μ‘΄μž¬ν•˜λŠ” λͺ¨λ“  것이닀.

 

μ»΄ν“¨ν„°μ—μ„œ ν”„λ‘œκ·Έλž¨μ΄ λ™μž‘ν•˜λŠ” 곳이 μ•„λ‹ˆλΌ, μ‹€μ œ 파일이 μ €μž₯된 λ””μŠ€ν¬λ„ ν˜„μ‹€μ„Έκ³„μ΄λ©° ν”„λ‘œκ·Έλž¨μ—μ„œλŠ” λ‹¨μˆœνžˆ 이λ₯Ό λŒ€ν‘œν•  뿐이닀.

 

GoF νŒ¨ν„΄μ€ λ‹€λ₯Έ 객체와 ν•¨κ»˜ μ‚¬μš©ν•˜κΈ° μœ„ν•œ νŒ¨ν„΄μ΄λ‹€. μ»¨νŠΈλ‘€λŸ¬λ‚˜ μ‹±κΈ€ν„΄, νŒ©ν„°λ¦¬ κ·Έ 자체둜 λ³Έλ‹€λ©΄ 쒋은 객체가 될 수 μ—†λ‹€. μ΄λŠ” GoF νŒ¨ν„΄μ΄ ν˜„μ‹€μ„Έκ³„μ˜ λŒ€ν‘œμžκ°€ 될 수 μ—†κΈ° λ•Œλ¬Έμ΄λ‹€.

 

 

 

 

 

 

κ°μ²΄λŠ” κ³ μœ ν•˜λ©°, λΆˆλ³€μ μ΄λ‹€.

 

 

μΊ‘μŠν™”λŠ” κ³ μœ μ„±μ„ μ§€ν‚€κΈ° μœ„ν•΄μ„œ 필연적이닀. λ§Œμ•½ λ³΅μ‚¬ν•˜λŠ” 것이 κ°€λŠ₯ν•˜λ‹€λ©΄, λ™μΌν•œ λ³΅μ œλ³Έμ„ κ°€μ§€κ²Œ 되며 μ΄λŠ” λ°”λžŒμ§ν•˜μ§€ μ•Šλ‹€.

 

κ·Έλ ‡κΈ° λ•Œλ¬Έμ— 쒋은 κ°μ²΄λŠ” μΊ‘μŠν™”ν•˜λŠ” μƒνƒœλ₯Ό μ§€ν‚€κΈ° μœ„ν•΄ λΆˆλ³€μ„±μ„ μœ μ§€ν•˜κ³ μž ν•œλ‹€. κ·Έλ ‡κ²Œ ν•˜μ—¬ κ°μ²΄λŠ” κ·Έ 객체가 λŒ€ν‘œν•˜λŠ” 것을 λ°°μ‹ ν•˜μ§€ μ•Šμ•„μ•Ό ν•œλ‹€.

 

@Immutable
final class HTTPStatus implements Status {
  private URL page;
  public HTTPStatus(URL url) {
    this.page = url;
  }
  @Override
  public int read() throws IOException {
    return HttpURLConnection.class.cast(
      this.page.openConnection()
    ).getResponseCode();
  }
}

 

 

_read()_ ν•¨μˆ˜κ°€ λ‹€λ₯Έ 값을 λ°˜ν™˜ν•˜λŠ” 것이 κ°€λŠ₯ν•˜λ”λΌλ„, μžμ‹ μ΄ λŒ€ν‘œν•˜λŠ” URL μžμ²΄λŠ” μ ˆλŒ€ λ³€ν•˜μ§€ μ•ŠμœΌλ©° _setter_λ₯Ό 톡해 λ°°μ‹ ν•˜λŠ” 일 λ”°μœ„λŠ” μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ”λ‹€.

 

κ·Έλ ‡λ‹€λ©΄, λΆˆλ³€μ„±μ΄ 보μž₯λœλ‹€λ©΄ μ–΄λ–€ μ μ—μ„œ λ”μš± μ’‹μ„κΉŒ?

 

  • 생성과 ν…ŒμŠ€νŠΈ, 그리고 μ‚¬μš©ν•˜κΈ° κ°„νŽΈν•˜λ‹€.
  • λΆˆλ³€ κ°μ²΄λŠ” μŠ€λ ˆλ“œ μ•ˆμ „(Thread Safe)ν•˜λ‹€.
  • λΆˆλ³€ κ°μ²΄λŠ” μ‹œκ°„μ  결합을 ν”Όν•˜λŠ”λ° 도움이 λœλ‹€.
  • λΆˆλ³€ κ°μ²΄λŠ” λΆ€μˆ˜νš¨κ³Ό(side effect)λ₯Ό μΌμœΌν‚€μ§€ μ•ŠλŠ”λ‹€.
  • λΆˆλ³€ κ°μ²΄λŠ” μ‹€νŒ¨μ›μžμ„±(Failure Atomic)을 λˆλ‹€.
  • μΊμ‹±ν•˜κΈ° μ‰¬μ›Œμ§„λ‹€.
  • NULL μ°Έμ‘°λ₯Ό λ°©μ§€ν•œλ‹€.

 

 

 

πŸ”Ά λΆˆλ³€ κ°μ²΄λŠ” μŠ€λ ˆλ“œ μ•ˆμ „ν•˜λ‹€.

μŠ€λ ˆλ“œ μ•ˆμ „ν•˜λ‹€λŠ” 말이 μ˜λ―Έν•˜λŠ” λ°”λŠ” κ³§, μ—¬λŸ¬ μŠ€λ ˆλ“œμ—μ„œ μ ‘κ·Όν•˜μ—¬λ„ μ’‹λ‹€λŠ” λœ»μ΄λ‹€. κ·Έλ ‡κ²Œ ν•˜μ—¬λ„ μ „ν˜€ μΆ©λŒν•  일이 λ°œμƒν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€. 

μ–΄λ–€ λ©”μ„œλ“œλ„ ν•΄λ‹Ή 객체의 μƒνƒœλ₯Ό λ³€κ²½ν•  수 μ—†μœΌλ©°, 각 κ°μ²΄λŠ” λ©”λͺ¨λ¦¬ 곡간 μƒμ˜ κ³ μœ ν•œ 자리λ₯Ό μ°¨μ§€ν•˜κ³  μžˆλ‹€.


πŸ”Ά λΆˆλ³€ κ°μ²΄λŠ” μ‹œκ°„μ  κ²°ν•©(Temporal Coupling)을 ν”Όν•  수 μžˆλ‹€.


μ‹œκ°„μ  결합은 A λ©”μ„œλ“œκ°€ B λ©”μ„œλ“œλ³΄λ‹€ λ°˜λ“œμ‹œ λ¨Όμ € ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€λŠ” κ²ƒμ—μ„œ λ°œμƒν•œλ‹€. μ΄λŸ¬ν•œ μƒνƒœλŠ” μž‘μ—…μ— μˆœμ„œμ— μ˜μ‘΄μ„±μ΄ μ‘΄μž¬ν•¨μ„ λ§ν•œλ‹€. λ§Œμ•½ μ‹œκ°„μ  결합이 μ—†λŠ” μž‘μ—…λ“€μ€ λ™μ‹œμ— 처리될 수 μžˆλ‹€. 즉, λ™μ‹œμ„±μ— λŒ€ν•œ 고민을 ν•  수 있고, 보닀 λ‚˜μ€ 섀계λ₯Ό ν•΄λ‚Ό 수 μžˆλ‹€. μ΄λŠ” λ”μš± 쒋은 ν™•μž₯ κ°€λŠ₯μ„±κ³Ό μ„±λŠ₯을 κ°€μ Έμ˜¨λ‹€.

λΆˆλ³€ 객체λ₯Ό μ‚¬μš©ν•¨μœΌλ‘œμ¨ μ΄λŸ¬ν•œ μ‹œκ°„μ  결합을 없앨 수 μžˆλ‹€. 


πŸ”Ά μ‹€νŒ¨ μ›μžμ μΈ(Faliure Atomic) λ©”μ†Œλ“œλ₯Ό λ§Œλ“€ 수 μžˆλ‹€.

κ°€λ³€ κ°μ²΄λŠ” μž‘μ—… 도쀑 μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ©΄, λΆˆμ•ˆμ •ν•œ μƒνƒœμ— λΉ μ§€κ²Œ λœλ‹€. μ΄λŠ” 또 λ‹€λ₯Έ μ—λŸ¬λ₯Ό μ•ΌκΈ°ν•  수 μžˆλ‹€. 반면, λΆˆλ³€ κ°μ²΄λŠ” 아무리 μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ”λΌλ„ 초기 λ©”μ„œλ“œ 호좜 μ΄μ „μ˜ μƒνƒœλ₯Ό 항상 μœ μ§€ν•  수 μžˆλ‹€. λ˜ν•œ μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ”λΌλ„ λ‹€μŒ 둜직의 μ²˜λ¦¬κ°€ κ°€λŠ₯ν•˜λ‹€.


πŸ”Ά λΆ€μˆ˜νš¨κ³Ό(side effect)λ₯Ό ν”Όν•΄ 였λ₯˜λ₯Ό ν”Όν•  수 μžˆλ‹€.

λΆ€μˆ˜νš¨κ³Όλž€ λ³€μˆ˜μ˜ κ°’, 객체의 ν•„λ“œ κ°’, μžλ£Œκ΅¬μ‘°κ°€ λ°”λ€Œκ±°λ‚˜ μ—λŸ¬λ‚˜ I/Oκ°€ λ°œμƒν•˜λŠ” 것을 μ˜λ―Έν•œλ‹€. λ§Œμ•½ _setter_λ₯Ό 톡해 값이 λ³€ν™”λœλ‹€λ©΄, μ „ν˜€ λΆ€μˆ˜νš¨κ³Όλ₯Ό μ§€λ‹ˆμ§€ λͺ»ν•˜λ©° 객체의 μƒνƒœλ₯Ό μ˜ˆμΈ‘ν•˜κΈ° μ–΄λ €μšΈ 것이닀.

λ”°λΌμ„œ λΆ€μˆ˜νš¨κ³Όλ₯Ό μ œκ±°ν•œ μˆœμˆ˜ν•¨μˆ˜λ₯Ό λ§Œλ“œλŠ” 것이 ꡉμž₯히 μ€‘μš”ν•΄μ§„λ‹€. μ΄λ•Œ, 객체가 λΆˆλ³€κ°μ²΄λΌλ©΄ μ΄λŸ¬ν•œ μˆœμˆ˜ν•¨μˆ˜λ₯Ό λ§Œλ“œλŠ” 데 μš©μ΄ν•΄μ§„λ‹€.

기본적으둜 λΆˆλ³€κ°μ²΄λŠ” μˆ˜μ •μ΄ λΆˆκ°€λŠ₯ν•˜λ©°, 객체λ₯Ό μƒμ„±ν•˜κ³  μ‚¬μš©ν•˜λŠ”λ° μ—¬λŸ¬κ°€μ§€ μ œν•œμ΄ μžˆλ‹€. 즉, λ©”μ„œλ“œλ“€λ„ μžμ—°μŠ€λŸ½κ²Œ λΆ€μˆ˜νš¨κ³Όκ°€ 제거된 μˆœμˆ˜ν•¨μˆ˜λ‘œ μ΄λ£¨μ–΄μ§ˆ 것이닀. μ΄λŠ” λ‹€λ₯Έ ν•¨μˆ˜μ— μ˜ν•΄μ„œ ν•΄λ‹Ή 객체의 μƒνƒœκ°€ λ³€ν•  수 μ—†μŒμ„ μ˜λ―Έν•˜λ©° 였λ₯˜λ₯Ό 쀄이고, μœ μ§€λ³΄μˆ˜μ„±μ„ 높일 수 μžˆλ‹€.

 

 

 

 

 

 

정적 λ©”μ„œλ“œλŠ” μ§€μ–‘ν•˜μž.

 

정적 λ©”μ„œλ“œλŠ” 객체지ν–₯ νŒ¨λŸ¬λ‹€μž„μ— λ°˜ν•˜λŠ” 섀계이닀. κ·Έ μ΄μœ λŠ” μ •μ λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•¨μœΌλ‘œμ¨, 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ΄ μ•„λ‹ˆλΌ ν΄λž˜μŠ€μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°μ„ λ°”λ€ŒκΈ° λ•Œλ¬Έμ΄λ‹€.

 

객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ„ μ‚¬μš©ν•¨μœΌλ‘œμ¨ 얻을 수 μžˆλŠ” 이점은 κ·Έ "고립성"에 μžˆλ‹€. 객체 μžμ‹ μ˜ 과업을 μˆ˜ν–‰ν•˜λŠ” 데 μ „λ…ν•˜λ©° 이 과정에 μžˆμ–΄ λ©”μ„œλ“œ μœ νš¨λ²”μœ„λŠ” μ§€μ—­λ³€μˆ˜μ— ν•΄λ‹Ήλœλ‹€. 반면, 정적 λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜κ²Œ 되면 μ–Έμ œλ‚˜ κ·Έ ν΄λž˜μŠ€λŠ” μ „μ—­ λ³€μˆ˜μ— ν•΄λ‹Ήλœλ‹€.

 

 

 

 

 

 

 

 

객체의 μ΄λ¦„μ—μ„œ -er은 ν”Όν•˜μž.

 

객체의 이름을 지을 λ•Œ 객체가 무엇을 ν•˜λŠ” μ§€λ³΄λ‹€λŠ” 객체가 무엇인 지에 μ΄ˆμ μ„ λ‘μž. "νŽ˜μ΄μ§€ λͺ¨μŒκΈ°"λΌλŠ” μ΄λ¦„λ³΄λ‹€λŠ” "μ±…" μ΄λΌλŠ” 이름이 훨씬 더 λ‚«λ‹€λŠ” 것이닀.

 

 

 

 

 

 

 

 

ν΄λž˜μŠ€λŠ” finalμ΄λ‚˜ abstractλ₯Ό μ“°μž.

 

 

_final_ν΄λž˜μŠ€λŠ” 상속을 톡해 ν™•μž₯ν•  수 μ—†λŠ” ν΄λž˜μŠ€μ΄λ‹€. 즉, λˆ„κ΅¬λ„ _@Override_ λ°μ½”λ ˆμ΄μ…˜μ„ ν†΅ν•΄μ„œ λ©”μ„œλ“œ κΈ°λŠ₯을 ν™•μž₯ν•  수 μ—†λ‹€.

 

κΈ°λŠ₯을 ν™•μž₯ν•  수 있으면 μ½”λ“œ μž‘μ„±μ„ 덜 해도 λ˜μ„œ μ’‹μ§€ μ•Šμ„κΉŒ? λΌλŠ” 생각이 λ“€ 수 μžˆλ‹€. λ‹€λ§Œ, κΈ°λŠ₯ ν™•μž₯ λ©΄μ—μ„œλŠ” 쒋을 μ§€ λͺ°λΌλ„ λΆ€λͺ¨ ν΄λž˜μŠ€μ— "κ΅¬ν˜„μ˜ 일뢀"λ₯Ό μ§‘μ–΄λ„£λŠ” μ…ˆμ΄κΈ° λ•Œλ¬Έμ— μƒλ‹Ήνžˆ 큰 μœ„ν—˜μ„ κ°μˆ˜ν•΄μ•Ό ν•œλ‹€.

 

즉, _@Override_λ₯Ό ν†΅ν•΄μ„œ λΆ€λͺ¨ 클래슀의 λ©”μ„œλ“œλ₯Ό 가져와 λ°”κΎΈκ²Œ 되면, ν•΄λ‹Ή λΆ€λͺ¨ 클래슀의 λͺ¨λ“  λ©”μ„œλ“œλŠ” _@Override_된 μžμ‹ λ©”μ„œλ“œμ— μ˜μ‘΄ν•˜λŠ” μ…ˆμ΄ λœλ‹€. λ§Œμ•½ μ΄λŸ¬ν•œ μƒνƒœμ—μ„œ μƒμœ„ 클래슀의 λ©”μ„œλ“œ 변경이 μƒκΈ°κ±°λ‚˜, μ μ ˆν•˜μ§€ λͺ»ν•˜κ²Œ _@Override_λœλ‹€λ©΄ μ›μΉ˜μ•ŠλŠ” 였λ₯˜κ°€ λ°œμƒν•  μˆ˜λ„ μžˆλ‹€.

 

반면, _final_둜 상속 자체λ₯Ό 막아버린닀면 μ΄λŸ¬ν•œ λ¬Έμ œλŠ” μ‰½κ²Œ ν•΄κ²°ν•  수 μžˆλ‹€. 그러면 _final_클래슀λ₯Ό ν™•μž₯ν•˜λŠ” 것은 μ•„μ–˜ λΆˆκ°€λŠ₯ν•œ κ²ƒμΌκΉŒ? μ—¬κΈ°μ—λŠ” "μ‘°ν•©"을 μ‚¬μš©ν•˜λ©΄ λœλ‹€.

 

final class OnlyValidStatus implements Status {
  private final Status origin;
  public OnlyValidStatus(Status status) {
    this.origin = status;
  }
  @Override
  public int read() throws IOException {
    int code = this.origin.read();
    if (code >= 400) {
      throw new RuntimeException("Unsuccessful HTTP code");
    }
    return code;
  }
}

 

 

μ΄ˆκΈ°μ— μƒμ„±μžλ₯Ό 톡해 _Status_ μΈμŠ€ν„΄μŠ€λŠ” μ œλŒ€λ‘œ μΊ‘μŠν™”λ˜μ–΄ λ©€λ²„λ³€μˆ˜λ‘œ μ €μž₯λœλ‹€. μ΄λ ‡κ²Œ 상속 λŒ€μ‹  λ©€λ²„λ³€μˆ˜λ‘œμ¨ 상속 λŒ€μƒμ„ λ°›κ²Œ 되면, λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” λ°©μ‹μœΌλ‘œ λ™μž‘ν•˜κΈ° λ•Œλ¬Έμ— μΊ‘μŠν™”λ₯Ό κΉ¨λœ¨λ¦¬μ§€ μ•ŠλŠ”λ‹€.

 

 

 

 

_abstract_ ν΄λž˜μŠ€λŠ” κ·Έ λ°˜λŒ€μ˜ κ²½μš°μ΄λ‹€. _abstract_κ°€ 뢙은 ν΄λž˜μŠ€λŠ” κ·Έ 자체둜 μ‚¬μš©ν•˜λŠ” 것이 λΆˆκ°€λŠ₯ν•˜λ‹€. 무쑰건 λ³„λ„μ˜ κ΅¬ν˜„ λ‘œμ§μ„ λΆ™μ—¬μ£Όμ–΄μ•Ό μž‘λ™ν•  수 μžˆλ‹€λŠ” 말이닀. μ΄λ•Œ, κ±΄λ“œλ¦΄ 수 있게 ν—ˆμš©ν•œ κ³³μ—λ§Œ 넣을 수 μžˆλ‹€.(_final_이 μ•„λ‹Œ 것)

 

abstract class ValidatedHTTPStatus implements Status {
  @Override
  public final int read() throws IOException {
    int code = this.origin.read();
    if (!this.isValid()) {
      throw new RuntimeException("Unsuccessful HTTP code");
    }
    return code;
  }
  protected abstract boolean isValid();
}

 

 

μœ„ μ½”λ“œλŠ” _final_κ³ΌλŠ” 달리, μ μ ˆν•œ 뢀뢄에 μžˆμ–΄μ„œ λ‘œμ§μ„ μ£Όμž…ν•΄μ£ΌκΈ°λ₯Ό μ›ν•˜κ³  μžˆλ‹€. κ·Έ 외에 κ±΄λ“œλ¦¬μ§€ μ•Šμ•„μ•Ό ν•  λ©”μ„œλ“œλŠ” final을 톡해 _@Override_λ‹Ήν•˜λŠ” 것을 λ§‰μŒμœΌλ‘œμ¨ λ°©μ–΄ν•΄ 쀄 수 μžˆλ‹€.

 

 

 

 

 

Reference