Elixir - 交叉切割问题

时间:2016-08-13 19:30:43

标签: elixir

在Elixir中执行某些交叉问题的方式是什么?假设我想检查用户是否取消订阅电子邮件 - 是否可以在执行任何电子邮件发送功能之前执行此操作?在Elixir文档中找不到任何关于交错其他函数的内容......就像在rails中的before_filter但在独立的Elixir应用程序中一样。可能会发送多封电子邮件 - 通知,营销,交易等。添加每个未订阅的电子邮件?手动检查每个功能是非常必要的。 Elixir有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

在Rails中,使用before_filter实际上会导致糟糕的设计。我知道以这种方式编写代码会更容易,但过了一段时间,代码库会增长,你会在这些回调中添加更多逻辑,然后开始放松对它们的控制。

你可以在没有回调的情况下做同样的事情,使用简单的函数,并以命令的方式保持控制(更容易推理和调试)。

假设您有一个具有多个电子邮件功能的模块

defmodule Mailer do
  def send_email1(params) do
    # do work
  end

  def send_email2(params) do
  end

  # ...
end

您可以简单地将代码添加到每个函数中,而不是添加某种before_filter吗?这很容易理解发生了什么。

defmodule Mailer do
  def send_email1(params) do
    if can_send?(params) do
      # do work
    end
  end

  # ...
end

现在你注意到你有重复的逻辑。那么......您可以将检查逻辑移动到更新的功能,并至少从每个功能中删除if。但是你也可以创建一个新的抽象并保持共享逻辑。

defmodule Mailer do
  def send_email(email_name, params) do
    if can_send?(params) do
      do_send_email(email_name, params)
    end
  end

  defp do_send_email("email1", params) do
    # do work
  end
  # ...
end

这比使用回调的任何替代方法更简单。你可以控制它。如果需要,可以轻松添加或更改共享逻辑,并为其添加条件逻辑。

答案 1 :(得分:0)

我喜欢使用Elixir的module attributes来启动一系列尾调优化函数调用。这样可以很容易地在一个地方声明回调。

defmodule MyMod do

  @before_filter [:check_email]

  def check_email(1), do: true
  def check_email(state), do: false

  def save(state) do
    save(state, @before_filter)
  end

  defp save(state, []) do
    # do actual save
    {:ok, state}
  end

  defp save(state, [callback|tail]) do
    if :erlang.apply(__MODULE__, callback, [state]) do
      save(state, tail)
    else
      {:error, callback, state}
    end
  end
end