Share
Embed
Code Review And Why Are We Wrong About It And How To Use It To Our Advantage
In this talk I take a look at code review as a tool in tech and how we can get the most out of this.
asendecka
February 10, 2019
Transcript
195 slides
-
Why Are We Wrong About It And How To Use
It To Our Advantage -
What is a code review? Goals of code review. What
we can catch in code review? -
What is a code review? Goals of code review. What
we can catch in code review? How wrong we are about code reviews? -
What is a code review? Goals of code review. What
we can catch in code review? How wrong we are about code reviews? What we can do about this? -
What is a code review? Goals of code review. What
we can catch in code review? How wrong we are about code reviews? What we can do about this? Ways to get the most out of code review. -
Modern Code Review a process that takes as input original
source code and outputs accepted source code. “ ” Moritz Beller, Elmar Juergens -
Moritz Beller, Elmar Juergens Modern Code Review the original source
code is a work that stemmed solely from the author, “ -
Moritz Beller, Elmar Juergens Modern Code Review the original source
code is a work that stemmed solely from the author, whereas in the accepted source code the author incorporated the reviewers’ suggestions “ -
Moritz Beller, Elmar Juergens Modern Code Review the original source
code is a work that stemmed solely from the author, whereas in the accepted source code the author incorporated the reviewers’ suggestions so that everybody is satisfied with the result. “ ” -
Moritz Beller, Elmar Juergens Modern Code Review the original source
code is a work that stemmed solely from the author, whereas in the accepted source code the author incorporated the reviewers’ suggestions so that everybody is satisfied with the result. “ ” -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
s. Team awareness. ss. -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. s. Team awareness. ss. -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. -
Code “Hygiene” Does the code pass linting and has consistent
code formatting? -
+def get_service_yaml(repo, service_name): + response = requests.get(makeServiceYamlUrl(repo, service_name), headers={'Accept': 'application/
vnd.github.v3.raw', 'Authorization': 'token {}'.format(settings.get('github_token'))}) + return response 21 22 23 -
+def get_service_yaml(repo, service_name): + response = requests.get(makeServiceYamlUrl(repo, service_name), headers={'Accept': 'application/
vnd.github.v3.raw', 'Authorization': 'token {}'.format(settings.get('github_token'))}) + return response 21 22 23 + response = requests.get(makeServiceYamlUrl(repo, service_name), headers={'Accept': 'application/ vnd.github.v3.raw', 'Authorization': 'token {}'.format(settings.get('github_token'))}) -
+def get_service_yaml(repo, service_name): + response = requests.get(makeServiceYamlUrl(repo, service_name), headers={'Accept': 'application/
vnd.github.v3.raw', 'Authorization': 'token {}'.format(settings.get('github_token'))}) + return response 21 22 23 makeServiceYamlUrl -
Code “Hygiene” Does the code pass linting and has consistent
code formatting? Is it clear what given function/class/method does? -
Code “Hygiene” Does the code pass linting and has consistent
code formatting? Is it clear what given function/class/method does? Do names reflect what code does? -
Makes a request to API. Extracts and formats results. Builds
attachments out of results. -
Makes a request to API. Extracts and formats results. Builds
attachments out of results. Sets the value of the attachments on the object… -
Code “Hygiene” Does the code pass linting and has consistent
code formatting? Is it clear what given function/class/method does? Do names reflect what code does? -
Code “Hygiene” Does the code pass linting and has consistent
code formatting? Is it clear what given function/class/method does? Do names reflect what code does? ⛳ Do functions have one responsibility? -
Code “Hygiene” Does the code pass linting and has consistent
code formatting? Is it clear what given function/class/method does? Do names reflect what code does? ⛳ Do functions have one responsibility? ✂ Could we split functions into smaller steps? -
Code “Hygiene” Does the code pass linting and has consistent
code formatting? Is it clear what given function/class/method does? Do names reflect what code does? ⛳ Do functions have one responsibility? ✂ Could we split functions into smaller steps? Does code have unexpected side effects? -
get_last_element(queue) returns last element of the queue but also removes
this element form the queue! -
get_last_element(queue) returns last element of the queue but also removes
this element form the queue ⁉ -
Code “Hygiene” Does the code pass linting and has consistent
code formatting? Is it clear what given function/class/method does? Do names reflect what code does? ⛳ Do functions have one responsibility? ✂ Could we split functions into smaller steps? Does code have unexpected side effects? -
Edge Cases & Broken Logic Edge cases for ifs, fors,
whiles and dates. -
+def can_be_displayed(publish_start_date): + today = datetime.date.today() + if today >
publish_start_date: + return True + return False 51 52 53 54 55 -
+def can_be_displayed(publish_start_date): + today = datetime.date.today() + if today >
publish_start_date: + return True + return False 51 52 53 54 55 + if today > publish_start_date: -
10th of February +def can_be_displayed(publish_start_date): + today = datetime.date.today() +
if today > publish_start_date: + return True + return False 51 52 53 54 55 + if today > publish_start_date: -
10th of February publish_start_date = date(2019, 2, 10) +def can_be_displayed(publish_start_date):
+ today = datetime.date.today() + if today > publish_start_date: + return True + return False 51 52 53 54 55 + if today > publish_start_date: -
10th of February publish_start_date = date(2019, 2, 10) today >
publish_start_date +def can_be_displayed(publish_start_date): + today = datetime.date.today() + if today > publish_start_date: + return True + return False 51 52 53 54 55 + if today > publish_start_date: -
10th of February publish_start_date = date(2019, 2, 10) today >
publish_start_date False +def can_be_displayed(publish_start_date): + today = datetime.date.today() + if today > publish_start_date: + return True + return False 51 52 53 54 55 + if today > publish_start_date: -
+def can_be_displayed(publish_start_date): + today = datetime.date.today() + if today >
publish_start_date: + return True + return False 51 52 53 54 55 + if today >= publish_start_date: True 10th of February publish_start_date = date(2019, 2, 10) today > publish_start_date -
Edge Cases & Broken Logic Edge cases for ifs, fors,
whiles and dates. Check Python gotchas. -
HTTP 414 URI Too Long https://our-internal-api.com/endpoint? fields=url,title,published_at,author, published_at,author,published_at,author, published_at,author,published_at,author, published_at,author,published_at,author,
published_at,author,published_at,author, published_at,author,published_at,author, published_at,author,published_at,author, published_at,author,published_at,author, published_at,author,published_at,author, published_at,author,published_at,author, published_at,author,published_at,author, published_at,author,published_at,author… -
17 18 19 20 21 22 23 24 25 26
+DEFAULT_FIELDS = [‘url','title'] + +def get_url(path, fields=()): + query_fields = DEFAULT_FIELDS + query_fields.extend(fields) + params = { + 'fields': ','.join(query_fields) + } + url = url_concat(path, params) + return url -
17 18 19 20 21 22 23 24 25 26
+DEFAULT_FIELDS = [‘url','title'] + +def get_url(path, fields=()): + query_fields = DEFAULT_FIELDS + query_fields.extend(fields) + params = { + 'fields': ','.join(query_fields) + } + url = url_concat(path, params) + return url + url = url_concat(path, params) -
17 18 19 20 21 22 23 24 25 26
+ query_fields = DEFAULT_FIELDS +DEFAULT_FIELDS = [‘url','title'] + +def get_url(path, fields=()): + query_fields = DEFAULT_FIELDS + query_fields.extend(fields) + params = { + 'fields': ','.join(query_fields) + } + url = url_concat(path, params) + return url -
17 18 19 20 21 22 23 24 25 26
+ query_fields.extend(fields) +DEFAULT_FIELDS = [‘url','title'] + +def get_url(path, fields=()): + query_fields = DEFAULT_FIELDS + query_fields.extend(fields) + params = { + 'fields': ','.join(query_fields) + } + url = url_concat(path, params) + return url -
17 18 19 20 21 22 23 24 25 26
+ query_fields = DEFAULT_FIELDS +DEFAULT_FIELDS = [‘url','title'] + +def get_url(path, fields=()): + query_fields = DEFAULT_FIELDS + query_fields.extend(fields) + params = { + 'fields': ','.join(query_fields) + } + url = url_concat(path, params) + return url -
id(DEFAULT_FIELDS) 4339573384 17 18 19 20 21 22 23 24
25 26 + query_fields = DEFAULT_FIELDS +DEFAULT_FIELDS = [‘url','title'] + +def get_url(path, fields=()): + query_fields = DEFAULT_FIELDS + query_fields.extend(fields) + params = { + 'fields': ','.join(query_fields) + } + url = url_concat(path, params) + return url id(query_fields) 4339573384 -
17 18 19 20 21 22 23 24 25 26
+DEFAULT_FIELDS = [‘url','title'] + +def get_url(path, fields=()): + query_fields = DEFAULT_FIELDS + query_fields.extend(fields) + params = { + 'fields': ','.join(query_fields) + } + url = url_concat(path, params) + return url +DEFAULT_FIELDS = [‘url','title'] Make it immutable! -
17 18 19 20 21 22 23 24 25 26
+DEFAULT_FIELDS = (‘url’,’title') + +def get_url(path, fields=()): + query_fields = DEFAULT_FIELDS + query_fields.extend(fields) + params = { + 'fields': ','.join(query_fields) + } + url = url_concat(path, params) + return url +DEFAULT_FIELDS = (‘url’,’title') Make it immutable! -
17 18 19 20 21 22 23 24 25 26
+DEFAULT_FIELDS = (‘url’,’title') + +def get_url(path, fields=()): + query_fields = DEFAULT_FIELDS + query_fields.extend(fields) + params = { + 'fields': ','.join(query_fields) + } + url = url_concat(path, params) + return url AttributeError: 'tuple' object has no attribute 'extend' + query_fields.extend(fields) -
Edge Cases & Broken Logic Edge cases for ifs, fors,
whiles and dates. Check Python gotchas. Are exceptions handled correctly? -
250 251 252 253 254 255 256 +try: + data
= fetch_video_data(video_id) +except Exception as err: + if err.code == 404: + handle_not_found() + else: + handle_http_error(err) -
+except Exception as err: 250 251 252 253 254 255
256 +try: + data = fetch_video_data(video_id) +except Exception as err: + if err.code == 404: + handle_not_found() + else: + handle_http_error(err) -
250 251 252 253 254 255 256 +try: + data
= fetch_video_data(video_id) +except Exception as err: + if err.code == 404: + handle_not_found() + else: + handle_http_error(err) + if err.code == 404: + handle_not_found() + else: + handle_http_error(err) -
250 251 252 253 254 255 256 +try: + data
= fetch_video_data(video_id) +except HTTPError as err: + if err.code == 404: + handle_not_found() + else: + handle_http_error(err) +except HTTPError as err: -
Edge Cases & Broken Logic Edge cases for ifs, fors,
whiles and dates. Check Python gotchas. Are exceptions handled correctly? -
Edge Cases & Broken Logic Edge cases for ifs, fors,
whiles and dates. Check Python gotchas. Are exceptions handled correctly? ➰ Are there unnecessary while loops? -
+day = datetime.date.today() +while not is_working_day(day): + day = day
+ datetime.timedelta(day=1) 43 44 45 -
+day = datetime.date.today() +while not is_working_day(day): + day = day
+ datetime.timedelta(day=1) 43 44 45 +day = datetime.date.today() -
+day = datetime.date.today() +while not is_working_day(day): + day = day
+ datetime.timedelta(day=1) 43 44 45 +while not is_working_day(day): -
+day = datetime.date.today() +while not is_working_day(day): + day = day
+ datetime.timedelta(day=1) 43 44 45 + day = day + datetime.timedelta(day=1) -
+day = datetime.date.today() +while not is_working_day(day): + day = day
+ datetime.timedelta(day=1) 43 44 45 +while not is_working_day(day): -
43 44 45 46 47 +day = datetime.date.today() +for offset
in range(31): + day = day + datetime.timedelta(day=offset) + if is_working_day(day): + break +for offset in range(31): -
Edge Cases & Broken Logic Edge cases for ifs, fors,
whiles and dates. Check Python gotchas. Are exceptions handled correctly? ➰ Are there unnecessary while loops? -
“Future-Self” Will Thank Me ♻ Is every line of code
used? Check usage of third party libraries. -
Third Party Libraries Check library documentation. Check if library choice
is consistent with the rest of the codebase. -
Third Party Libraries Check library documentation. Check if library choice
is consistent with the rest of the codebase. What’s the licence of the library? -
Third Party Libraries Check library documentation. Check if library choice
is consistent with the rest of the codebase. What’s the licence of the library? Is it actively maintained? -
“Future-Self” Will Thank Me ♻ Is every line of code
used? Check usage of third party libraries. -
“Future-Self” Will Thank Me ♻ Is every line of code
used? Check usage of third party libraries. E Is solution performant? -
“Future-Self” Will Thank Me ♻ Is every line of code
used? Check usage of third party libraries. E Is solution performant? Does optimisation hurt code readability? -
“Future-Self” Will Thank Me ♻ Is every line of code
used? Check usage of third party libraries. E Is solution performant? Does optimisation hurt code readability? Look for security vulnerabilities. -
“Future-Self” Will Thank Me ♻ Is every line of code
used? Check usage of third party libraries. E Is solution performant? Does optimisation hurt code readability? Look for security vulnerabilities. What is missing (tests, docs, metrics, logs, etc.)? -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Finding defects. -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Finding defects. edge cases -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Finding defects. edge cases programmatic errors -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Finding defects. edge cases programmatic errors simple logic issues -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Code improvements. edge cases programmatic errors simple logic issues -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Code improvements. smaller functions edge cases programmatic errors simple logic issues -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Code improvements. smaller functions naming edge cases programmatic errors simple logic issues -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Finding alternative solutions. smaller functions naming edge cases programmatic errors simple logic issues -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Finding alternative solutions. smaller functions naming edge cases programmatic errors simple logic issues -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Knowledge transfer. smaller functions naming edge cases programmatic errors simple logic issues -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Knowledge transfer. reviewers see the code smaller functions naming edge cases programmatic errors simple logic issues -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Team awareness. reviewers see the code smaller functions naming edge cases programmatic errors simple logic issues -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Team awareness. reviewers see the code smaller functions naming edge cases programmatic errors simple logic issues -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Improving dev process. reviewers see the code smaller functions naming edge cases programmatic errors simple logic issues mandatory linting -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. Improving dev process. reviewers see the code smaller functions naming edge cases programmatic errors simple logic issues mandatory linting -
Alberto Bacchelli, Christian Bird Goals of Code Review Finding defects.
Code improvements. Finding alternative solutions. Knowledge transfer. Team awareness. Improving dev process. smaller functions naming edge cases programmatic errors simple logic issues -
75% code maintainability M. Mäntylä and C. Lassenius. What Types
of Defects Are Really Discovered in Code Reviews? -
25% improve functionality M. Mäntylä and C. Lassenius. What Types
of Defects Are Really Discovered in Code Reviews? -
25% improve functionality M. Mäntylä and C. Lassenius. What Types
of Defects Are Really Discovered in Code Reviews? -
A. Bacchelli, C. Bird, Modern Code Reviews in Open-Source Projects:
Which Problems Do They Fix? There is a mismatch between the expectations and the actual outcomes of code reviews. “ -
A. Bacchelli, C. Bird, Modern Code Reviews in Open-Source Projects:
Which Problems Do They Fix? There is a mismatch between the expectations and the actual outcomes of code reviews. [...] review does not result in identifying defects as often as project members would like “ -
A. Bacchelli, C. Bird, Modern Code Reviews in Open-Source Projects:
Which Problems Do They Fix? There is a mismatch between the expectations and the actual outcomes of code reviews. [...] review does not result in identifying defects as often as project members would like “ and even more rarely detects deep, subtle, or “macro” level issues. -
A. Bacchelli, C. Bird, Modern Code Reviews in Open-Source Projects:
Which Problems Do They Fix? Relying on code review in this way for quality assurance may be fraught. There is a mismatch between the expectations and the actual outcomes of code reviews. [...] review does not result in identifying defects as often as project members would like “ ” and even more rarely detects deep, subtle, or “macro” level issues. -
A. Bacchelli, C. Bird, Modern Code Reviews in Open-Source Projects:
Which Problems Do They Fix? Modern code reviews provide benefits beyond finding defects. “ -
A. Bacchelli, C. Bird, Modern Code Reviews in Open-Source Projects:
Which Problems Do They Fix? Modern code reviews provide benefits beyond finding defects. “ Code review can be used to improve code style, find alternative solutions, increase learning, share code ownership, etc.. -
A. Bacchelli, C. Bird, Modern Code Reviews in Open-Source Projects:
Which Problems Do They Fix? Modern code reviews provide benefits beyond finding defects. “ ” Code review can be used to improve code style, find alternative solutions, increase learning, share code ownership, etc.. This should guide code review policies. -
✍ Write an architecture proposal. Organize a critique meeting for
bigger projects. -
✍ Write an architecture proposal. Organize a critique meeting for
bigger projects. Discuss (Slack, JIRA cards, GitHub issues) smaller tasks. -
If you involve people at the beginning, they are more
likely to provide help as during implementation process. Architecture Proposals -
Move responsibility from a single individual to a team. If
you involve people at the beginning, they are more likely to provide help as during implementation process. Architecture Proposals -
✍ Write an architecture proposal. Organize a critique meeting for
bigger projects. Discuss (Slack, JIRA cards, GitHub issues) smaller tasks. -
Improving code maintainability. Understanding and sharing best practices. What code
review really can help us with? -
Improving code maintainability. Understanding and sharing best practices. Knowledge sharing/education.
What code review really can help us with? -
Two reviewers Less experienced who will learn something new. Expert
that will catch deeper issues. -
Improving code maintainability. Understanding and sharing best practices. Knowledge sharing/education.
Building blameless culture. What code review really can help us with? -
How to promote blameless culture with code reviews? Let the
author fix all the issues in their pull request. -
How to promote blameless culture with code reviews? Let the
author fix all the issues in their pull request. ⏰ Get involved earlier in a process. Not when code is ready. -
Let the author fix all the issues in their pull
request. ⏰ Get involved earlier in a process. Not when code is ready. Take time to explain suggested improvements. How to promote blameless culture with code reviews? -
Let the author fix all the issues in their pull
request. ⏰ Get involved earlier in a process. Not when code is ready. Take time to explain suggested improvements. Require documentation. How to promote blameless culture with code reviews? -
README.md # _name of the service_ ## Point of contact
and Slack channel ## Usage ## Running the service ## System ## Runbook ## Monitoring ## Documentation https://tinyurl.com/better-docs -
Let the author fix all the issues in their pull
request. ⏰ Get involved earlier in a process. Not when code is ready. Take time to explain suggested improvements. Require documentation. Mind your language! How to promote blameless culture with code reviews? -
You don’t point something, because you are worried that author
will feel horrible about it. Two dangers -
You don’t point something, because you are worried that author
will feel horrible about it. You deliver your feedback in unhelpful and blunt way that make an author angry. Two dangers -
You don’t point something, because you are worried that author
will feel horrible about it. You deliver your feedback in unhelpful and blunt way that make an author angry. Two dangers -
You don’t point something, because you are worried that author
will feel horrible about it. You deliver your feedback in unhelpful and blunt way that make an author angry. Two dangers -
Improving code maintainability. Understanding and sharing best practices. Knowledge sharing/education.
Building blameless culture. a Preventing knowledge silos. What code review really can help us with? -
Improving code maintainability. Understanding and sharing best practices. Knowledge sharing/education.
Building blameless culture. a Preventing knowledge silos. Encouraging shared ownership & responsibility. What code review really can help us with? -
There is a surprising disparity between our expectations about code
reviews and what they can actually achieve.