Clean code in Go Mateusz Dymiski Nokia Whoami

  • Slides: 52
Download presentation
Clean code in Go Mateusz Dymiński Nokia

Clean code in Go Mateusz Dymiński Nokia

Whoami Mateusz Dymiński • Software Developer at Nokia • 8+ exp with Java •

Whoami Mateusz Dymiński • Software Developer at Nokia • 8+ exp with Java • 4+ exp with Go • One of the organizer Go. Wroc - Golang Wroclaw Meetup • Github: github. com/mateuszdyminski • Twitter: @m_dyminski • Linked. In: linkedin. com/in/mdyminski

Thesis • Writing clean code in Go is really easy • Go supports clean

Thesis • Writing clean code in Go is really easy • Go supports clean code by design • Every programmer should learn Go

Agenda • Definition(s) of Clean Code • History of Go • Go inventors assumptions

Agenda • Definition(s) of Clean Code • History of Go • Go inventors assumptions • Why I think that Go is cleanest programming language • Summary

github. com/mateuszdyminski/clean

github. com/mateuszdyminski/clean

Clean Code definition(s)

Clean Code definition(s)

Clean Code definition Bjarne Stroustrup - inventor of C++ I like my code to

Clean Code definition Bjarne Stroustrup - inventor of C++ I like my code to be elegant and efficient. The logic should be straightforward and make it hard for bugs to hide, the dependencies minimal to ease maintenance, error handling complete according to an articulated strategy, and performance close to optimal so as not to tempt people to make the code messy with unprincipled optimizations. Clean code does one thing well.

Clean Code definition Michael Feathers - author of Working Effectively with Legacy Code I

Clean Code definition Michael Feathers - author of Working Effectively with Legacy Code I could list all of the qualities that I notice in clean code, but there is one overarching quality that leads to all of them. Clean code always looks like it was written by someone who cares. There is nothing obvious that you can do to make it better. All of those things were thought about by the code’s author, and if you try to imagine improvements, you are led back to where you are, sitting in appreciation of the code someone left for you—code written by someone who cared deeply about the craft.

Clean Code definition Ward Cunningham, inventor of Wiki and Fit, co-inventor of Extreme Programming

Clean Code definition Ward Cunningham, inventor of Wiki and Fit, co-inventor of Extreme Programming You know you are working with clean code when each routine you read turns out to be pretty much what you expected. You can call it beautiful code when the code also makes it look like the language was made for the problem.

Uncle Bob about Ward Cunningham definition of Clean Code

Uncle Bob about Ward Cunningham definition of Clean Code

Go history

Go history

Go timeline Version 1. 0 published in 2012

Go timeline Version 1. 0 published in 2012

Why Google created Golang? Go is the answer on the problem of engineering scale

Why Google created Golang? Go is the answer on the problem of engineering scale at Google In 2011: - 5000+ developers across 40+ offices - 20+ changes per minute - 50% of code base changes every month - 50 million test cases executed per day - single code tree Solution: design the language for large code bases

Google - observations • The less code we need to read = the better

Google - observations • The less code we need to read = the better - inheritance hierarchy is bad, operators overloading is bad etc. • We read code far more often than we write it • Code lives longer that we expect • Usually maintainer of the code is not the person who wrote that code • In big organizations programming skills may be vary • Processors speed is not increasing as expected(Moore's law is failing)

Golang - assumptions Go should be: • clean procedural language • simple • readable

Golang - assumptions Go should be: • clean procedural language • simple • readable • maintainable • concise

Ward’s definition of Clean Code You know you are working with clean code when

Ward’s definition of Clean Code You know you are working with clean code when each routine you read turns out to be pretty much what you expected.

Why I think that Go supports clean code by its design

Why I think that Go supports clean code by its design

Go does not compete on features

Go does not compete on features

Golang does not compete on features • New versions of Java, Java. Script (ECMAScript),

Golang does not compete on features • New versions of Java, Java. Script (ECMAScript), Typescript, C#, C++, Hack (PHP) and many more add new features. • These languages actively borrow features from one another. • They are converging into a single huge language. Source: https: //talks. golang. org/2015/simplicity-is-complicated. slide

Golang does not compete on features • Go is different. • Go does not

Golang does not compete on features • Go is different. • Go does not try to be like the other languages. • Go does not compete on features. • As of Go 1, the language is fixed. • Many newcomers to Go ask for features from languages they know. But those features do not belong in Go—and the language is fixed. • Adding features to Go would not make it better, just bigger. • That would make Go less interesting by being less different. Source: https: //talks. golang. org/2015/simplicity-is-complicated. slide

Missing map/reduce/filter func user. Names(filter string) []string { filtered : = make([]user, 0, 0)

Missing map/reduce/filter func user. Names(filter string) []string { filtered : = make([]user, 0, 0) for _, u : = range users { if strings. Contains(u. name, filter) { filtered = append(filtered, u) } } public static List<String> get. User. Names(String filter) { return users. stream() . filter(p -> p. get. Name(). contains(filter)) . sorted(Comparator. comparing(User: : get. Name)) . map(u -> u. get. Name()) . collect(Collectors. to. List()); } sort. Sort(by. Name(filtered)) result : = make([]string, 0, 0) for _, u : = range users { result = append(result, u. name) } return result } Lo. C: Go vs Java - 17 vs 6

Small Specification

Small Specification

Small specification • Java 8 spec - 788 pages PDF -> http: //docs. oracle.

Small specification • Java 8 spec - 788 pages PDF -> http: //docs. oracle. com/javase/specs/jls/se 8/jls 8. pdf • Scala spec - 191 pages PDF -> http: //www. scalalang. org/docu/files/Scala. Reference. pdf • Python spec - 150 pages PDF -> https: //docs. python. org/3/reference/ • Golang spec - 51 pages PDF -> https: //golang. org/ref/spec

A bit primitive but very concise

A bit primitive but very concise

A bit primitive but very concise • If a language has too many features,

A bit primitive but very concise • If a language has too many features, you waste time choosing which ones to use. • Then implement, refine, possibly rethink and redo. • Preferable to have just one way, or at least fewer, simpler ways. • Features add complexity. Go wants simplicity. • Features hurt readability. Go wants readability. • Readability is paramount. Source: https: //talks. golang. org/2015/simplicity-is-complicated. slide

Dead simple syntax

Dead simple syntax

Dead simple syntax • Java or C# have more than 50 keywords, Go -

Dead simple syntax • Java or C# have more than 50 keywords, Go - only 25 • Less features = less keywords • Simple scoping rules • If package level variables start with a lowercase letter, they are scoped to the package. If they start with upper-case, it means variables are scoped publically. • Build-In garbage collection • Go creators built-in the garbage collection to simplify memory management which helps to write clean code and eliminate tech debt right away.

Dependencies

Dependencies

Dependencies • Code with unused dependency would not compile • One of the Golang

Dependencies • Code with unused dependency would not compile • One of the Golang proverb: „a little copying is better than a little dependency” • Keep your dependency tree small • If you could copy 5 lines of code instead of add new dependency – do that! • Even golang standard library is doing that!

No inheritance

No inheritance

No inheritance • It avoids really crazy issues with multiple inheritance… • … but

No inheritance • It avoids really crazy issues with multiple inheritance… • … but still provides you with Interfaces which is really the pattern of choice today. • It limits the complexity of individual parts of the system which is really what we want from the big systems we create. • It enables really fast compile times with strict type checking.

No overloading

No overloading

No overloading • Methods with the same name but different signatures was occasionally useful

No overloading • Methods with the same name but different signatures was occasionally useful but that it could also be confusing and fragile in practice. • Matching only by name and requiring consistency in the types was a major simplifying decision in Go's type system. • In Go a function can be assigned to a variable or passed as a parameter. If functions can be overloaded, how will programmers indicate which variant of an overloaded function they meant? • Regarding operator overloading, it seems more a convenience than an absolute requirement. Again, things are simpler without it.

No exceptions

No exceptions

No exceptions • Go solves the exception problem by not having exceptions. • Instead

No exceptions • Go solves the exception problem by not having exceptions. • Instead Go allows functions to return an error type in addition to a result via its support for multiple return values. • By declaring a return value of the interface type error you indicate to the caller that this method could go wrong. • Errors are values! • Java and C++ throw new Someone. Elses. Problem() • Go panic(„it’s game over”)

Error handling

Error handling

Error handling

Error handling

Error handling • In Go, a common complaint from newly-minted gophers who come from

Error handling • In Go, a common complaint from newly-minted gophers who come from another language is the error handling pattern: result, err : = Do. Something() if err != nil { return nil, err } another, err : = Something. Else(result) if err != nil { return nil, err } if err : = More. Work(another); err != nil { return nil, err }. . . • Any time we write similar-looking code over and over, that’s considered boilerplate.

Error handling • An error check is always an error check – and its

Error handling • An error check is always an error check – and its far better than exception propagation or try-catchfinally clause • Solution:

No generics

No generics

No generics • Generics may well be added at some point. • The language

No generics • Generics may well be added at some point. • The language is more mature now, and there is scope to consider some form of generic programming. • Generics are convenient but they come at a cost in complexity in the type system and run-time, although creators of Go continue to think about it. • The topic remains open. For a look at several previous unsuccessful attempts to design a good generics solution for Go, see this proposal.

No generics func sort(users []user, field string) { if field == „name” { sort.

No generics func sort(users []user, field string) { if field == „name” { sort. Sort(by. Name(users)) } sort. Sort(by. Score(users)) } type by. Name []user func (s by. Name) Len() int { return len(s) } func (s by. Name) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s by. Name) Less(i, j int) bool { return s[i]. Name < s[j]. Name } type by. Score []user func (s by. Score) Len() int { return len(s) } func (s by. Score) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s by. Score) Less(i, j int) bool { return s[i]. Score < s[j]. Score }

Auto formatter

Auto formatter

Build-In auto formatter • Go has auto formatter build-in $ go fmt path/to/your/package •

Build-In auto formatter • Go has auto formatter build-in $ go fmt path/to/your/package • Every Golang IDE runs go fmt automatically • Gofmt'd code is: • easier to write: never worry about minor formatting concerns while hacking away, • easier to read: when all code looks the same you need not mentally convert others' formatting style into something you can understand. • easier to maintain: mechanical changes to the source don't cause unrelated changes to the file's formatting; diffs show only the real changes. • uncontroversial: never have a debate about spacing or brace position ever again!

Documentation

Documentation

Documentation • Documentation is a huge part of making software accessible and maintainable. Its

Documentation • Documentation is a huge part of making software accessible and maintainable. Its one of characteristic of Clean Code • Go has a great emphasis on simple, no-nonsense documentation right out of the box. • The comments read by godoc are not language constructs (as with Docstring) nor must they have their own machine-readable syntax (as with Javadoc). • All documentation in one place: https: //godoc. org/ • You can even run your local server with godoc • Example: https: //godoc. org/github. com/mateuszdyminski/bloomfilter/bloom

But sometimes Go is not clean

But sometimes Go is not clean

Go concurrency sometime is not Clean func sum. Files(done <-chan struct{}, root string) (<-chan

Go concurrency sometime is not Clean func sum. Files(done <-chan struct{}, root string) (<-chan result, <-chan error) { // For each regular file, start a goroutine that sums the file and sends the result on c. c : = make(chan result) errc : = make(chan error, 1) go func() { var wg sync. Wait. Group err : = filepath. Walk(root, func(path string, info os. File. Info, error) error { if err != nil { return err } if !info. Mode(). Is. Regular() { return nil } wg. Add(1) go func() { data, err : = ioutil. Read. File(path) select { case c <- result{path, md 5. Sum(data), err}: case <-done: } wg. Done() }() // Abort the walk if done is closed. select { case <-done: return errors. New("walk canceled") default: return nil }) // Walk has returned, so all calls to wg. Add are done. go func() { wg. Wait() close(c) }() // No select needed here, since errc is buffered. errc <- err }() return c, errc

Summary

Summary

Summary • You could learn Go in 24 h • https: //tour. golang. org

Summary • You could learn Go in 24 h • https: //tour. golang. org • https: //golang. org/doc/effective_go. html • After 24 h you could write production grade code • Golang code written 10(6) years ago looks almost the same as Golang code written nowadays. • Go code looks boring and ugly – but you will know what’s doing even in the middle of the night

Summary • Writing clean code in Go is really easy • Go as programming

Summary • Writing clean code in Go is really easy • Go as programming language supports you in writing Clean Code • Creators of Go sacrifice lots of new fancy features to preserve cleanliness of code • Go supports clean code by design • Go does not implementing features from different paradigms • Every programmer should learn Go • Hopefully it’s obvious : )

Thank you!

Thank you!