From 8d64ab7b767cd7156c6abe67787235658caca1cf Mon Sep 17 00:00:00 2001 From: mrkaspa Date: Thu, 7 Jul 2016 10:51:05 -0500 Subject: [PATCH] code improvements --- TODO.md | 7 +-- lib/exstreme/graph.ex | 60 ++++++++++++---------- lib/exstreme/graph_builder.ex | 19 +++---- lib/exstreme/graph_creator.ex | 69 +++++++++++++------------- mix.exs | 3 +- mix.lock | 4 +- test/exstreme/graph_creator_test.exs | 2 +- test/exstreme/graph_test.exs | 4 +- test/exstreme/graph_validator_test.exs | 4 +- 9 files changed, 92 insertions(+), 80 deletions(-) diff --git a/TODO.md b/TODO.md index 2e46e0d..3ca7116 100644 --- a/TODO.md +++ b/TODO.md @@ -3,11 +3,12 @@ x- Named nodes with graph name x- Add documentation x- Use nid to connect X- Get nid for a node -- A node must have a function -- The function in Broadcast and Funnel nodes can be optional +X- A node must have a function +X- The function in Broadcast and Funnel nodes can be optional - Add Supervisors functionality - Use counters for stats x- Improve test -- Improve API +Future +- Improve API - Update to GenStage diff --git a/lib/exstreme/graph.ex b/lib/exstreme/graph.ex index 26ba3c6..0d9f70c 100644 --- a/lib/exstreme/graph.ex +++ b/lib/exstreme/graph.ex @@ -44,13 +44,13 @@ defmodule Exstreme.Graph do end @doc """ - Gets the starting node + Gets the starting gnode """ @spec find_start_node(t) :: [atom] def find_start_node(%Graph{nodes: nodes, connections: connections}) do is_first? = - fn(node) -> - at_first?(connections, node) and not(at_last?(connections, node)) + fn(gnode) -> + at_first?(connections, gnode) and not(at_last?(connections, gnode)) end nodes @@ -64,8 +64,8 @@ defmodule Exstreme.Graph do @spec find_last_node(t) :: [atom] def find_last_node(%Graph{nodes: nodes, connections: connections}) do is_last? = - fn(node) -> - not(at_first?(connections, node)) and at_last?(connections, node) + fn(gnode) -> + not(at_first?(connections, gnode)) and at_last?(connections, gnode) end nodes @@ -77,37 +77,43 @@ defmodule Exstreme.Graph do Gets the nodes before the current one """ @spec get_before_nodes(t, atom) :: [atom] - def get_before_nodes(%Graph{connections: connections}, node) do + def get_before_nodes(%Graph{connections: connections}, gnode) do compare_func = fn(current_node, {from, to}) -> {current_node == to, from} end - Enum.reduce(connections, [], fn(connection, res) -> - List.flatten(get_nodes_func(node, connection, res, compare_func), res) - end) |> Enum.uniq + + connections + |> Enum.reduce([], fn(connection, res) -> + List.flatten(get_nodes_func(gnode, connection, res, compare_func), res) + end) + |> Enum.uniq end @doc """ Gets the nodes after the current one """ @spec get_after_nodes(t, atom) :: [atom] - def get_after_nodes(%Graph{connections: connections}, node) do + def get_after_nodes(%Graph{connections: connections}, gnode) do compare_func = fn(current_node, {from, to}) -> {current_node == from, to} end - Enum.reduce(connections, [], fn(connection, res) -> - res ++ get_nodes_func(node, connection, res, compare_func) - end) |> Enum.uniq + + connections + |> Enum.reduce([], fn(connection, res) -> + res ++ get_nodes_func(gnode, connection, res, compare_func) + end) + |> Enum.uniq end @doc """ - Gets the name in the Graph for one node + Gets the name in the Graph for one gnode """ @spec nid(t, atom) :: atom - def nid(%Graph{name: name}, node) do + def nid(%Graph{name: name}, gnode) do [char, rest] = - node + gnode |> Atom.to_string |> String.codepoints String.to_atom("#{char}_#{name}_#{rest}") @@ -119,8 +125,8 @@ defmodule Exstreme.Graph do @spec map_to_connections(t) :: [atom] defp map_to_connections(%Graph{nodes: nodes, connections: connections}) do to_connections = - fn(node) -> - case {at_first?(connections, node), at_last?(connections, node)} do + fn(gnode) -> + case {at_first?(connections, gnode), at_last?(connections, gnode)} do {true, true} -> :connected {true, false} -> :begin {false, true} -> :end @@ -133,26 +139,26 @@ defmodule Exstreme.Graph do |> Enum.map(to_connections) end - # Checks if a node is the first position of a connection + # Checks if a gnode is the first position of a connection @spec at_first?(%{key: atom}, atom) :: boolean - defp at_first?(connections, node) do - Map.has_key?(connections, node) + defp at_first?(connections, gnode) do + Map.has_key?(connections, gnode) end - # Checks if a node is the last position of a connection + # Checks if a gnode is the last position of a connection @spec at_last?(%{key: atom}, atom) :: boolean - defp at_last?(connections, node) do + defp at_last?(connections, gnode) do connections |> Map.values |> List.flatten - |> Enum.member?(node) + |> Enum.member?(gnode) end @spec get_nodes_func(atom, {atom, atom}, [atom], ((atom, {atom, atom}) -> boolean)) :: [atom] - defp get_nodes_func(node, {from, to} = pair, res, func) do + defp get_nodes_func(gnode, {from, to} = pair, res, func) do case to do to when is_atom(to) -> - {ok, add_node} = func.(node, pair) + {ok, add_node} = func.(gnode, pair) if ok do [add_node | res] else @@ -160,7 +166,7 @@ defmodule Exstreme.Graph do end to when is_list(to) -> Enum.reduce(to, res, fn(current_to, new_res) -> - List.flatten(get_nodes_func(node, {from, current_to}, new_res, func), new_res) + List.flatten(get_nodes_func(gnode, {from, current_to}, new_res, func), new_res) end) end end diff --git a/lib/exstreme/graph_builder.ex b/lib/exstreme/graph_builder.ex index 24bf80d..70be31b 100644 --- a/lib/exstreme/graph_builder.ex +++ b/lib/exstreme/graph_builder.ex @@ -27,13 +27,13 @@ defmodule Exstreme.GraphBuilder do @spec update_nodes_relations(Graph.t) :: Graph.t defp update_nodes_relations(graph) do update_node_func = - fn({node, params}) -> + fn({gnode, params}) -> new_params = params - |> Keyword.put(:before_nodes, Graph.get_before_nodes(graph, node)) - |> Keyword.put(:after_nodes, Graph.get_after_nodes(graph, node)) + |> Keyword.put(:before_nodes, Graph.get_before_nodes(graph, gnode)) + |> Keyword.put(:after_nodes, Graph.get_after_nodes(graph, gnode)) - {node, new_params} + {gnode, new_params} end update_in(graph.nodes, &(&1 |> Enum.map(update_node_func) |> Map.new)) @@ -49,13 +49,13 @@ defmodule Exstreme.GraphBuilder do end) end - # Starts a node + # Starts a gnode @spec start_node({atom, [term: any]}) :: {atom, [key: any]} - defp start_node({node, params}) do + defp start_node({gnode, params}) do type = Keyword.get(params, :type) params = params - |> Keyword.put(:nid, node) + |> Keyword.put(:nid, gnode) |> Keyword.put_new(:func, fn(data, _) -> {:ok, data} end) {:ok, _} = case type do @@ -63,7 +63,7 @@ defmodule Exstreme.GraphBuilder do :funnel -> Funnel.start_link(params) _ -> Common.start_link(params) end - {node, params} + {gnode, params} end # Connects all nodes @@ -76,7 +76,8 @@ defmodule Exstreme.GraphBuilder do # Connects two nodes @spec connect_pair({atom, [atom]}, %{key: [key: term]}) :: no_return defp connect_pair({from, to}, nodes) when is_list(to) do - Enum.map(1..Enum.count(to), fn(_) -> from end) + 1..Enum.count(to) + |> Enum.map(fn(_) -> from end) |> Enum.zip(to) |> Enum.each(&(connect_pair(&1, nodes))) end diff --git a/lib/exstreme/graph_creator.ex b/lib/exstreme/graph_creator.ex index 236173b..3ae7683 100644 --- a/lib/exstreme/graph_creator.ex +++ b/lib/exstreme/graph_creator.ex @@ -17,7 +17,8 @@ defmodule Exstreme.GraphCreator do @spec create_graph([key: term]) :: Graph.t def create_graph(params) do name = - :crypto.strong_rand_bytes(@default_length_name) + @default_length_name + |> :crypto.strong_rand_bytes |> Base.url_encode64 |> binary_part(0, @default_length_name) create_graph(name, params) @@ -30,7 +31,7 @@ defmodule Exstreme.GraphCreator do def create_graph(name, params), do: %Graph{name: name, params: params} @doc """ - Creates a simple node + Creates a simple gnode """ @spec create_node(Graph.t, [key: term]) :: {Graph.t, atom} def create_node(graph = %Graph{nodes: nodes}, params \\ []) do @@ -41,7 +42,7 @@ defmodule Exstreme.GraphCreator do end @doc """ - Creates a broadcast node + Creates a broadcast gnode """ @spec create_broadcast(Graph.t, [key: term]) :: {Graph.t, atom} def create_broadcast(graph = %Graph{nodes: nodes}, params \\ []) do @@ -52,7 +53,7 @@ defmodule Exstreme.GraphCreator do end @doc """ - Creates a funnel node + Creates a funnel gnode """ @spec create_funnel(Graph.t, [key: term]) :: {Graph.t, atom} def create_funnel(graph = %Graph{nodes: nodes}, params \\ []) do @@ -72,7 +73,7 @@ defmodule Exstreme.GraphCreator do update_in(graph.connections, store_connection_fn(start, finish)) end else - raise ArgumentError, message: "You can't connect to the same node" + raise ArgumentError, message: "You can't connect to the same gnode" end end @@ -101,7 +102,7 @@ defmodule Exstreme.GraphCreator do end end - # validations before adding a node + # validations before adding a gnode # Validates when a relation already exists @spec validate_repeated(%{key: atom}, atom, atom) :: %{key: atom} @@ -120,52 +121,52 @@ defmodule Exstreme.GraphCreator do end end - # Validates the node position + # Validates the gnode position @spec validate_position(%{key: atom}, atom, :start | :end) :: %{key: atom} - defp validate_position(connections, node, position) do - case node |> Atom.to_string |> String.first do - "n" -> validate_position_node(connections, node, position) - "b" -> validate_position_broadcast(connections, node, position) - "f" -> validate_position_funnel(connections, node, position) - _ -> raise ArgumentError, message: "invalid node" + defp validate_position(connections, gnode, position) do + case gnode |> Atom.to_string |> String.first do + "n" -> validate_position_node(connections, gnode, position) + "b" -> validate_position_broadcast(connections, gnode, position) + "f" -> validate_position_funnel(connections, gnode, position) + _ -> raise ArgumentError, message: "invalid gnode" end end - # Validates if a normal node can be at the beginning of the relation + # Validates if a normal gnode can be at the beginning of the relation @spec validate_position_node(%{key: atom}, atom, :start) :: %{key: atom} - defp validate_position_node(connections, node, :start) do - validate_position_start(connections, node,"the node can't be twice at start position #{node}") + defp validate_position_node(connections, gnode, :start) do + validate_position_start(connections, gnode,"the gnode can't be twice at start position #{gnode}") end - # Validates if a normal node can be at the end of the relation + # Validates if a normal gnode can be at the end of the relation @spec validate_position_node(%{key: atom}, atom, :end) :: %{key: atom} - defp validate_position_node(connections, node, :end) do - validate_position_end(connections, node,"the node can't be twice at end position") + defp validate_position_node(connections, gnode, :end) do + validate_position_end(connections, gnode,"the gnode can't be twice at end position") end - # Validates if a broadcast node can be at the beginning of the relation + # Validates if a broadcast gnode can be at the beginning of the relation @spec validate_position_broadcast(%{key: atom}, atom, :start) :: %{key: atom} defp validate_position_broadcast(connections, _node, :start), do: connections - # Validates if a broadcast node can be at the end of the relation + # Validates if a broadcast gnode can be at the end of the relation @spec validate_position_broadcast(%{key: atom}, atom, :end) :: %{key: atom} defp validate_position_broadcast(connections, bct, :end) do validate_position_end(connections, bct, "the broadcast can't be twice at end position") end - # Validates if a funnel node can be at the beginning of the relation + # Validates if a funnel gnode can be at the beginning of the relation @spec validate_position_funnel(%{key: atom}, atom, :start) :: %{key: atom} - defp validate_position_funnel(connections, node, :start) do - validate_position_start(connections, node,"the funnel can't be twice at start position #{node}") + defp validate_position_funnel(connections, gnode, :start) do + validate_position_start(connections, gnode,"the funnel can't be twice at start position #{gnode}") end - # Validates if a funnel node can be at the normal of the relation + # Validates if a funnel gnode can be at the normal of the relation @spec validate_position_funnel(%{key: atom}, atom, :end) :: %{key: atom} defp validate_position_funnel(connections, _node, :end), do: connections @spec validate_position_start(%{key: atom}, atom, String.t) :: %{key: atom} - defp validate_position_start(connections, node, msg) do - exist = Map.has_key?(connections, node) + defp validate_position_start(connections, gnode, msg) do + exist = Map.has_key?(connections, gnode) if exist do raise ArgumentError, message: msg else @@ -174,11 +175,11 @@ defmodule Exstreme.GraphCreator do end @spec validate_position_end(%{key: atom}, atom, String.t) :: %{key: atom} - defp validate_position_end(connections, node, msg) do + defp validate_position_end(connections, gnode, msg) do exist = connections |> Map.values - |> Enum.member?(node) + |> Enum.member?(gnode) if exist do raise ArgumentError, message: msg else @@ -186,17 +187,17 @@ defmodule Exstreme.GraphCreator do end end - # Validates the node exist on the graph + # Validates the gnode exist on the graph @spec validate_node_exist(%{key: [key: term]}, atom) :: true - defp validate_node_exist(nodes, node) do - if Map.has_key?(nodes, node) do + defp validate_node_exist(nodes, gnode) do + if Map.has_key?(nodes, gnode) do true else - raise ArgumentError, message: "node #{node} not found" + raise ArgumentError, message: "gnode #{gnode} not found" end end - # Gets the next key for the node, these begin with the 'n' letter + # Gets the next key for the gnode, these begin with the 'n' letter @spec next_node_key(Graph.t, %{key: atom}) :: atom defp next_node_key(graph, nodes) do next_key(graph, nodes, "n") diff --git a/mix.exs b/mix.exs index 75c9a80..e7935c7 100644 --- a/mix.exs +++ b/mix.exs @@ -32,7 +32,8 @@ defmodule Exstreme.Mixfile do # Type "mix help deps" for more examples and options defp deps do [ - {:dialyxir, "~> 0.3", only: [:dev]} + {:dialyxir, "~> 0.3", only: [:dev]}, + {:credo, "~> 0.4", only: [:dev, :test]} ] end end diff --git a/mix.lock b/mix.lock index 2ed836d..6eca57c 100644 --- a/mix.lock +++ b/mix.lock @@ -1 +1,3 @@ -%{"dialyxir": {:hex, :dialyxir, "0.3.3", "2f8bb8ab4e17acf4086cae847bd385c0f89296d3e3448dc304c26bfbe4b46cb4", [:mix], []}} +%{"bunt": {:hex, :bunt, "0.1.6", "5d95a6882f73f3b9969fdfd1953798046664e6f77ec4e486e6fafc7caad97c6f", [:mix], []}, + "credo": {:hex, :credo, "0.4.5", "5c5daaf50a2a96068c0f21b6fbd382d206702efa8836a946eeab0b8ac25f5f22", [:mix], [{:bunt, "~> 0.1.6", [hex: :bunt, optional: false]}]}, + "dialyxir": {:hex, :dialyxir, "0.3.3", "2f8bb8ab4e17acf4086cae847bd385c0f89296d3e3448dc304c26bfbe4b46cb4", [:mix], []}} diff --git a/test/exstreme/graph_creator_test.exs b/test/exstreme/graph_creator_test.exs index 6d5496b..6d76ea9 100644 --- a/test/exstreme/graph_creator_test.exs +++ b/test/exstreme/graph_creator_test.exs @@ -30,7 +30,7 @@ defmodule Exstreme.GraphCreatorTest do end test "throws an error when adding again a self relation", %{graph: graph, n1: n1} do - assert_raise ArgumentError, "You can't connect to the same node", fn -> + assert_raise ArgumentError, "You can't connect to the same gnode", fn -> graph |> GraphCreator.add_connection(n1, n1) end diff --git a/test/exstreme/graph_test.exs b/test/exstreme/graph_test.exs index 249da43..ac2c8ac 100644 --- a/test/exstreme/graph_test.exs +++ b/test/exstreme/graph_test.exs @@ -20,11 +20,11 @@ defmodule Exstreme.GraphTest do assert Graph.connections_stats(graph) == %{begin: 1, connected: 5, end: 1} end - test "the start node is n1", %{graph: graph, n1: n1} do + test "the start gnode is n1", %{graph: graph, n1: n1} do assert Graph.find_start_node(graph) == [n1] end - test "the last node is n5", %{graph: graph, n5: n5} do + test "the last gnode is n5", %{graph: graph, n5: n5} do assert Graph.find_last_node(graph) == [n5] end diff --git a/test/exstreme/graph_validator_test.exs b/test/exstreme/graph_validator_test.exs index cc9a3f1..442ab09 100644 --- a/test/exstreme/graph_validator_test.exs +++ b/test/exstreme/graph_validator_test.exs @@ -8,7 +8,7 @@ defmodule Exstreme.GraphValidatorTest do assert :ok = GraphValidator.validate(graph_many_nodes) end - test "the graph with one node must be invalid" do + test "the graph with one gnode must be invalid" do assert {:error, _} = GraphValidator.validate(graph_one_node_no_connections) end @@ -16,7 +16,7 @@ defmodule Exstreme.GraphValidatorTest do assert {:error, _} = GraphValidator.validate(graph_no_connections) end - test "the graph should start in a node" do + test "the graph should start in a gnode" do assert {:error, _} = GraphValidator.validate(graph_start_with_broadcast) assert {:error, _} = GraphValidator.validate(graph_start_with_funnnel) end