Patrones de diseño - Android

bLero

Hola a todos,

Hace poco leí en algún hilo, que a mucha gente se le hacía difícil escribir código limpio en Android, dada la facilidad con la que este sistema nos induce a escribir código funcional pero súcio.

Pues bien, yo soy uno de ellos. Estoy hablando sobretodo de grandes aplicaciones, que necesitan consumir servicios, utilizar hilos, etc.

A diferencia del resto de lenguajes, donde siempre voy siguiendo unas buenas pautas de diseño, y el resultado es un código bastante decente, cuando programo para android, a poco tiempo que programe ya me doy cuenta de que estoy haciendo guarradas increibles como tirar de clases estáticas, pasar todo a traves del contexto, etc. Y es que me pongo a refactorizar y casi prefiero empezar un nuevo proyecto antes que arreglar todo el destrozo que he liao.

Esto creo que se debe principalmente al gran cambio que hay entre programar para aplicaciones de escritorio o web, a programar para android.

Dicho esto me gustaría preguntaros si a vosotros os pasa, u os ha pasado lo mismo, y si conocéis algún libro sobre patrones de diseño para android, o al menos que explique bien los entresijos del sistema operativo.

Me he leído Desarrollo de aplicaciones para Android de Anaya pero es una castaña. No toca nada de comunicaciones, ni explica bien conceptos importantes como el contexto, servicios, intents, etc. Además sus ejemplos son demasiado simples.

sasher

Pues me ha pasado, si, con Android como dices. El proyecto que realicé para una asignatura iba de geolocalización + música + socialmedia y no sabes el caos que era mantener un código limpio tocando el código 4 personas a la vez en GitHub. Yo me ponía de mala ostia cada vez que veía el código que subían los demás por ejemplo.

Con otro proyecto que realicé después para lanzarlo al market (ya está hecho, ahora me falta la pasta para abrirme la cuenta) y que es bastante pequeño (solo una actividad y un server en un hilo, y un cliente en PC) tuve mas cuidado al hacer las cosas organizando todo en paquetes, utilizando un nombrado de strings adecuado, etc. Pero si, hay cosas que me siguen dando "asco": los listeners por ejemplo si vuelvo a tocar android para aplicaciones (espero que no), supongo que intentaré meterlos de forma mas aislada y no a saco dentro del "main".

1 respuesta
C

#1 Suscribo todo lo que dices. Desde que programar en Android se convierte en algo muy "guarro" a que no hay absolutamente nada de material de calidad.

En mi actual y eterna fase de aprendizaje me ha ayudado mucho ver código de aplicaciones opensource. Y aun así, se percibe cierto guarreo con los hilos, servicios y demás. Seguro que es posible hacer las cosas mejores, pero esa sensación de código sucio en Android creo que hay que acostumbrarse a ella.

Hay cosas que se pueden mejorar. Yo ahora estoy con un tema de fragments en los que para comunicarme con ellos desde la actividad principal hago ciertas guarradas y hay formas mejores. Por ejemplo, tengo un listview en el fragment. Pero el fragment está dentro de un ViewPager y, por tanto, se crea y destruye cada vez. Con lo cual para no perder la referencia al listview, el objeto que apunta a él lo tengo estático. He visto por ahí código de gente que pilota que lo que hace es implementar una interfaz para comunicar los dos elementos.

Se puede mejorar algo. Pero insisto, el código guarro de Android va a ser siempre guarro. ¿O no ha sido así en web hasta que aparecieron los frameworks? Pues lo mismo. Y damos gracias que ahora empiezan a aparecer patrones de la IU con un cierto estatus de estándares, porque hasta ahora la interfaz payaso de VB6 se veía (y se sigue viendo...) en un huevo de aplicaciones.

Lo único que puedo pasarte son unos cuantos blogs de gente que realmente pilota. Pero libros y tal... difícil lo veo.

edito #2, ajajaja me parto con lo que dices de los listeners. Pero confiesa: ¿a que si lo haces así (separado) te da la sensación (absurda) de que si alguien ve el código va a pensar que eres un n00b) xDDD
Yo hace tiempo que si el contenido del evento tiene más de dos líneas, me hago el listener por un lado en su objeto correspondiente y luego lo vinculo.

1 respuesta
B

Como os comprendo hermanos. Me doy asco a mi mismo como desarrollador cuando veo mi código en Android.

El tema de los listeners y los AsyncTasks es la hostia, yo creo que voy a acabar haciéndolos en clases aparte como dice #3.

Eso sí, yo lo que hago es crearme varios métodos para separar bien todo (initializeButtons, reloadData, lo que sea, para que al menos no me salgan funciones de 100 líneas asquerosas).

Esmoris

Yo vengo de programar en java , c ,c++ y c#, y quería ponerme a aprender a desarrollar en Android y m encuentro con este post.. xD

A mi lo de quedarme un código muy guarro me pasó en java pero porque fui muy naab ^.
Desarrolle una aplicación web con java y vaadin, para mi desgracia me baje las librerías de vaadin sin darme cuenta de que no eran las más actuales. El problema de esto fue que muchas funciones no las traía esta librería antigua, con lo que tuve que complicarme a crear las funciones de manera manual con lo que al final me quedaron más de 7000 líneas de código y tan solo 4 clases, una de ellas era un xml para ocultar las conexiones a las bases de datos xD.
Tenía en mente empezar a desarrollar en Android , podéis facilitarme algunos links útiles para poder empezar? Os lo agradecería mucho , gracias!

MTX_Anubis

El problema de Android es que aunque el SDK es bastante funcional no está estructurado para desarrollar aplicaciones multicapa, solo hay que ver cualquier applicación para ver que se mezcla todo en la actividad, lógica de UI, acceso a datos y lógica de la app y lo peor, en los tutoriales te incitan a hacerlo así.

Los AsynTask siempre los hago en clases a parte, los listeners jamás como clases anónimas e intento seguir un patrón multicapa lo máximo posible. Cuando algunos componentes de la vista tienen mucha lógica, creo un widget con esa lógica para no acabar con actividades de 800 lineas.

Para mi una actividad es sinónimo de vista digan lo que digan, se pueden utilizar librerías de inyección de dependencias y demás historias, aquí hablan bastante sobre ello y recomiendo su lectura para ahorros miles de líneas de código repetidas.

http://blog.springsource.org/2011/08/26/clean-code-with-android/

Otra opción es hacer las apps totalmente modulares, esto lo hice con OSGi en una app para telefónica. Es un poco jaleo la verdad pero algo así bien estructurado.

1 respuesta
cabron

#6:

"y lo peor, en los tutoriales te incitan a hacerlo así"

Y bien que está hecho, al menos en mi opinión. No es lo mismo un ejemplo, que una aplicación real. No hay nada peor que un ejemplo donde al autor le da por estructurar cosas y meter control de errores, y al final acabas diciendo "pero donde coño está lo que quiero ver".

Además eso no ocurre solo en Android, en la documentación oficial de casi cualquier cosa los ejemplos suelen ser siempre así, algo en lo que estoy de acuerdo. Yo prefiero ver todo junto y que sea fácil localizar de donde sale cada cosa y como se usa. No creo que los tutoriales estén hechos en ese plan para "incitar" a que lo hagas así, si no para que sean lo más claro posibles.

Puni

#1 Hombre todo depende de lo guarro que seas y cuanto te guste refactorizar. Tuve la suerte de currar con un tío que llevaba programando en java una burrada de años y adquirí muy buenos hábitos para programar, por ejemplo siempre que podía, en cuanto algo olía a código repetido crear superclases o interfaces, clases de utilidad para tonterías (quitar decimales a labels de números) y dejar cada cosas en su sitio.

Yo simplemente procuro programar en capas, dejar toda la lógica de negocio para el modelo, es decir, no usar POJOs si no objetos que realmente se ocupen de hacer lo importante. En las activitys hacer UI exclusivamente y si necesitas asynctask y listener exclusivos de esa clase dejarlos ahí, al fin y al cabo es E/S. Y hacer una capa de persistencia, incluso por encima del orm. Las clases estáticas no tienen porqué estar mal, para mí tienen mucho sentido

No se, yo prefiero un SDK que te permita hacer guarradas e ir haciendo las cosas bien por costumbre a que me obliguen a una estructura determinada.

Eso si: al final tengo proyectos con 6000 lineas de código repartidas en 300 archivos xD

1 respuesta
Zapador

Aprovechando el hilo, lanzo una pregunta de noob total.

He comenzado un curso de android esta semana y ahora estoy empezando a familiarizarme con layouts, jugando con los textviews y demás.....pero me pasa algo curioso ¿por qué cuando cambio la id de un elemento se me descuadra toda la puta ventana?.

El ide que uso es eclipse.

1 respuesta
C

#8 Me quedo con tu frase: No se, yo prefiero un SDK que te permita hacer guarradas e ir haciendo las cosas bien por costumbre a que me obliguen a una estructura determinada.

Pienso igual. Los frameworks estarán bien y aumentarán la productividad en tanto en cuanto cualquier nuevo programador que se incorpore al equipo le costará menos entender todo. Pero como tener la libertad de hacer lo que te de la gana... esto es como el sexo! lo mismo! xd

1 respuesta
elkaoD

#10 indeed.

Yo he comprobado que la reusabilidad de un framework es bastante limitada. Me llevo pegando con distintos frameworks JS desde hace unos meses y TODOS son para un tipo de aplicación concreta.

Al final me quedé con un par que no te obligan a usar ciertas cosas y tomar ciertos caminos, pero tienen capas de abstracción intermedias bastante innecesarias IMHO. Al final he acabado "arrejuntando" librerías y fin.

1 respuesta
cabron

#11

Hombre, es que para son los frameworks, solo sirven para hacer un tipo de aplicación y estructurado todo siempre de la misma forma. Por su propia definición, es imposible que encuentres uno que te valga para hacer varios tipos de aplicaciones, o poder hacerlas a tu manera.

Lo que sí que hay es lo que dices (en general no solo javascript),algunos donde la estructura del framework es opcional, y si quieres puedes acceder a su funcionalidad a modo de libreria.

1 respuesta
elkaoD

#12 no lo creo. Es como un si un framework de videojuegos sólo me permitiera hacer FPS.

cabron

la mayoria de cosas que se anuncisn como frameworks de juegos tienen mas de librería que de framework

1 respuesta
Li3cht

#9 Porque estás usando el layout de fábrica, si usas un Linear Layout se acabó tu problema xD

elkaoD

#14 la linea entre framework y librería es muy difusa. ¿Puedes poner un ejemplo?

De hecho hay más frameworks que librerías, porque los que son librerías hacen poco más que cargar texturas y manejar I/O (véase SDL, SFML, etc.)

1 respuesta
cabron

#16

Hombre, yo de un framework espero cosas que funcionan directamente, y solo hay que poner los detalles de que hay que hacer. Por ejemplo el primer framework que usé hace ya años fue MFC, el framework de Microsoft para programar en Windows antes que que sacasen .net. Con MFC, tu creas un proyecto nuevo, y sin escribir ni una línea de código, tienes algo más o menos así:

Todos los botones de la barra de iconos eran totalmente funcionales, el de abrir, te mostraba la ventana de abrir documentos, y podías seleccionar un archivo (aunque no hacía nada), el de imprimir imprimía la ventana, la barra de estado mostraba lo que hacía cada icono al pasar el ratón por encima, etc. A partir de ahí tú ibas especificando lo que había que hacer con cada operación, y obviamente puedes añadir y quitar iconos, modificar la barra de menús, y todo eso.

Ahora si piensas en un juego, y las cosas típicas que cualquier juego de cualquier género tiene: mapas, npcs, records, pantalla de presentación, cutscenes, etc, si algo no da soporte directo para todo eso, no considero que se pueda decir que es un framework para juegos. Por ejemplo el Source SDK de Valve tiene todo eso, es más, sin escribir una línea de código, simplemente creando un proyecto nuevo del SDK, tienes algo totalmente funcional donde puedes cargar un mapa vacío y moverte en todas direcciones. Si quieres añadir algo al juego, creas una subclase de CBaseAnimating, la inicializas, y automáticamente tienes algo que aparece en el mapa con el modelo 3d que hayas especificado y que colisiona con la física del mapa. Todo el sistema para cambiar de un mapa a otro, para iniciar y terminar la partida, en fin, lo típico que se hace en un juego, está ya hecho y tú lo usas como necesites. Si buscas todo eso en cosas como cocos2d-x o libgdx, es inexistente, lo que tienes es una colección de clases para que las uses como tú veas y te crees tu propio sistema para hacer todas esas cosas.

Normalmente los frameworks funcionan con "hooks", que vienen a ser funciones vacías donde tú pones el código concreto de tú aplicación. Si no escribes nada, tienes una aplicación completamente funcional, que puedes ejecutar y usar, solo que no realiza ninguna tarea concreta. Cada elemento del framework tiene sus propios métodos que funcionan a modo de gancho, así que la forma típica de usar un framework suele ser crear tu propia subclase que hereda del componente del framework que quieres usar, y sobreescribes los métodos que te interesan. Tú ni siquiera controlas cuando se llaman esos métodos, es algo que viene predefinido por el framework.

Vamos que con un framework, más que hacer una aplicación, tienes más la sensación de estar extendiendo una aplicación ya hecha, solo que esa aplicación que extiendes es tan básica, que la puedes convertir un poco en lo que quieras, pero claro eso ya implica que la estructura de la aplicación viene predefinida y es algo que no puedes cambiar.

1 1 respuesta
elkaoD

#17 lo que describes de MVC no es un framework, sino un proyecto de ejemplo xD Muchos frameworks vienen con proyectos de ejemplo, pero eso no hace que un framework deje de ser framework si no viene con un proyecto de ejemplo. Puedes hacer un proyecto MVC desde cero, sin tirar del proyecto de ejemplo.

El Source SDK es un SDK como su propio nombre indica. Es MUCHO más que un framework. Es un framework, assets, una toolset, etc.

¿Django no es un framework? Porque con Django no extiendes ninguna aplicación ya hecha. Construyes desde cero (a no ser que partas de un proyecto de ejemplo.)

Y lo que comentas de extender clases y tal... en efecto, así funcionan todos los frameworks de videojuegos que conozco. Extiendes de GameLoop y tienes tu loop. Extiendes de Entity y tienes tu entidad. Extiendes de Sprite y tienes tu sprite, etc.

Insisto, ¿algún ejemplo concreto? Porque lo que comentas en tus últimos párrafos es exactamente como funcionan todos los frameworks de videojuegos que conozco, desde XNA hasta cocos2d.

¿Ejemplos que no funcionan así? Pues por ejemplo SDL y SFML, pero la L de su nombre es de "Library".

1 respuesta
cabron

#18

que no hombre, no es un proyecto de ejemplo, que es que toda la aplicación se hace así, todo tú código está en una subclase de una clase del framework, y hacer una aplicación consiste en eso, haces subclase de X, sobreescribes unos métodos, y ya está. Todo el ciclo de la aplicación para que se ejecuten esos métodos es ajeno a ti y no tienes control sobre ello, y como solo puedes hacer operaciones de esta forma, la estructura de la aplicación ya te viene predefinida.

Al final el problema va a estar en que en programación existe la fea costumbre de usar la misma palabra para todo, es como "componente" que es probablemente la palabra más sobreecargada de todas. Yo la primera vez que vi la palabra framework fue en ese contexto, y es a lo que la asocio.

Y es cierto que en cocos2dx puedes hacer eso, pero está limitado a la parte gráfica, si quieres decir que es un framework gráfico para juegos, estoy de acuerdo en que lo es, pero de ahí no pasa.

Además que yo no he dicho MVC, he dicho MFC (microsoft fundation classes), no tiene nada que ver...

1 respuesta
elkaoD

#19 es un proyecto de ejemplo, te pongas como te pongas. No hace falta partir del código de ejemplo para hacer un proyecto. Si hablas de la forma de trabajar "extendiendo" clases, ok, pero no me digas que tienes que tirar a partir del código (la screenshot) que pones, porque es un ejemplo y punto. Borras ese código y empiezas de cero y funciona igual. Muchos frameworks estructurados tienen proyectos de ejemplo para tirar desde ellos, pero ni es obligatorio usarlos, ni es parte del framework. Es como los sistemas de scaffolding MVC, un "plus", pero no es lo que los convierte en un framework.

Cocos2d no es sólo la parte gráfica (a no ser que sistemas de esqueleto, partículas, colisiones, audio, etc. los consideres también parte gráfica.) Y un framework es un framework tenga la extensión que tenga, a ver si un framework va a tener que hacer TODO lo del universo... Nope, hay frameworks más o menos simples y con mayor o menor funcionalidad. Si un framework MVC no te ata al modelo... ¿deja de ser un framework? (véase Locomotive para Node.)

Vuelvo a insistir ya que evitas responder... ¿me pones un ejemplo de framework para juegos que no funcione así? xD Dime UN SÓLO framework de videojuegos que no tengas que extender su loop directamente.

PD: lo de MVC fue un lapsus, conozco MFC de cuando programaba en VS y decía "¿y qué coño es eso de MFC?" xD Me pilló jovencito.

EDIT: por cierto, supongo que era sólo un ejemplo, pero es muy reduccionista basarlo todo en "extender" clases. Un framework no tiene por qué ser orientado a objetos.

1 respuesta
cabron

#20

En MFC, si borras el código que te crea el asistente, y lo haces desde 0, ¿con qué acabas? con el mismo código que te ha hecho el asistente... por lo que la estructura de la aplicación viene ya definida, que es lo importante que define el framework, y tú solo trabajas extendiendo esa estructura de la forma que ya hemos hablado, por eso insisto en que no es un proyecto de ejemplo, es que es la única forma que hay de hacerlo.

"Y un framework es un framework tenga la extensión que tenga, a ver si un framework va a tener que hacer TODO lo del universo"

De acuerdo, pero la cuestión es Framework para XXX, ¿puedes decir que cocos es un framework web solo por ser un framework? obviamente no... pues eso mismo, yo no los considero framework para juegos, por que les falta muchas cosas que absolutamente todos los juegos tienen.... a partir de ahí eso ya es una opinión subjetiva, tu puedes pensar que lo mínimo que se necesita es una cosa y yo otra, y yo no los veo lo suficientemente completos. ¿puedes controlar el ciclo de vida de una entidad del juego?, ¿puedes controlar el ciclo de vida de una partida?, no, lo tienes que hacer tú, y dime que juego no necesita eso...

1 respuesta
elkaoD

#21 paro la discusión porque lo de "¿puedes decir que cocos es un framework web solo por ser un framework?" es una absurdez como la copa de un pino.

Según tu teoría ningún framework es un framework porque todos podrían hacer más de lo que hacen.

#23 anda, libgdx no es un framework para juegos? xDD No, no creo que lo digas de forma despectiva pero... someone is wrong on the internet :P

1 respuesta
cabron

#22

No seas perro, paras la discusión pero sueltas una última coletilla final, y no, no he dicho eso, lo que he dicho es que si algo afirma ser un framework para juegos, tiene que tener soporte ya hecho (no que lo tengas que hacer tú) para lo que mínimo que va a tener siempre un juego. Si no lo tiene, no considero que sea un framework de juegos, y como ya te he dicho (no voy a entrar en bucle repitiendo lo mismo) para considerarlo framework tiene que haber algo más que simplemente clases y funciones relacionadas con eso.

Los juegos normales tienen una partida con un inicio, una duración, y un fin, entidades que son más que un simple elemento visual, etc. Los puedes considerar framework gráficos, framework físicos, framework lo que quieras, pero no es un framework para juegos, es una libreria para juegos, por que te da piezas para que lo hagas tú, no viene ya hecho.

De todas formas no se si crees que esto lo digo con connationes negativas o algo, yo digo que libgdx no es un framework para juegos y lo uso igual, ya ves tú lo que me importa llamarlo A o B....

1 respuesta

Usuarios habituales