Suscribete en nuestro Newsletter

Regístrate en nuestro Newsletter para estar al tanto de las noticias, talleres y podcast que tendremos próximamente
Suscríbete aqui

Foto del autor Adrian

API's fluidos (Ejemplo en Java-Android context)

API's fluidos (Ejemplo en Java-Android context)

Motivación

Somos nuevos desarrollando para Android y los mas normal es que tarde o temprano tengamos que interactuar con un servidor vía http, buscamos en google[1] y veremos algo como esto :

                public static void connect(String url)
                {
                
                    HttpClient httpclient = new DefaultHttpClient();
                
                    // Prepare a request object
                    HttpGet httpget = new HttpGet(url); 
                
                    // Execute the request
                    HttpResponse response;
                    try {
                        response = httpclient.execute(httpget);
                        // Examine the response status
                        Log.i("Praeda",response.getStatusLine().toString());
                
                        // Get hold of the response entity
                        HttpEntity entity = response.getEntity();
                        // If the response does not enclose an entity, there is no need
                        // to worry about connection release
                
                        if (entity != null) {
                
                            // A Simple JSON Response Read
                            InputStream instream = entity.getContent();
                            String result= convertStreamToString(instream);
                            // now you have the string representation of the HTML request
                            instream.close();
                        }
                
                
                    } catch (Exception e) {}
                }
                
                    private static String convertStreamToString(InputStream is) {
                    /*
                     * To convert the InputStream to String we use the BufferedReader.readLine()
                     * method. We iterate until the BufferedReader return null which means
                     * there's no more data to read. Each line will appended to a StringBuilder
                     * and returned as String.
                     */
                    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                    StringBuilder sb = new StringBuilder();
                
                    String line = null;
                    try {
                        while ((line = reader.readLine()) != null) {
                            sb.append(line + "\n");
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            is.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    return sb.toString();
                

Al ver eso pensamos bueno es Java es de esperarse porque google no uso *inserte lenguaje nuevo aquí* para el desarrollo de aplicaciones, bla , bla. Al final tenemos que ponernos a la tarea de lidiar con eso, decidimos hacer un pequeño api http para integrarlo a nuestra aplicación.

Solución Procedimental

Podemos hacer un método por cada método http que necesitemos y enviarle una lista de parámetros y headers, quedando algo así :

                public class Rest{
                
                        public static get(String url,List<NamePair> params,List<NamePair> headers){
                                // hacer la llamada get
                        }
                
                        public static post(String url,List<NamePair> params,List<NamePair> headers){
                                // hacer la llamada post
                        }
                
                }
                

Bueno no luce tan mal(right), veamos como seria un cliente de eso

                List<NamePair> params = new ArrayList<NamePair>();
                params.add(new BasicNamePair("key1","value1"));
                params.add(new BasicNamePair("key2","value2"));
                
                List<NamePair> headers = new ArrayList<NamePair>();
                headers.add(new BasicNamePair("key1","value1"));
                headers.add(new BasicNamePair("key2","value2"));
                
                String response = Rest.get(URL_BASE,params,headers);
                
                

Bueno peor de lo que se esperaba, que tal si no confundo el orden de los parámetros o si quiero agregar otro parámetro. En definitiva este código es propenso a errores y difícil de extender.

Solución Orientada a Objectos

Pensamos bueno Java es OO que tal si abstraemos la combinación de url, parámetros y headers en un objecto llamado "Request"

                public class Request{
                        private String url;
                        private List<NamePair> params;
                        private List<NamePair> headers;
                
                        public Resquest(String url){
                                this.url = url;
                        }
                
                        public void addParam(String key,String value){
                                params.add(new BasicNamePair(key,value)); 
                        }
                
                        public void addHeader(String key,String value){
                                headers.add(new BasicNamePair(key,value)); 
                        }
                        
                        //otras cosas
                
                }
                
                
                public class Rest{
                        
                        public static String get(Resquest request){
                                // la llamada al get
                        }
                } 
                
                //cliente
                
                Request request = new Request(URL);
                request.addParam("key1","value1");
                request.addParam("key2","value2");
                request.addHeader("key1","value1");
                request.addHeader("key2","value2");
                
                String response = Rest.get(resquest);
                
                
                

Un poco mejor, podemos extenderlo simplemente agregándole mas atributos al objecto request pero todavía no se ve una solución del todo elegante(dentro de lo que Java nos deja).

Solución API Fluido(Fluent Interface)[2]

Un API fluido(o Interfaz Fluida) es un patrón de diseño que consiste en encadenar llamadas a métodos, donde un objecto se modifica y retorna así mismo con un fin definido. En este caso el fin es enviar parámetros opcionales y finalmente enviar el request.
                public class Rest{
                        private String url;
                        private List<NamePair> params;
                        private List<NamePair> headers;
                
                        private Rest(String url){
                        }
                
                        public static Rest client(String url){
                                new Rest(url);
                        }
                
                        public Rest param(String key,String value){
                                this.params.add(new BasicNameValue(key,value));
                                return this;
                        }
                
                        public Rest header(String key,String value){
                                this.headers.add(new BasicNameValue(key,value));
                                return this;
                        }
                
                        public String get(){
                                //hacer la llamada get
                        }
                
                }
                 
                //Cliente
                
                String response = Rest.client(URL)
                                      .param("key1","value1")
                                      .param("key2","value2")
                                      .header("key1","value1")
                                      .header("key2","value2")
                                      .get();
                
                

Mucho mejor, si quisieras extenderlo como por ejemplo depurar(debug) las llamadas o integrarlo a un json parser(eg gson) después de modificar la clase Rest tu cliente podría quedar algo así.

                User user = Rest.client(URL)
                                .param("id","V-111111")
                                .header("Autorization","1234")
                                .debug()
                                .from(Json.class)
                                .to(User.class)
                                .get();
                
                

Fluent Interface se puede aplicar en cualquier lenguaje, de hecho JQuery sigue fuertemente este patrón de diseño. Usado apropiadamente puede simplificar considerablemente la forma de interactuar con tu código.