github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2014/readability.slide (about)

     1  When in Go, do as Gophers do
     2  Go Conference 2014 autumn
     3  30 Nov 2014
     4  
     5  Fumitoshi Ukai
     6  Google Software Engineer - Chrome Infra team
     7  ukai@google.com
     8  https://plus.google.com/+FumitoshiUkai
     9  @fumitoshi_ukai
    10  
    11  * Go Readability Approver
    12  
    13  A team to review Go readability.
    14  
    15  - help to learn idiomatic Go though code review
    16  - review code of projects that are not main project of the reviewer
    17  
    18  - [[http://blogger.ukai.org/2013/12/code-readability.html][I joined the team about a year ago]] as 20% time, and reviewed ~200 CLs
    19  - For now, I'm reviewing at most 3 CLs per day, 12 CLs per week.
    20  
    21  .image readability/project.png
    22  .caption _Gopher_ by [[http://www.reneefrench.com][Renée French]]
    23  
    24  * What is Readability skill?
    25  
    26  Literacy of a programming language.
    27  
    28  A skill to read or write *idiomatic* code.
    29  
    30  Each programming language has its own preferred style.
    31  In C++, each project chooses a preferred style.
    32  
    33  - [[http://google-styleguide.googlecode.com/svn/trunk/cppguide.html][google]] ([[http://www.chromium.org/developers/coding-style][chromium]]), [[https://www.webkit.org/coding/coding-style.html][webkit]] ([[http://www.chromium.org/blink/coding-style][blink]])
    34  
    35  Don't write Go code as you write code in C++/Java/Python.
    36  Write Go code as Gophers write code.
    37  
    38  * Go code should ...
    39  
    40  - be articulate, concise.
    41  - provide a simple API.
    42  - have precise comments.
    43  - be readable, top-down code.
    44  
    45  _"_Want_to_understand_something_in_google_servers?_Read_the_Go_implementation!_"_
    46  
    47  .caption by some Googler
    48  
    49  .image readability/pkg.png
    50  .caption _Gopher_ by [[http://www.reneefrench.com][Renée French]]
    51  
    52  
    53  * Good tools
    54  
    55  [[https://golang.org/cmd/gofmt/][go fmt]] - format Go programs.
    56  [[https://godoc.org/golang.org/x/tools/cmd/vet][go vet]] - report suspicious code
    57  [[https://github.com/golang/lint][golint]] - report coding style errors.
    58  [[http://blog.golang.org/godoc-documenting-go-code][godoc]] - browse documenation
    59  
    60  # Go code is easy to read for tools too.
    61  
    62  * Tools are not enough
    63  
    64  # Developer doesn't read code the same as tools.
    65  # Programs(compiler, etc) will read code if its syntax is ok.
    66  # Tools are not enough, have false-positive/false-negative.
    67  # Needs human judgments.
    68  
    69  Readable code == easy to recognize, less burden for brain.
    70  Both writer and reader should have readability skills.
    71  Go is very simple ([[https://golang.org/ref/spec][lang spec]] is about 50 pages)
    72  
    73  .image readability/gophers5th.jpg
    74  .caption _Gopher_ by [[http://www.reneefrench.com][Renée French]]
    75  
    76  * Readability Reviews
    77  
    78  - Any mistakes/bugs?
    79  - Layout?
    80  - Simple code flow?
    81  - Simple API?
    82  
    83  .image readability/gopher-ok-no.png
    84  .caption _Gopher_ by [[http://www.reneefrench.com][Renée French]], and [[https://github.com/tenntenn/gopher-stickers/][tenntenn]]
    85  
    86  * mistakes/bugs
    87  
    88  * error check
    89  
    90  original code
    91  
    92  .code readability/err_regexp_bad.go
    93  
    94  revised
    95  
    96  .code readability/err_regexp_good.go
    97  
    98  - Check error with [[https://golang.org/pkg/regexp/#MustCompile][regexp.MustCompile]].
    99  - Must should be used only in [[http://golang.org/ref/spec#Package_initialization][initialization]] (package `var` or `init()`).
   100  
   101  - [[http://golang.org/ref/spec#String_literals][Raw string literal]] makes it easy to read regexp.
   102  
   103  * error check: original code
   104  
   105  .code readability/err_close_write_bad.go
   106  
   107  * error check: revised
   108  
   109  .code readability/err_close_write_good.go
   110  
   111  - Check error of Close for write.
   112  - No need to use defer, when it's simpler.
   113  
   114  * in-band error: original code
   115  
   116  .code readability/in-band-error-client.go
   117  
   118  .code readability/in-band-error.go
   119  
   120  * return value and error: revised
   121  
   122  .code readability/val-and-error.go
   123  
   124  [[http://golang.org/doc/effective_go.html#multiple-returns][Return error as error, not as some value]]
   125  
   126  * error design
   127  
   128  If client doesn't need to distinguish errors, e.g. ok with `err` `!=` `nil` check only.
   129  
   130  	fmt.Errorf("error in %s", val) or errors.New("error msg")
   131  
   132  If client wants to distinguish several errors by error code.
   133  
   134  	var (
   135  	  ErrInternal   = errors.New("foo: inetrnal error")
   136  	  ErrBadRequest = errors.New("foo: bad request")
   137  	)
   138  
   139  If you want to put detailed information in error.
   140  
   141  	type FooError struct { /* fields of error information */ }
   142  	func (e *FooError) Error() string { return /* error message */ }
   143  
   144  	&FooError{ /* set error data */ }
   145  
   146  Don't use `panic`.
   147  But when you do, use it only within the package, and [[http://golang.org/doc/effective_go.html#recover][return error with catching it by recover]].
   148  
   149  * nil error
   150  
   151  .code readability/nil_error.go
   152  
   153  [[https://golang.org/doc/faq#nil_error][FAQ: Why is my nil error value not equal to nil?]]
   154  
   155  [[http://blog.golang.org/laws-of-reflection][interface has 2 data]] (type and value). interface value is nil == both are nil.
   156  
   157  * embed interface: original code
   158  
   159  .code readability/implement-interface-bad.go
   160  
   161  - `scan.Writer` is an interface.
   162  - `ColumnWriter` will have methods of the `scan.Writer` interface (i.e. `ColumnWriter` implements the `scan.Writer` interface), but ...
   163  
   164  * check interface implementation: revised
   165  
   166  .code readability/implement-interface-good.go
   167  
   168  - The original author wanted to check `ColumnWriter` [[http://golang.org/doc/effective_go.html#blank_implements][implements]] the `scan.Writer` interface.
   169  
   170  * embed interface
   171  
   172  If a struct doesn't have a method of a interface explicitly, the interface is embedded in the struct, and you didn't set the interface field to a concrete value (i.e. the interface field value is nil), the method call will panic.
   173  
   174  .code readability/nil_interface_en.go
   175  
   176  It would be useful in a test when you want to implement only a subset of methods in the huge interface.
   177  
   178  * Readable layout
   179  
   180  * layout of fields in struct: original code
   181  
   182  .code readability/struct-field-bad.go
   183  
   184  * layout of fields in struct: revised
   185  
   186  .code readability/struct-field-good.go
   187  
   188  - Organize fields in groups, with blank lines between them.
   189  - Put [[https://golang.org/pkg/sync/#Mutex][sync.Mutex]] in top of a block of fields that the mutex protects.
   190  
   191  * Long line
   192  
   193  .code readability/long-line-fold.go
   194  
   195  * Merge into one line
   196  
   197  .code readability/long-line-nofold.go
   198  
   199  - [[https://golang.org/s/comments#Line_Length][No rigid line length limit]]
   200  - though, can't we make it shorter?
   201  
   202  * Choose concise names
   203  
   204  [[https://golang.org/s/comments#Variable_Names][Choose good name in the context]]
   205  
   206  - Long names are not always better than short names.
   207  
   208  Short and accurate names.
   209  
   210  - [[https://golang.org/s/comments#Package_Names][SamplingServer in sampling package is stutter]]. Name `Server`, which clients will write as `sampling.Server`.
   211  - Use [[https://golang.org/s/comments#Receiver_Names][one or two letters for receiver names]].
   212  - Use short names for parameters since type name will give some information.
   213  - Use descriptive names for basic types, though.
   214  - Use short names for local variables: prefer `i` to `index`, `r` to `reader`.
   215  - Short names should be fine if function is not long.
   216  
   217  * Revised one line version
   218  
   219  .code readability/long-line-short.go
   220  
   221  * top-down code
   222  
   223  * conditional branch
   224  
   225  - [[https://golang.org/s/comments#Indent_Error_Flow][Keep the normal code path at a minimal indentation.]]
   226  
   227  original code
   228  
   229  .code readability/if-else-bad.go
   230  
   231  revised
   232  
   233  .code readability/if-else-good.go
   234  
   235  * conditional branch (2): original code
   236  
   237  .code readability/resthandler.go
   238  
   239  * conditional branch (2): revised
   240  
   241  .code readability/resthandler-fix2.go
   242  
   243  - factor out function.
   244  
   245  * conditional branch (3): original code
   246  
   247  .code readability/if-switch-bad.go
   248  
   249  * conditional branch (3): revised
   250  
   251  .code readability/if-switch-good.go
   252  
   253  - use [[http://golang.org/ref/spec#Switch_statements][switch]]
   254  
   255  * Simpler code
   256  
   257  * time.Duration
   258  
   259  Use [[https://golang.org/pkg/time/#Duration][time.Duration]] ([[https://golang.org/pkg/flag/#Duration][flag.Duration]]) rather than `int` or `float` to represent time duration.
   260  
   261  original code
   262  
   263  .code readability/time_duration_bad.go
   264  .code readability/time_duration_bad1.go
   265  .code readability/time_duration_bad2.go
   266  
   267  revised
   268  
   269  .code readability/time_duration_good.go
   270  
   271  - Don't write unnecessary type conversion.
   272  - Since [[http://blog.golang.org/constants][const is untyped]], no need to convert 30 to `time.Duration`.
   273  - Don't write unnecessary comments.
   274  
   275  * sync.Mutex and sync.Cond: original code
   276  
   277  .code readability/close-cond-bad.go
   278  
   279  * chan: revised
   280  
   281  .code readability/close-cond-good.go
   282  
   283  - You could use [[http://golang.org/ref/spec#Channel_types][chan]], instead of [[https://golang.org/pkg/sync/#Mutex][sync.Mutex]] and [[https://golang.org/pkg/sync/#Cond][sync.Cond]].
   284  
   285  * reflect: original code
   286  
   287  .code readability/reflect-bad.go
   288  
   289  * without reflect: revised
   290  
   291  .code readability/reflect-good.go
   292  
   293  - Don't use [[https://golang.org/pkg/reflect/][reflect]], if you know the type at compilation time.
   294  
   295  * Test
   296  
   297  * Test code
   298  
   299  .code readability/test-pattern_en.go
   300  
   301  - [[https://golang.org/s/comments#Useful_Test_Failures][Have helpful test failure messages]]
   302  - Don't create yet-another assert function. Use existing programming language features.
   303  - Write [[https://golang.org/pkg/testing/#hdr-Examples][an example test]] rather than writing how to use API in a doc comment.
   304  
   305  .code readability/example_test.go
   306  
   307  * Comment
   308  
   309  * Comment
   310  
   311  [[https://golang.org/s/comments#Package_Comments][Write package comment.]]  Write command comment in main package.
   312  [[https://golang.org/s/comments#Doc_Comments][Write comments on exported names.]]
   313  [[https://golang.org/s/comments#Comment_Sentences][Doc comment should be a complete sentence that starts with the name being declared.]]
   314  
   315  	// Package math provides basic constants and mathematical functions.
   316  	package math
   317  
   318  	// A Request represents a request to run a command.
   319  	type Request struct { ..
   320  
   321  	// Encode writes the JSON encoding of req to w.
   322  	func Encode(w io.Writer, req *Request) {
   323  
   324  Browse with [[http://blog.golang.org/godoc-documenting-go-code][godoc]]
   325  
   326  	$ godoc bytes Buffer
   327  
   328  	$ godoc -http=:6060  # http://localhost:6060/pkg
   329  
   330  If you feel comments are unclear or hard to write concisely, reconsider your API design.
   331  
   332  * API design
   333  
   334  Important to choose a good package name.
   335  
   336  - e.g. package `util` is not good name, since most packages are utilities of something.
   337  # split it into smaller packages, or merge it in bigger package, or wrong package boundary.
   338  
   339  Make API simple.
   340  
   341  - [[http://golang.org/doc/effective_go.html#multiple-returns][Use multiple returns]]. Don't use pointers as output parameters.
   342  - Don't use pointer to slice, map, chan or interface.
   343  - [[http://golang.org/doc/effective_go.html#multiple-returns][Return error as error]]: [[https://golang.org/s/comments#Don't_Panic][don't panic]]
   344  - Implement common interfaces ([[https://golang.org/pkg/fmt/#Stringer][fmt.Stringer]], [[https://golang.org/pkg/io/#Reader][io.Reader]] and so on) if they match your code.
   345  - Use interfaces for parameters. They makes it easier to test. e.g.: If a function reads from a file, use [[https://golang.org/pkg/io/#Reader][io.Reader]] as a parameter instead of [[https://golang.org/pkg/os/#File][*os.File]].
   346  - Prefer synchronous API to async API: refrain from using chan across package boundary.
   347  - Clients can easily run synchronous API concurrently with goroutine and chan.
   348  
   349  * To write readable code
   350  
   351  * Code is communication
   352  
   353  Be articulate:
   354  
   355  - Choose good names.
   356  - Design simple APIs.
   357  - Write precise documentation.
   358  - Don't be too complicated.
   359  
   360  .image readability/talks.png
   361  .caption _Gopher_ by [[http://www.reneefrench.com][Renée French]]
   362  
   363  * When you write code
   364  
   365  Keep in mind
   366  
   367  - Articulate, concise.
   368  - Provide simple API.
   369  - Have precise comment.
   370  - Readable, top-down code.
   371  
   372  * References
   373  
   374  - Effective Go: [[https://golang.org/doc/effective_go.html][https://golang.org/doc/effective_go.html]]
   375  - standard package:  [[https://golang.org/pkg/][https://golang.org/pkg/]]
   376  - Code Review Comments:  [[https://golang.org/s/comments][https://golang.org/s/comments]]
   377  
   378  - Go for gophers: [[http://talks.golang.org/2014/go4gophers.slide][http://talks.golang.org/2014/go4gophers.slide]]
   379  - What's in a name? [[http://talks.golang.org/2014/names.slide][http://talks.golang.org/2014/names.slide]]
   380  - Organizing Go code: [[http://talks.golang.org/2014/organizeio.slide][http://talks.golang.org/2014/organizeio.slide]]
   381  
   382  .image readability/ref.png
   383  .caption _Gopher_ by [[http://www.reneefrench.com][Renée French]]