Home Menu

Menu



Programación y Desarrollo para Android Subforo exclusivo para temas de programación de software para PDAs y desarrollo de aplicaciones, interfaces, etc bajo Android


 
Herramientas
  #1  
Viejo 14/05/16, 20:51:06
Avatar de vAlmaraz
vAlmaraz vAlmaraz no está en línea
Miembro del foro
Mensajes: 207
 
Fecha de registro: dic 2012
Mensajes: 207
Modelo de smartphone: Nexus 5, Pomp P8, Sony Xperia X10 Mini Pro
Versión de ROM: Android 6.0.1
Tu operador: Jazztel
Mencionado: 0 comentarios
Tagged: 0 hilos
Patrones de diseño y de arquitectura

Buenas,

Para todo el que le interese aprender sobre patrones de diseño y arquitectura, aporto un artículo en mi blog sobre el patrón de repositorios y un repositorio en GitHub que he creado con un proyecto Android simple para aprender a aplicar MVP en apps.

Enlaces:
http://www.valmaraz.com/blog-41-patr...lo-de-software
https://github.com/vAlmaraz/mvp-android

Para los que no tengan mucha experiencia aplicando patrones, convendría empezar por el de repositorios. Una vez familiarizado con él, resulta más fácil pasar a otros patrones, como MVP y Clean Architecture.

En el README del repositorio hay una explicación (en inglés) de conceptos básicos, pasos previos, etc para aprender a sobre arquitectura de software.

Es totalmente convertible o traducible para iOS:
- Activities por ViewControllers
- Adapters por DataSources y Delegates
- Retrofit por AFNetworking
- Application por AppDelegate
- ....

Iré completando y mejorando el proyecto para hacerlo más completo y con una interfaz más atractiva.

Cualquier duda, estoy disponible dentro de las posibilidades de mi tiempo libre, tanto por aquí como en issues en el repositorio.
Se agradecen estrellas en el repo!

Un saludo!
Responder Con Cita
Gracias de parte de:


  #2  
Viejo 15/05/16, 10:49:26
Avatar de mocelet
mocelet mocelet no está en línea
Desarrollador
Mensajes: 2,203
 
Fecha de registro: may 2011
Localización: Madrid
Mensajes: 2,203
Tu operador: -
Mencionado: 17 comentarios
Tagged: 2 hilos
Qué bueno, está muy bien concienciar sobre el uso de patrones y buenas prácticas, así como de las guías de estilo de código para mejorar la legibilidad y mantener coherencia.

Muchos de todas formas se deberían llamar "patrón sentido común si quieres añadir funcionalidad más adelante" o "patrón sentido común del uso de interfaces que están para algo".

A veces me recuerdan a las normas de convivencia que tuvieron que redactar en mi comunidad de vecinos con cosas como "no tiren basura al patio común": si hay que dejar por escrito esas cosas es que hay un problema de fondo más grave, normalmente de falta de empatía (otros vecinos que sufren tu dejadez u otros desarrolladores que tengan que modificar algo o incluso uno mismo en un futuro cuando ya no te acuerdas de qué hiciste y quieres cambiar algo).
Responder Con Cita
  #3  
Viejo 15/05/16, 11:05:56
Avatar de Dexafree
Dexafree Dexafree no está en línea
Mr. FAQMan
Mensajes: 8,021
Compra y venta: (1)
 
Fecha de registro: dic 2008
Mensajes: 8,021
Modelo de smartphone: Samsung Galaxy S i9000 + Galaxy Tab 10.1 WiFi
Versión de ROM: Android 4.1.1 Jelly Bean
Versión de Radio: KF1
Tu operador: Movistar
Mencionado: 65 comentarios
Tagged: 2 hilos
La mayoría de artículos sobre MVP y CleanArchitecture están en ingles, cosa que a algún que otro desarrollador español puede suponerle una barrera de entrada (aunque el 99% del material y documentación sobre programación que existe es e inglés...) así que buen trabajo traduciendo recursos al español

Desde hace un año aproximadamente trabajo con la arquitectura MVP-I (Model-View-Presenter-Interactor), y desde luego ha mejorado muchísimo el desacople de mi código.

En algunos proyectos además utilizo RxJava, que aunque al principio cueste un poco cogerle el "flow", acaba siendo bastante cómodo para concatenación de operaciones, transformaciones de recursos recibidos de APIs...

Desde luego aprender a utilizar patrones y diseñar arquitecturas es un paso adelante para cualquier desarrollador, no solo de Android, sino en general.


PD: En el subreddit de /r/androiddev hay muchísimos artículos de este tipo. Dagger, nuevas libs que van apareciendo, artículos sobre arquitecturas... https://es.reddit.com/r/androiddev

Cita:
Originalmente Escrito por mocelet Ver Mensaje
"patrón sentido común del uso de interfaces que están para algo".
Esa me la apunto, grande

Última edición por Dexafree Día 15/05/16 a las 11:13:02
Responder Con Cita
Gracias de parte de:
  #4  
Viejo 15/05/16, 13:30:50
Avatar de mocelet
mocelet mocelet no está en línea
Desarrollador
Mensajes: 2,203
 
Fecha de registro: may 2011
Localización: Madrid
Mensajes: 2,203
Tu operador: -
Mencionado: 17 comentarios
Tagged: 2 hilos
Cita:
Originalmente Escrito por Dexafree Ver Mensaje
Desde hace un año aproximadamente trabajo con la arquitectura MVP-I (Model-View-Presenter-Interactor), y desde luego ha mejorado muchísimo el desacople de mi código.
O_O Desconocía el término, en efecto parece el caso de "uso de interfaces que para eso están".

Los programas de ajedrez de los 80 y 90 tenían un protocolo basado en texto para comunicarse con la implementación de la interfaz de usuario, que podía ser línea de comandos, gráfica, de ventanas, e incluso de sistemas operativos diferentes. La lógica no había que tocarla, y la capa de presentación simplemente le comunicaba a la lógica eventos (ha movido aquí) o los recibía (mueve tal pieza). Creo que incluso algunos motores programados en C en su día se integran con apps móviles hoy día que únicamente aportan la capa de visualización.
Responder Con Cita
Gracias de parte de:
  #5  
Viejo 15/05/16, 17:09:39
Avatar de Dexafree
Dexafree Dexafree no está en línea
Mr. FAQMan
Mensajes: 8,021
Compra y venta: (1)
 
Fecha de registro: dic 2008
Mensajes: 8,021
Modelo de smartphone: Samsung Galaxy S i9000 + Galaxy Tab 10.1 WiFi
Versión de ROM: Android 4.1.1 Jelly Bean
Versión de Radio: KF1
Tu operador: Movistar
Mencionado: 65 comentarios
Tagged: 2 hilos
También ayuda muchísimo a la escritura de tests, ya que toda la parte de "Presenter" puedes escribirla en Java puro, con lo cual los tests se pueden ejecutar con JUNIT, sin tener que recurrir a tests de instrumentación (lo que conlleva a arrancar un emulador y ejecutarlos).

Eso + Dagger2 es amor
Responder Con Cita
  #6  
Viejo 15/05/16, 19:37:48
Avatar de vAlmaraz
vAlmaraz vAlmaraz no está en línea
Miembro del foro
Mensajes: 207
 
Fecha de registro: dic 2012
Mensajes: 207
Modelo de smartphone: Nexus 5, Pomp P8, Sony Xperia X10 Mini Pro
Versión de ROM: Android 6.0.1
Tu operador: Jazztel
Mencionado: 0 comentarios
Tagged: 0 hilos
Cita:
Originalmente Escrito por Dexafree Ver Mensaje
[...]

Desde hace un año aproximadamente trabajo con la arquitectura MVP-I (Model-View-Presenter-Interactor), y desde luego ha mejorado muchísimo el desacople de mi código.

[...]

Desde luego aprender a utilizar patrones y diseñar arquitecturas es un paso adelante para cualquier desarrollador, no solo de Android, sino en general.

[...]

Si, la verdad es que solo separando la capa de acceso a datos, la legibilidad y calidad del código mejora mucho.
Si además divides en más capas las implementaciones de las vistas...

Ojalá hubiera empezado antes a aplicar arquitectura. Me hubiera ahorrado mucho tiempo con cambios imprevistos. Además que el patrón de repositorios y las capas independientes del framework, a la hora de hacer una app para Android e iOS, es un simple copia y pega traduciendo el lenguaje.
Responder Con Cita
  #7  
Viejo 24/05/16, 01:04:45
Avatar de manolazo
manolazo manolazo no está en línea
Miembro del foro
Mensajes: 219
 
Fecha de registro: jun 2012
Localización: Madrid
Mensajes: 219
Modelo de smartphone: Samsung Galaxy S7 edge
Tu operador: Pepephone
Mencionado: 1 comentarios
Tagged: 0 hilos
Buenas
Me he descargado el proyecto desde github https://github.com/vAlmaraz/mvp-android para echarle un ojo pero no funciona , se queda la pantalla principal con un boton de retry .

He mirado el codigo parece bastante enrevesado al menos para mi nivel , realmente no veo la sencillez del modelo (anotaciones @NONNull pasandolas por parametro en las funciones, uso de librerias retrofit2, etc ).

Hasta que punto es mejor usar este modelo al modelo tradicional para este tipo de apps? Supongo que sera un ejemplo sencillo y que lo ideal seria usarlo para proyectos complejos?

Esta claro que vosotros estais a un nivel de programacion muy por encima de la media que del foro y lo veis de otra manera , pero bueno, de ahi mis dudas.

Última edición por manolazo Día 24/05/16 a las 01:08:48
Responder Con Cita
  #8  
Viejo 24/05/16, 11:39:47
Avatar de mocelet
mocelet mocelet no está en línea
Desarrollador
Mensajes: 2,203
 
Fecha de registro: may 2011
Localización: Madrid
Mensajes: 2,203
Tu operador: -
Mencionado: 17 comentarios
Tagged: 2 hilos
Cita:
Originalmente Escrito por manolazo Ver Mensaje
Hasta que punto es mejor usar este modelo al modelo tradicional para este tipo de apps? Supongo que sera un ejemplo sencillo y que lo ideal seria usarlo para proyectos complejos?
En el fondo sigue siendo el modelo de siempre (MVC) metiendo interfaces por medio para que el código que trata con la vista (layouts, textviews, botones...) esté perfectamente aislado (desacoplado) de la lógica de tu aplicación.

O, en otras palabras, que la lógica de tu aplicación esté en una clase independiente y no veas ni una sola referencia a cosas de la vista por ninguna parte. Así, si algún día cambias la vista, tu lógica no cambia. Y si tienes que cambiar la lógica, será más fácil.

Ejemplo muy básico, tienes una app que permite actualizar su contenido online y mezclado con el código que descarga cosas tienes un textView.setText("Actualizando") y un textView.setVisibility(View.VISIBLE).

Lo primero que te dice el sentido común a poco que empieces a cambiar cosas en el código es crear un método en la misma clase que se llame mostrarProgreso() y ahí ya meter el setText y el setVisibility. Al menos ahora el método que descarga cosas no tiene referencias feas a textviews y si algún día quieres cambiar el textview por un progressbar o por una animación súper chula solo tienes que tocar en un sitio.

Sin embargo, la clase sigue teniendo código de lógica o de funcionalidad y código de visualización. La siguiente idea feliz es separarlos. En una clase la lógica y en otra el actualizar la vista. Para que la lógica le pueda decir a la capa de presentación que muestre el mensaje de actualización es necesario que la capa de presentación implemente una interfaz que tenga el método mostrarProgreso()

Y esa es la base del MVP, añadir una capa de abstracción para que la lógica sólo indique QUÉ hay que mostrar, el CÓMO ya lo decidirá la capa de presentación.

Idem para las acciones del usuario (interacciones), en vez de tratar directamente el evento de un botón con onActualizar(View v) por ejemplo, tu lógica implementa el método actualizar() y otra clase se encarga de llamarlo al recibir el evento del usuario (que puede ser de un botón o igual mañana es un gesto de deslizar, a tu lógica le da igual). En este caso lo que le importa a la lógica es QUÉ acción es (actualizar), no CÓMO se generó (se apretó un botón de nombre tal).

Los modelos, patrones, arquitecturas, etc. no son más que recomendaciones o buenas prácticas. Al final todas van dirigidas a que el código sea más legible, más manejable, menos propenso a errores y más extensible. En definitiva, más intuitivo. Qué aplicar en cada caso ya queda a criterio del desarrollador, desacoplar por desacoplar no tiene sentido (por eso los ejemplos sencillos son desafortunados, da la idea de que es matar moscas a cañonazos).

Con las funciones de refactorización que tiene Android Studio tampoco se tarda mucho en extraer una interfaz y empezar a desacoplar funcionalidad.
Responder Con Cita
  #9  
Viejo 24/05/16, 11:40:01
Avatar de Dexafree
Dexafree Dexafree no está en línea
Mr. FAQMan
Mensajes: 8,021
Compra y venta: (1)
 
Fecha de registro: dic 2008
Mensajes: 8,021
Modelo de smartphone: Samsung Galaxy S i9000 + Galaxy Tab 10.1 WiFi
Versión de ROM: Android 4.1.1 Jelly Bean
Versión de Radio: KF1
Tu operador: Movistar
Mencionado: 65 comentarios
Tagged: 2 hilos
Cita:
Originalmente Escrito por manolazo Ver Mensaje
He mirado el codigo parece bastante enrevesado al menos para mi nivel , realmente no veo la sencillez del modelo
El modelo no tiene por qué ser sencillo ni complejo, sino fácilmente desgranable en partes más pequeñas que permitan tratarlas de forma independiente. Esto no es propio de Android, sino buena práctica del desarrollo en general.

También es cierto que utilizar este tipo de arquitecturas no es lo recomendable cuando simplemente estás aprendiendo, ya que la arquitectura termina siendo una forma de organizar tu código una vez has superado la barrera de entrada inicial (saber cómo obtener los resultados que deseas). Al final al usuario le da igual si lo tienes todo en una activity de 10000 líneas o si lo has separado utilizando una arquitectura hexagonal, el solo quiere que al darle al botón se vea lo que se tenga que ver.


Cita:
Originalmente Escrito por manolazo Ver Mensaje
anotaciones @NONNull pasandolas por parametro en las funciones
No es que esté pasando la anotación por parámetro, sino que la anotación está asociada al parámetro.
Esa anotación puede estar asociada a métodos que nunca pueden devolver null, o a parámetros que nunca pueden ser null.

Cita:
Originalmente Escrito por manolazo Ver Mensaje
uso de librerias retrofit2
El uso de esta librería es bastante común cuando se habla de hacer peticiones sobre HTTP, y además es bastante cómoda de utilizar. Es de las más utilizadas en la comunidad Android, te recomiendo que si algún día necesitas hacer peticiones de red le eches un ojo

Cita:
Originalmente Escrito por manolazo Ver Mensaje
Hasta que punto es mejor usar este modelo al modelo tradicional para este tipo de apps?
Como he puesto arriba,

Cita:
También es cierto que utilizar este tipo de arquitecturas no es lo recomendable cuando simplemente estás aprendiendo, ya que la arquitectura termina siendo una forma de organizar tu código una vez has superado la barrera de entrada inicial
Además, no es algo que se entienda en una leída de código, hay que pegarse con el hasta que tienes un poco el "momento ajá!" y entiendes por qué se hace cada cosa.
Ten en cuenta también que una arquitectura no es un estándar, cada uno puede adaptarla a sus necesidades.


---

Dicho esto, paso a hacer un par de comentarios sobre el código... Como siempre, la programación es el mundo del cuñadismo por excelencia (aka: "Pues yo esto lo haría de otro modo...")

1. Clase Network. Cada vez recreas un RetrofitService, cosa que es bastante costosa (ya que se hace por reflection). Te recomiendo que lo cachees y lo reutilices (ej: singleton, por ejemplo).
La aproximación que suelo utilizar en esos casos es utilizar Dagger2 e inyectarlo donde se necesite (lo mismo con el OkHttpInterceptor)

2. Retrofit. Generas la URL directamente desde código. Te recomiendo que le eches un ojo a las anotaciones de Retrofit, ya que puedes pasarle directamente los parámetros y el automáticamente te hace las concatenaciones: http://square.github.io/retrofit (apartado URL Manipulation).

3. getContext en las vistas. En tu caso estás utilizando la propia vista como contexto. Ten cuidado, ya que eso puede llevar a que tengas memory leaks. Siempre que necesites un Context, deberías intentar llamar a .getApplicationContext, ya que ese contexto siempre está disponible mientras viva la aplicación y no está ligado a ninguna activity en concreto. Ya lo que sería genial sería que fuera parte del grafo de dependencias, y así podrías dejar la interfaz de la vista totalmente libre de Android, cosa que si planeas hacer tests para el presenter será de gran ayuda, ya que podrás ejecutarlos directamente desde JUnit.

Esas son las primeras opiniones después de echarle un ojo rápido al código. Espero que no te molesten!

Última edición por Dexafree Día 24/05/16 a las 11:44:09
Responder Con Cita
  #10  
Viejo 26/05/16, 00:25:19
Avatar de manolazo
manolazo manolazo no está en línea
Miembro del foro
Mensajes: 219
 
Fecha de registro: jun 2012
Localización: Madrid
Mensajes: 219
Modelo de smartphone: Samsung Galaxy S7 edge
Tu operador: Pepephone
Mencionado: 1 comentarios
Tagged: 0 hilos
Esta claro que es otra forma de trabajar y sobre todo de tener los proyectos mas organizados , el tema es como dice Mocelet que para cosas sencillas yo lo veo como matar moscas a cañonazos y quieras o no , para alguien que programa por hobby como yo habiendo aprendido de forma autodidacta desde casa a base de pdfs , libros y tutoriales y que en casi ninguno usen este modelo de organizacion pues cuesta un poco cambiar el chip.

De todas formas de lo que se trata es de seguir aprendiendo y echarle un ojo a este modelo porque al menos en mi caso soy un poco desastre ya que programo de forma un poco desordenada , empiezo con algo sencillo y poco codigo al que voy añadiendo mas funciones y mas clases a medida que voy agrandando el proyecto y al final se convierte en algo que es dificil de mantener y actualizar. La verdad que cuando hay tanto codigo no se como organizarlo.

La verdad que da gusto leeros a los PROS del foro (Kriogen, mocelet, dexafree...) se aprende bastante con vosotros y haceis una gran labor resolviendo las dudas que os planteamos.

Saludos.
Responder Con Cita
  #11  
Viejo 26/05/16, 13:40:43
Avatar de mocelet
mocelet mocelet no está en línea
Desarrollador
Mensajes: 2,203
 
Fecha de registro: may 2011
Localización: Madrid
Mensajes: 2,203
Tu operador: -
Mencionado: 17 comentarios
Tagged: 2 hilos
Cita:
Originalmente Escrito por manolazo Ver Mensaje
soy un poco desastre ya que programo de forma un poco desordenada , empiezo con algo sencillo y poco codigo al que voy añadiendo mas funciones y mas clases a medida que voy agrandando el proyecto y al final se convierte en algo que es dificil de mantener y actualizar. La verdad que cuando hay tanto codigo no se como organizarlo.
¿Acaso se puede empezar de otra forma? Empezar con algo sencillo e ir ampliando es lo habitual salvo que tengas un proyecto con una especificación cerrada o todas tus apps tengan el mismo molde. En apps que van refinándose conforme a lo que piden los usuarios, comentarios, ideas nuevas e incluso lo que tú mismo vas aprendiendo con la experiencia, no queda otra.

Da igual el nivel que tengas, en cuanto pase un tiempo el código anterior te hará daño a la vista y además pensarás "esto ahora lo haría de otra forma". A veces porque la propia tecnología cambia y favorece ciertas prácticas, otras simplemente porque nos falta una bola de cristal que te diga cómo va a evolucionar el proyecto.

Y al final, si la app evoluciona mucho, que se convierta en algo difícil de mantener es inevitable. A mí me pasa con el cuatro en raya que lleva cinco años ya... creo que las únicas líneas que se mantienen de siempre son unas pocas líneas muy feas de la inteligencia artificial que funcionan muy bien y "mejor no tocar". El resto, reescrito más de una vez.

Curiosamente hace poco reescribí el online aplicando el modelo MVP sin saber su nombre Quería separar completamente el comportamiento online de la gestión de sockets y del apartado gráfico en previsión de dejar de usar custom views y pasarme a un motor de juegos tipo libgdx y algún día quitar los sockets y usar websockets. Como también estoy preparando la versión de iOS, si la lógica es independiente de la parte gráfica y de la conexión puedo tener un código que a grandes rasgos sea el mismo en Java y en Swift (cambiando la sintaxis, pero el "pseudocódigo" sería el mismo). La parte específica de cada sistema estará en su clase independiente, más fácil de probar también y de intercambiar (hoy uso una biblioteca de conectividad, mañana otra y al resto de la app no le importa porque la interfaz se mantiene).

Es más código y más interfaces, pero es un caso claro donde merece la pena desacoplar.
Responder Con Cita
  #12  
Viejo 08/06/16, 07:57:53
Avatar de vAlmaraz
vAlmaraz vAlmaraz no está en línea
Miembro del foro
Mensajes: 207
 
Fecha de registro: dic 2012
Mensajes: 207
Modelo de smartphone: Nexus 5, Pomp P8, Sony Xperia X10 Mini Pro
Versión de ROM: Android 6.0.1
Tu operador: Jazztel
Mencionado: 0 comentarios
Tagged: 0 hilos
Perdonad que no haya contestado antes. He estado bastante liado entre el trabajo y otras cosas.

Respondo a un par de cosas:

El proyecto tal cual no funciona porque la api key para OpenWeather es inválida (no puedo regalar mi api key). Es necesario registrarse y sustituir por una buena.
La api key se cambia en la clase Environment.

Cita:
Originalmente Escrito por Dexafree Ver Mensaje
Dicho esto, paso a hacer un par de comentarios sobre el código... Como siempre, la programación es el mundo del cuñadismo por excelencia (aka: "Pues yo esto lo haría de otro modo...")
Respecto a las mejoras del código, lo primero muchas gracias por tu opinión, lo agradezco mucho.
Si, Network podría ser un singleton, ya he probado antes con él, pero como siempre dicen que es un antipatrón... de todas formas tengo pendiente hacer pruebas a ver si realmente no merece la pena.
Lo de las anotaciones de Retrofit es como las usaba en el modo tradicional de programar. La ventaja en esta otra forma es que no lleno en una sola interfaz distintas llamadas. Tambien tengo pendiente pensar cómo aprovechar las anotaciones y dividirlas por cada cliente.
Sobre el contexto, toda la razón. El código lo he hecho en ratos libres y corriendo y hay muchas cosas por mejorar.

En global, si, es una arquitectura más compleja para iniciados, pero merece la pena aplicarla siempre, por muy pequeña que sea la app. Con experiencia, os daréis cuenta.

Un saludo!


EDITO: Explico un poco más en detalle la principal razón para no utilizar las anotaciones de Retrofit:
El objetivo es desligar por completo las clases Client de Network (implementación básica de la conexión) de tal manera que ningún Client sepa qué librería se utiliza.
Esto permite que si se decide cambiar de Retrofit a Volley, por ejemplo, el cambio sólo sería en Network, dejando intactos todos los Client.
O un ejemplo más real, si Retrofit se actualiza, como ha pasado de la 1 a la 2, cambiando muchos de los métodos principales y callbacks, sólo afecta a la clase Network.

Sigo teniendo pendiente encontrar una forma de aprovechar mejor las anotaciones, pero por ahora, a falta de tiempo para investigar, eso es lo que se me ha ocurrido para permitir el desacoplamiento.

Última edición por vAlmaraz Día 09/06/16 a las 07:53:08
Responder Con Cita
Respuesta

Estás aquí
Regresar   HTCMania > Todo sobre Android > Programación y Desarrollo para Android


Reglas de Mensajes
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Las caritas están On
Código [IMG] está On
Código HTML está Off

Saltar a Foro



Hora actual: 16:16:16 (GMT +2)

Cookies
Powered by vBulletin™
Copyright © vBulletin Solutions, Inc. All rights reserved.
 
HTCMania: líderes desde el 2007