Software development often deals with rethinking decisions.
Ultimately causes reworking portions of the code.
Code is not final, it needs to evolve
Almost every time you change the source code you end up rewritting/reworking or restructuring it. Is that refactoring?
“Disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior.” — Martin Fowler.
Source: Refactoring: Improving the Design of Existing Code. Addison-Wesley, Boston, MA, Second, 2019.
Easier to clean a room if only a few things are out of place
Rule of Three.
Code Smells
Variables and functions with a meaningful name make the code easiser to understand.
Find an equivalent way to replace a block of code
Divide to conquer
Welcome to the GSS course!
Today's lecture is about refactoring.
What is your name? Bob
Hello Bob!
It’s the opposite of extract! If we only do it once, might as well not have it encapsulated in a function.
Group functionality in a module.
E.g. move is_prime to another file
The Fibonacci sequence is defined by the recurrence relation:
\[ F(n) = F(n-1) + F(n-2) \]
with initial numbers:
\[ F(0) = 0,\quad F(1) = 1 \]
Resulting in: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …
report.py.grades_report.test_grades_report.py (with pytest) to ensure behaviour remains.report.py
def get_grades():
students = list()
grades = list()
while True:
name = input("Insert student name (quit to finish):")
if "quit" in name:
return students, grades
grade = int(input(f"Insert {name}'s grade:"))
students.append(name)
grades.append(grade)
def grades_report(students, grades):
average = 0
maxgrade = 0
mingrade = 100
counter = 0 # do we need this variable?
for grade in grades: # can this be improved?
counter += 1 # len(grades) will give the number of students
# do we need this? we can just return avg, max and min
report = {"students": students, "grades": grades, "size": counter}
for i in range(counter):
grade = grades[i]
average += grade
if maxgrade < grade:
maxgrade = grade
if mingrade > grade:
mingrade = grade
if counter > 0:
average = average / counter
else:
average = None
maxgrade = None
mingrade = None
return average, maxgrade, mingrade
def format_report(students, grades, average, maxgrade, mingrade):
report = "Report of " + str(len(students)) + " students:\n"
for i in range(len(students)):
name = students[i]
grade = grades[i]
report += str(name) + " -> " + str(grade) + "\n"
report += " Average: " + str(average) + "\n"
report += " Maximum: " + str(maxgrade) + "\n"
report += " Minimum: " + str(mingrade) + "\n"
return report
if __name__ == "__main__":
students, grades = get_grades()
average, maxgrade, mingrade = grades_report(students, grades)
report = format_report(students, grades, average, maxgrade, mingrade)
print(report)test_grades_report.py
from report import grades_report, format_report
def test_empty_report():
students = list()
grades = list()
assert (None, None, None) == grades_report(students, grades)
def test_grades_report():
students = ["Alice", "Bob"]
grades = [1, 2]
assert len(students) == len(grades)
size = len(students)
assert (
1.5,
2,
1,
) == grades_report(students, grades)
def test_format_report():
students = ["Alice", "Bob"]
grades = [1, 2]
expected = (
"Report of 2 students:\n"
"Alice -> 1\n"
"Bob -> 2\n"
" Average: 1.5\n"
" Maximum: 2\n"
" Minimum: 1\n"
)
report = format_report(students, grades, 1.5, 2, 1)
assert report == expected$ python3 report.py
Insert student name (quit to finish):Alice
Insert Alice's grade:2
Insert student name (quit to finish):Bob
Insert Bob's grade:1
Insert student name (quit to finish):quit
Report of 2 students:
Alice -> 2
Bob -> 1
Average: 1.5
Maximum: 2
Minimum: 1
pytest test_grades_report.py
================== test session starts ==================
platform linux -- Python 3.10.12, pytest-8.3.5
plugins: anyio-4.4.0
collected 3 items
test_grades_report.py::test_empty_report PASSED [ 33%]
test_grades_report.py::test_grades_report PASSED [ 66%]
test_grades_report.py::test_format_report PASSED [100%]
=================== 3 passed in 0.01s ===================