Refactoring practice: Get rid of `attr_accessors` in `ogre.rb` in 2 minutes
Article Table of Contents
Preparing for Turing Series Index #
What follows is an eight-part series that will help you pick up useful information about a number of topics related to Ruby, specifically geared for students learning the Ruby programming language, as part of the Turing School’s Backend Software Development Program
It’s generally intended that you progress sequentially, but there’s no “right way” or “right order” to encounter these topics. You could convince me I have the order exactly backwards. I’d disagree, but only slightly.
I encourage you to skim around these chapters, get the “shape” of what’s to come, in your mind, and then dive in wherever you want. Good luck, and bug reports are welcome.
- Chapter 1: Make Mod 1 Easier Than It Otherwise Would Be
- Chapter 2: Your first passing tests!
- Chapter 3: Objects in Ruby and Mythical Creatures:
unicorn.rb
,dragon.rb
, andhobbit.rb
- Chapter 4: Arrays, Hashes, and Nested Collections
- Chapter 5: Refactoring common errors - in
wizard.rb
- Chapter 6: Refactoring practice - Getting rid of
attr_accessors
inogre.rb
you are here - Chapter 7: Building out the
medusa
mythical creature - Chapter 8: Refactoring the
medusa
mythical creature - Appendix: Troubleshooting Errors
More refactoring practice!
I was reading Practical Object Oriented Design in Ruby, and then was looking at a Turing student’s work on the ogre
mythical creature when I realized this was a perfect chance to explain a little about some principles of Object-Oriented Design.
Here’s a quick TWO MINUTE walk-through:
Here’s the code we’re starting with:
class Ogre
attr_reader :name, :home, :swings, :encounter_counter
def initialize(name, home = "Swamp")
@name = name
@home = home
@swings = 0
@encounter_counter = 0
end
def encounter(human)
@encounter_counter += 1
human.encounter_counter += 1
if human.notices_ogre?
swing_at(human)
end
end
def swing_at(human)
@swings += 1
end
def apologize(human)
human.encounter_counter = 0
@swings = 0
end
end
class Human
attr_accessor :encounter_counter
attr_reader :name
def initialize(name = "Jane")
@name = name
@encounter_counter = 0
end
def notices_ogre?
return @encounter_counter % 3 == 0
end
def knocked_out?
return true if encounter_counter >= 3
false
end
end
All tests pass.
I made changes to any time the Ogre
class changed the “internal state” of another object (aka the Human
class)
Copy-paste the code into your editor, and make the changes yourself!
The finished refactored version:
update: 👏 to Gaby Mendez for catching an error I made in the refactored code!
class Ogre
attr_reader :name, :home, :swings, :encounter_counter
def initialize(name, home = "Swamp")
@name = name
@home = home
@swings = 0
@encounter_counter = 0
end
def encounter(human)
@encounter_counter += 1
human.increment_encounters
if human.notices_ogre?
swing_at(human)
end
end
def swing_at(human)
@swings += 1
# Gaby pointed out that the human needed to actually get knocked unconscious
# at a certain point. Duh! I added this line in response:
human.knock_unconscious if swings % 2 == 0
end
def apologize(human)
# Gaby pointed out an error, so in fixing it I am deviating from the
# finished code in the video walkthrough.
human.revive
@swings = 0
end
end
class Human
attr_reader :name, :encounter_counter, :knocked_out
def initialize(name = "Jane")
@name = name
@encounter_counter = 0
@knocked_out = false
end
def increment_encounters
@encounter_counter += 1
end
def revive
@encounter_counter = 0
@knocked_out = false
end
def knock_unconscious
@knocked_out = true
end
def notices_ogre?
encounter_counter % 3 == 0
end
def knocked_out?
# updated this a bit too. Sorry for the confusion!!!!!
knocked_out
end
end
Preparing for Turing Series Index #
What follows is an eight-part series that will help you pick up useful information about a number of topics related to Ruby, specifically geared for students learning the Ruby programming language, as part of the Turing School’s Backend Software Development Program
It’s generally intended that you progress sequentially, but there’s no “right way” or “right order” to encounter these topics. You could convince me I have the order exactly backwards. I’d disagree, but only slightly.
I encourage you to skim around these chapters, get the “shape” of what’s to come, in your mind, and then dive in wherever you want. Good luck, and bug reports are welcome.
- Chapter 1: Make Mod 1 Easier Than It Otherwise Would Be
- Chapter 2: Your first passing tests!
- Chapter 3: Objects in Ruby and Mythical Creatures:
unicorn.rb
,dragon.rb
, andhobbit.rb
- Chapter 4: Arrays, Hashes, and Nested Collections
- Chapter 5: Refactoring common errors - in
wizard.rb
- Chapter 6: Refactoring practice - Getting rid of
attr_accessors
inogre.rb
you are here - Chapter 7: Building out the
medusa
mythical creature - Chapter 8: Refactoring the
medusa
mythical creature - Appendix: Troubleshooting Errors