forked from google/eng-practices
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.tex
1938 lines (1584 loc) · 79.9 KB
/
main.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
% Options for packages loaded elsewhere
\PassOptionsToPackage{unicode}{hyperref}
\PassOptionsToPackage{hyphens}{url}
%
\documentclass[
]{article}
\usepackage{amsmath,amssymb}
\usepackage[margin=2.5cm]{geometry}
\usepackage{iftex}
\ifPDFTeX
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{textcomp} % provide euro and other symbols
\else % if luatex or xetex
\usepackage{unicode-math} % this also loads fontspec
\defaultfontfeatures{Scale=MatchLowercase}
\defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}
\fi
\usepackage{lmodern}
\ifPDFTeX\else
% xetex/luatex font selection
\fi
% Use upquote if available, for straight quotes in verbatim environments
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
\IfFileExists{microtype.sty}{% use microtype if available
\usepackage[]{microtype}
\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
}{}
\makeatletter
\@ifundefined{KOMAClassName}{% if non-KOMA class
\IfFileExists{parskip.sty}{%
\usepackage{parskip}
}{% else
\setlength{\parindent}{0pt}
\setlength{\parskip}{6pt plus 2pt minus 1pt}}
}{% if KOMA class
\KOMAoptions{parskip=half}}
\makeatother
\usepackage{xcolor}
\usepackage{color}
\usepackage{fancyvrb}
\newcommand{\VerbBar}{|}
\newcommand{\VERB}{\Verb[commandchars=\\\{\}]}
\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
% Add ',fontsize=\small' for more characters per line
\newenvironment{Shaded}{}{}
\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}}
\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}}
\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
\newcommand{\BuiltInTok}[1]{\textcolor[rgb]{0.00,0.50,0.00}{#1}}
\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}}
\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}}
\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}}
\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}}
\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}}
\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}}
\newcommand{\ExtensionTok}[1]{#1}
\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}}
\newcommand{\ImportTok}[1]{\textcolor[rgb]{0.00,0.50,0.00}{\textbf{#1}}}
\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}}
\newcommand{\NormalTok}[1]{#1}
\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}}
\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}}
\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}}
\newcommand{\RegionMarkerTok}[1]{#1}
\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}}
\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}}
\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
\usepackage{longtable,booktabs,array}
\usepackage{calc} % for calculating minipage widths
% Correct order of tables after \paragraph or \subparagraph
\usepackage{etoolbox}
\makeatletter
\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{}
\makeatother
% Allow footnotes in longtable head/foot
\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}}
\makesavenoteenv{longtable}
\setlength{\emergencystretch}{3em} % prevent overfull lines
\providecommand{\tightlist}{%
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
% \setcounter{secnumdepth}{-\maxdimen} % remove section numbering
\ifLuaTeX
\usepackage{selnolig} % disable illegal ligatures
\fi
\usepackage{bookmark}
\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
\urlstyle{same}
\hypersetup{
hidelinks,
pdfcreator={LaTeX via pandoc}}
\title{Google Generic Coding Good Practices Guidelines}
\date{\today}
\makeatletter
\renewcommand{\maketitle}{
\begin{titlepage}
\begin{center}
\vspace*{\fill}
{\Huge \textbf{\@title}}
\par\vspace{1.5cm}
{\large \@date} \\[4cm]
\hrule
\begin{abstract}
\large
This document outlines the engineering practices followed at Google, which encompass guidelines applicable to all programming languages and projects.
These practices, derived from extensive experience and expertise, aim to enhance the quality and efficiency of code reviews and version control processes.
Key sections include detailed guides for code reviewers and change authors, offering insights into conducting effective code reviews and submitting high-quality changelists.
The document also clarifies common terminologies, such as "changelist" (CL) and "LGTM" (Looks Good to Me), to bridge any understanding gaps for external audiences.
This resource is intended to provide valuable best practices that can be adopted by open-source projects and other organizations.
\end{abstract}
\hrule
\vspace*{\fill}
\end{center}
\end{titlepage}
}
\makeatother
\begin{document}
\maketitle
\clearpage
{
\setcounter{tocdepth}{3}
\tableofcontents
}
\clearpage
\section{Google Engineering Practices
Documentation}\label{google-engineering-practices-documentation}
Google has many generalized engineering practices that cover all
languages and all projects. These documents represent our collective
experience of various best practices that we have developed over time.
It is possible that open source projects or other organizations would
benefit from this knowledge, so we work to make it available publicly
when possible.
Currently this contains the following documents:
\begin{itemize}
\tightlist
\item
\href{review/index.md}{Google's Code Review Guidelines}, which are
actually two separate sets of documents:
\begin{itemize}
\tightlist
\item
\href{review/reviewer/index.md}{The Code Reviewer's Guide}
\item
\href{review/developer/index.md}{The Change Author's Guide}
\end{itemize}
\end{itemize}
\subsection{Terminology}\label{terminology}
There is some Google-internal terminology used in some of these
documents, which we clarify here for external readers:
\begin{itemize}
\tightlist
\item
\textbf{CL}: Stands for ``changelist'', which means one self-contained
change that has been submitted to version control or which is
undergoing code review. Other organizations often call this a
``change'', ``patch'', or ``pull-request''.
\item
\textbf{LGTM}: Means ``Looks Good to Me''. It is what a code reviewer
says when approving a CL.
\end{itemize}
\subsection{License}\label{license}
The documents in this project are licensed under the
\href{LICENSE}{CC-By 3.0 License}, which encourages you to share these
documents. See \url{https://creativecommons.org/licenses/by/3.0/} for
more details.
\section{Writing good CL
descriptions}\label{writing-good-cl-descriptions}
A CL description is a public record of change, and it is important that
it communicates:
\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\item
\textbf{What} change is being made? This should summarize the major
changes such that readers have a sense of what is being changed
without needing to read the entire CL.
\item
\textbf{Why} are these changes being made? What contexts did you have
as an author when making this change? Were there decisions you made
that aren't reflected in the source code? etc.
\end{enumerate}
The CL description will become a permanent part of our version control
history and will possibly be read by hundreds of people over the years.
Future developers will search for your CL based on its description.
Someone in the future might be looking for your change because of a
faint memory of its relevance but without the specifics handy. If all
the important information is in the code and not the description, it's
going to be a lot harder for them to locate your CL.
And then, after they find the CL, will they be able to understand
\emph{why} the change was made? Reading source code may reveal what the
software is doing but it may not reveal why it exists, which can make it
harder for future developers to know whether they can move
\href{https://abseil.io/resources/swe-book/html/ch03.html\#understand_context}{Chesterton's
fence}.
A well-written CL description will help those future engineers --
sometimes, including yourself!
\subsection{First Line}\label{first-line}
\begin{itemize}
\tightlist
\item
Short summary of what is being done.
\item
Complete sentence, written as though it was an order.
\item
Follow by empty line.
\end{itemize}
The \textbf{first line} of a CL description should be a short summary of
\emph{specifically} \textbf{what} \emph{is being done by the CL},
followed by a blank line. This is what appears in version control
history summaries, so it should be informative enough that future code
searchers don't have to read your CL or its whole description to
understand what your CL actually \emph{did} or how it differs from other
CLs. That is, the first line should stand alone, allowing readers to
skim through code history much faster.
Try to keep your first line short, focused, and to the point. The
clarity and utility to the reader should be the top concern.
By tradition, the first line of a CL description is a complete sentence,
written as though it were an order (an imperative sentence). For
example, say "\textbf{Delete} the FizzBuzz RPC and \textbf{replace} it
with the new system.'' instead of "\textbf{Deleting} the FizzBuzz RPC
and \textbf{replacing} it with the new system.'' You don't have to write
the rest of the description as an imperative sentence, though.
\subsection{Body is Informative}\label{informative}
The \hyperref[first-line]{first line} should be a short, focused
summary, while the rest of the description should fill in the details
and include any supplemental information a reader needs to understand
the changelist holistically. It might include a brief description of the
problem that's being solved, and why this is the best approach. If there
are any shortcomings to the approach, they should be mentioned. If
relevant, include background information such as bug numbers, benchmark
results, and links to design documents.
If you include links to external resources consider that they may not be
visible to future readers due to access restrictions or retention
policies. Where possible include enough context for reviewers and future
readers to understand the CL.
Even small CLs deserve a little attention to detail. Put the CL in
context.
\subsection{Bad CL Descriptions}\label{bad}
``Fix bug'' is an inadequate CL description. What bug? What did you do
to fix it? Other similarly bad descriptions include:
\begin{itemize}
\tightlist
\item
``Fix build.''
\item
``Add patch.''
\item
``Moving code from A to B.''
\item
``Phase 1.''
\item
``Add convenience functions.''
\item
``kill weird URLs.''
\end{itemize}
Some of those are real CL descriptions. Although short, they do not
provide enough useful information.
\subsection{Good CL Descriptions}\label{good}
Here are some examples of good descriptions.
\subsubsection{Functionality change}\label{functionality-change}
Example:
\begin{quote}
RPC: Remove size limit on RPC server message freelist.
Servers like FizzBuzz have very large messages and would benefit from
reuse. Make the freelist larger, and add a goroutine that frees the
freelist entries slowly over time, so that idle servers eventually
release all freelist entries.
\end{quote}
The first few words describe what the CL actually does. The rest of the
description talks about the problem being solved, why this is a good
solution, and a bit more information about the specific implementation.
\subsubsection{Refactoring}\label{refactoring}
Example:
\begin{quote}
Construct a Task with a TimeKeeper to use its TimeStr and Now methods.
Add a Now method to Task, so the borglet() getter method can be removed
(which was only used by OOMCandidate to call borglet's Now method). This
replaces the methods on Borglet that delegate to a TimeKeeper.
Allowing Tasks to supply Now is a step toward eliminating the dependency
on Borglet. Eventually, collaborators that depend on getting Now from
the Task should be changed to use a TimeKeeper directly, but this has
been an accommodation to refactoring in small steps.
Continuing the long-range goal of refactoring the Borglet Hierarchy.
\end{quote}
The first line describes what the CL does and how this is a change from
the past. The rest of the description talks about the specific
implementation, the context of the CL, that the solution isn't ideal,
and possible future direction. It also explains \emph{why} this change
is being made.
\subsubsection{Small CL that needs some
context}\label{small-cl-that-needs-some-context}
Example:
\begin{quote}
Create a Python3 build rule for status.py.
This allows consumers who are already using this as in Python3 to depend
on a rule that is next to the original status build rule instead of
somewhere in their own tree. It encourages new consumers to use Python3
if they can, instead of Python2, and significantly simplifies some
automated build file refactoring tools being worked on currently.
\end{quote}
The first sentence describes what's actually being done. The rest of the
description explains \emph{why} the change is being made and gives the
reviewer a lot of context.
\subsection{Using tags}\label{tags}
Tags are manually entered labels that can be used to categorize CLs.
These may be supported by tools or just used by team convention.
For example:
\begin{itemize}
\tightlist
\item
``{[}tag{]}''
\item
``{[}a longer tag{]}''
\item
``\#tag''
\item
``tag:''
\end{itemize}
Using tags is optional.
When adding tags, consider whether they should be in the
\hyperref[informative]{body} of the CL description or the
\hyperref[first-line]{first line}. Limit the usage of tags in the first
line, as this can obscure the content.
Examples with and without tags:
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{// Tags are okay in the first line if kept short.}
\NormalTok{[banana] Peel the banana before eating.}
\NormalTok{// Tags can be inlined in content.}
\NormalTok{Peel the \#banana before eating.}
\NormalTok{// Tags are optional.}
\NormalTok{Peel the banana before eating.}
\NormalTok{// Multiple tags are acceptable if kept short.}
\NormalTok{\#banana \#apple: Assemble a fruit basket.}
\NormalTok{// Tags can go anywhere in the CL description.}
\NormalTok{\textgreater{} Assemble a fruit basket.}
\NormalTok{\textgreater{}}
\NormalTok{\textgreater{} \#banana \#apple}
\end{Highlighting}
\end{Shaded}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{// Too many tags (or tags that are too long) overwhelm the first line.}
\NormalTok{//}
\NormalTok{// Instead, consider whether the tags can be moved into the description body}
\NormalTok{// and/or shortened.}
\NormalTok{[banana peeler factory factory][apple picking service] Assemble a fruit basket.}
\end{Highlighting}
\end{Shaded}
\subsection{Generated CL descriptions}\label{generated-cl-descriptions}
Some CLs are generated by tools. Whenever possible, their descriptions
should also follow the advice here. That is, their first line should be
short, focused, and stand alone, and the CL description body should
include informative details that help reviewers and future code
searchers understand each CL's effect.
\subsection{Review the description before submitting the
CL}\label{review-the-description-before-submitting-the-cl}
CLs can undergo significant change during review. It can be worthwhile
to review a CL description before submitting the CL, to ensure that the
description still reflects what the CL does.
Next: \href{small-cls.md}{Small CLs}
\section{How to handle reviewer
comments}\label{how-to-handle-reviewer-comments}
When you've sent a CL out for review, it's likely that your reviewer
will respond with several comments on your CL. Here are some useful
things to know about handling reviewer comments.
\subsection{Don't Take it Personally}\label{personal}
The goal of review is to maintain the quality of our codebase and our
products. When a reviewer provides a critique of your code, think of it
as their attempt to help you, the codebase, and Google, rather than as a
personal attack on you or your abilities.
Sometimes reviewers feel frustrated and they express that frustration in
their comments. This isn't a good practice for reviewers, but as a
developer you should be prepared for this. Ask yourself, ``What is the
constructive thing that the reviewer is trying to communicate to me?''
and then operate as though that's what they actually said.
\textbf{Never respond in anger to code review comments.} That is a
serious breach of professional etiquette that will live forever in the
code review tool. If you are too angry or annoyed to respond kindly,
then walk away from your computer for a while, or work on something else
until you feel calm enough to reply politely.
In general, if a reviewer isn't providing feedback in a way that's
constructive and polite, explain this to them in person. If you can't
talk to them in person or on a video call, then send them a private
email. Explain to them in a kind way what you don't like and what you'd
like them to do differently. If they also respond in a non-constructive
way to this private discussion, or it doesn't have the intended effect,
then escalate to your manager as appropriate.
\subsection{Fix the Code}\label{code}
If a reviewer says that they don't understand something in your code,
your first response should be to clarify the code itself. If the code
can't be clarified, add a code comment that explains why the code is
there. If a comment seems pointless, only then should your response be
an explanation in the code review tool.
If a reviewer didn't understand some piece of your code, it's likely
other future readers of the code won't understand either. Writing a
response in the code review tool doesn't help future code readers, but
clarifying your code or adding code comments does help them.
\subsection{Think Collaboratively}\label{think}
Writing a CL can take a lot of work. It's often really satisfying to
finally send one out for review, feel like it's done, and be pretty sure
that no further work is needed. It can be frustrating to receive
comments asking for changes, especially if you don't agree with them.
At times like this, take a moment to step back and consider if the
reviewer is providing valuable feedback that will help the codebase and
Google. Your first question to yourself should always be, ``Do I
understand what the reviewer is asking for?''
If you can't answer that question, ask the reviewer for clarification.
And then, if you understand the comments but disagree with them, it's
important to think collaboratively, not combatively or defensively:
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{Bad: "No, I\textquotesingle{}m not going to do that."}
\end{Highlighting}
\end{Shaded}
\begin{Shaded}
\begin{Highlighting}[]
\NormalTok{Good: "I went with X because of [these pros/cons] with [these tradeoffs]}
\NormalTok{My understanding is that using Y would be worse because of [these reasons].}
\NormalTok{Are you suggesting that Y better serves the original tradeoffs, that we should}
\NormalTok{weigh the tradeoffs differently, or something else?"}
\end{Highlighting}
\end{Shaded}
Remember,
\textbf{\href{https://chromium.googlesource.com/chromium/src/+/master/docs/cr_respect.md}{courtesy
and respect} should always be a first priority}. If you disagree with
the reviewer, find ways to collaborate: ask for clarifications, discuss
pros/cons, and provide explanations of why your method of doing things
is better for the codebase, users, and/or Google.
Sometimes, you might know something about the users, codebase, or CL
that the reviewer doesn't know. \hyperref[code]{Fix the code} where
appropriate, and engage your reviewer in discussion, including giving
them more context. Usually you can come to some consensus between
yourself and the reviewer based on technical facts.
\subsection{Resolving Conflicts}\label{conflicts}
Your first step in resolving conflicts should always be to try to come
to consensus with your reviewer. If you can't achieve consensus, see
\href{../reviewer/standard.md}{The Standard of Code Review}, which gives
principles to follow in such a situation.
\section{The CL author's guide to getting through code
review}\label{the-cl-authors-guide-to-getting-through-code-review}
The pages in this section contain best practices for developers going
through code review. These guidelines should help you get through
reviews faster and with higher-quality results. You don't have to read
them all, but they are intended to apply to every Google developer, and
many people have found it helpful to read the whole set.
\begin{itemize}
\tightlist
\item
\href{cl-descriptions.md}{Writing Good CL Descriptions}
\item
\href{small-cls.md}{Small CLs}
\item
\href{handling-comments.md}{How to Handle Reviewer Comments}
\end{itemize}
See also \href{../reviewer/index.md}{How to Do a Code Review}, which
gives detailed guidance for code reviewers.
\section{Small CLs}\label{small-cls}
\subsection{Why Write Small CLs?}\label{why}
Small, simple CLs are:
\begin{itemize}
\tightlist
\item
\textbf{Reviewed more quickly.} It's easier for a reviewer to find
five minutes several times to review small CLs than to set aside a 30
minute block to review one large CL.
\item
\textbf{Reviewed more thoroughly.} With large changes, reviewers and
authors tend to get frustrated by large volumes of detailed commentary
shifting back and forth---sometimes to the point where important
points get missed or dropped.
\item
\textbf{Less likely to introduce bugs.} Since you're making fewer
changes, it's easier for you and your reviewer to reason effectively
about the impact of the CL and see if a bug has been introduced.
\item
\textbf{Less wasted work if they are rejected.} If you write a huge CL
and then your reviewer says that the overall direction is wrong,
you've wasted a lot of work.
\item
\textbf{Easier to merge.} Working on a large CL takes a long time, so
you will have lots of conflicts when you merge, and you will have to
merge frequently.
\item
\textbf{Easier to design well.} It's a lot easier to polish the design
and code health of a small change than it is to refine all the details
of a large change.
\item
\textbf{Less blocking on reviews.} Sending self-contained portions of
your overall change allows you to continue coding while you wait for
your current CL in review.
\item
\textbf{Simpler to roll back.} A large CL will more likely touch files
that get updated between the initial CL submission and a rollback CL,
complicating the rollback (the intermediate CLs will probably need to
be rolled back too).
\end{itemize}
Note that \textbf{reviewers have discretion to reject your change
outright for the sole reason of it being too large.} Usually they will
thank you for your contribution but request that you somehow make it
into a series of smaller changes. It can be a lot of work to split up a
change after you've already written it, or require lots of time arguing
about why the reviewer should accept your large change. It's easier to
just write small CLs in the first place.
\subsection{What is Small?}\label{what-is-small}
In general, the right size for a CL is \textbf{one self-contained
change}. This means that:
\begin{itemize}
\tightlist
\item
The CL makes a minimal change that addresses \textbf{just one thing}.
This is usually just one part of a feature, rather than a whole
feature at once. In general it's better to err on the side of writing
CLs that are too small vs. CLs that are too large. Work with your
reviewer to find out what an acceptable size is.
\item
The CL should \hyperref[test_code]{include related test code}.
\item
Everything the reviewer needs to understand about the CL (except
future development) is in the CL, the CL's description, the existing
codebase, or a CL they've already reviewed.
\item
The system will continue to work well for its users and for the
developers after the CL is checked in.
\item
The CL is not so small that its implications are difficult to
understand. If you add a new API, you should include a usage of the
API in the same CL so that reviewers can better understand how the API
will be used. This also prevents checking in unused APIs.
\end{itemize}
There are no hard and fast rules about how large is ``too large.'' 100
lines is usually a reasonable size for a CL, and 1000 lines is usually
too large, but it's up to the judgment of your reviewer. The number of
files that a change is spread across also affects its ``size.'' A
200-line change in one file might be okay, but spread across 50 files it
would usually be too large.
Keep in mind that although you have been intimately involved with your
code from the moment you started to write it, the reviewer often has no
context. What seems like an acceptably-sized CL to you might be
overwhelming to your reviewer. When in doubt, write CLs that are smaller
than you think you need to write. Reviewers rarely complain about
getting CLs that are too small.
\subsection{When are Large CLs Okay?}\label{large-okay}
There are a few situations in which large changes aren't as bad:
\begin{itemize}
\tightlist
\item
You can usually count deletion of an entire file as being just one
line of change, because it doesn't take the reviewer very long to
review.
\item
Sometimes a large CL has been generated by an automatic refactoring
tool that you trust completely, and the reviewer's job is just to
verify and say that they really do want the change. These CLs can be
larger, although some of the caveats from above (such as merging and
testing) still apply.
\end{itemize}
\subsection{Writing Small CLs Efficiently}\label{efficiently}
If you write a small CL and then you wait for your reviewer to approve
it before you write your next CL, then you're going to waste a lot of
time. So you want to find some way to work that won't block you while
you're waiting for review. This could involve having multiple projects
to work on simultaneously, finding reviewers who agree to be immediately
available, doing in-person reviews, pair programming, or splitting your
CLs in a way that allows you to continue working immediately.
\subsection{Splitting CLs}\label{splitting}
When starting work that will have multiple CLs with potential
dependencies among each other, it's often useful to think about how to
split and organize those CLs at a high level before diving into coding.
Besides making things easier for you as an author to manage and organize
your CLs, it also makes things easier for your code reviewers, which in
turn makes your code reviews more efficient.
Here are some strategies for splitting work into different CLs.
\subsubsection{Stacking Multiple Changes on Top of Each
Other}\label{stacking}
One way to split up a CL without blocking yourself is to write one small
CL, send it off for review, and then immediately start writing another
CL \emph{based} on the first CL. Most version control systems allow you
to do this somehow.
\subsubsection{Splitting by Files}\label{splitting-files}
Another way to split up a CL is by groupings of files that will require
different reviewers but are otherwise self-contained changes.
For example: you send off one CL for modifications to a protocol buffer
and another CL for changes to the code that uses that proto. You have to
submit the proto CL before the code CL, but they can both be reviewed
simultaneously. If you do this, you might want to inform both sets of
reviewers about the other CL that you wrote, so that they have context
for your changes.
Another example: you send one CL for a code change and another for the
configuration or experiment that uses that code; this is easier to roll
back too, if necessary, as configuration/experiment files are sometimes
pushed to production faster than code changes.
\subsubsection{Splitting Horizontally}\label{splitting-horizontally}
Consider creating shared code or stubs that help isolate changes between
layers of the tech stack. This not only helps expedite development but
also encourages abstraction between layers.
For example: You created a calculator app with client, API, service, and
data model layers. A shared proto signature can abstract the service and
data model layers from each other. Similarly, an API stub can split the
implementation of client code from service code and enable them to move
forward independently. Similar ideas can also be applied to more
granular function or class level abstractions.
\subsubsection{Splitting Vertically}\label{splitting-vertically}
Orthogonal to the layered, horizontal approach, you can instead break
down your code into smaller, full-stack, vertical features. Each of
these features can be independent parallel implementation tracks. This
enables some tracks to move forward while other tracks are awaiting
review or feedback.
Back to our calculator example from
\hyperref[splitting-horizontally]{Splitting Horizontally}. You now want
to support new operators, like multiplication and division. You could
split this up by implementing multiplication and division as separate
verticals or sub-features, even though they may have some overlap such
as shared button styling or shared validation logic.
\subsubsection{Splitting Horizontally \&
Vertically}\label{splitting-grid}
To take this a step further, you could combine these approaches and
chart out an implementation plan like this, where each cell is its own
standalone CL. Starting from the model (at the bottom) and working up to
the client:
\begin{longtable}[]{@{}
>{\raggedright\arraybackslash}p{(\columnwidth - 4\tabcolsep) * \real{0.1111}}
>{\raggedright\arraybackslash}p{(\columnwidth - 4\tabcolsep) * \real{0.3968}}
>{\raggedright\arraybackslash}p{(\columnwidth - 4\tabcolsep) * \real{0.4921}}@{}}
\caption{: : multiplication : \textbar{} Model \textbar{} Add proto
definition \textbar{} Add proto definition \textbar{}}\tabularnewline
\toprule\noalign{}
\begin{minipage}[b]{\linewidth}\raggedright
Layer
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
Feature: Multiplication
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
Feature: Division
\end{minipage} \\
\midrule\noalign{}
\endfirsthead
\toprule\noalign{}
\begin{minipage}[b]{\linewidth}\raggedright
Layer
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
Feature: Multiplication
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
Feature: Division
\end{minipage} \\
\midrule\noalign{}
\endhead
\bottomrule\noalign{}
\endlastfoot
Client & Add button & Add button \\
API & Add endpoint & Add endpoint \\
Service & Implement transformations & Share transformation logic with \\
\end{longtable}
\subsection{Separate Out Refactorings}\label{refactoring}
It's usually best to do refactorings in a separate CL from feature
changes or bug fixes. For example, moving and renaming a class should be
in a different CL from fixing a bug in that class. It is much easier for
reviewers to understand the changes introduced by each CL when they are
separate.
Small cleanups such as fixing a local variable name can be included
inside of a feature change or bug fix CL, though. It's up to the
judgment of developers and reviewers to decide when a refactoring is so
large that it will make the review more difficult if included in your
current CL.
\subsection{Keep related test code in the same CL}\label{test-code}
CLs should include related test code. Remember that
\hyperref[what-is-small]{smallness} here refers the conceptual idea that
the CL should be focused and is not a simplistic function on line count.
Tests are expected for all Google changes.
A CL that adds or changes logic should be accompanied by new or updated
tests for the new behavior. Pure refactoring CLs (that aren't intended
to change behavior) should also be covered by tests; ideally, these
tests already exist, but if they don't, you should add them.
\emph{Independent} test modifications can go into separate CLs first,
similar to the \hyperref[refactoring]{refactorings guidelines}. That
includes:
\begin{itemize}
\tightlist
\item
Validating pre-existing, submitted code with new tests.
\begin{itemize}
\tightlist
\item
Ensures that important logic is covered by tests.
\item
Increases confidence in subsequent refactorings on affected code.
For example, if you want to refactor code that isn't already covered
by tests, submitting test CLs \emph{before} submitting refactoring
CLs can validate that the tested behavior is unchanged before and
after the refactoring.
\end{itemize}
\item
Refactoring the test code (e.g.~introduce helper functions).
\item
Introducing larger test framework code (e.g.~an integration test).
\end{itemize}
\subsection{Don't Break the Build}\label{break}
If you have several CLs that depend on each other, you need to find a
way to make sure the whole system keeps working after each CL is
submitted. Otherwise you might break the build for all your fellow
developers for a few minutes between your CL submissions (or even longer
if something goes wrong unexpectedly with your later CL submissions).
\subsection{Can't Make it Small Enough}\label{cant}
Sometimes you will encounter situations where it seems like your CL
\emph{has} to be large. This is very rarely true. Authors who practice
writing small CLs can almost always find a way to decompose
functionality into a series of small changes.
Before writing a large CL, consider whether preceding it with a
refactoring-only CL could pave the way for a cleaner implementation.
Talk to your teammates and see if anybody has thoughts on how to
implement the functionality in small CLs instead.
If all of these options fail (which should be extremely rare) then get
consent from your reviewers in advance to review a large CL, so they are
warned about what is coming. In this situation, expect to be going
through the review process for a long time, be vigilant about not
introducing bugs, and be extra diligent about writing tests.
Next: \href{handling-comments.md}{How to Handle Reviewer Comments}
\section{Emergencies}\label{emergencies}
Sometimes there are emergency CLs that must pass through the entire code
review process as quickly as possible.
\subsection{What Is An Emergency?}\label{what}
An emergency CL would be a \textbf{small} change that: allows a major
launch to continue instead of rolling back, fixes a bug significantly
affecting users in production, handles a pressing legal issue, closes a
major security hole, etc.
In emergencies we really do care about the speed of the entire code
review process, not just the \href{reviewer/speed.md}{speed of
response}. In this case \emph{only}, the reviewer should care more about
the speed of the review and the correctness of the code (does it
actually resolve the emergency?) than anything else. Also (perhaps
obviously) such reviews should take priority over all other code
reviews, when they come up.
However, after the emergency is resolved you should look over the
emergency CLs again and give them a \href{reviewer/looking-for.md}{more
thorough review}.
\subsection{What Is NOT An Emergency?}\label{not}
To be clear, the following cases are \emph{not} an emergency:
\begin{itemize}
\tightlist
\item
Wanting to launch this week rather than next week (unless there is
some actual \hyperref[deadlines]{hard deadline} for launch such as a
partner agreement).
\item
The developer has worked on a feature for a very long time and they
really want to get the CL in.
\item
The reviewers are all in another timezone where it is currently
nighttime or they are away on an off-site.
\item
It is the end of the day on a Friday and it would just be great to get
this CL in before the developer leaves for the weekend.
\item
A manager says that this review has to be complete and the CL checked
in today because of a \hyperref[deadlines]{soft (not hard) deadline}.
\item
Rolling back a CL that is causing test failures or build breakages.
\end{itemize}
And so on.
\subsection{What Is a Hard Deadline?}\label{deadlines}
A hard deadline is one where \textbf{something disastrous would happen}
if you miss it. For example:
\begin{itemize}
\tightlist
\item
Submitting your CL by a certain date is necessary for a contractual
obligation.
\item
Your product will completely fail in the marketplace if not released
by a certain date.
\item
Some hardware manufacturers only ship new hardware once a year. If you
miss the deadline to submit code to them, that could be disastrous,
depending on what type of code you're trying to ship.
\end{itemize}
Delaying a release for a week is not disastrous. Missing an important
conference might be disastrous, but often is not.
Most deadlines are soft deadlines, not hard deadlines. They represent a
desire for a feature to be done by a certain time. They are important,
but you shouldn't be sacrificing code health to make them.
If you have a long release cycle (several weeks) it can be tempting to
sacrifice code review quality to get a feature in before the next cycle.
However, this pattern, if repeated, is a common way for projects to
build up overwhelming technical debt. If developers are routinely
submitting CLs near the end of the cycle that ``must get in'' with only
superficial review, then the team should modify its process so that
large feature changes happen early in the cycle and have enough time for
good review.
\subsection{Introduction}\label{intro}
A code review is a process where someone other than the author(s) of a
piece of code examines that code.
At Google, we use code review to maintain the quality of our code and
products.
This documentation is the canonical description of Google's code review
processes and policies.
This page is an overview of our code review process. There are two other
large documents that are a part of this guide:
\begin{itemize}
\tightlist
\item
\textbf{\href{reviewer/index.md}{How To Do A Code Review}}: A detailed
guide for code reviewers.
\item
\textbf{\href{developer/index.md}{The CL Author's Guide}}: A detailed
guide for developers whose CLs are going through review.
\end{itemize}
\subsection{What Do Code Reviewers Look For?}\label{look_for}
Code reviews should look at:
\begin{itemize}
\tightlist
\item
\textbf{Design}: Is the code well-designed and appropriate for your
system?
\item
\textbf{Functionality}: Does the code behave as the author likely
intended? Is the way the code behaves good for its users?
\item
\textbf{Complexity}: Could the code be made simpler? Would another
developer be able to easily understand and use this code when they
come across it in the future?