2016-05-27 3 views
2

Есть ли способ реорганизовать это в Elixir, чтобы сделать его более читаемым?Как избежать вложенных операторов if в 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 

Что это за эликсир, потому что этот код выглядит как PHP. Я этого не писал.

+1

Разложить код на подфункции. У меня нет времени прямо сейчас, чтобы переписать этот код, но отрисуйте самую внутреннюю 'if' в отдельную функцию и, возможно, аналогично с другим' if''s –

+1

, ваш разработчик должен принять это замечательное руководство по началу работы, понять по крайней мере, ключевые моменты: http://elixir-lang.org/getting-started/introduction.html – webdeb

+1

Похоже, что этот вопрос будет больше дома на бирже обзора кода –

ответ

4

Вы правы, это похоже на 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} 

что-то вроде этого, это не работает код на всех , просто чтобы дать представление, то как сопоставление с образцом для работы и ее преимущества

+1

Ваш последний аргумент 'handle_error' никогда не будет соответствовать. Это эквивалентно первому, но просто игнорирует параметр. Вы предполагали, что это просто 'handle_error()' - без параметра? – CoderDennis

+0

спасибо, его обновили;) – webdeb

2

Вы можете попробовать переписать этот код, используя 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 может потребовать больше изменений в другой трески e или введение вспомогательных функций для возврата распознаваемых значений и ошибок. with в настоящее время не поддерживает защиту в шаблонах, но в 1.3.

+0

Выглядит более организованным, но все же беспорядок ИМХО. – kgpdeveloper

0

Вот немного другого подхода, который мне нравится использовать, когда логика становится очень сложной, а инструкции с/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 
Смежные вопросы