Este está se tornando um assunto bem abordado. Mas eu acho que isso é tão incrível que quero compartilhar minha visão.
Contexto
Estou desenvolvendo um processo de login OAuth para meu aplicativo play2: www.trendytics.com
OAuth requer algumas viagens de ida e volta para a troca de informações.
Além disso, estou buscando informações de forma incremental.
Portanto, o jogo 2 tem esta interface incrível para buscar urls com variáveis post / get:
WS.url("www.google.com")
Você pode então compor isso com cabeçalhos e parâmetros, fazer uma solicitação GET ou POST, transformá-la em json, etc.
A certa altura, precisei fazer 3 dessas chamadas de url, cada uma exigindo informações da chamada anterior.
Eu continuei recebendo erros neles .. então eu adotei uma abordagem diferente
Entre em qualquer um
Qualquer um codifica dois tipos de retorno. Tradicionalmente, as pessoas colocam erros e sucessos nelas, mas você pode colocar o que quiser / precisar.
Portanto, com Either você pode codificar sucessos e erros.
O que o torna interessante? Bem, você pode fazer isso:
type Error = String
type Success = String
def call(url:String):Either[Error,Success]={
val response = WS.url(url).get.value.get
if (valid(response))
Right(response.body)
else Left("Response is not valid")
}
Isso retorna um Sucesso ou um Erro (ambas as Strings, neste caso) se uma função válida não aceitar a resposta.
Left () cria uma instância Either com o elemento left atribuído (neste caso, um erro).
Right () faz o oposto.
Na prática, essas classes instanciam Esquerda e Direita que são subclasses do tipo Either, mas são tratadas como Either
Além disso, você pode até adicionar tratamento de exceção a isso.
E daí, você pergunta?
Bem, agora trabalhamos com o Either
Cada chamador agora tem a capacidade de refinar ainda mais o valor de Sucesso ou retornar um Erro se ele falhar – o que causará falha em toda a operação com uma mensagem de erro
Exemplo:
def example(parameter:String):Either[Error,Success]=
for (parameter1 <- call("www.site.com/parameter").right;
parameter2 <- call("www.site.com/"+parameter1).right;
parameter3 <- call("www.site.com/"+parameter2).right) yield
(parameter3)
E isso chama cada url e combina as três chamadas em que cada uma é feita apenas se a anterior for bem-sucedida.
Em resumo: combinar três chamadas erradas, sem perder dados nem explodir na cara do usuário, em um belo pacote.
Por fim, podemos retornar o sucesso ou mostrar as mensagens de erro, se houver. Mas o processamento intermediário não precisava saber disso.
O que estou fazendo é dobrá-lo:
example("parameter").fold(treatIfErrors(), treatIfSuccess())
Essas funções retornam o mesmo tipo. O Fold pode então ser usado para unificar seus resultados de processamento, tratando erros e acertos conforme necessário.
Como você faz isso na sua linguagem de programação favorita? (sem se e outros)