first do no harm: surgical refactoring
TRANSCRIPT
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
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…
TransportationEnergy sources
But…it’s not life or death, right?
First Do No Harm: Surgical Refactoring @nellshamrell
Software is being integrated into…
TransportationEnergy sourcesMedical Devices
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 Approaches1) Edit and Pray
How should I refactor?
First Do No Harm: Surgical Refactoring @nellshamrell
2 Common Approaches1) Edit and Pray
2) Cover and Modify
How should I refactor?
First Do No Harm: Surgical Refactoring @nellshamrell
2 Common Approaches1) Edit and Pray
2) Cover and Modify- “Working Effectively with Legacy Code”
What is surgical refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Change exactly what we INTEND to changeAnd 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 refactoring2) 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 somethingCode is too inefficient
What is a necessary refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Need to add somethingCode 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
No business need to change code
What is a cosmetic refactoring?
First Do No Harm: Surgical Refactoring @nellshamrell
Something about it just bugs usNo 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
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
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!
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
endExecutes 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
endIn a series directories and files
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
endWhat 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
endAdding 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
endPlacing 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.rbcontext ‘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.rbcontext ‘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.rbcontext ‘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.rbcontext ‘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.rbcontext ‘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.rbcontext ‘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:
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.rbcontext ‘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.rbcontext ‘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.rbcontext ‘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.rbcontext ‘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.rbcontext ‘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.rbcontext ‘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.rbcontext ‘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.rbcontext ‘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.rbcontext ‘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!
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!
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
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
Thank You!
First Do No Harm: Surgical Refactoring @nellshamrell
Nell Shamrell-Harrington
Software Development Engineer at Chef
@nellshamrell
www.nellshamrell.com
Thank you Jim and Jen!!!!