In one timeline, a quick path to clarity. In the other, a long and painful journey trying to understand the obscure intent of a line of code. The only difference between the two realities? The revision history...
This is a story about writing maintainable software. But rather than the code itself, we’ll see how a well-crafted revision history is as important to maintainability as choosing the right abstraction. We'll explore the differences between a useful history and an unhelpful one. And you'll learn about the practices, tools and techniques that help make the difference.
4. class PatientsController < ApplicationController
before_action :load_doctor
def index
@patients = sorted_patients
end
def show
@patient = @doctor.patients.find(params[:id])
end
private
def sorted_patients
@doctor.patients.sort { |patient| patient.name }
end
def load_doctor
@doctor = doctor_from_current_session
5. class PatientsController < ApplicationController
before_action :load_doctor
def index
@patients = sorted_patients
end
def show
@patient = @doctor.patients.find(params[:id])
end
private
def sorted_patients
@doctor.patients.sort { |patient| patient.name }
end
def load_doctor
@doctor = doctor_from_current_session
6. class PatientsController < ApplicationController
before_action :load_doctor
def index
@patients = sorted_patients
end
def show
@patient = @doctor.patients.find(params[:id])
end
private
def sorted_patients
@doctor.patients.order(:name)
end
def load_doctor
@doctor = doctor_from_current_session
7. class PatientsController < ApplicationController
before_action :load_doctor
def index
@patients = sorted_patients
end
def show
@patient = @doctor.patients.find(params[:id])
end
private
def sorted_patients
@doctor.patients.order(:name)
end
def load_doctor
@doctor = doctor_from_current_session
$ rake
Run options: --seed 45260
# Running:
....................................................................
....................................................................
....................................................................
....................................
Finished in 123.299088s, 23.8629 runs/s, 34.6397 assertions/s.
3311 runs, 45124 assertions, 0 failures, 0 errors, 0 skips
8. class Patient < ApplicationRecord
has_many :appointments
validates_presence_of :name, :address, :date_of_birth
end
class Doctor < ApplicationRecord
has_many :appointments
has_many :patients, through: :appointments
belongs_to :practice
validates_presence_of :name, :practice
end
29. class PatientsController < ApplicationController
before_filter :load_doctor
def index
@patients = @doctor.patients.order(:name)
end
def show
@patient = @doctor.patients.find(params[:id])
end
private
def load_doctor
@doctor = doctor_from_current_session
end
end
30. class PatientsController < ApplicationController
before_filter :load_doctor
def index
@patients = @doctor.patients.order(:name)
end
def show
@patient = @doctor.patients.find(params[:id])
end
private
def load_doctor
@doctor = doctor_from_current_session
end
end
31. class Doctor < ApplicationRecord
has_many :appointments, order: :appointment_date
has_many :patients, through: :appointments
belongs_to :practice
validates_presence_of :name, :practice
end
32. class Doctor < ApplicationRecord
has_many :appointments, order: :appointment_date
has_many :patients, through: :appointments
belongs_to :practice
validates_presence_of :name, :practice
end
33. class Doctor < ApplicationRecord
has_many :appointments, order: :appointment_date
has_many :patients, through: :appointments
belongs_to :practice
validates_presence_of :name, :practice
end
doctor.patients.order(:name)
Patients Load (1.0ms) SELECT "patients".* FROM "patients"
INNER JOIN "appointments" ON "patients"."id" = "appointments"."patient_id"
WHERE “appointments"."doctor_id" = $1
ORDER BY “appointments"."appointment_date" ASC, "patients"."name" ASC
irb(main):003:0>
34. class Doctor < ApplicationRecord
has_many :appointments
has_many :patients, through: :appointments
belongs_to :practice
validates_presence_of :name, :practice
end
, order: :appointment_date
35. class Doctor < ApplicationRecord
has_many :appointments
has_many :patients, through: :appointments
belongs_to :practice
validates_presence_of :name, :practice
end
$ rake
Run options: --seed 45260
# Running:
.....F..........FFFF.........F..........FF..............FFFFFFFFF...
..............FFFFFFFFFFFFFFFFFF............................FFFF
Finished in 1.273019s, 24.3516 runs/s, 35.3490 assertions/s.
36. class PatientsController < ApplicationController
before_filter :load_doctor
def index
@patients = @doctor.patients.order(:name)
end
def show
@patient = @doctor.patients.find(params[:id])
end
private
def load_doctor
@doctor = doctor_from_current_session
end
end
37. class PatientsController < ApplicationController
before_filter :load_doctor
def index
@patients =
end
def show
@patient = @doctor.patients.find(params[:id])
end
private
def load_patients
@doctor.patients.sort { |pateint| pateint.name }
end
def load_doctor
@doctor = doctor_from_current_session
load_patients
67. class PatientsController < ApplicationController
before_action :load_doctor
def index
@patients = sorted_patients
end
def show
@patient = @doctor.patients.find(params[:id])
end
private
def sorted_patients
@doctor.patients.sort { |patient| patient.name }
end
def load_doctor
@doctor = doctor_from_current_session
68. 3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 1) # Controller for listing a doctor's pa
3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 2) class PatientsController < Application
3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 3) before_filter :load_doctor
3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 4)
3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 5) def index
6047246d (Josie P 2010-10-29 09:32:25 +0100 6) @patients = sorted_patients
3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 7) end
3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 8)
9598514f (Josie P 2010-06-28 17:03:21 +0100 9) def show
9598514f (Josie P 2010-06-28 17:03:21 +0100 10) @patient = @doctor.patients.find(p
9598514f (Josie P 2010-06-28 17:03:21 +0100 11) end
9598514f (Richard E 2010-06-28 17:03:21 +0100 12)
3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 13) private
dbdd0fb9 (Josie P 2010-10-29 09:31:52 +0100 18)
6047246d (Josie P 2010-10-29 09:32:25 +0100 19) def sorted_patients
33ec144e (Josie P 2010-10-29 09:31:52 +0100 20) @doctor.patients.sort {|patient| p
dbdd0f69 (Josie P 2010-10-29 09:31:52 +0100 21) end
3fc122c2 (Richard E 2010-06-28 17:02:54 +0100 14)
$ git blame app/controllers/patients_controller.rb
Git Fu: git blame
69. $ git log 33ec144e --patch
commit 33ec144e70b91e6925903553f07df3becc9414
Author: Josie Pickford<josie@docs-r-us.com>
Date: Friday Oct 29 09:44:49 2010 +0100
Fix patient ordering bug
The patients association is returning patients in appointment date
order, even when called with an explicit `order(:name)` scope. This is
because the patients association is a has_many :through the appointments
association, which has a default order by appointment_date. This causes
any queries on the association to always sort first by appointment date:
ORDER BY “appointments"."appointment_date" ASC, "patients"."name" ASC)
Removing the default ordering from the appointments association is going
to take a bit of unpicking. To get the bug resolved in the meantime we
can re-sort the patient records after they've been loaded. Separate
work has been planned to remove the default ordering altogether.
Git Fu: git blame
70. class Doctor < ApplicationRecord
has_many :appointments
has_many :patients, through: :appointments
belongs_to :practice
validates_presence_of :name, :practice
end
89. Git Fu
1. Configure an environment for good commit
messages
2. Capture the why, not the what
4. Treat (local) commits as mutable
3. Shape each commit
90. Treat (local) commits as mutable
• $ git commit --amend
• $ git rebase --interactive
• $ git rebase --abort
• --fixup / --autosquash
91. Git Fu
1. Configure an environment for good commit
messages
2. Capture the why, not the what
5. Build your instincts; search your histories
4. Treat (local) commits as mutable
3. Shape each commit
93. Git Fu
1. Configure an environment for good commit
messages
2. Capture the why, not the what
5. Treat (local) commits as mutable
4. Build your instincts; search your histories
3. Shape each commit
99. Seema Memoji
Josie Memoji
Created by
Inspiration for the story-based approach
Talk Feedback and Advice
Slide Advisor
Git Fu Indent
Hospital Icon
Winding Road Photo
Sound Effects
TEKIN SULEYMAN
TEKIN SULEYMAN
TEKIN SULEYMAN
NADIA ODUNAYO
ANDY CROLL
ANGELA TODD
GRAHAM ASHTON
MURRAY STEELE
NADIA ODUNAYO
KATRINA OWEN
BRUCE LEE, ENTER THE DRAGON (1972)
FLATICON.COM
JESSE BOWSER ON UNSPLASH
LEGEND OF ZELDA, A LINK TO THE PAST
Cast