μλ¬Έ : http://www.pragmaticprogrammer.com/ppllc/papers/1998_05.html μ€ 'Tell vs Ask'
~cpp Alec Sharp, in the recent book Smalltalk by Example [SHARP], points up a very valuable lesson in few words: Procedural code gets information then makes decisions. Object-oriented code tells objects to do things. --- Alec Sharp
then μμ than μ΄ λμ΄μΌ νλ κ²μ΄ μλκΉμ? μ κ° μλ¬Έμ λͺ»λ΄μ ν¨λΆλ‘ κ³ μΉκΈ°λ νλ€κ΅°μ.
μλ μ€νμ "Smalltalk by Example" μ΄λΌλ μ΅κ·Όμ μ±
μμλ μμ£Ό κ°μ΄μΉμλ κ΅νμ κ°μ‘°νλ€.λ§λ μ§μ μΈλ°. μλ¬Έλ then μ΄κ΅°. λ΄κ° ν΄μμ than μΌλ‘ μ½κ³ μ€μνλ€. Thanks.~
μ μ°¨μ μΈ μ½λμμλ μ 보λ₯Ό μ»κ³ λ λ€ ν μΌμ κ²°μ νλ€. κ°μ²΄ μ§ν₯ μ½λμμλ κ°μ²΄μκ² νλμ νλλ‘ μν¨λ€.
~cpp That is, you should endeavor to tell objects what you want them to do; do not ask them questions about their state, make a decision, and then tell them what to do.
μλ, λΉμ μ κ°μ²΄λ€λ‘ νμ¬κΈ λΉμ μ΄ μνλ μΌμ νλλ‘ λ
Έλ ₯ν΄μΌ νλ€. κ°μ²΄λ€μ μνμ λν΄ κ°μ²΄λ€μκ² λ¬»μ§ λ§κ³ , κ²°μ νλΌ. κ·Έλ¦¬κ³ κ°μ²΄λ€μκ² μνλ μΌμ νλλ‘ νλΌ.
~cpp The problem is that, as the caller, you should not be making decisions based on the state of the called object that result in you then changing the state of the object. The logic you are implementing is probably the called object's responsibility, not yours. For you to make decisions outside the object violates its encapsulation.
λ¬Έμ μ μ caller λ‘μ, λΉμ μ called object μ μνμ κΈ°λ°ν κ²°μ μ λ΄λ¦¬λ©΄ μλλ€λ κ²μ΄λ€.
λΉμ μ΄ κ΅¬ννλ €λ logic μ μλ§λ νΈμΆλ κ°μ²΄μ μ± μμ΄μ§, λΉμ μ μ± μμ΄ μλλ€. (μ¬κΈ°μ you λ ν΄λΉ object λ₯Ό μ΄μ©νλ client. caller) λΉμ μ΄ object μ λ°κΉ₯μͺ½μμ κ²°μ μ λ΄λ¦¬λ κ²μ ν΄λΉ object μ encapsulation μ μλ°λλ€.
λΉμ μ΄ κ΅¬ννλ €λ logic μ μλ§λ νΈμΆλ κ°μ²΄μ μ± μμ΄μ§, λΉμ μ μ± μμ΄ μλλ€. (μ¬κΈ°μ you λ ν΄λΉ object λ₯Ό μ΄μ©νλ client. caller) λΉμ μ΄ object μ λ°κΉ₯μͺ½μμ κ²°μ μ λ΄λ¦¬λ κ²μ ν΄λΉ object μ encapsulation μ μλ°λλ€.
~cpp Sure, you may say, that's obvious. I'd never write code like that. Still, it's very easy to get lulled into examining some referenced object and then calling different methods based on the results. But that may not be the best way to go about doing it. Tell the object what you want. Let it figure out how to do it. Think declaratively instead of procedurally!
μλ§ λΉμ μ μ΄λ κ² λ§ν μ§λ λͺ¨λ₯Έλ€. "λλ κ·Έλ° μ½λλ₯Ό μμ±ν μ μ΄ μμ΄!" νμ§λ§, referenced object μ κ°μ μ‘°μ¬ν΄μ κ·Έ κ²°κ³Όκ°μ λ°λΌ κ°κ° λ€λ₯Έ λ©μλλ₯Ό νΈμΆνλ μμΌλ‘ μ λΉν ꡬννλ©° μΌλ¨Έλ¬΄λ¦¬λ κ²½μ°λ ννλ€.
exam) μλ§ Refactoring μ±
μλ λμ¬κ²μ΄μ§λ§.
~cpp switch (person.gender) { case IS_MALE: ____ case IS_FEMALE: ____ }μ΄λ°μμ μ½λλ€. λ³΄ν΅ μ΄λ°κ±΄ Polymorphism μΌλ‘ ν΄κ²°ν΄μΌ ν λ¬Έμ λ€μ΄μ§μ.
νμ§λ§, μ΄λ μ’μ λ°©λ²μ΄ μλλ€. λΉμ μ΄ μνλ μΌμ λν΄μ object μκ² μμΌλΌ. (μ¦, μ νμμ λν κ²°μ μ object λ΄μμ ν΄κ²°νκ²λ) object λ‘ νμ¬κΈ μ΄λ»κ² ν΄μΌ ν μ§ ν΄κ²°νλλ‘ νλΌ. μ μ°¨μ μ΄λ €νκΈ° 보λ¨, μμ μ μ΄λ €κ³ νλΌ. (μ΄λ OOP μμ μ΄μΌκΈ°νλ―, Object λ€ κ°μ νλλ€μ λν΄μ.)
~cpp It is easier to stay out of this trap if you start by designing classes based on their responsibilities, you can then progress naturally to specifying commands that the class may execute, as opposed to queries that inform you as to the state of the object.
λ§μΌ λΉμ μ΄ κ° ν΄λμ€λ€μ μ±
μμ κΈ°λ°ν λμμΈμΌλ‘ μμνλ€λ©΄ μ΄λ¬ν ν¨μ μ νμΆνλ μΌμ μ½λ€.
(ResponsibilityDrivenDesign) κ·Έλ¬ν κ²½μ°, λΉμ μ λΉμ μκ² κ°μ²΄μ μνλ₯Ό μ리λλ‘ μ§μλ¬Έμ μμ±νλ λμ (μ£Όλ‘ getter λ€μ ν΄λΉλλ¦¬λΌ μκ°), class λ€μ΄ μ€νν μ μλ command λ€μ μμ°μ€λ½κ² λ°μ μμΌ λκ° κ²μ΄λ€.
(ResponsibilityDrivenDesign) κ·Έλ¬ν κ²½μ°, λΉμ μ λΉμ μκ² κ°μ²΄μ μνλ₯Ό μ리λλ‘ μ§μλ¬Έμ μμ±νλ λμ (μ£Όλ‘ getter λ€μ ν΄λΉλλ¦¬λΌ μκ°), class λ€μ΄ μ€νν μ μλ command λ€μ μμ°μ€λ½κ² λ°μ μμΌ λκ° κ²μ΄λ€.
λ§μ½ κ·Έλ€μ μ±
μ(μλ―Έ)μ κΈ°λ°ν΄μ ν΄λμ€ μ€κ³λ₯Ό μμνλ€λ©΄ μ΄λ°ν λ«μμ λ²μ΄λκΈ°μ λ μ½λ€.
Reference - Smalltalk By Example μ€ 'Tell, Don't Ask' (http://www.iam.unibe.ch/~ducasse/WebPages/FreeBooks.html μ 곡κ°λμ΄μλ€.)
See also κ°μ²΄μ§ν₯vsμ μ°¨μ§ν₯ - μ§κΈ μ¬κΈ° μλ²κ° μ£½μκ² κ°μλ° μλ² μ΄μλλ©΄ νμ΄μ§ λ°κ»λλ€...;; - μμΈν