SlideShare uma empresa Scribd logo
1 de 58
리펙토링 루비
4번째 발표
컬렉션 캡슐화
248p
준비
• 컬렉션이란?
– 1개 이상의 엘리먼트들을 담는 자료 구조
– C++ : 컨테이너
• Vector, map, set, hash_map, …
• 컬렉션 캡슐화란?
– 컬렉션을 캡슐화 하여 직접 읽거나 쓰지 않고
컬렉션 접근 메소드를 통해 읽거나 쓰도록 하
는 것.
동기
• 의도되지 않은 자료 조작을 방지
– Add/Remove할 때 추가적인 처리가 필요한
경우
– 상황에 따라 Add/Remove등의 조작을 제한하
고 싶을 경우
– …
• 내부 데이터 구조 노출
– 구조 변경이 어려워짐
– 클라이언트에게 불필요한 인식을 요구
1. add/remove메소드 추가
• def add_course(course)
@courses << course
end
def remove_course(course)
@courses.delete(course)
end
2. 컬렉션 초기화
• Def initialize
@courses = []
end
3. Setter 호출 부분 수정(before)
• kent = Person.new
• courses = []
• courses << Course.new("Smalltalk
Programming", false)
• courses << Course.new("Appreciating
Single Malts", true)
• kent.course =courses
3. Setter 호출 부분 수정(after)
• kent = Person.new
• Kent.add_course(Course.new("Smalltalk
Programming", false))
• Kent.add_course(Course.new("Appreciatin
g Single Malts", true))
4. Getter가 사본을 리턴하도록 수
정
• Def courses
@courses.dup
end
• Def courses
@courses.class
end
5. 컬렉션을 사용하는 객체로 들어
가야 할 기능 추출 및 이동(before)
• number_of_advanced_courses =
kent.courses.select do |course|
course.advanced?
end.size
5. 컬렉션을 사용하는 객체로 들어
가야 할 기능 추출 및 이동(after1)
• def number_of_advanced_courses
kent.courses.select { |course|
course.advanced? }.size
end
5. 컬렉션을 사용하는 객체로 들어
가야 할 기능 추출 및 이동(after2)
• def number_of_advanced_courses
@courses.select { |course|
course.advanced? }.size
end
• Def number_of_courses
@courses.size
end
레코드를 데이터 클래스로 전환
254p
준비
• 레코드란?
– 일련의 기록
• 덤 데이터 객체(dumb data object)란?
– 데이터만 존재하는 클래스(구조체)
– 데이터와 인터페이스가 함께 존재해야 한다는
객체 지향의 원칙과는 맞지 않음
동기
• 레코드 구조를 “가독성 있고 편리하게” 인터페이
싱 할 수 있도록 해줌
– 배열을 객체로 전환과 비슷
• Struct UserData
• {
– Name
– Age
– Email
• }
• Open회원가입Dialog(UserData data)
방법
• 레코드를 나타낼 클래스를 작성
• 클래스에 필드 추가 및 필요한 항목에 대
한 접근 메서드 작성
• 끝
– 나머진 후에 나옴.( 다른 분께서… )
타입 코드를 재정의로 전환
255p
준비
• 타입 코드란?
– 흔히 말하는 enum
• BikeType_Rigid
BikeType_FrontSuspension
BikeType_FullSuspension
• 재정의란?
– 타입별 기능에 대한 재정의를 말함(원서 225p)
동기
• 조건문 제거
– 코드의 복잡성을 낮춤
1. 타입에 해당하는 클래스 작성 및
기본 클래스를 모듈로 변환
• Class RigidMountainBike
include MoutainBike
end
Class FrontSuspensionMountainBike
include MountainBike
end
Class FullSuspensionMountainBike
include MountainBike
end
Class module MountainBike
….
2. 원본 클래스 생성을 원하는 타입
의 클래스 생성으로 대체 및 테스트
• Bike = MountainBike.new(…)
• -> Bike =
FrontSuspensionMountainBike.new(…)
3. 타입 코드에 의존적인 메서드 중 하
나를 각 타입 클래스에 맞게 재정의 및
테스트
• Class RigidMountainBike …
def price
end
Class FrontSuspensionMountainBike …
def price
end
Class FullSuspensionMountainBike …
def price
end
module MountainBike …
def price
4. 나머지 메서드도 재정의 및 테스
트
• Class RigidMountainBike …
def price
def off_road_ability
end
Class FrontSuspensionMountainBike …
def price
def off_road_ability
end
Class FullSuspensionMountainBike …
def price
def off_road_ability
end
module MountainBike …
def price
def off_road_ability
5. 모듈 제거
• module MountainBike …
def price
def off_road_ability
end
타입 코드를 모듈 확장으로 전환
263p
준비
• 모듈 확장(Module Extension)이란?
– Class에 모듈을 붙여 기능을 확장시키는 것
– C/C++에서는 지원하지 않음
동기
• 조건문 제거
• 객체의 타입 동적 전환
– 타입 코드를 재정의로 전환에서는 불가능
• 모듈에서 확장될 클래스의 멤버 변수 접근
가능(편리)
• # 객체의 타입 동적 전환이 가능하다고는
하지만 자유롭지는 못하다
– 확장이 되면 축소하기가 복잡함
1. 타입 코드에 필드 자체 캡슐화
실시
• 234p
2. 타입에 맞는 모듈 작성 및 타입 변경
에 따른 모듈 확장, 원본 클래스는 기본
기능을 반환하도록 수정
• Module FrontSuspensionMountainBike
def price
end
Module FullSuspensionMountainBike
def price
end
class MountainBike …
def type_code=(value)
@type_code = value
case type_code
when :front_suspension: extend(FrontSuspensionMountainBike)
when :full_suspension: extend(FullSuspensionMountainBike)
end
def price
# return rigid_price…
end
end
3. 나머지 메서드도 재정의 및 테스
트
• Module FrontSuspensionMountainBike
def price
def off_road_ability
end
Module FullSuspensionMountainBike
def price
def off_road_ability
end
class MountainBike …
def type_code=(value)
@type_code = value
case type_code
when :front_suspension: extend(FrontSuspensionMountainBike)
when :full_suspension: extend(FullSuspensionMountainBike)
end
def price
# return rigid_price…
end
def off_road_ability
# return rigid road ability…
end
end
4. 타입 코드 대신 모듈을 전달
(before)
• Def type_code=(value)
@type_code = value
case type_code … # extend module
• Bike = MountainBike.new
Bike.type_code = :front_suspension
…
4. 타입 코드 대신 모듈을 전달
(after)
• Def type_code=(mod)
extend(mod)
end
• Bike = MountainBike.new
Bike.type_code =
FrontSuspensionMountainBike
…
타입 코드를 상태/전략 패턴으로
전환
270p
동기
• 조건문 제거
• 타입 코드의 자유로운 동적 전환
1. 타입 코드 필드 자체 캡슐화
• 모듈 확장과 동일
2. 타입에 해당하는 클래스 작성
• Class RigidMountainBike
end
Class FrontSuspensionMountainBike
end
Class FullSuspensionMountainBike
end
3. 타입 코드가 변할 때 해당하는
타입 클래스 생성
• Class MountainBike …
def type_code=(value)
@type_code = value
@bike_type = case type_code
when :rigid: RigidMountainBike.new
when :front_suspension: FrontSuspensionMountainBike.new
when :full_suspension: FullSuspensionMountainbike.new
end
end
4. 하나의 메서드를 선택해 타입 객
체에 위임 및 타입 객체 생성시 필
요한 data 전달• Class RigidMountainBike
def off_road_ability
@tire_width * TIRE_WIDTH_FACTOR
end
end
Class FrontSuspensionMountainBike
def off_road_ability …
end
Class FullSuspensionMountainBike
def off_road_ability …
end
Class MountainBike …
extend Forwardable
def_delegators :@bike_type, :off_road_ability
def type_code(value) ...
… when :rigid: RigidMountainBike.new( :tire_width => @tire_width)
…
end
5. 나머지 메서드도 타입 객체에 위
임
• Class RigidMountainBike
def off_road_ability
def price
end
Class FrontSuspensionMountainBike
def off_road_ability
def price
end
Class FullSuspensionMountainBike
def off_road_ability
def price
end
Class MountainBike …
extend Forwardable
def_delegators :@bike_type, :off_road_ability, :price
end
6. 타입 코드 대신 타입 객체로 생
성
• Bike =
MountainBike.new(FrontSuspensionMountai
nBike.new(
:tire_width => @tire_width,
:front_fork_travel => @front_fork_travel,
… ))
• Class MountainBike …
def initialize(bike_type)
@bike_type = bike_type
end
end
7. 기타(upgradable parameters)
• Class RigidMountainBike…
def upgradable_parameters {
:tire_width => @tire_width,
:base_price => @base_price,
…
}
end
Class FrontSuspensionMountainBike …
def upgradable_parameters { … }
…
• Class MountainBike…
def add_front_suspension(params)
@bike_type =
FrontSuspensionMountainBike.new(
@bike_type.upgradable_parameters.merge(params)
end
end
하위클래스를 필드로 전환
283p
동기
• 하위 클래스가 상수 메서드만 정의
– 상속 구조가 복잡도를 증가시킴
리펙토링 전
• Class Person…
end
class Female < Person
def female?
true
end
def code
‘F’
end
end
class Male < Person
def female?
false
end
def code?
‘M’
end
end
1. 생성자를 팩토리 메서드로 전환
• Class Person
def self.create_female
Female.new
end
def self.create_male
Male.new
end
end
2. 호출 코드를 팩토리 메서드로 전
환
• Scott = Male.new
• -> Scott = Person.create_male
3. 상위클래스에 필드 추가 및 하위
클래스 초기화시 필드 초기화
• Class Person …
def initialize( female, code )
@female = female
@code = code
end
Class Female …
def initialize
super( true, ‘F’ )
end
Class Male …
def initialize
super( false, ‘M’ )
end
4.팩토리 메서드에 초기화 메서드
내용 직접 삽입 및 하위클래스 제거
• Person …
Def self.create_female
Person.new(true, ‘F’)
end
Def self.create_male
Person.new(false, ‘M’)
end
end
• Class male < Person …
Class female < Person …
속성 초기화를 사용시로 미루기
287p
동기
• 가독성
– 초기화 메서드가 복잡한 경우 초기화 로직을
분리
방법1. ||= 사용하기(before)
• Class Employee
attr_reader :emails, :voice_mails
def initialize
@emails = []
@voice_mails = []
end
end
방법1. ||= 사용하기(after)
• Class Employee
def emails
@emails ||= []
end
def voice_mails
@voice_mails ||= []
end
end
방법2. instance_variable_defined?
사용하기(before)
• 이유
– 속성에게 nil이나 false가 “유효한” 값이라면 1
번 방법을 사용할 수 없다.
• Class Employee
def initialize
@assistant = Employee.find_by_boss_id( self.id )
end
end
방법2. instance_variable_defined?
사용하기(after)
• Class Employee
def assistant
unless instance_variable_defined? :@assistant
@assistant = Employee.find_by_boss_id( self.id )
end
end
속성 초기화를 생성 시로 당기기
290p
동기
• 가독성
– 어떤 사람은 한 곳에 있는게 편하다!;;
방법
• 다시 원래 대로…
• 두 기법 중 하나를 선택하여 일관되게 사
용하는 것이 중요
감사합니다

Mais conteúdo relacionado

Semelhante a Refactoring with Ruby (리펙토링 루비)

Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4
연우 김
 

Semelhante a Refactoring with Ruby (리펙토링 루비) (20)

Django admin site 커스텀하여 적극적으로 활용하기
Django admin site 커스텀하여 적극적으로 활용하기Django admin site 커스텀하여 적극적으로 활용하기
Django admin site 커스텀하여 적극적으로 활용하기
 
MySQL_MariaDB-성능개선-202201.pptx
MySQL_MariaDB-성능개선-202201.pptxMySQL_MariaDB-성능개선-202201.pptx
MySQL_MariaDB-성능개선-202201.pptx
 
Refactoring
RefactoringRefactoring
Refactoring
 
Refactoring
RefactoringRefactoring
Refactoring
 
[15]Android Kotlin을 통한 개발 전략
[15]Android Kotlin을 통한 개발 전략[15]Android Kotlin을 통한 개발 전략
[15]Android Kotlin을 통한 개발 전략
 
Effective c++ 정리 chapter 6
Effective c++ 정리 chapter 6Effective c++ 정리 chapter 6
Effective c++ 정리 chapter 6
 
PySpark 배우기 Ch 06. ML 패키지 소개하기
PySpark 배우기 Ch 06. ML 패키지 소개하기PySpark 배우기 Ch 06. ML 패키지 소개하기
PySpark 배우기 Ch 06. ML 패키지 소개하기
 
Java_05 class
Java_05 classJava_05 class
Java_05 class
 
Java class
Java classJava class
Java class
 
Chapter7~9 ppt
Chapter7~9 pptChapter7~9 ppt
Chapter7~9 ppt
 
Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4Effective c++ 정리 chapter 4
Effective c++ 정리 chapter 4
 
Hibernate 기초
Hibernate 기초Hibernate 기초
Hibernate 기초
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
 
Django를 Django답게, Django로 뉴스 사이트 만들기
Django를 Django답게, Django로 뉴스 사이트 만들기Django를 Django답게, Django로 뉴스 사이트 만들기
Django를 Django답게, Django로 뉴스 사이트 만들기
 
자바야 놀자 PPT
자바야 놀자 PPT자바야 놀자 PPT
자바야 놀자 PPT
 
파이썬 유용한 라이브러리
파이썬 유용한 라이브러리파이썬 유용한 라이브러리
파이썬 유용한 라이브러리
 
Java, android 스터티4
Java, android 스터티4Java, android 스터티4
Java, android 스터티4
 
Java, android 스터티4
Java, android 스터티4Java, android 스터티4
Java, android 스터티4
 
Linq
LinqLinq
Linq
 
Effective C++ Chaper 1
Effective C++ Chaper 1Effective C++ Chaper 1
Effective C++ Chaper 1
 

Refactoring with Ruby (리펙토링 루비)

  • 3. 준비 • 컬렉션이란? – 1개 이상의 엘리먼트들을 담는 자료 구조 – C++ : 컨테이너 • Vector, map, set, hash_map, … • 컬렉션 캡슐화란? – 컬렉션을 캡슐화 하여 직접 읽거나 쓰지 않고 컬렉션 접근 메소드를 통해 읽거나 쓰도록 하 는 것.
  • 4. 동기 • 의도되지 않은 자료 조작을 방지 – Add/Remove할 때 추가적인 처리가 필요한 경우 – 상황에 따라 Add/Remove등의 조작을 제한하 고 싶을 경우 – … • 내부 데이터 구조 노출 – 구조 변경이 어려워짐 – 클라이언트에게 불필요한 인식을 요구
  • 5. 1. add/remove메소드 추가 • def add_course(course) @courses << course end def remove_course(course) @courses.delete(course) end
  • 6. 2. 컬렉션 초기화 • Def initialize @courses = [] end
  • 7. 3. Setter 호출 부분 수정(before) • kent = Person.new • courses = [] • courses << Course.new("Smalltalk Programming", false) • courses << Course.new("Appreciating Single Malts", true) • kent.course =courses
  • 8. 3. Setter 호출 부분 수정(after) • kent = Person.new • Kent.add_course(Course.new("Smalltalk Programming", false)) • Kent.add_course(Course.new("Appreciatin g Single Malts", true))
  • 9. 4. Getter가 사본을 리턴하도록 수 정 • Def courses @courses.dup end • Def courses @courses.class end
  • 10. 5. 컬렉션을 사용하는 객체로 들어 가야 할 기능 추출 및 이동(before) • number_of_advanced_courses = kent.courses.select do |course| course.advanced? end.size
  • 11. 5. 컬렉션을 사용하는 객체로 들어 가야 할 기능 추출 및 이동(after1) • def number_of_advanced_courses kent.courses.select { |course| course.advanced? }.size end
  • 12. 5. 컬렉션을 사용하는 객체로 들어 가야 할 기능 추출 및 이동(after2) • def number_of_advanced_courses @courses.select { |course| course.advanced? }.size end • Def number_of_courses @courses.size end
  • 14. 준비 • 레코드란? – 일련의 기록 • 덤 데이터 객체(dumb data object)란? – 데이터만 존재하는 클래스(구조체) – 데이터와 인터페이스가 함께 존재해야 한다는 객체 지향의 원칙과는 맞지 않음
  • 15. 동기 • 레코드 구조를 “가독성 있고 편리하게” 인터페이 싱 할 수 있도록 해줌 – 배열을 객체로 전환과 비슷 • Struct UserData • { – Name – Age – Email • } • Open회원가입Dialog(UserData data)
  • 16. 방법 • 레코드를 나타낼 클래스를 작성 • 클래스에 필드 추가 및 필요한 항목에 대 한 접근 메서드 작성 • 끝 – 나머진 후에 나옴.( 다른 분께서… )
  • 18. 준비 • 타입 코드란? – 흔히 말하는 enum • BikeType_Rigid BikeType_FrontSuspension BikeType_FullSuspension • 재정의란? – 타입별 기능에 대한 재정의를 말함(원서 225p)
  • 19. 동기 • 조건문 제거 – 코드의 복잡성을 낮춤
  • 20. 1. 타입에 해당하는 클래스 작성 및 기본 클래스를 모듈로 변환 • Class RigidMountainBike include MoutainBike end Class FrontSuspensionMountainBike include MountainBike end Class FullSuspensionMountainBike include MountainBike end Class module MountainBike ….
  • 21. 2. 원본 클래스 생성을 원하는 타입 의 클래스 생성으로 대체 및 테스트 • Bike = MountainBike.new(…) • -> Bike = FrontSuspensionMountainBike.new(…)
  • 22. 3. 타입 코드에 의존적인 메서드 중 하 나를 각 타입 클래스에 맞게 재정의 및 테스트 • Class RigidMountainBike … def price end Class FrontSuspensionMountainBike … def price end Class FullSuspensionMountainBike … def price end module MountainBike … def price
  • 23. 4. 나머지 메서드도 재정의 및 테스 트 • Class RigidMountainBike … def price def off_road_ability end Class FrontSuspensionMountainBike … def price def off_road_ability end Class FullSuspensionMountainBike … def price def off_road_ability end module MountainBike … def price def off_road_ability
  • 24. 5. 모듈 제거 • module MountainBike … def price def off_road_ability end
  • 25. 타입 코드를 모듈 확장으로 전환 263p
  • 26. 준비 • 모듈 확장(Module Extension)이란? – Class에 모듈을 붙여 기능을 확장시키는 것 – C/C++에서는 지원하지 않음
  • 27. 동기 • 조건문 제거 • 객체의 타입 동적 전환 – 타입 코드를 재정의로 전환에서는 불가능 • 모듈에서 확장될 클래스의 멤버 변수 접근 가능(편리) • # 객체의 타입 동적 전환이 가능하다고는 하지만 자유롭지는 못하다 – 확장이 되면 축소하기가 복잡함
  • 28. 1. 타입 코드에 필드 자체 캡슐화 실시 • 234p
  • 29. 2. 타입에 맞는 모듈 작성 및 타입 변경 에 따른 모듈 확장, 원본 클래스는 기본 기능을 반환하도록 수정 • Module FrontSuspensionMountainBike def price end Module FullSuspensionMountainBike def price end class MountainBike … def type_code=(value) @type_code = value case type_code when :front_suspension: extend(FrontSuspensionMountainBike) when :full_suspension: extend(FullSuspensionMountainBike) end def price # return rigid_price… end end
  • 30. 3. 나머지 메서드도 재정의 및 테스 트 • Module FrontSuspensionMountainBike def price def off_road_ability end Module FullSuspensionMountainBike def price def off_road_ability end class MountainBike … def type_code=(value) @type_code = value case type_code when :front_suspension: extend(FrontSuspensionMountainBike) when :full_suspension: extend(FullSuspensionMountainBike) end def price # return rigid_price… end def off_road_ability # return rigid road ability… end end
  • 31. 4. 타입 코드 대신 모듈을 전달 (before) • Def type_code=(value) @type_code = value case type_code … # extend module • Bike = MountainBike.new Bike.type_code = :front_suspension …
  • 32. 4. 타입 코드 대신 모듈을 전달 (after) • Def type_code=(mod) extend(mod) end • Bike = MountainBike.new Bike.type_code = FrontSuspensionMountainBike …
  • 33. 타입 코드를 상태/전략 패턴으로 전환 270p
  • 34. 동기 • 조건문 제거 • 타입 코드의 자유로운 동적 전환
  • 35. 1. 타입 코드 필드 자체 캡슐화 • 모듈 확장과 동일
  • 36. 2. 타입에 해당하는 클래스 작성 • Class RigidMountainBike end Class FrontSuspensionMountainBike end Class FullSuspensionMountainBike end
  • 37. 3. 타입 코드가 변할 때 해당하는 타입 클래스 생성 • Class MountainBike … def type_code=(value) @type_code = value @bike_type = case type_code when :rigid: RigidMountainBike.new when :front_suspension: FrontSuspensionMountainBike.new when :full_suspension: FullSuspensionMountainbike.new end end
  • 38. 4. 하나의 메서드를 선택해 타입 객 체에 위임 및 타입 객체 생성시 필 요한 data 전달• Class RigidMountainBike def off_road_ability @tire_width * TIRE_WIDTH_FACTOR end end Class FrontSuspensionMountainBike def off_road_ability … end Class FullSuspensionMountainBike def off_road_ability … end Class MountainBike … extend Forwardable def_delegators :@bike_type, :off_road_ability def type_code(value) ... … when :rigid: RigidMountainBike.new( :tire_width => @tire_width) … end
  • 39. 5. 나머지 메서드도 타입 객체에 위 임 • Class RigidMountainBike def off_road_ability def price end Class FrontSuspensionMountainBike def off_road_ability def price end Class FullSuspensionMountainBike def off_road_ability def price end Class MountainBike … extend Forwardable def_delegators :@bike_type, :off_road_ability, :price end
  • 40. 6. 타입 코드 대신 타입 객체로 생 성 • Bike = MountainBike.new(FrontSuspensionMountai nBike.new( :tire_width => @tire_width, :front_fork_travel => @front_fork_travel, … )) • Class MountainBike … def initialize(bike_type) @bike_type = bike_type end end
  • 41. 7. 기타(upgradable parameters) • Class RigidMountainBike… def upgradable_parameters { :tire_width => @tire_width, :base_price => @base_price, … } end Class FrontSuspensionMountainBike … def upgradable_parameters { … } … • Class MountainBike… def add_front_suspension(params) @bike_type = FrontSuspensionMountainBike.new( @bike_type.upgradable_parameters.merge(params) end end
  • 43. 동기 • 하위 클래스가 상수 메서드만 정의 – 상속 구조가 복잡도를 증가시킴
  • 44. 리펙토링 전 • Class Person… end class Female < Person def female? true end def code ‘F’ end end class Male < Person def female? false end def code? ‘M’ end end
  • 45. 1. 생성자를 팩토리 메서드로 전환 • Class Person def self.create_female Female.new end def self.create_male Male.new end end
  • 46. 2. 호출 코드를 팩토리 메서드로 전 환 • Scott = Male.new • -> Scott = Person.create_male
  • 47. 3. 상위클래스에 필드 추가 및 하위 클래스 초기화시 필드 초기화 • Class Person … def initialize( female, code ) @female = female @code = code end Class Female … def initialize super( true, ‘F’ ) end Class Male … def initialize super( false, ‘M’ ) end
  • 48. 4.팩토리 메서드에 초기화 메서드 내용 직접 삽입 및 하위클래스 제거 • Person … Def self.create_female Person.new(true, ‘F’) end Def self.create_male Person.new(false, ‘M’) end end • Class male < Person … Class female < Person …
  • 50. 동기 • 가독성 – 초기화 메서드가 복잡한 경우 초기화 로직을 분리
  • 51. 방법1. ||= 사용하기(before) • Class Employee attr_reader :emails, :voice_mails def initialize @emails = [] @voice_mails = [] end end
  • 52. 방법1. ||= 사용하기(after) • Class Employee def emails @emails ||= [] end def voice_mails @voice_mails ||= [] end end
  • 53. 방법2. instance_variable_defined? 사용하기(before) • 이유 – 속성에게 nil이나 false가 “유효한” 값이라면 1 번 방법을 사용할 수 없다. • Class Employee def initialize @assistant = Employee.find_by_boss_id( self.id ) end end
  • 54. 방법2. instance_variable_defined? 사용하기(after) • Class Employee def assistant unless instance_variable_defined? :@assistant @assistant = Employee.find_by_boss_id( self.id ) end end
  • 55. 속성 초기화를 생성 시로 당기기 290p
  • 56. 동기 • 가독성 – 어떤 사람은 한 곳에 있는게 편하다!;;
  • 57. 방법 • 다시 원래 대로… • 두 기법 중 하나를 선택하여 일관되게 사 용하는 것이 중요