有没有办法在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 != 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
Elixir的做法是什么,因为这段代码看起来像PHP。我没有写。
答案 0 :(得分:4)
你是对的,它看起来像PHP。不使用elixir的模式匹配的好处。
很难重构这一件,因为似乎其他方法也应该重构,以使其更干净。例如,POST /accounts/client/_search
{
"bool": {
"must": [
{
"match": {
"name": "big" <--- free text name match
}
}
],
"filter": {
"geo_shape": {
"location": {
"indexed_shape": {
"id": "M320JG-2", <--- located within two miles of M32 0JG
"type": "UK_postcode",
"index": "locations",
"path": "location"
}
}
}
}
}
}
函数“可以”返回一个元组而不是一个布尔值,所以你可以对它进行模式匹配,你会这样做:
validate_oauth_params
类似这样的东西,这根本不是代码,只是为了给出一个想法,模式匹配如何工作及其好处
答案 1 :(得分:3)
您可以尝试使用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
然而,这样的refactiong可能需要在其他代码中进行更多更改或引入辅助函数以返回可识别的值和错误。 with
目前不支持模式中的守卫,但它将在1.3中支持。
答案 2 :(得分:-1)
当逻辑变得非常复杂且带有/ 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