Slide 1

Slide 1 text

How To Be A Bad-Ass Code Reviewer KubeCon Contributor Summit Nov, 2019 Tim Hockin Software Engineer, Google @thockin (c) Google LLC

Slide 2

Slide 2 text

Kubernetes has become a phenomenon • One of the most active OSS projects EVAR! • Hundreds of repos on github • Contributors from every timezone and almost every continent (Antarcticans - if you’re out there, holla!) We receive scores to hundreds of Pull Requests per day Every single PR needs someone to review it! Why do I care?

Slide 3

Slide 3 text

Good code review is HARD

Slide 4

Slide 4 text

Make time^H^H^H^H^H enough time • Doing a full pass in a single sitting is best Get into the mindset • Close email, chat, Slack, IRC, Zoom, etc. • Headphones or similar environmental neutralizers Read the associated bugs • There ARE bugs linked, right? Understand WHY the change is being made Before starting

Slide 5

Slide 5 text

Read and understand the change Understand the context: the surrounding code and adjacent features matter a lot Think about: • Test cases • APIs • Comments and docs Start the hard work

Slide 6

Slide 6 text

Every change makes the code either better or worse

Slide 7

Slide 7 text

Let’s talk about how to do stronger code reviews

Slide 8

Slide 8 text

Is the bug cited? Is the bug real and worth fixing? Does this actually fix it? Does this prove that it fixes it (tests, benchmarks)? Is this the “right” fix? If not - it’s OK to push back Motivation: Bug fix

Slide 9

Slide 9 text

Do we really want the feature? How does it interact with other features? Is the community (SIGs) OK with the design? Where’s the KEP? Motivation: Feature

Slide 10

Slide 10 text

Style

Slide 11

Slide 11 text

Is it the simplest way to express the solution? • Can it be broken down further? Are functions, types, variables named clearly? • Go style encourages short names for locals, but sometimes “frobber” really is better than “f” • Code should “read well” Whitespace can be as valuable as code to clarity Clarity

Slide 12

Slide 12 text

Do the changes make sense in the places they are being made? Do they fit the mission of the type or function? • It’s OK to add new types or functions • Don’t force-fit! Cohesion

Slide 13

Slide 13 text

Can the change be broken down any further? • Smaller, focused PRs are better Is it complete? • Opposite of above - don’t commit half-cooked work Is it exposing details that callers don’t need to know? • Can it be pre-factored to reduce scope? Scope

Slide 14

Slide 14 text

The more deeply embedded, the less the API matters • E.g. breaking out a function for readability vs exporting The more widely visible, the more the API and generality matters • Hyrum’s law - all exposed surface will be used • Special cases for things like k/utils Generality

Slide 15

Slide 15 text

Substance

Slide 16

Slide 16 text

If code does ANYTHING non-obvious, it needs to explain WHY • Almost never “what” or “how”, unless obscure • If you did some analysis to make a decision, say what • If you chose something at random, say that • If you think you will need to revisit some decision later and you are leaving room for that, say so If the next reader’s instinct will be to undo some of this, make sure to leave a note Comments

Slide 17

Slide 17 text

Does the code handle errors? • Return, log, retry - DO NOT IGNORE (or comment why) • Wrap errors when context is needed Think about corner-cases and “pathological” situations Does it fail gracefully? • Will it retry? • Is this clear in the code and comments? • How will the user know something failed? Errors and failure

Slide 18

Slide 18 text

Does it log significant actions and errors? • Are the logs useful and/or actionable? • Are they spammy? • Do they have enough data to comprehend what actually happened? Does it have metrics, when appropriate? • Do they tell us something we actually want to know? Observability

Slide 19

Slide 19 text

If the PR involves config fields, APIs, CLIs, or flags: • Think about how they will be used: do they feel natural? • Are they consistent with other instances? • Would they impede or confuse other planned work? • Principle Of Least Surprise • If we were starting it all over, what we would want? UX

Slide 20

Slide 20 text

Almost all code changes require test changes • A code PR without tests is an immediate smell • Even if tests didn’t exist before, do better Warning signs • Do the tests require twiddling some global variable or flag? • Do the tests anticipate the most obvious ways for future me to break your feature? • Are the tests at the smallest scope possible? • Do the tests use time.Sleep? Testing

Slide 21

Slide 21 text

Some PRs are about performance, lock contention, resource usage, scalability, etc. These sorts of changes must be well commented These PRs really should come with a benchmark • To demonstrate efficacy • To prevent regressions Performance and scale

Slide 22

Slide 22 text

Is the PR complete? • API definitions and implementation • Client and server • All the functionality for a whole change We don’t want to merge half-complete features • It’s too easy to miss a release cutoff • OK to seek review before complete, but not merge Completeness

Slide 23

Slide 23 text

Many PRs require knowledge of the context • What has been done in the past • Why things were done the way they were • What performance metrics matter or have been a problem in the past • How other features will interact with this change • What we want to do in the future Domain specific knowledge

Slide 24

Slide 24 text

If you need context you do not have: GO GET IT! • Go exploring - software archaeology is fun • git grep is your friend • Do experiments or patch in the change and try it • Ask for a consult • Ask PR author to document the results in comments • links to previous issues / changes / discussions are VERY helpful for future others I’ve seen too many PRs approved without sufficient context that need to be fixed later • I have been guilty of this, too Domain specific knowledge

Slide 25

Slide 25 text

If you don’t know how a change interacts with other code or features, or how it fits into the subsystem: DO NOT APPROVE! Domain specific knowledge

Slide 26

Slide 26 text

Commits matter • They are the permanent record of what happened and why Organize large PRs into intentional, discrete steps • Easier up-front, but possible ex post facto Commits should almost always stand on their own OK to have “fix feedback” commits during review • Need to fold those back to real commits BEFORE merging • Yes it is tedious, sorry (not sorry) Commit hygiene

Slide 27

Slide 27 text

PRs are not really represented in git history PR comment should summarize, explain what the PR is about and why, link to relevant docs (e.g. KEPs) and reference bugs Commit comments should be thorough and detailed • Enough for git log to be useful • WHY > HOW PR and commit comments

Slide 28

Slide 28 text

Like refactoring, but done BEFORE making changes • Arranges code to better accommodate a future change • Reduces the size and scope of the real change • Should be no-op code changes, plus tests Prefactoring is not just acceptable - encourage it! • Any significant change will almost certainly require it • Can be separate PRs or commits in a larger PR Prefactoring

Slide 29

Slide 29 text

Process

Slide 30

Slide 30 text

DO: Ask questions and seek to understand • “Am I following this correctly?” • “Why was this choice made?” • If you send every comment you write, you are probably doing it wrong DO: Explain your thinking • “If X is true, then Y can’t be true, but this doesn’t handle that case” Communication

Slide 31

Slide 31 text

DO: Be clear about nits vs. requirements vs. questions • Nit: A small thing that could be improved • Required: “I will not /lgtm until you fix this” DON’T: Pick a bunch of nits if the real problem is that the PR has the wrong approach • Architectural guidance should be first priority Requesting changes

Slide 32

Slide 32 text

DO: Indicate progress • Be clear about whether you’re finished reviewing or not, or what state you think the PR is in overall • It’s frustrating to get batch after batch of comments when you thought you were done DON’T: Approve because of deadlines or guilt • There’s always another release • Again: There’s. Always. Another. Release. Progress

Slide 33

Slide 33 text

DON’T: Be timid about asking for changes • You are the defenders of this codebase • THIS IS YOUR JOB (for the moment) DO: Be reasonable • They won’t do everything exactly how you would have DO: Be willing to be wrong; trust, but verify DO: Be willing to acquiesce on reasonable debate Discussion

Slide 34

Slide 34 text

Critique CODE not PEOPLE

Slide 35

Slide 35 text

Strategic tech-debt should be rare but not unheard of Discuss debt and tradeoffs with your SIGs and other reviewers, if needed This project is massively distributed - we HAVE TO trust each other to make good decisions Tradeoffs

Slide 36

Slide 36 text

Code review is community service, and must not be taken lightly • Make time, and don't half-ass it • We have to live in the codebase we create • Trust your instincts: if it doesn’t smell right, investigate • You’re guaranteed to find either a bug in the code or a bug in your instincts • Do not approve things you don’t understand fully At the end of the day...

Slide 37

Slide 37 text

DO NOT BE A RUBBER STAMP I’d rather we slow the whole project down than merge garbage

Slide 38

Slide 38 text

TO PR AUTHORS Code review time is exponential to the PR size Smaller PRs have many more chances to schedule!

Slide 39

Slide 39 text

No content