From
Object Oriented Programming
to
Functional Programming
About Me
@qhwa
(Ruby-China/Twitter/Github)
web developer
Elixir/Ruby/JavaScript/Go
helijia.com
switching your programming pattern is like ...
WHY NOT OOP
WHY FP
HOW TO FP
WHY NOT OOP
WHY FP
HOW TO FP
Problems Of OOP
- problems of inheriting
- encapsulation is not safe
Problems Of Inheriting
The problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.
-- Joe Armstrong, creator of Erlang
Inheriting (is a...)
+ Containing (has a...)
Is that enough?
Documents / Company
Company / Documents
OR
/
It's not always
parent-child
Inheriting makes program unreliable
class BasicLogic
def initialize
@core = []
end
def add(element)
@core.add(element)
end
def add_all(elements)
elements.each {|e| @core.add(e) }
end
end
class ChildLogic < BasicLogic
def initialize
@count = 0
end
def add(element)
super
@count ++
end
def add_all(elements)
super
@count += elements.size
end
end
Someday...
class BasicLogic
def initialize
@core = []
end
def add(element)
@core.add(element)
end
def add_all(elements)
elements.each {|e| @core.add(e) }
end
end
class BasicLogic
def initialize
@core = []
end
def add(element)
@core.add(element)
end
def add_all(elements)
elements.each {|e| add(e) }
end
end
parents change😃
parents pass tests😃
children are broken🤔
Problems Of Encapsulation
class MyBusiness
def initialize(obj)
@obj = obj
end
def some_logic
@obj[:count] = 0
end
end
one class changes😃
one class passes tests😃
others are broken🤔
Problems Of OOP
- problems of inheriting
- encapsulation is not safe
WHY NOT OOP
WHY FP
HOW TO FP
What makes functional programming style?
- pure function & immutable data
- high order function
Pure Function
data = "some quote"
String.upcase(data) #=> "SOME QUOTE"
data #=> "some quote"
Reuse code at function level
not module/file/class/jungle level
thanks to pure functions
iex> import List, only: [duplicate: 2]
List
iex> duplicate :ok, 3
[:ok, :ok, :ok]
Reliable
same input means same output
Less variables, Closer to business
class WordCount
NON_WORDS = %w[
a the and of to i it
in or is d s as so
but be
]
def self.stats(words)
result = Hash.new(0)
words.each do |w|
w = w.downcase
unless NON_WORDS.include? w
result[w] += 1
end
end
result
end
end
puts WordCount.stats(%w[I am a programmer i love programming])
# {"am"=>1, "programmer"=>1, "love"=>1, "programming"=>1}
defmodule WordCount do
@non_words ~w[
a the and of to i it
in or is d s as so
but be
]
def stats(words) do
words
|> Enum.map(&String.downcase/1)
|> Enum.reject(&(Enum.member?(@non_words, &1)))
|> compute_stats
end
defp compute_stats(words) do
Enum.reduce(words, %{}, fn w, result ->
Map.update(result, w, 1, &(&1+1))
end)
end
end
Easy to address crash reason
no more inheriting chains
WHY NOT OOP
WHY FP
HOW TO FP
Learn some Elixir
Use
filtering/mapping/reducing
Use
pure functions
Books
Articles
https://medium.com/search?q=functional%20programming
Thanks!
函数式编程
By qhwa
函数式编程
- 970