如何避免Elixir中的嵌套if语句?
有没有办法在Elixir中重构它,使它更具可读性如何避免Elixir中的嵌套if语句?,elixir,Elixir,有没有办法在Elixir中重构它,使它更具可读性 def validate(params) do Repo.start_link if validate_oauth_params(params) === true do oauth_client = Repo.get_by(OauthClient, random_id: params["client_id"], secret: params["secret"]) if oauth_client !=
def validate(params) do
Repo.start_link
if validate_oauth_params(params) === true do
oauth_client = Repo.get_by(OauthClient, random_id: params["client_id"], secret: params["secret"])
if oauth_client != nil do
allowed_grant_types = Poison.Parser.parse!(oauth_client.allowed_grant_types)
if Map.has_key?(allowed_grant_types, params["grant_type"]) do
case params["grant_type"] do
"password" ->
process_password_grant(params, oauth_client)
"refresh_token" ->
process_refresh_token_grant(params["refresh_token"], oauth_client)
"client_credentials" ->
process_client_credentials_grant(oauth_client)
nil ->
%{message: "Invalid oauth credentials", code: 400}
end
end
else
%{message: "Invalid oauth credentials", code: 400}
end
else
%{message: "Invalid oauth credentials", code: 400}
end
end
因为这段代码看起来像PHP,所以它的灵丹妙药是什么。不是我写的。你说得对,它看起来像PHP。没有使用类似长生不老药的模式匹配的好处 重构这一部分是很困难的,因为似乎其他方法也应该重构,以使其更干净。例如,
validate_oauth_params
函数“可以”返回一个元组而不是布尔值,因此可以对其进行模式匹配,操作如下:
def validate(params) do
case validate_oauth_params(params) do
{:ok, params} -> choose_oauth_method params
{:error} -> handle_error "Invalid params"
end
end
defp choose_oauth_method(%{"grant_type" => "password"} = params) do
process_password_grant(params)
end
defp choose_oauth_method(%{"grant_type" => nil}) do
handle_error "Method undefined"
end
defp handle_error(msg), do: %{message: msg, code: 400}
defp handle_error(msg, code), do: %{message: msg, code: code}
defp handle_error(), do: %{message: "Default error massage", code: 400}
类似这样的代码根本不起作用,只是想说明一下模式匹配的工作原理及其优点您可以尝试使用
with
表达式将此代码重写为
def validate(params) do
with
{:ok, p} <- validate_oauth_params(params),
{:ok, client} = get_client_for_params(p),
{:ok, allowed_grant_types} <- Poison.Parser.parse(oauth_client.allowed_grant_types)
do
case params["grant_type"] do
"password" ->
process_password_grant(params, oauth_client)
"refresh_token" ->
process_refresh_token_grant(params["refresh_token"], oauth_client)
"client_credentials" ->
process_client_credentials_grant(oauth_client)
nil -> :error
end
end |> case do
{:ok, something} -> something
_ -> %{message: "Invalid oauth credentials", code: 400}
end
end
def验证(参数)do
具有
{:好的,p}
处理刷新令牌授权(参数[“刷新令牌”],oauth\u客户端)
“客户端凭据”->
处理客户端凭据授权(oauth客户端)
无->:错误
结束
结束|>case do
{:好的,什么东西}->什么东西
_->%{消息:“无效的oauth凭据”,代码:400}
结束
结束
然而,这样的重构可能需要在其他代码中进行更多的更改,或者引入辅助函数来返回可识别的值和错误<带有的代码>目前不支持模式中的防护,但在1.3中会支持 当逻辑变得非常复杂,并且with/do语句不够时,我喜欢使用一种不同的方法
def validate(params) do
try do
if !validate_oauth_params(params), do:
throw({:error, %{message: "Invalid oauth credentials", code: 400}})
if !oauth_client, do:
throw({:error, %{message: "Invalid oauth credentials", code: 400}})
allowed_grant_types = Poison.Parser.parse!(oauth_client.allowed_grant_types)
if !Map.has_key?(allowed_grant_types, params["grant_type"]), do:
throw({:error, %{message: "No grant type", code: 400}})
case params["grant_type"] do
"password" ->
process_password_grant(params, oauth_client)
"refresh_token" ->
process_refresh_token_grant(params["refresh_token"], oauth_client)
"client_credentials" ->
process_client_credentials_grant(oauth_client)
nil ->
throw({:error, %{message: "Invalid oauth credentials", code: 400}})
end
catch
{:error, map} -> {:error, map}
else
result -> {:ok, result}
end
end
将代码分解为子函数。我现在没有时间重新编写代码,但将最里面的
if
抽象为一个单独的函数,并可能对另一个if
也这样做。您的开发人员应该学习这本很棒的入门指南,至少要理解关键点:似乎这个问题在代码审查交换中更为常见。如何将它转移到那里?希望有办法。很抱歉。我以为这里有更多的潜伏者。看起来更有条理,但仍然很混乱。你最后的handle\u error
子句永远不会匹配。它与第一个等效,但忽略了参数。您是否希望它只是handle\u error()
——没有参数?