Learning Functional Programming in Go.Pdf
Total Page:16
File Type:pdf, Size:1020Kb
Learning Functional Programming in Go Lex Sheehan BIRMINGHAM - MUMBAI Learning Functional Programming in Go Copyright © 2017 Packt Publishing First published: November 2017 Production reference: 1221117 Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK. ISBN 7-1-772-13-4 www.packtpub.com Contents Preface 1 Chapter 1: Pure Functional Programming in Go 11 Motivation for using FP 12 Getting the source code 13 The directory structure of the source files 13 How to run our first Go application 14 Imperative versus declarative programming 15 Pure functions 1 Fibonacci sequence - a simple recursion and two performance improvements 1 Memoization 21 The difference between an anonymous function and a closure 24 FP using Go's concurrency constructs 26 Testing FP using test-driven development 2 A note about paths 30 How to run our tests 31 A journey from imperative programming to pure FP and enlightenment 36 Benchmark test for the imperative SumLoop function 37 Benchmark test for the SumRecursive function 37 A time of reckoning 3 A quick example of a function literal 3 Summary 40 Chapter 2: Manipulating Collections 41 Iterating through a collection 42 Piping Bash commands 44 Functors 45 Functions that modify functions 46 A coding example of functions that modify functions 46 A visual example of functions that modify functions 47 Composition in Mindcraft 4 Tacit programming 4 Tacit programming with Unix pipes 4 Programming CMOS with Unix pipes 4 Tacit programming with FP 50 Non-TCO recursive example 50 TCO recursive example 51 The importance of recursion 52 Various intermediate and terminal functions 53 Reduce example 54 Intermediate functions 54 Common intermediate functions 55 Map Example 55 Terminal functions 56 Common terminal functions 56 Join example 56 GroupBy example 57 Reduce example 57 Predicates 57 Reflection 60 Combinator pattern 61 Map and filter 61 Contains 67 Iterating over a collection of cars 6 The empty interface 6 The Contains() method 6 If Go had generics 70 Map function 71 Testing our empty interface-based Map function 71 Itertools 72 Go channels used by the New function 74 Testing itertool's Map function 74 Testing iterators for element equality 75 Functional packages 76 Another time of reflection 76 Go is awesome 76 Go is awesome, but 76 The cure 77 Gleam - distributed MapReduce for Golang 77 LuaJIT's FFI library 7 Unix pipe tools 7 Processing Gleam collections 7 Summary 0 Chapter 3: Using High-Order Functions 1 Characteristics of FP 1 Function composition 2 Monads allow us to chain continuations 3 Generics 4 First-class functions 5 Closure 6 Dynamically scoped 7 Pure function Immuable Data Persistent data structures for Go Use of expressions 101 Sample HOF application 101 The chapter4 application code 102 Build and runtime instructions 103 More application code 104 The Filter function 105 Reality check 106 FilterFunc 107 Filter function 107 RESTful resources 10 Chaining functions 10 More cars 110 Reality check 110 The Map function 111 Improved performance from the Map function 112 The Reduce function 113 More high-order functions 114 Generators 115 RESTful server 116 The GenerateCars function 116 Currying Goroutine 11 A closer look at currying 11 Extending our currying example 120 Using a WaitGroup variable to manage concurrency 121 Finishing up the GenerateCars function 121 Handling concurrency 122 The final HOF example 123 Summary 124 Chapter 4: SOLID Design in Go 125 Why many Gophers loath Java 125 More reasons for loathing Java 127 Digging deeper into error handling 12 A conversation - Java developer, idiomatic Go developer, FP developer 12 Software design methodology 132 Good design 133 Bad design 134 Good versus bad design over time 134 SOLID design principles 135 Single responsibility principle 136 Function composition 13 Open/closed principle 13 Open / close principle in functional programming 141 FantasyLand JavaScript specification 142 Setoid algebra 142 Ord algebra 143 The expression problem 143 Liskov substitution principle 144 This OOP method stinks 144 Our FP function smells like roses 145 In FP, contracts don't lie 146 Duck typing 150 What can go wrong with inheritance? 150 Interface segregation principle 152 Dependency inversion principle 152 The big reveal 153 MapReduce 154 MapReduce example 155 What else can Monads do? 157 Viva La Duck 15 Pass by value or reference? 161 Type embedding with Go interfaces 163 Interface embedding to add minor features 164 A Go error handling idiom 164 It's time to run our program 165 Summary 16 Chapter 5: Adding Functionality with Decoration 16 Interface composition 170 Go's complimentary Reader and Writer interfaces 170 Example usages of the Reader and Writer interfaces 171 Design with Duck Typing 171 More reasons to design using interfaces 172 Using the Reader and Writer interfaces 174 Decorator pattern 176 Type hierarchy UML 177 How Procedural design compares to functional Inversion of Control (IoC) 17 Procedural design example 17 Functional IoC example 17 A decorator implementation 10 The main.go file 10 The decorator/simple_log.go file 12 Example InitLog calls 13 Back to our main package 14 Understanding our statistics using the easy-metrics GUI 17 Quick look at the Dot Init update 1 Easy-metrics - 1 of 3 1 The decorator/decorator.go file 10 A framework to inject dependencies 11 Wrapping a client request with decorators (in main) 11 Authorization decorator 12 Logging decorator 12 LoadBalancing decorator 13 Strategy pattern 13 Inversion of control and dependency injection 15 Our first failure 16 Easy metrics - 2 of 3 16 Groking our trace log file 17 The rest of the graph 1 Easy metrics - 3 of 3 1 Examining the trace log 200 The decorator/requestor.go file 200 The job variable declared in main() 201 Back to the requestor.go file 201 Using channels to manage the life cycle 202 All requests done 204 Launching our makeRequest goroutine 204 Our DI framework in action 205 Summary 206 Chapter 6: Applying FP at the Architectural Level 207 Application architectures 20 What is software architecture? 20 Client-server architecture 20 Cloud architecture 210 Why does architecture matter? 211 The role of systems engineering 212 Real systems 212 IT system specialty groups 212 Systems engineering is lean 213 Requirements, scope and terms 213 Defining terms 213 Software requirements 214 System 214 System architecture 214 System elements 214 System Boundaries 214 Managing Complexity 214 The best tool for the job 215 Divide and conquer 215 Designing for state management 216 Add a microservice 216 FP influenced architectures 21 Domain Driven Design 21 Dependency rule 220 Cyclic dependency 221 Working code 221 Code with cyclic dependency error 222 The Golang difference 223 Solution for cyclic dependencies 224 Domain Driven Design 224 Interface-driven development 225 Hollywood principle 226 Observer pattern 226 Dependency injection 22 A cloud bucket application 230 Directory structure 230 main.go 231 func HandlePanic 232 Dependency injection 233 func main() 234 Layers in the architecture 234 Domain layer 235 Use cases layer 240 Compatible interfaces 242 Interfaces layer 244 Why global variables are bad 252 Format the response 253 Testing our interfaces 25 Infrastructure layer 262 Context object 264 Benefits of DDD 266 Adaptability 266 Sustainability 267 Testability 267 Comprehensibility 267 A solid architectural foundation 267 FP and Micyoservices 267 Message passing 26 All parties must participate 26 Communication across boundaries 26 Polyglot Persistence 26 Lambda architecture 270 Speed 270 Batch 270 Servicing 271 Next generation big data architecture 271 CQRS 271 Benefits of CQRS 272 Infrastructure architecture 273 Share nothing architecture 274 Integrating services 274 Agreed upon protocol 274 Circuit breakers 274 Functional reactive architecture 275 Go is ideal for building microservices 276 Size matters 277 Benefits of gRPC 27 Who is using Go? 27 Summary 27 Chapter 7: Functional Parameters 20 Refactoring long parameter lists 21 What's wrong with a function signature with more than seven parameters? 21 Refactoring - the book 22 Edsger W. Dijkstra says OOP is a bad idea 23 What else did Edsger W. Dijkstra say? 24 The underlying OOP problem 26 OOP inconsistency 27 Functional programming and cloud computing 27 A closer look at f(x) 2 A closer look at refactoring 2 Passing every parameter a function requires to do its job is not a good idea 2 Methods can query other objects' methods internally for data required to make decisions 20 Methods should depend on their host class for needed data 20 Pass a whole object with required attributes to reduce the number of required parameters 20 Replace parameter with method technique to reduce the number of required parameters 21 Before applying Replace Parameter with Method technique 21 After applying Replace Parameter with Method technique 21 Use a parameter object when we have unrelated data elements to pass 21 Long parameter lists will change over time and are inherently difficult to understand 23 The solution 24 Three ways to pass multiple parameters 25 Simply passing multiple parameters 25 Passing a configuration object/struct that contains multiple attributes 25 Partial application 26 Functional parameters 27 Contexts 301 Context limitations 304 Report example 305 Writing good code is not unlike a good game of soccer 305 Functional parameters - Rowe 307 Report example 307 A more practical Context use case 307 src/server/server.go 30 The src/server/server_options.go file 315 Summary 31 Chapter : Increasing