14. A pure function is just
input output; no side effects
You can tell what it does without
Looking at surrounding context.
15. Consider:
Let’s parse a string like “Richmond, VIC 3121”
def parseLocation(str: String): Location = {
val parts = str.split(“,”)
val secondStr = parts(1)
val parts2 = secondStr.split(“ “)
Location(
parts(0), parts2(0), parts(1).toInt)
}
16. Could be null
Possible errors: 1
def parseLocation(str: String): Location = {
val parts = str.split(“,”)
val secondStr = parts(1)
val parts2 = secondStr.split(“ “)
Location(
parts(0), parts2(0), parts(1).toInt)
}
17. def parseLocation(str: String): Location = {
val parts = str.split(“,”)
val secondStr = parts(1)
val parts2 = secondStr.split(“ “)
Location(
parts(0), parts2(0), parts(1).toInt)
}
Might not have enough elements
Possible errors: 2
18. def parseLocation(str: String): Location = {
val parts = str.split(“,”)
val secondStr = parts(1)
val parts2 = secondStr.split(“ “)
Location(
parts(0), parts2(0), parts(1).toInt)
}
Might not have enough elements
Possible errors: 3
19. def parseLocation(str: String): Location = {
val parts = str.split(“,”)
val secondStr = parts(1)
val parts2 = secondStr.split(“ “)
Location(
parts(0), parts2(0), parts(1).toInt)
}
Might not have enough elements
Possible errors: 4
20. def parseLocation(str: String): Location = {
val parts = str.split(“,”)
val secondStr = parts(1)
val parts2 = secondStr.split(“ “)
Location(
parts(0), parts2(0), parts(1).toInt)
}
Might not have enough elements
Possible errors: 5
21. def parseLocation(str: String): Location = {
val parts = str.split(“,”)
val secondStr = parts(1)
val parts2 = secondStr.split(“ “)
Location(
parts(0), parts2(0), parts(1).toInt)
}
Might not be an int
Possible errors: 6
22. def doSomethingElse(): Unit = {
// ...Do other stuff
parseLocation(“Melbourne, VIC 3000”)
}
Possible errors: 6 + 3 = 9
6
3
23. def anotherThing(): Unit = {
// ...Do even more stuff
doSomethingElse()
}
Possible errors: 9 + 4 = 13
4
9
24. Code inherits all the
errors and side-effects of
code it calls.
Local reasoning becomes
impossible; modularity is
lost.
48. Simplicity
• Modularity – Reason locally
• Abstraction – say only what you need, hide
everything you don’t
• Composability – scale without accruing complexity
56. Xi’an offshore team
• Many teams are partly based in Xi’an.
• They’re very good, but…
• Communication is hard!
• It works, but requires great investment of time and
money
72. Architect
Mountain
Just needs
more Agile
Don’t forget
your
velocity
More
meetings,
but littler
NO
No no no no no no no
no no no no no no no
no no no no no no no
no no no no no no no
no no no no not like
this. Wake up it’s a
school day
104. LOC
Web
JSON
DB
Dep Inj
Play2
Play2
6K
Squeryl / Play2
Constructors
Type API
• Mentor
• Code reviews
Learning Investment Report card
Learning curve
Technical result
Productivity
Sentiment
Steep but ok
OK; slight dip
Great; but FWs
too heavy
#1
108. LOC
Web
JSON
DB
Dep Inj
Play2
Argonaut
3K
Squeryl / Play2
Constructors
Type API
• Almost none
Learning Investment Report card
Learning curve
Technical result
Productivity
Sentiment
Learning?
Meh
Needed rework;
OK in the end
#2
!!!
109. Lesson #1
New tech, mindset
requires investment in
learning
Invest in your people!
113. Jul 13 Jan 14
1 2
4
6
5
New team; new ideas!
3
114. LOC
Web
JSON
DB
Dep Inj
Unfinagled
Argonaut
2K, 3K, 4K, 1K
Slick
Constructors
Type Web app, libs, API x 2
• 2 x Mentor
Learning Investment Report card
Learning curve
Technical result
Productivity
Sentiment
Not bad
Great
Great
#3,4,
5,6
120. Monad Transformers
Good technical benefits, but…
Only 2 people could understand the code
Experienced engineers felt totally helpless
Learning curve way too steep
145. Pure core
Routes Controllers Logic Script
Interpreter
Actual DB
“Authenticate”
“Use config”
“Get from DB”
“Update DB”
“Log result”
Web Framework
Server
App runtime
146. Pure core
Routes Controllers Logic Script
Pure Interpreter
Pure tests
Input
Output
Assert
“Authenticate”
“Use config”
“Get from DB”
“Update DB”
“Log result”