functional solid
DESCRIPTION
As given at the St. Louis Java User Group on August 9, 2012.TRANSCRIPT
Matt Stine
Functional Soλid
• Senior Consultant, PSOvFabric, Cloud Application PlatformVMware
• Speaker (JavaOne, SpringOne/2GX, CodeMash, NFJS, RWX, PAX, UberConf)
• Author (GroovyMag, NFJS the Magazine, Selenium 2.0 Refcard)
• Founder of the Memphis/Mid-South Java User Group
• Former Agile Zone Leader @ DZone
About your speaker...
SOLIDPrinciples
FunctionalProgramming
SOLIDPrinciples
FunctionalProgramming
Pitch
• Software designs tend to rot.
• Design rot impedes our effectiveness.
• SOLID principles help treat design rot.
• Achieving SOLID designs is another reason to learn FP!
Motivation
Trends
• How Software Systems Evolve
• Programming Paradigms
• The Quest for “Best Practices”
The evolution of software...
http://www.flickr.com/photos/unloveable/2400895854
http://www.flickr.com/photos/billselak/427719926
From simplicity to complexity...
Software starts to rot like a
bad piece of meat.
“Uncle Bob” Martin
http://www.flickr.com/photos/thejcgerm/379082415
We don’t handle change well...
Unclear or incomplete change specifications...
Extreme time pressure...
Team members unfamiliar with original design/architecture...
It smells!
Rigidity
Fragility
Immobility
Viscosity
Needless Complexity
Needless Repetition
Opacity
Programming Paradigms
Programming eras...
• Structured Programming(late 1960’s - late 1980’s)
• Object Oriented Programming(mid 1970’s - present day)
• Functional Programming(early 1990’s - ???)
TH
E C
HA
SM
Accumulation of Knowledge?
Accumulation of Knowledge?
Paradigm Shifts
http://www.gotw.ca/publications/concurrency-ddj.htm
The Quest for
“Best Practices”
• Which web framework should I use?
• Why are there so many persistence API’s?
• Which is better: Scala or Clojure (or Erlang)?
• How should I use design patterns?
• How do I build a good architecture?
http://en.wikipedia.org/wiki/No_Silver_Bullet
What are the FP best practices?
The Perfect Storm
TheSOLID
Principles
SRP OCP LSP
ISP DIP
http://clojure.org
http://www.infoq.com/presentations/SOLID-Clojure
The Single Responsibility Principle
A class (module) should have only one reason
to change.
Tom DeMarco Meilir Page-Jones
COHESION
Rectangle
+ draw()+ area() : double
GraphicalApplication
Computational Geometry Application
GUI
Rectangle
+ draw()
GraphicalApplication
Computational Geometry Application
GUI
GeometricRectangle
+ area() : double
Metaresponsibilities of an OO class...
• Model state
• Model behavior
State
• car.color = black• elevator.floor = 10• account.balance = 2500
Behavior
• car.drive()• elevator.climb()• account.deposit(500)
How many metaresponsibilities?
It is better to have 100 functions operate on one data structure than to have 10 functions operate
on 10 data structures.
Alan J. Perlis
Metaresponsibilities of an OO class...
• Model state
• Model behavior
• Model identity
IDENTITY
VALUE
car1 != car2
car1 == car2
Concurrent System
• Automated “Needs Service” Notification System
• Thread 1: Update mileage and “ready for service indicators”
• Thread 2: Harvest cars ready for service and send notifications
The Open Closed Principle
Bertrand Myer
Software entities should be open for extension but closed for modification.
Open for extension...
...closed for modification.
Abstraction!
• Java:
• interface
• abstract class
(pause OCP)
Let’s do design!
• OO language (Java)
• We want to use the OCP
• We’ll create one or more inheritance hierarchies!
• Well...
Inheritance Hierarchies?
• What do good ones look like?
• Are there rules we can follow (best practices even)?
• Are there traps we can fall in to?
Barbara Liskov
The Liskov Substitution Principle
What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is
substituted for o2, then S is a subtype of T.
Subtypes must be substitutable for their
base types.
f(B b) { }
D extends B
B d = new D();f(d)
f(B b) { if (b instance of D) { //deal with D } else { //continue as before }}
(resume OCP)
CompositionThe Functional OCP
First-class Functions
Higher-order Functions
The Interface Segregation Principle
Clients should not be forced to depend on
methods they do not use.
<<interface>>TimerClient
+ timeout()Timer
0..*
Door
TimedDoor
<<interface>>TimerClient
+ timeout()Timer
0..*Door
DoorTimerAdapter
+ timeout()
<<creates>>
TimedDoor
+ doorTimeOut()
<<interface>>TimerClient
+ timeout()Timer Door
TimedDoor
+ timeout()
Thinking in Verbs
Verbs
• Open
• Close
• Register Timeout
• Trigger Timeout
OK...what about that unique ID problem?
The Dependency Inversion Principle
Abstractions should not depend upon details. Details
should depend upon abstractions.
High-level modules should not depend on
low-level modules.
Policy Layer
Mechanism Layer
Utility Layer
Policy Layer
Mechanism Layer
Utility Layer
<<interface>>Policy Service
Interface
<<interface>>Mechanism
Service Interface
Our verbs have been taken captive by
nouns...
http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
http://www.infoq.com/presentations/Simple-Made-Easy/
Complectedness
SRP
Complecting responsibilities leads to rigid and/or fragile design.
OCP
Problematic:Complecting concretions of an
abstraction in such a way that new concretions adversely affect
existing, working concretions.
LSP
Reuse via inheritance is dangerous. Often complects entities not in a true “is-a” relationship. Leads to non-
substitutability.
ISP
Don’t complect unrelated operations in a single entity!
DIP
Transitive dependency leads to transitive complectedness!
Design is the art of breaking things apart.
- Rich Hickey