Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go Package & Design

chinglin
September 15, 2017

Go Package & Design

chinglin

September 15, 2017
Tweet

More Decks by chinglin

Other Decks in Programming

Transcript

  1. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 3/49 How does Gophers

    do di erently ? We've heard of: When you write go, do as the Gophers do. github.com/go-proverbs/go-proverbs.github.io/issues/21#issuecomment-304559209 (https://github.com/go-proverbs/go-proverbs.github.io/issues/21#issuecomment-304559209) The question is how and why ?
  2. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 4/49 What is go

    package ? A package in Go is simply a directory/folder with one or more .go les inside of it. All Go code lives in a package and a package is the entry point to access Go code. Understanding and establishing good practices around packages is important to write e ective Go code.
  3. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 5/49 Why should we

    care go package that much ? Package is also the key to: Abstract Design Reusability Composability And perhaps productivity. Gophers by golang.org/doc/gopher (https://golang.org/doc/gopher)
  4. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 8/49 Use multiple les

    - doc.go // package documentation - headers.go // HTTP headers types and code - cookies.go // HTTP cookies types and code - http.go // HTTP client implementation, request and response types, etc. Do not overuse it, restrict it by responsibility ( single domain concept ).
  5. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 9/49 Organize by responsibility

    A common practise from other languages is to organize types together in a package called models or types. package models // DON'T DO IT!!! // User represents a user in the system. type User struct {...} A User type should live in a service-layer package. package mngtservice // User represents a user in the system. type User struct {...} func UsersByQuery(ctx context.Context, q *Query) ([]*User, *Iterator, error) func UserIDByEmail(ctx context.Context, email string) (int64, error) In Go, we organize code by their functional responsibilities.
  6. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 10/49 Other package organizing

    guidelines Keep types close Optimize for godoc Provide examples to ll the gaps Don’t export from main
  7. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 12/49 Good package names

    make code better A package's name provides context for its contents, making it easier for clients to understand what the package is for and how to use it. The name also helps package maintainers determine what does and does not belong in the package as it evolves. Well-named packages make it easier to nd the code you need.
  8. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 13/49 Short, but representative

    names Package names should be short, but should be unique and representative. Users of the package should be able to grasp its purpose from just the package’s name. Avoid overly broad package names like “common” and “util”. import "pkgs.org/common" // DON'T!!! If you cannot avoid a bad name, it is very likely that there is a problem with your overall structure and code organization.
  9. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 14/49 Package name convention

    Packages are given lower case, single-word names; there should be no need for underscores or mixedCaps The package name is the base name of its source directory ( eg. base64 ) Use package name to avoid stutter ( eg. bu o.Reader, not bu o.BufReader ) A helpful doc comment can often be more valuable than an extra long name.
  10. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 15/49 Other package naming

    guidelines Lowercase only Clean import paths No plurals package httputils // DON'T DO IT, USE SINGULAR FORM!! Renames should follow the same rules Enforce vanity URLs bonus slide: talks.golang.org/2014/names.slide#1 (https://talks.golang.org/2014/names.slide#1)
  11. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 16/49 Bad package names

    Avoid meaningless package names Break up generic packages Don't use a single package for all your APIs Avoid unnecessary package name collisions
  12. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 18/49 Always document the

    package Package documentation is a top-level comment immediately preceding the package clause. // Package ioutil implements some I/O utility functions. package ioutil // Command gops lists all the processes running on your system. package main // Sample helloworld demonstrates how to use x. package main Sometimes, package docs can get very lengthy, specially when they provide details of usage and guidelines. If so, move the package's doc to a doc.go le.
  13. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 19/49 What user want

    to see in the package doc A helpful doc explaining what and how ( extra why for the source code ) Package examples to ll the gaps
  14. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 21/49 Package layout guideline

    Most of the time follow "Clean import paths". ( eg. github.com/upspin/upspin (https://github.com/upspin/upspin) ) For projects that provide both binaries and libraries, or combine Go code with other, non-Go assets. Put library code under a pkg/ subdirectory Put binaries under a cmd/ subdirectory
  15. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 22/49 Package layout demo

    github.com/peterbourgon/foo/ circle.yml Dockerfile cmd/ foosrv/ main.go foocli/ main.go pkg/ fs/ fs.go fs_test.go mock.go mock_test.go merge/ merge.go merge_test.go api/ api.go api_test.go
  16. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 23/49 Package layout bad

    example Don't do this. mvc ├── controllers ├── models └── views Instead organize by responsibility.
  17. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 25/49 Why from package

    to design ? Design is the art of arranging code that needs to work today, and to be easy to change forever. –Sandi Metz I think we will missing some important things to talk only about package without talking about design. Package is the tool for how you implement design. You will see package and design are closely related. - Be aware we are going to have a more high level of thinking !
  18. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 26/49 Design is the

    rst step Design the architecture, name the components, document the details. go-proverbs.github.io/ (http://go-proverbs.github.io/)
  19. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 27/49 Design features of

    Go packages Namespacing Allows us to choose short and clear names for types and functions in a package. We don’t need to worry if common names have already been used in other packages. Encapsulation We control what is accessible outside of a package. The possibility of having a very intentional API at the package level. The flexibility to change unexported code without worrying about breaking that API. Internal packages Disallows the importing of code containing the element “internal”
  20. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 28/49 S.O.L.I.D principles S.O.L.I.D

    is an acronym for the rst ve object-oriented design(OOD) principles by Robert C. Martin, popularly known as Uncle Bob. Agile Software Development, Principles, Patterns, and Practices (https://www.amazon.co.uk/dp/0135974445/ref=pd_lpo_sbs_dp_ss_2/253-1946330-6751666?pf_rd_m=A3P5ROKL5A1OLE&pf_rd_s=lpo-top- stripe&pf_rd_r=23C4AHYV7EXGYHKD6G8Q&pf_rd_t=201&pf_rd_p=569136327&pf_rd_i=0132760584)
  21. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 29/49 Solid Design Single

    Responsibility Principle Open / Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle
  22. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 30/49 Single Responsibility Principle

    A class should have one, and only one, reason to change. –Robert C Martin Go obviously doesn’t have classes—instead we have the far more powerful notion of composition (https://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html) . Encourages you to structure the functions, types, and methods into packages that exhibit natural cohesion. For package, it is mean the single domain package.
  23. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 31/49 Go’s UNIX philosophy

    Small, sharp tools which combine to solve larger tasks, oftentimes tasks which were not envisioned by the ori –Doug McIlroy Go packages embody the spirit of the UNIX philosophy. In e ect each Go package is itself a small Go program, a single unit of change, with a single responsibility.
  24. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 32/49 Open / Closed

    Principle ( part 1 ) Software entities should be open for extension, but closed for modification. –Bertrand Meyer, Object-Oriented Software Construction Encourages you to compose simple types into more complex ones using embedding.
  25. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 33/49 Open / Closed

    Principle - Go embedding ( part 2 ) Embedding is a powerful tool which allows Go’s types to be open for extension. type Cat struct { Name string } func (c Cat) Legs() int { return 4 } func (c Cat) PrintLegs() { fmt.Printf("I have %d legs\n", c.Legs()) } type OctoCat struct { Cat } func (o OctoCat) Legs() int { return 5 } func main() { var octo OctoCat fmt.Println(octo.Legs()) octo.PrintLegs() } Run
  26. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 34/49 Open / Closed

    Principle - Go Package ( part 3 ) SQL Drivers import ( "database/sql" _ "github.com/go-sql-driver/mysql" _ "github.com/lib/pq" // and many others... ) Oauth providers import ( "github.com/markbates/goth" "github.com/markbates/goth/gothic" "github.com/markbates/goth/providers/amazon" "github.com/markbates/goth/providers/auth0" // and many others... )
  27. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 35/49 Liskov Substitution Principle

    ( part 1 ) Two types are substitutable if they exhibit behaviour such that the caller is unable to tell the di erence. In a class based language, It is commonly interpreted as a speci cation for an abstract base class with various concrete subtypes. But Go does not have classes, or inheritance, so substitution cannot be implemented in terms of an abstract class hierarchy.
  28. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 36/49 Liskov Substitution Principle

    - Go Interface ( part 2 ) I think it achieved by Go’s interfaces, the general abstraction. Well designed interfaces are more likely to be small interfaces Small interfaces lead to simple implementations, because it is hard to do otherwise. Which leads to packages comprised of simple implementations connected by common behaviour.
  29. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 37/49 Liskov Substitution Principle

    - Go Interface ( part 3 ) io.Reader type Reader interface { // Read reads up to len(buf) bytes into buf. Read(buf []byte) (n int, err error) } It seems simple but it’s very powerful. Because io.Reader‘s deal with anything that can be expressed as a stream of bytes, we can construct readers over just about anything. Such as A constant string, a byte array, standard in, a network stream, a gzip’d tar file.
  30. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 38/49 Liskov Substitution Principle

    - Go Interface ( part 4 ) So the Liskov substitution principle, applied to Go, could be summarised by this lovely aphorism from the late Jim Weirich. Require no more, promise no less. –Jim Weirich Encourages you to express the dependencies between your packages in terms of interfaces, not concrete types.
  31. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 39/49 Interface Segregation Principle

    Clients should not be forced to depend on methods they do not use. –Robert C. Martin Refer as process of isolating the behaviour required for a function to do its job. A great rule of thumb for Go is Accept interfaces, return structs. –Jack Lindamood Encourages you to de ne functions and methods that depend only on the behaviour that they need.
  32. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 40/49 Where we are

    ? If you’ve applied all the principles we’ve talked about up to this point then your code should already be factored into discrete packages, each with a single well de ned responsibility or purpose. Your code should describe its dependencies in terms of interfaces, and those interfaces should be factored to describe only the behaviour those functions require. There shouldn’t be much left to do.
  33. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 41/49 Dependency Inversion Principle

    ( part 1 ) High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions. –Robert C. Martin In the context of Go, it is the structure of your import graph. The import graph of a well designed Go program should be a wide, and relatively at, rather than tall and narrow.
  34. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 42/49 Dependency Inversion Principle

    ( part 2 ) If you have a package whose functions cannot operate without enlisting the aid of another package, that is perhaps a sign that code is not well factored along package boundaries. Encourages you to push the responsibility for the speci cs, as high as possible up the import graph, to your main package or top level handler. Leaving the lower level code to deal with abstractions–interfaces. Which also means to move the knowledge of the things your package depends on from compile time to run time.
  35. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 43/49 Go to SOLID

    Interfaces let you apply the SOLID principles to Go programs. Because interfaces describe what their package provides–not how it does it. Another way of saying “decoupling”, which is indeed the goal. Loosely coupled is software that is easier to change.
  36. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 44/49 Conclusion Single domain

    responsibility is the key to both package and good design. Abstract design is helpful for re-use ( design into library ). A good design Reduce maintenance costs ( easier to change and refactoring ) Increase productivity by make our work more e ciency
  37. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 45/49 Back to the

    rst question How does Gophers do differently ? Here we explained one aspect of how Gophers do di erent about package and design. I hope you now have a better understanding of how does Gophers do di erently. At last, We now recommend: Design go packages as Gophers do.
  38. 8/17/2017 Go Package & Design http://b.clwen.com:3999/go-package-and-design/go-package-and-design.slide#1 46/49 Reference rakyll.org/style-packages/ (https://rakyll.org/style-packages/)

    blog.golang.org/package-names (https://blog.golang.org/package-names) golang.org/doc/e ective_go.html#names (https://golang.org/doc/e ective_go.html#names) talks.golang.org/2014/names.slide (https://talks.golang.org/2014/names.slide) talks.golang.org/2014/organizeio.slide (https://talks.golang.org/2014/organizeio.slide) dave.cheney.net/2016/08/20/solid-go-design (https://dave.cheney.net/2016/08/20/solid-go-design) peter.bourgon.org/go-best-practices-2016/#repository-structure (https://peter.bourgon.org/go-best-practices- 2016/#repository-structure) dave.cheney.net/2016/08/20/solid-go-design (https://dave.cheney.net/2016/08/20/solid-go-design) blog.gopheracademy.com/advent-2016/go-and-package-focused-design/ (https://blog.gopheracademy.com/advent-2016/go-and-package-focused-design/) commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html