SlideShare une entreprise Scribd logo
1  sur  191
Télécharger pour lire hors ligne
First Do No Harm
Surgical Refactoring
Nell Shamrell-Harrington
@nellshamrell
Section I:
Refactoring
First Do No Harm: Surgical Refactoring @nellshamrell
First Do No Harm: Surgical Refactoring @nellshamrell
Refactoring is a change
and changes can go wrong
What is refactoring?
But…it’s not life or death, right?
First Do No Harm: Surgical Refactoring @nellshamrell
But…it’s not life or death, right?
First Do No Harm: Surgical Refactoring @nellshamrell
Software is being integrated into…
But…it’s not life or death, right?
First Do No Harm: Surgical Refactoring @nellshamrell
Software is being integrated into…
Transportation
But…it’s not life or death, right?
First Do No Harm: Surgical Refactoring @nellshamrell
Software is being integrated into…
Transportation
Energy sources
But…it’s not life or death, right?
First Do No Harm: Surgical Refactoring @nellshamrell
Software is being integrated into…
Transportation
Energy sources
Medical Devices
So…is refactoring bad, then?
First Do No Harm: Surgical Refactoring @nellshamrell
So…is refactoring bad, then?
First Do No Harm: Surgical Refactoring @nellshamrell
Refactoring is neither inherently good OR bad
So…is refactoring bad, then?
First Do No Harm: Surgical Refactoring @nellshamrell
How you do it is what matters
How should I refactor?
First Do No Harm: Surgical Refactoring @nellshamrell
2 Common Approaches
How should I refactor?
First Do No Harm: Surgical Refactoring @nellshamrell
2 Common Approaches
1) Edit and Pray
How should I refactor?
First Do No Harm: Surgical Refactoring @nellshamrell
2 Common Approaches
1) Edit and Pray
2) Cover and Modify
How should I refactor?
First Do No Harm: Surgical Refactoring @nellshamrell
2 Common Approaches
1) Edit and Pray
2) Cover and Modify
- “Working Effectively with Legacy Code”
Section II:
Surgical Refactoring
First Do No Harm: Surgical Refactoring @nellshamrell
What is surgical refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Change exactly what we INTEND to change
And ONLY what we intend to change
What is surgical refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
First do no harm!
First Do No Harm: Surgical Refactoring @nellshamrell
Surgical refactoring is a series of
good habits that reduce risk
What is surgical refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
2 categories of refactoring
What is surgical refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
2 categories of refactoring
What is surgical refactoring?
1) Necessary refactoring
First Do No Harm: Surgical Refactoring @nellshamrell
2 categories of refactoring
What is surgical refactoring?
1) Necessary refactoring
2) Cosmetic refactoring
What is a necessary refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Need to add something
What is a necessary refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Need to add something
Code is too inefficient
What is a necessary refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Need to add something
Code is too inefficient
Blocked from achieving a business need
What is a necessary refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Necessary refactorings have a
moderate to high risk tolerance
What is a cosmetic refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
What is a cosmetic refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
No business need to change code
What is a cosmetic refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Something about it just bugs us
No business need to change code
What is a cosmetic refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Cosmetic refactorings
have a low risk tolerance
What about whitespace refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
What about whitespace refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Ultimate cosmetic refactoring
What about whitespace refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Ultimate cosmetic refactoring
Get a style guide
(i.e. Github style guide)
What about whitespace refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Ultimate cosmetic refactoring
Get a style guide
(i.e. Github style guide)
If whitespace does not violate style
guide, leave it alone!
What’s involved in surgical refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
What’s involved in surgical refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
1) Pre-op: what to do before touching the code
What’s involved in surgical refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
1) Pre-op: what to do before touching the code
2) Operation: doing the actual refactoring
What’s involved in surgical refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
1) Pre-op: what to do before touching the code
2) Operation: doing the actual refactoring
3) Recovery: verifying the refactor
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Thanks, @mikelorant!
Section IV:
Pre-Op
First Do No Harm: Surgical Refactoring @nellshamrell
What is involved in pre-op?
First Do No Harm: Surgical Refactoring @nellshamrell
Diagnosis
(What exactly does the code do?)
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end Calls Ruby’s system method
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Executes sed command with
some flags
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Performs a substitution
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
In a series directories and files
So…do we know what it does?
First Do No Harm: Surgical Refactoring @nellshamrell
So…do we know what it does?
First Do No Harm: Surgical Refactoring @nellshamrell
Map is influenced by our own
experiences and expectations
So…do we know what it does?
First Do No Harm: Surgical Refactoring @nellshamrell
Only definite way of knowing what the code
does is to execute the code itself
So…do we know what it does?
First Do No Harm: Surgical Refactoring @nellshamrell
Best way to repeatedly execute the
code is through automated tests
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Now what does this
system call do?
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
let(:do_system_things) { DoSystemThings.new }
Instantiate the class
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
let(:do_system_things) { DoSystemThings.new }
let(:dir) { ‘something’ }
Sample argument
to pass to class
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
let(:do_system_things) { DoSystemThings.new }
let(:dir) { ‘something’ }
describe ‘making the system call’ do
it ‘calls the Ruby#system method’ do
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
let(:do_system_things) { DoSystemThings.new }
let(:dir) { ‘something’ }
describe ‘making the system call’ do
it ‘calls the Ruby#system method’ do
expect(do_system_things)
.to receive(:system).with(anything())
end
end
Expect that our instance
of the class
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
Will receive a system call
with any args
let(:do_system_things) { DoSystemThings.new }
let(:dir) { ‘something’ }
describe ‘making the system call’ do
it ‘calls the Ruby#system method’ do
expect(do_system_things)
.to receive(:system).with(anything())
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
let(:do_system_things) { DoSystemThings.new }
let(:dir) { ‘something’ }
describe ‘making the system call’ do
it ‘calls the Ruby#system method’ do
expect(do_system_things)
.to receive(:system).with(anything())
do_system_things.do_the_thing(dir)
end
end
Call the method
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
let(:do_system_things) { DoSystemThings.new }
let(:dir) { ‘something’ }
describe ‘making the system call’ do
it ‘calls the Ruby#system method’ do
expect(do_system_things)
.to receive(:system).with(anything())
do_system_things.do_the_thing(dir)
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
"sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Remove the system call
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
"sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Spec Fails!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Put the system call back
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
What return is expected?
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end Rdocs: system call returns true
when the command executes
successfully
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
let(:dir) { ‘something’ }
context ‘when the method call is successful’ do
it ‘returns true’ do
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
let(:dir) { ‘something’ }
context ‘when the method call is successful’ do
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
end
Expect the return from calling
the method on the instance
of the class
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
let(:dir) { ‘something’ }
context ‘when the method call is successful’ do
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
end
To return true
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
let(:dir) { ‘something’ }
context ‘when the method call is successful’ do
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
end
Spec Fails!
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
'sed: directory/*/.rb: No such file or directory'
let(:dir) { ‘something’ }
context ‘when the method call is successful’ do
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘when the method call is successful’ do
let(:directory_name) { ‘some_directory’ }
let(:sub_directory) { ‘some_sub_directory’ }
let(:file) { ‘some_file.rb’ }
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
end
Set the directory, subdirectory, and file names
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘when the method call is successful’ do
let(:directory_name) { ‘some_directory’ }
let(:sub_directory) { ‘some_sub_directory’ }
let(:file) { ‘some_file.rb’ }
before do
FileUtils.mkdir_p(File.join(directory_name, sub_directory))
end
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
end
Create directories and sub-directories
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘when the method call is successful’ do
let(:directory_name) { ‘some_directory’ }
let(:sub_directory) { ‘some_sub_directory’ }
let(:file) { ‘some_file.rb’ }
before do
FileUtils.mkdir_p(File.join(directory_name, sub_directory))
path = File
.join(directory_name,subdirectory_name,file_name)
end
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
end
Create the path for
the file
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘when the method call is successful’ do
let(:directory_name) { ‘some_directory’ }
let(:sub_directory) { ‘some_sub_directory’ }
let(:file) { ‘some_file.rb’ }
before do
FileUtils.mkdir_p(File.join(directory_name, sub_directory))
path = File
.join(directory_name,subdirectory_name,file_name)
file = File.new(path, ‘w’)
file.write(‘look, there is something in this file’)
file.close
end
it ‘returns true’ do
Create the actual file
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘when the method call is successful’ do
let(:directory_name) { ‘some_directory’ }
let(:sub_directory) { ‘some_sub_directory’ }
let(:file) { ‘some_file.rb’ }
before do
FileUtils.mkdir_p(File.join(directory_name, sub_directory))
path = File
.join(directory_name,subdirectory_name,file_name)
file = File.new(path, ‘w’)
file.write(‘look, there is something in this file’)
file.close
end
it ‘returns true’ do
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘when the method call is successful’ do
let(:directory_name) { ‘some_directory’ }
let(:sub_directory) { ‘some_sub_directory’ }
let(:file) { ‘some_file.rb’ }
before do
FileUtils.mkdir_p(File.join(directory_name, sub_directory))
path = File
.join(directory_name,subdirectory_name,file_name)
file = File.new(path, ‘w’)
file.write(‘look, there is something in this file’)
file.close
end
it ‘returns true’ do That’s a lot of setup code…
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
def create_required_directories_and_files(path, filename)
FileUtils.mkdir_p(File.join(path))
file = File.new(File.join(path,file_name), ‘w’)
file.write(‘look, there is something in this file’)
file.close
end
Takes a path and
file name
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
def create_required_directories_and_files(path, filename)
FileUtils.mkdir_p(File.join(path))
file = File.new(File.join(path,file_name), ‘w’)
file.write(‘look, there is something in this file’)
file.close
end
Makes the directories
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
def create_required_directories_and_files(path, filename)
FileUtils.mkdir_p(File.join(path))
file = File.new(File.join(path,file_name), ‘w’)
file.write(‘look, there is something in this file’)
file.close
end
Makes the file
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
before do
create_required_directories_and_files(
File.join(directory_name,subdirectory_name), file_name
)
end
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
Call the setup
method
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
before do
create_required_directories_and_files(
File.join(directory_name,subdirectory_name), file_name
)
end
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
Create and pass
the path for the file
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
before do
create_required_directories_and_files(
File.join(directory_name,subdirectory_name), file_name
)
end
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
Pass the file name
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
before do
create_required_directories_and_files(
File.join(directory_name,subdirectory_name), file_name
)
end
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
before do
create_required_directories_and_files(
File.join(directory_name,subdirectory_name), file_name
)
end
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
after do
FileUtils.rm_rf(directory_name)
end
Remove created
directories and file
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
before do
create_required_directories_and_files(
File.join(directory_name,subdirectory_name), file_name
)
end
it ‘returns true’ do
expect(do_system_things.do_the_thing(dir)).to eq(true)
end
after do
FileUtils.rm_rf(directory_name)
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
*pause*
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
sed is a streaming text editor
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
Find match for this pattern
s/:([[:alnum:]]+)[[:space:]]=>/1:/g'
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
Replace it with this pattern
s/:([[:alnum:]]+)[[:space:]]=>/1:/g'
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
//.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
end
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘'}
end
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {''}
it 'matches a string' do
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {''}
it 'matches a string' do
expect(do_system_things.first_regex_match(string))
.not_to be_nil
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
//.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Returns nil if no successful match
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {''}
it 'matches a string' do
expect(do_system_things.first_regex_match(string))
.not_to be_nil
end
end
Means it found a successful match
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {''}
it 'matches a string' do
expect(do_system_things.first_regex_match(string))
.not_to be_nil
end
end
first character is ‘:’
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string))
.not_to be_nil
end
end
add ‘:’ to string
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string))
.not_to be_nil
end
end
Spec Fails!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
add ‘:’ to regex
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string))
.not_to be_nil
end
end
Next character is alnum
character class
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:a'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string))
.not_to be_nil
end
end
Add letter to test string
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
Spec Fails!
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:a'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string))
.not_to be_nil
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:[[:alnum:]]/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
add alnum to regex
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:[[:alnum:]]/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:a'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string))
.not_to be_nil
end
end Means character must
appear one or more times
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:ab'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string))
.not_to be_nil
end
end
Add character to test string
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
Spec Passes!
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:ab'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string))
.not_to be_nil
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
But…we were expecting a failure…
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:ab'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string))
.not_to be_nil
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:[[:alnum:]]/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end Will return successful match with
only one character
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:ab'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string)
.to_s).to include(‘:ab’)
end
end
Examining content of string that was
captured by the regex
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
Spec Fails!
describe ‘what the regex matches’
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:ab'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string)
.to_s).to include(‘:ab’)
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:[[:alnum:]]+/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
add + quantifier
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:[[:alnum:]]+/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:ab'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string)
.to_s).to include(‘:ab’)
end
Capture group
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:ab'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string)
.to_s).to include(‘:ab’)
end
it ‘captures a group’ do
end
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:ab'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string)
.to_s).to include(‘:ab’)
end
it ‘captures a group’ do
expect(do_system_things.first_regex_match(string)[1])
.not_to be_nil
end Testing that match captures
a capture group ([1] references
first capture group)
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
Spec Fails!
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:ab'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string)
.to_s).to include(‘:ab’)
end
it ‘captures a group’ do
expect(do_system_things.first_regex_match(string)[1])
.not_to be_nil
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:[[:alnum:]]+()/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Adding empty capture group
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:[[:alnum:]]+()/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:ab'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string)
.to_s).to include(‘:ab’)
end
it ‘captures a group’ do
expect(do_system_things.first_regex_match(string)[1])
.not_to be_nil
expect(do_system_things.first_regex_match(string)[1])
.to eq(‘ab’)
end
Testing content of capture group
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
Spec Fails!
# FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/
let(:string) {‘:ab'}
it 'matches a string' do
expect(do_system_things.first_regex_match(string)
.to_s).to include(‘:ab’)
end
it ‘captures a group’ do
expect(do_system_things.first_regex_match(string)[1])
.not_to be_nil
expect(do_system_things.first_regex_match(string)[1])
.to eq(‘ab’)
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:([[:alnum:]]+)/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Placing capture group in
correct place
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:([[:alnum:]]+)/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:([[:alnum:]]+)[[:space]]=>/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end Fast Forward…
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def first_regex_match(string)
/:([[:alnum:]]+)[[:space]]=>/.match(string)
end
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end We know what this
regex does!
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
before do
file = File.open(File.join(directory_path,file_name))
file.write(':ab =>')
file.close
end
end
Write sample string to file
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
it ‘changes the file’ do
original_contents =
File.read(File.join(directory_path,file_name))
end
end
Capture original contents of file
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
it ‘changes the file’ do
original_contents =
File.read(File.join(directory_path,file_name))
do_system_things.do_the_thing(directory_name)
end
end
Call the method
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
it ‘changes the file’ do
original_contents =
File.read(File.join(directory_path,file_name))
do_system_things.do_the_thing(directory_name)
new_contents = File.read
(File.join(directory_path,file_name))
end
end
Capture new contents of file
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
it ‘changes the file’ do
original_contents =
File.read(File.join(directory_path,file_name))
do_system_things.do_the_thing(directory_name)
new_contents = File.read
(File.join(directory_path,file_name))
expect(original_contents).not_to eq(new_contents)
end
end
Make sure file changes
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
it ‘changes the file’ do
original_contents =
File.read(File.join(directory_path,file_name))
do_system_things.do_the_thing(directory_name)
new_contents = File.read
(File.join(directory_path,file_name))
expect(original_contents).not_to eq(new_contents)
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
*pause*
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
Replace match for the
first pattern with this
second pattern
s/:([[:alnum:]]+)[[:space:]]=>/1:/g'
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
1:
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
1:
Escape - so we can use a literal 
as the next character
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
1:
Uses the result of the first capture group
from the first pattern
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
1:
Adds a literal colon
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
s/:([[:alnum:]]+)[[:space:]]=>/1:/g'
‘:ab =>’
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
s/:([[:alnum:]]+)[[:space:]]=>/1:/g'
‘ab:’‘:ab =>’ replace with
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
let(:orig_string) { “:ab => “}
let(:new_string) { “ab: ‘}
it ‘changes the file’ do
original_contents = File.read(File.join(directory_path,file_name))
do_system_things.do_the_thing(directory_name)
new_contents = File.read(File.join(directory_path,file_name))
end
end
Expected content of file
before and after
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
let(:orig_string) { “:ab => “}
let(:new_string) { “ab: ‘}
it ‘changes the file’ do
original_contents = File.read(File.join(directory_path,file_name))
do_system_things.do_the_thing(directory_name)
new_contents = File.read(File.join(directory_path,file_name))
expect(new_contents).not_to include(orig_string)
expect(new_contents).to include(new_string)
end
end
Verify contents of
modified file
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
let(:orig_string) { “:ab => “}
let(:new_string) { “ab: ‘}
it ‘changes the file’ do
original_contents = File.read(File.join(directory_path,file_name))
do_system_things.do_the_thing(directory_name)
new_contents = File.read(File.join(directory_path,file_name))
expect(new_contents).not_to include(orig_string)
expect(new_contents).to include(new_string)
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
*pause*
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
s/:([[:alnum:]]+)[[:space:]]=>/1:/g'
Replace all matches for the
first pattern with the second
pattern
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
let(:orig_string) { “:ab => :ab =>“}
let(:new_string) { “ab: ab:’}
it ‘changes all matches within the file’ do
original_contents = File.read(File.join(directory_path,file_name))
do_system_things.do_the_thing(directory_name)
new_contents = File.read(File.join(directory_path,file_name))
expect(new_contents).not_to include(orig_string)
expect(new_contents).to include(new_string)
end
end
Expected content of
file before and after
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
let(:orig_string) { “:ab => :ab =>“}
let(:new_string) { “ab: ab:’}
it ‘changes all matches within the file’ do
original_contents = File.read(File.join(directory_path,file_name))
do_system_things(directory_name)
new_contents = File.read(File.join(directory_path,file_name))
expect(new_contents).not_to include(orig_string)
expect(new_contents).to include(new_string)
end
end Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/"
#{dir}/**/*.rb"
end
end
Taking out the
global flag
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/"
#{dir}/**/*.rb"
end
end
Spec Fails!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
Putting the flag
back in
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
Take -E flag out
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
Spec Fails!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
Put -E flag back in
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
-i flag: sed alters
files in place
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
-i flag: sed alters
files in place
Passing an empty
extension
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
it ‘does not save a backup copy of the file’ do
expect
(Dir[“#{directory_name}/#{subdirectory_name}/*”]
.count).to eq(1)
end
end
Expect only one file in
directory/subdirectory
path
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
it ‘does not save a backup copy of the file’ do
expect
(Dir[“#{directory_name}/#{subdirectory_name}/*”]
.count).to eq(1)
do_system_things.do_the_thing(directory_name)
end
end
Call the method
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
it ‘does not save a backup copy of the file’ do
expect
(Dir[“#{directory_name}/#{subdirectory_name}/*”]
.count).to eq(1)
do_system_things.do_the_thing(directory_name)
expect(
Dir[“#{directory_name}/#{subdirectory_name}/*”]
.count).to eq(1)
end
end
Expect only one file in
directory/subdirectory
path
First Do No Harm: Surgical Refactoring @nellshamrell
spec/do_system_things_spec.rb
context ‘changing the file’ do
it ‘does not save a backup copy of the file’ do
expect
(Dir[“#{directory_name}/#{subdirectory_name}/*”]
.count).to eq(1)
do_system_things.do_the_thing(directory_name)
expect
(Dir[“#{directory_name}/#{subdirectory_name}/*”]
.count).to eq(1)
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i .tmp ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
Pass extension to -i flag
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i .tmp ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
Spec Fails!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
Passing an empty
extension again
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g"
#{dir}/**/*.rb"
end
end
We know what this does!
Section V:
Operation
First Do No Harm: Surgical Refactoring @nellshamrell
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
#{dir}/**/*.rb"
end
private
def substitute_command
's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb"
end
private
def substitute_command
's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
end
end
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb"
end
private
def substitute_command
's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
end
end
Spec Passes!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb"
end
private
def substitute_command
's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
end
end Really old regex syntax
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb"
end
private
def substitute_command
’s/:(w+)s=>/1:/g’
end
end New regex syntax
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb"
end
private
def substitute_command
’s/:(w+)s=>/1:/g’
end
end Spec Fails!
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb"
end
private
def substitute_command
's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
end
end Back to the old
regex syntax
First Do No Harm: Surgical Refactoring @nellshamrell
lib/do_system_things.rb
class DoSystemThings
def do_the_thing(dir)
system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb"
end
private
def substitute_command
's/:([[:alnum:]]+)[[:space:]]=>/1:/g'
end
end
Spec Passes!
Section VI:
Recovery
First Do No Harm: Surgical Refactoring @nellshamrell
What do I need to do after refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Need to know two things decisively
What do I need to do after refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Need to know two things decisively
1) Does the behavior still exist?
What do I need to do after refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Need to know two things decisively
1) Does the behavior still exist?
2) Is it connected correctly?
What do I need to do after refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
What about QA?
What do I need to do after refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Ideally, QA should find nothing
What if something goes wrong?
First Do No Harm: Surgical Refactoring @nellshamrell
What if something goes wrong?
First Do No Harm: Surgical Refactoring @nellshamrell
1) Take responsibility - what your code does
in production is your responsibility
What if something goes wrong?
First Do No Harm: Surgical Refactoring @nellshamrell
1) Take responsibility - what your code does
in production is your responsibility
2) Evaluate risk of another change
(a change to a change is still a change)
What if something goes wrong?
First Do No Harm: Surgical Refactoring @nellshamrell
1) Take responsibility - what your code does
in production is your responsibility
2) Evaluate risk of another change
(a change to a change is still a change)
3) Fix the problem (if you can’t, find someone
who can!)
Thank You!
First Do No Harm: Surgical Refactoring @nellshamrell
Nell Shamrell-Harrington
Software Development Engineer at Chef
@nellshamrell
www.nellshamrell.com
nshamrell@chef.io
Thank You!
First Do No Harm: Surgical Refactoring @nellshamrell
Nell Shamrell-Harrington
Software Development Engineer at Chef
@nellshamrell
www.nellshamrell.com
nshamrell@chef.io
Thank you
Jim and Jen!!!!

Contenu connexe

En vedette

Apostila html e css
Apostila html e cssApostila html e css
Apostila html e cssRoney Sousa
 
Food signs in radiology
Food signs in radiologyFood signs in radiology
Food signs in radiologyMedia Genie
 
DevOps Picc12 Management Talk
DevOps Picc12 Management TalkDevOps Picc12 Management Talk
DevOps Picc12 Management TalkMichael Rembetsy
 
S3とSNSで動画機能をつくる話
S3とSNSで動画機能をつくる話S3とSNSで動画機能をつくる話
S3とSNSで動画機能をつくる話Ahmad Shiina
 
Continuous Delivery & DevOps - IT Value Stream Improvements Roadmap Chapter 2 v8
Continuous Delivery & DevOps - IT Value Stream Improvements Roadmap Chapter 2 v8Continuous Delivery & DevOps - IT Value Stream Improvements Roadmap Chapter 2 v8
Continuous Delivery & DevOps - IT Value Stream Improvements Roadmap Chapter 2 v8Janusz Stankiewicz
 

En vedette (7)

20150911102025
2015091110202520150911102025
20150911102025
 
Presentation1
Presentation1Presentation1
Presentation1
 
Apostila html e css
Apostila html e cssApostila html e css
Apostila html e css
 
Food signs in radiology
Food signs in radiologyFood signs in radiology
Food signs in radiology
 
DevOps Picc12 Management Talk
DevOps Picc12 Management TalkDevOps Picc12 Management Talk
DevOps Picc12 Management Talk
 
S3とSNSで動画機能をつくる話
S3とSNSで動画機能をつくる話S3とSNSで動画機能をつくる話
S3とSNSで動画機能をつくる話
 
Continuous Delivery & DevOps - IT Value Stream Improvements Roadmap Chapter 2 v8
Continuous Delivery & DevOps - IT Value Stream Improvements Roadmap Chapter 2 v8Continuous Delivery & DevOps - IT Value Stream Improvements Roadmap Chapter 2 v8
Continuous Delivery & DevOps - IT Value Stream Improvements Roadmap Chapter 2 v8
 

Similaire à First Do No Harm: Surgical Refactoring

The limits of unit testing by Craig Stuntz
The limits of unit testing by Craig StuntzThe limits of unit testing by Craig Stuntz
The limits of unit testing by Craig StuntzQA or the Highway
 
The Limits of Unit Testing by Craig Stuntz
The Limits of Unit Testing by Craig StuntzThe Limits of Unit Testing by Craig Stuntz
The Limits of Unit Testing by Craig StuntzQA or the Highway
 
Stand back; I'm going to try Scientist!
Stand back; I'm going to try Scientist!Stand back; I'm going to try Scientist!
Stand back; I'm going to try Scientist!Matt Eland
 
Simple Essay Example Amat
Simple Essay Example  AmatSimple Essay Example  Amat
Simple Essay Example AmatJennifer Moore
 
Characteristics of PVS-Studio Analyzer by the Example of EFL Core Libraries, ...
Characteristics of PVS-Studio Analyzer by the Example of EFL Core Libraries, ...Characteristics of PVS-Studio Analyzer by the Example of EFL Core Libraries, ...
Characteristics of PVS-Studio Analyzer by the Example of EFL Core Libraries, ...PVS-Studio
 
SRE Lessons for the Enterprise
SRE Lessons for the Enterprise SRE Lessons for the Enterprise
SRE Lessons for the Enterprise Rundeck
 
Normal accidents and outpatient surgeries
Normal accidents and outpatient surgeriesNormal accidents and outpatient surgeries
Normal accidents and outpatient surgeriesJonathan Creasy
 

Similaire à First Do No Harm: Surgical Refactoring (11)

The limits of unit testing by Craig Stuntz
The limits of unit testing by Craig StuntzThe limits of unit testing by Craig Stuntz
The limits of unit testing by Craig Stuntz
 
The Limits of Unit Testing by Craig Stuntz
The Limits of Unit Testing by Craig StuntzThe Limits of Unit Testing by Craig Stuntz
The Limits of Unit Testing by Craig Stuntz
 
Stand back; I'm going to try Scientist!
Stand back; I'm going to try Scientist!Stand back; I'm going to try Scientist!
Stand back; I'm going to try Scientist!
 
Model-checking for efficient malware detection
Model-checking for efficient malware detectionModel-checking for efficient malware detection
Model-checking for efficient malware detection
 
Simple Essay Example Amat
Simple Essay Example  AmatSimple Essay Example  Amat
Simple Essay Example Amat
 
Characteristics of PVS-Studio Analyzer by the Example of EFL Core Libraries, ...
Characteristics of PVS-Studio Analyzer by the Example of EFL Core Libraries, ...Characteristics of PVS-Studio Analyzer by the Example of EFL Core Libraries, ...
Characteristics of PVS-Studio Analyzer by the Example of EFL Core Libraries, ...
 
Art_of_DefectReporting080214
Art_of_DefectReporting080214Art_of_DefectReporting080214
Art_of_DefectReporting080214
 
Quality tools
Quality toolsQuality tools
Quality tools
 
Rtt preso
Rtt presoRtt preso
Rtt preso
 
SRE Lessons for the Enterprise
SRE Lessons for the Enterprise SRE Lessons for the Enterprise
SRE Lessons for the Enterprise
 
Normal accidents and outpatient surgeries
Normal accidents and outpatient surgeriesNormal accidents and outpatient surgeries
Normal accidents and outpatient surgeries
 

Plus de Nell Shamrell-Harrington

This Week in Rust: 400 Issues and Counting!
This Week in Rust: 400 Issues and Counting!This Week in Rust: 400 Issues and Counting!
This Week in Rust: 400 Issues and Counting!Nell Shamrell-Harrington
 
Higher. Faster. Stronger. Your Applications with Habitat
Higher. Faster. Stronger. Your Applications with HabitatHigher. Faster. Stronger. Your Applications with Habitat
Higher. Faster. Stronger. Your Applications with HabitatNell Shamrell-Harrington
 
Containers, Virtual Machines, and Bare Metal, Oh My!
Containers, Virtual Machines, and Bare Metal, Oh My!Containers, Virtual Machines, and Bare Metal, Oh My!
Containers, Virtual Machines, and Bare Metal, Oh My!Nell Shamrell-Harrington
 
Creating Packages that Run Anywhere with Chef Habitat
Creating Packages that Run Anywhere with Chef HabitatCreating Packages that Run Anywhere with Chef Habitat
Creating Packages that Run Anywhere with Chef HabitatNell Shamrell-Harrington
 
First Do No Harm: Surgical Refactoring (extended edition)
First Do No Harm: Surgical Refactoring (extended edition)First Do No Harm: Surgical Refactoring (extended edition)
First Do No Harm: Surgical Refactoring (extended edition)Nell Shamrell-Harrington
 
A Supermarket of Your Own: Running a Private Chef Supermarket
A Supermarket of Your Own: Running a Private Chef SupermarketA Supermarket of Your Own: Running a Private Chef Supermarket
A Supermarket of Your Own: Running a Private Chef SupermarketNell Shamrell-Harrington
 

Plus de Nell Shamrell-Harrington (20)

This Week in Rust: 400 Issues and Counting!
This Week in Rust: 400 Issues and Counting!This Week in Rust: 400 Issues and Counting!
This Week in Rust: 400 Issues and Counting!
 
The Rust Borrow Checker
The Rust Borrow CheckerThe Rust Borrow Checker
The Rust Borrow Checker
 
Higher. Faster. Stronger. Your Applications with Habitat
Higher. Faster. Stronger. Your Applications with HabitatHigher. Faster. Stronger. Your Applications with Habitat
Higher. Faster. Stronger. Your Applications with Habitat
 
Habitat Service Discovery
Habitat Service DiscoveryHabitat Service Discovery
Habitat Service Discovery
 
Web Operations101
Web Operations101Web Operations101
Web Operations101
 
Rust Traits And You: A Deep Dive
Rust Traits And You: A Deep DiveRust Traits And You: A Deep Dive
Rust Traits And You: A Deep Dive
 
Rust, Redis, and Protobuf - Oh My!
Rust, Redis, and Protobuf - Oh My!Rust, Redis, and Protobuf - Oh My!
Rust, Redis, and Protobuf - Oh My!
 
Containers, Virtual Machines, and Bare Metal, Oh My!
Containers, Virtual Machines, and Bare Metal, Oh My!Containers, Virtual Machines, and Bare Metal, Oh My!
Containers, Virtual Machines, and Bare Metal, Oh My!
 
Chef Vault: A Deep Dive
Chef Vault: A Deep DiveChef Vault: A Deep Dive
Chef Vault: A Deep Dive
 
Open Source Governance 101
Open Source Governance 101Open Source Governance 101
Open Source Governance 101
 
DevOps in Politics
DevOps in PoliticsDevOps in Politics
DevOps in Politics
 
Open Source Governance - The Hard Parts
Open Source Governance - The Hard PartsOpen Source Governance - The Hard Parts
Open Source Governance - The Hard Parts
 
Creating Packages that Run Anywhere with Chef Habitat
Creating Packages that Run Anywhere with Chef HabitatCreating Packages that Run Anywhere with Chef Habitat
Creating Packages that Run Anywhere with Chef Habitat
 
Refactoring terraform
Refactoring terraformRefactoring terraform
Refactoring terraform
 
Refactoring Infrastructure Code
Refactoring Infrastructure CodeRefactoring Infrastructure Code
Refactoring Infrastructure Code
 
Devops: A History
Devops: A HistoryDevops: A History
Devops: A History
 
First Do No Harm: Surgical Refactoring (extended edition)
First Do No Harm: Surgical Refactoring (extended edition)First Do No Harm: Surgical Refactoring (extended edition)
First Do No Harm: Surgical Refactoring (extended edition)
 
A Supermarket of Your Own: Running a Private Chef Supermarket
A Supermarket of Your Own: Running a Private Chef SupermarketA Supermarket of Your Own: Running a Private Chef Supermarket
A Supermarket of Your Own: Running a Private Chef Supermarket
 
Public Supermarket: The Insider's Tour
Public Supermarket: The Insider's TourPublic Supermarket: The Insider's Tour
Public Supermarket: The Insider's Tour
 
Beneath the Surface - Rubyconf 2013
Beneath the Surface - Rubyconf 2013Beneath the Surface - Rubyconf 2013
Beneath the Surface - Rubyconf 2013
 

Dernier

Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 

Dernier (20)

Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 

First Do No Harm: Surgical Refactoring

  • 1. First Do No Harm Surgical Refactoring Nell Shamrell-Harrington @nellshamrell
  • 2. Section I: Refactoring First Do No Harm: Surgical Refactoring @nellshamrell
  • 3. First Do No Harm: Surgical Refactoring @nellshamrell Refactoring is a change and changes can go wrong What is refactoring?
  • 4. But…it’s not life or death, right? First Do No Harm: Surgical Refactoring @nellshamrell
  • 5. But…it’s not life or death, right? First Do No Harm: Surgical Refactoring @nellshamrell Software is being integrated into…
  • 6. But…it’s not life or death, right? First Do No Harm: Surgical Refactoring @nellshamrell Software is being integrated into… Transportation
  • 7. But…it’s not life or death, right? First Do No Harm: Surgical Refactoring @nellshamrell Software is being integrated into… Transportation Energy sources
  • 8. But…it’s not life or death, right? First Do No Harm: Surgical Refactoring @nellshamrell Software is being integrated into… Transportation Energy sources Medical Devices
  • 9. So…is refactoring bad, then? First Do No Harm: Surgical Refactoring @nellshamrell
  • 10. So…is refactoring bad, then? First Do No Harm: Surgical Refactoring @nellshamrell Refactoring is neither inherently good OR bad
  • 11. So…is refactoring bad, then? First Do No Harm: Surgical Refactoring @nellshamrell How you do it is what matters
  • 12. How should I refactor? First Do No Harm: Surgical Refactoring @nellshamrell 2 Common Approaches
  • 13. How should I refactor? First Do No Harm: Surgical Refactoring @nellshamrell 2 Common Approaches 1) Edit and Pray
  • 14. How should I refactor? First Do No Harm: Surgical Refactoring @nellshamrell 2 Common Approaches 1) Edit and Pray 2) Cover and Modify
  • 15. How should I refactor? First Do No Harm: Surgical Refactoring @nellshamrell 2 Common Approaches 1) Edit and Pray 2) Cover and Modify - “Working Effectively with Legacy Code”
  • 16. Section II: Surgical Refactoring First Do No Harm: Surgical Refactoring @nellshamrell
  • 17. What is surgical refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Change exactly what we INTEND to change And ONLY what we intend to change
  • 18. What is surgical refactoring? First Do No Harm: Surgical Refactoring @nellshamrell First do no harm!
  • 19. First Do No Harm: Surgical Refactoring @nellshamrell Surgical refactoring is a series of good habits that reduce risk What is surgical refactoring?
  • 20. First Do No Harm: Surgical Refactoring @nellshamrell 2 categories of refactoring What is surgical refactoring?
  • 21. First Do No Harm: Surgical Refactoring @nellshamrell 2 categories of refactoring What is surgical refactoring? 1) Necessary refactoring
  • 22. First Do No Harm: Surgical Refactoring @nellshamrell 2 categories of refactoring What is surgical refactoring? 1) Necessary refactoring 2) Cosmetic refactoring
  • 23. What is a necessary refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Need to add something
  • 24. What is a necessary refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Need to add something Code is too inefficient
  • 25. What is a necessary refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Need to add something Code is too inefficient Blocked from achieving a business need
  • 26. What is a necessary refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Necessary refactorings have a moderate to high risk tolerance
  • 27. What is a cosmetic refactoring? First Do No Harm: Surgical Refactoring @nellshamrell
  • 28. What is a cosmetic refactoring? First Do No Harm: Surgical Refactoring @nellshamrell No business need to change code
  • 29. What is a cosmetic refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Something about it just bugs us No business need to change code
  • 30. What is a cosmetic refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Cosmetic refactorings have a low risk tolerance
  • 31. What about whitespace refactoring? First Do No Harm: Surgical Refactoring @nellshamrell
  • 32. What about whitespace refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Ultimate cosmetic refactoring
  • 33. What about whitespace refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Ultimate cosmetic refactoring Get a style guide (i.e. Github style guide)
  • 34. What about whitespace refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Ultimate cosmetic refactoring Get a style guide (i.e. Github style guide) If whitespace does not violate style guide, leave it alone!
  • 35. What’s involved in surgical refactoring? First Do No Harm: Surgical Refactoring @nellshamrell
  • 36. What’s involved in surgical refactoring? First Do No Harm: Surgical Refactoring @nellshamrell 1) Pre-op: what to do before touching the code
  • 37. What’s involved in surgical refactoring? First Do No Harm: Surgical Refactoring @nellshamrell 1) Pre-op: what to do before touching the code 2) Operation: doing the actual refactoring
  • 38. What’s involved in surgical refactoring? First Do No Harm: Surgical Refactoring @nellshamrell 1) Pre-op: what to do before touching the code 2) Operation: doing the actual refactoring 3) Recovery: verifying the refactor
  • 39. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Thanks, @mikelorant!
  • 40. Section IV: Pre-Op First Do No Harm: Surgical Refactoring @nellshamrell
  • 41. What is involved in pre-op? First Do No Harm: Surgical Refactoring @nellshamrell Diagnosis (What exactly does the code do?)
  • 42. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end
  • 43. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Calls Ruby’s system method
  • 44. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Executes sed command with some flags
  • 45. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Performs a substitution
  • 46. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end In a series directories and files
  • 47. So…do we know what it does? First Do No Harm: Surgical Refactoring @nellshamrell
  • 48. So…do we know what it does? First Do No Harm: Surgical Refactoring @nellshamrell Map is influenced by our own experiences and expectations
  • 49. So…do we know what it does? First Do No Harm: Surgical Refactoring @nellshamrell Only definite way of knowing what the code does is to execute the code itself
  • 50. So…do we know what it does? First Do No Harm: Surgical Refactoring @nellshamrell Best way to repeatedly execute the code is through automated tests
  • 51. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Now what does this system call do?
  • 52. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb let(:do_system_things) { DoSystemThings.new } Instantiate the class
  • 53. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb let(:do_system_things) { DoSystemThings.new } let(:dir) { ‘something’ } Sample argument to pass to class
  • 54. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb let(:do_system_things) { DoSystemThings.new } let(:dir) { ‘something’ } describe ‘making the system call’ do it ‘calls the Ruby#system method’ do end end
  • 55. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb let(:do_system_things) { DoSystemThings.new } let(:dir) { ‘something’ } describe ‘making the system call’ do it ‘calls the Ruby#system method’ do expect(do_system_things) .to receive(:system).with(anything()) end end Expect that our instance of the class
  • 56. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb Will receive a system call with any args let(:do_system_things) { DoSystemThings.new } let(:dir) { ‘something’ } describe ‘making the system call’ do it ‘calls the Ruby#system method’ do expect(do_system_things) .to receive(:system).with(anything()) end end
  • 57. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb let(:do_system_things) { DoSystemThings.new } let(:dir) { ‘something’ } describe ‘making the system call’ do it ‘calls the Ruby#system method’ do expect(do_system_things) .to receive(:system).with(anything()) do_system_things.do_the_thing(dir) end end Call the method
  • 58. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb let(:do_system_things) { DoSystemThings.new } let(:dir) { ‘something’ } describe ‘making the system call’ do it ‘calls the Ruby#system method’ do expect(do_system_things) .to receive(:system).with(anything()) do_system_things.do_the_thing(dir) end end Spec Passes!
  • 59. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Remove the system call
  • 60. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Spec Fails!
  • 61. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Put the system call back
  • 62. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Spec Passes!
  • 63. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end What return is expected?
  • 64. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Rdocs: system call returns true when the command executes successfully
  • 65. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb let(:dir) { ‘something’ } context ‘when the method call is successful’ do it ‘returns true’ do end end
  • 66. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb let(:dir) { ‘something’ } context ‘when the method call is successful’ do it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end end Expect the return from calling the method on the instance of the class
  • 67. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb let(:dir) { ‘something’ } context ‘when the method call is successful’ do it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end end To return true
  • 68. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb let(:dir) { ‘something’ } context ‘when the method call is successful’ do it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end end Spec Fails!
  • 69. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb 'sed: directory/*/.rb: No such file or directory' let(:dir) { ‘something’ } context ‘when the method call is successful’ do it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end end
  • 70. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘when the method call is successful’ do let(:directory_name) { ‘some_directory’ } let(:sub_directory) { ‘some_sub_directory’ } let(:file) { ‘some_file.rb’ } it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end end Set the directory, subdirectory, and file names
  • 71. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘when the method call is successful’ do let(:directory_name) { ‘some_directory’ } let(:sub_directory) { ‘some_sub_directory’ } let(:file) { ‘some_file.rb’ } before do FileUtils.mkdir_p(File.join(directory_name, sub_directory)) end it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end end Create directories and sub-directories
  • 72. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘when the method call is successful’ do let(:directory_name) { ‘some_directory’ } let(:sub_directory) { ‘some_sub_directory’ } let(:file) { ‘some_file.rb’ } before do FileUtils.mkdir_p(File.join(directory_name, sub_directory)) path = File .join(directory_name,subdirectory_name,file_name) end it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end end Create the path for the file
  • 73. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘when the method call is successful’ do let(:directory_name) { ‘some_directory’ } let(:sub_directory) { ‘some_sub_directory’ } let(:file) { ‘some_file.rb’ } before do FileUtils.mkdir_p(File.join(directory_name, sub_directory)) path = File .join(directory_name,subdirectory_name,file_name) file = File.new(path, ‘w’) file.write(‘look, there is something in this file’) file.close end it ‘returns true’ do Create the actual file
  • 74. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘when the method call is successful’ do let(:directory_name) { ‘some_directory’ } let(:sub_directory) { ‘some_sub_directory’ } let(:file) { ‘some_file.rb’ } before do FileUtils.mkdir_p(File.join(directory_name, sub_directory)) path = File .join(directory_name,subdirectory_name,file_name) file = File.new(path, ‘w’) file.write(‘look, there is something in this file’) file.close end it ‘returns true’ do Spec Passes!
  • 75. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘when the method call is successful’ do let(:directory_name) { ‘some_directory’ } let(:sub_directory) { ‘some_sub_directory’ } let(:file) { ‘some_file.rb’ } before do FileUtils.mkdir_p(File.join(directory_name, sub_directory)) path = File .join(directory_name,subdirectory_name,file_name) file = File.new(path, ‘w’) file.write(‘look, there is something in this file’) file.close end it ‘returns true’ do That’s a lot of setup code…
  • 76. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb def create_required_directories_and_files(path, filename) FileUtils.mkdir_p(File.join(path)) file = File.new(File.join(path,file_name), ‘w’) file.write(‘look, there is something in this file’) file.close end Takes a path and file name
  • 77. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb def create_required_directories_and_files(path, filename) FileUtils.mkdir_p(File.join(path)) file = File.new(File.join(path,file_name), ‘w’) file.write(‘look, there is something in this file’) file.close end Makes the directories
  • 78. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb def create_required_directories_and_files(path, filename) FileUtils.mkdir_p(File.join(path)) file = File.new(File.join(path,file_name), ‘w’) file.write(‘look, there is something in this file’) file.close end Makes the file
  • 79. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb before do create_required_directories_and_files( File.join(directory_name,subdirectory_name), file_name ) end it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end Call the setup method
  • 80. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb before do create_required_directories_and_files( File.join(directory_name,subdirectory_name), file_name ) end it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end Create and pass the path for the file
  • 81. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb before do create_required_directories_and_files( File.join(directory_name,subdirectory_name), file_name ) end it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end Pass the file name
  • 82. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb before do create_required_directories_and_files( File.join(directory_name,subdirectory_name), file_name ) end it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end Spec Passes!
  • 83. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb before do create_required_directories_and_files( File.join(directory_name,subdirectory_name), file_name ) end it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end after do FileUtils.rm_rf(directory_name) end Remove created directories and file
  • 84. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb before do create_required_directories_and_files( File.join(directory_name,subdirectory_name), file_name ) end it ‘returns true’ do expect(do_system_things.do_the_thing(dir)).to eq(true) end after do FileUtils.rm_rf(directory_name) end Spec Passes!
  • 85. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end *pause*
  • 86. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end sed is a streaming text editor
  • 87. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end
  • 88. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb Find match for this pattern s/:([[:alnum:]]+)[[:space:]]=>/1:/g'
  • 89. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb Replace it with this pattern s/:([[:alnum:]]+)[[:space:]]=>/1:/g'
  • 90. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end
  • 91. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) //.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end
  • 92. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ end
  • 93. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘'} end
  • 94. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {''} it 'matches a string' do end end
  • 95. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {''} it 'matches a string' do expect(do_system_things.first_regex_match(string)) .not_to be_nil end end
  • 96. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) //.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Returns nil if no successful match
  • 97. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {''} it 'matches a string' do expect(do_system_things.first_regex_match(string)) .not_to be_nil end end Means it found a successful match
  • 98. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {''} it 'matches a string' do expect(do_system_things.first_regex_match(string)) .not_to be_nil end end first character is ‘:’
  • 99. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:'} it 'matches a string' do expect(do_system_things.first_regex_match(string)) .not_to be_nil end end add ‘:’ to string
  • 100. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:'} it 'matches a string' do expect(do_system_things.first_regex_match(string)) .not_to be_nil end end Spec Fails!
  • 101. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end add ‘:’ to regex
  • 102. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Spec Passes!
  • 103. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:'} it 'matches a string' do expect(do_system_things.first_regex_match(string)) .not_to be_nil end end Next character is alnum character class
  • 104. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:a'} it 'matches a string' do expect(do_system_things.first_regex_match(string)) .not_to be_nil end end Add letter to test string
  • 105. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb Spec Fails! describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:a'} it 'matches a string' do expect(do_system_things.first_regex_match(string)) .not_to be_nil end end
  • 106. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:[[:alnum:]]/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end add alnum to regex
  • 107. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:[[:alnum:]]/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Spec Passes!
  • 108. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:a'} it 'matches a string' do expect(do_system_things.first_regex_match(string)) .not_to be_nil end end Means character must appear one or more times
  • 109. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:ab'} it 'matches a string' do expect(do_system_things.first_regex_match(string)) .not_to be_nil end end Add character to test string
  • 110. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb Spec Passes! describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:ab'} it 'matches a string' do expect(do_system_things.first_regex_match(string)) .not_to be_nil end end
  • 111. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb But…we were expecting a failure… describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:ab'} it 'matches a string' do expect(do_system_things.first_regex_match(string)) .not_to be_nil end end
  • 112. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:[[:alnum:]]/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Will return successful match with only one character
  • 113. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:ab'} it 'matches a string' do expect(do_system_things.first_regex_match(string) .to_s).to include(‘:ab’) end end Examining content of string that was captured by the regex
  • 114. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb Spec Fails! describe ‘what the regex matches’ # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:ab'} it 'matches a string' do expect(do_system_things.first_regex_match(string) .to_s).to include(‘:ab’) end end
  • 115. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:[[:alnum:]]+/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end add + quantifier
  • 116. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:[[:alnum:]]+/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Spec Passes!
  • 117. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:ab'} it 'matches a string' do expect(do_system_things.first_regex_match(string) .to_s).to include(‘:ab’) end Capture group
  • 118. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:ab'} it 'matches a string' do expect(do_system_things.first_regex_match(string) .to_s).to include(‘:ab’) end it ‘captures a group’ do end
  • 119. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:ab'} it 'matches a string' do expect(do_system_things.first_regex_match(string) .to_s).to include(‘:ab’) end it ‘captures a group’ do expect(do_system_things.first_regex_match(string)[1]) .not_to be_nil end Testing that match captures a capture group ([1] references first capture group)
  • 120. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb Spec Fails! # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:ab'} it 'matches a string' do expect(do_system_things.first_regex_match(string) .to_s).to include(‘:ab’) end it ‘captures a group’ do expect(do_system_things.first_regex_match(string)[1]) .not_to be_nil end
  • 121. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:[[:alnum:]]+()/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Adding empty capture group
  • 122. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:[[:alnum:]]+()/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Spec Passes!
  • 123. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:ab'} it 'matches a string' do expect(do_system_things.first_regex_match(string) .to_s).to include(‘:ab’) end it ‘captures a group’ do expect(do_system_things.first_regex_match(string)[1]) .not_to be_nil expect(do_system_things.first_regex_match(string)[1]) .to eq(‘ab’) end Testing content of capture group
  • 124. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb Spec Fails! # FOR REFERENCE: /:([[:alnum:]]+)[[:space:]]=>/ let(:string) {‘:ab'} it 'matches a string' do expect(do_system_things.first_regex_match(string) .to_s).to include(‘:ab’) end it ‘captures a group’ do expect(do_system_things.first_regex_match(string)[1]) .not_to be_nil expect(do_system_things.first_regex_match(string)[1]) .to eq(‘ab’) end
  • 125. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:([[:alnum:]]+)/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Placing capture group in correct place
  • 126. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:([[:alnum:]]+)/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Spec Passes!
  • 127. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:([[:alnum:]]+)[[:space]]=>/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end Fast Forward…
  • 128. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def first_regex_match(string) /:([[:alnum:]]+)[[:space]]=>/.match(string) end def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end We know what this regex does!
  • 129. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do before do file = File.open(File.join(directory_path,file_name)) file.write(':ab =>') file.close end end Write sample string to file
  • 130. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do it ‘changes the file’ do original_contents = File.read(File.join(directory_path,file_name)) end end Capture original contents of file
  • 131. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do it ‘changes the file’ do original_contents = File.read(File.join(directory_path,file_name)) do_system_things.do_the_thing(directory_name) end end Call the method
  • 132. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do it ‘changes the file’ do original_contents = File.read(File.join(directory_path,file_name)) do_system_things.do_the_thing(directory_name) new_contents = File.read (File.join(directory_path,file_name)) end end Capture new contents of file
  • 133. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do it ‘changes the file’ do original_contents = File.read(File.join(directory_path,file_name)) do_system_things.do_the_thing(directory_name) new_contents = File.read (File.join(directory_path,file_name)) expect(original_contents).not_to eq(new_contents) end end Make sure file changes
  • 134. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do it ‘changes the file’ do original_contents = File.read(File.join(directory_path,file_name)) do_system_things.do_the_thing(directory_name) new_contents = File.read (File.join(directory_path,file_name)) expect(original_contents).not_to eq(new_contents) end end Spec Passes!
  • 135. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end *pause*
  • 136. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb Replace match for the first pattern with this second pattern s/:([[:alnum:]]+)[[:space:]]=>/1:/g'
  • 137. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb 1:
  • 138. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb 1: Escape - so we can use a literal as the next character
  • 139. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb 1: Uses the result of the first capture group from the first pattern
  • 140. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb 1: Adds a literal colon
  • 141. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb s/:([[:alnum:]]+)[[:space:]]=>/1:/g' ‘:ab =>’
  • 142. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb s/:([[:alnum:]]+)[[:space:]]=>/1:/g' ‘ab:’‘:ab =>’ replace with
  • 143. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do let(:orig_string) { “:ab => “} let(:new_string) { “ab: ‘} it ‘changes the file’ do original_contents = File.read(File.join(directory_path,file_name)) do_system_things.do_the_thing(directory_name) new_contents = File.read(File.join(directory_path,file_name)) end end Expected content of file before and after
  • 144. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do let(:orig_string) { “:ab => “} let(:new_string) { “ab: ‘} it ‘changes the file’ do original_contents = File.read(File.join(directory_path,file_name)) do_system_things.do_the_thing(directory_name) new_contents = File.read(File.join(directory_path,file_name)) expect(new_contents).not_to include(orig_string) expect(new_contents).to include(new_string) end end Verify contents of modified file
  • 145. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do let(:orig_string) { “:ab => “} let(:new_string) { “ab: ‘} it ‘changes the file’ do original_contents = File.read(File.join(directory_path,file_name)) do_system_things.do_the_thing(directory_name) new_contents = File.read(File.join(directory_path,file_name)) expect(new_contents).not_to include(orig_string) expect(new_contents).to include(new_string) end end Spec Passes!
  • 146. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end *pause*
  • 147. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb s/:([[:alnum:]]+)[[:space:]]=>/1:/g' Replace all matches for the first pattern with the second pattern
  • 148. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do let(:orig_string) { “:ab => :ab =>“} let(:new_string) { “ab: ab:’} it ‘changes all matches within the file’ do original_contents = File.read(File.join(directory_path,file_name)) do_system_things.do_the_thing(directory_name) new_contents = File.read(File.join(directory_path,file_name)) expect(new_contents).not_to include(orig_string) expect(new_contents).to include(new_string) end end Expected content of file before and after
  • 149. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do let(:orig_string) { “:ab => :ab =>“} let(:new_string) { “ab: ab:’} it ‘changes all matches within the file’ do original_contents = File.read(File.join(directory_path,file_name)) do_system_things(directory_name) new_contents = File.read(File.join(directory_path,file_name)) expect(new_contents).not_to include(orig_string) expect(new_contents).to include(new_string) end end Spec Passes!
  • 150. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/" #{dir}/**/*.rb" end end Taking out the global flag
  • 151. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/" #{dir}/**/*.rb" end end Spec Fails!
  • 152. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end Putting the flag back in
  • 153. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end Spec Passes!
  • 154. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end Take -E flag out
  • 155. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end Spec Fails!
  • 156. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end Put -E flag back in
  • 157. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end Spec Passes!
  • 158. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end -i flag: sed alters files in place
  • 159. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end -i flag: sed alters files in place Passing an empty extension
  • 160. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do it ‘does not save a backup copy of the file’ do expect (Dir[“#{directory_name}/#{subdirectory_name}/*”] .count).to eq(1) end end Expect only one file in directory/subdirectory path
  • 161. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do it ‘does not save a backup copy of the file’ do expect (Dir[“#{directory_name}/#{subdirectory_name}/*”] .count).to eq(1) do_system_things.do_the_thing(directory_name) end end Call the method
  • 162. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do it ‘does not save a backup copy of the file’ do expect (Dir[“#{directory_name}/#{subdirectory_name}/*”] .count).to eq(1) do_system_things.do_the_thing(directory_name) expect( Dir[“#{directory_name}/#{subdirectory_name}/*”] .count).to eq(1) end end Expect only one file in directory/subdirectory path
  • 163. First Do No Harm: Surgical Refactoring @nellshamrell spec/do_system_things_spec.rb context ‘changing the file’ do it ‘does not save a backup copy of the file’ do expect (Dir[“#{directory_name}/#{subdirectory_name}/*”] .count).to eq(1) do_system_things.do_the_thing(directory_name) expect (Dir[“#{directory_name}/#{subdirectory_name}/*”] .count).to eq(1) end end Spec Passes!
  • 164. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i .tmp ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end Pass extension to -i flag
  • 165. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i .tmp ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end Spec Fails!
  • 166. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end Passing an empty extension again
  • 167. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end Spec Passes!
  • 168. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' ’s/:([[:alnum:]]+)[[:space:]]=>/1:/g" #{dir}/**/*.rb" end end We know what this does!
  • 169. Section V: Operation First Do No Harm: Surgical Refactoring @nellshamrell
  • 170. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end
  • 171. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end end
  • 172. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' #{dir}/**/*.rb" end private def substitute_command 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' end end
  • 173. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb" end private def substitute_command 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' end end
  • 174. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb" end private def substitute_command 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' end end Spec Passes!
  • 175. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb" end private def substitute_command 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' end end Really old regex syntax
  • 176. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb" end private def substitute_command ’s/:(w+)s=>/1:/g’ end end New regex syntax
  • 177. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb" end private def substitute_command ’s/:(w+)s=>/1:/g’ end end Spec Fails!
  • 178. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb" end private def substitute_command 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' end end Back to the old regex syntax
  • 179. First Do No Harm: Surgical Refactoring @nellshamrell lib/do_system_things.rb class DoSystemThings def do_the_thing(dir) system "sed -E -i '' #{substitute_command} #{dir}/**/*.rb" end private def substitute_command 's/:([[:alnum:]]+)[[:space:]]=>/1:/g' end end Spec Passes!
  • 180. Section VI: Recovery First Do No Harm: Surgical Refactoring @nellshamrell
  • 181. What do I need to do after refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Need to know two things decisively
  • 182. What do I need to do after refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Need to know two things decisively 1) Does the behavior still exist?
  • 183. What do I need to do after refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Need to know two things decisively 1) Does the behavior still exist? 2) Is it connected correctly?
  • 184. What do I need to do after refactoring? First Do No Harm: Surgical Refactoring @nellshamrell What about QA?
  • 185. What do I need to do after refactoring? First Do No Harm: Surgical Refactoring @nellshamrell Ideally, QA should find nothing
  • 186. What if something goes wrong? First Do No Harm: Surgical Refactoring @nellshamrell
  • 187. What if something goes wrong? First Do No Harm: Surgical Refactoring @nellshamrell 1) Take responsibility - what your code does in production is your responsibility
  • 188. What if something goes wrong? First Do No Harm: Surgical Refactoring @nellshamrell 1) Take responsibility - what your code does in production is your responsibility 2) Evaluate risk of another change (a change to a change is still a change)
  • 189. What if something goes wrong? First Do No Harm: Surgical Refactoring @nellshamrell 1) Take responsibility - what your code does in production is your responsibility 2) Evaluate risk of another change (a change to a change is still a change) 3) Fix the problem (if you can’t, find someone who can!)
  • 190. Thank You! First Do No Harm: Surgical Refactoring @nellshamrell Nell Shamrell-Harrington Software Development Engineer at Chef @nellshamrell www.nellshamrell.com nshamrell@chef.io
  • 191. Thank You! First Do No Harm: Surgical Refactoring @nellshamrell Nell Shamrell-Harrington Software Development Engineer at Chef @nellshamrell www.nellshamrell.com nshamrell@chef.io Thank you Jim and Jen!!!!