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