I made up the term “object-oriented”, and I can tell you
OOP is a means of communication, a state of the process, an extreme late binding of all things.
I’m sorry that I’ve been coined the term “objects”. The big idea is “messaging”.
It would be much more important to develop how it should be implemented.
It was less effort than traditional early binding systems (C, C ++, Java, etc.)
I still like dynamic typing.
Code.load_file("school.exs")
ExUnit.start
defmodule SchoolTest do
use ExUnit.Case, async: true
import School, only: [add_student: 3, students_by_grade: 1, students_by_grade: 2]
test "get students in a non existant grade" do
school = School.new
assert [] == school |> students_by_grade(5)
end
test "add student" do
school = School.new
school |> add_student("Aimee", 2)
assert ["Aimee"] == school |> students_by_grade(2)
end
test "add students to different grades" do
school = School.new
school |> add_student("Aimee", 3)
school |> add_student("Beemee", 7)
assert ["Aimee"] == school |> students_by_grade(3)
assert ["Beemee"] == school |> students_by_grade(7)
end
test "grade with multiple students" do
school = School.new
grade = 6
students = ~w(Aimee Beemee Ceemee)
students |> Enum.each(fn(student) -> school |> add_student(student, grade) end)
assert students == school |> students_by_grade(grade)
end
test "grade with multiple students sorts correctly" do
school = School.new
grade = 6
students = ~w(Beemee Aimee Ceemee)
students |> Enum.each(fn(student) -> school |> add_student(student, grade) end)
assert Enum.sort(students) == school |> students_by_grade(grade)
end
test "empty students by grade" do
school = School.new
assert [] == school |> students_by_grade
end
test "students_by_grade with one grade" do
school = School.new
grade = 6
students = ~w(Beemee Aimee Ceemee)
students |> Enum.each(fn(student) -> school |> add_student(student, grade) end)
assert [[grade: 6, students: Enum.sort(students)]] == school |> students_by_grade
end
test "students_by_grade with different grades" do
school = School.new
everyone |> Enum.each(fn([grade: grade, students: students]) ->
students |> Enum.each(fn(student) -> school |> add_student(student, grade) end)
end)
assert everyone_sorted == school |> students_by_grade
end
defp everyone do
[
[ grade: 3, students: ~w(Deemee Eeemee) ],
[ grade: 1, students: ~w(Effmee Geemee) ],
[ grade: 2, students: ~w(Aimee Beemee Ceemee) ]
]
end
defp everyone_sorted do
[
[ grade: 1, students: ~w(Effmee Geemee) ],
[ grade: 2, students: ~w(Aimee Beemee Ceemee) ],
[ grade: 3, students: ~w(Deemee Eeemee) ]
]
end
end
school = School.new
school |> add_student("Aimee", 2) # => :ok
school |> students_by_grade(2) # => ["Aimee"]
school |> students_by_grade # => [[grade: 2, students: ["Aimee"]]]
school = School.new
School.add_student(school, "Aimee", 2) # => :ok
School.students_by_grade(school, 2) # => ["Aimee"]
School.students_by_grade(school) # => [[grade: 2, students: ["Aimee"]]]
defmodule School do
use GenServer
# API
@doc """
Start School process.
"""
def new do
{:ok, pid} = GenServer.start_link(__MODULE__, %{})
pid
end
@doc """
Add a student to a particular grade in school.
"""
def add_student(pid, name, grade) do
GenServer.cast(pid, {:add, name, grade})
end
@doc """
Return the names of the students in a particular grade.
"""
def students_by_grade(pid, grade) do
GenServer.call(pid, {:students_by_grade, grade})
end
@doc """
Return the names of the all students separated by grade.
"""
def students_by_grade(pid) do
GenServer.call(pid, :all_students)
end
# Callbacks
def handle_cast({:add, name, grade}, state) do
state = Map.update(state, grade, [name], &([name|&1]))
{:noreply, state}
end
def handle_call({:students_by_grade, grade}, _from, state) do
students = Map.get(state, grade, []) |> Enum.sort
{:reply, students, state}
end
def handle_call(:all_students, _from, state) do
all_students = state
|> Map.keys
|> Enum.map(fn(grade) ->
[grade: grade, students: get_students_by_grade(state, grade)]
end)
{:reply, all_students, state}
end
# Private functions
defp get_students_by_grade(state, grade) do
Map.get(state, grade, []) |> Enum.sort
end
end
Source: https://habr.com/ru/post/307720/
All Articles